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_READLINKAT(conn,
5850 if (link_len == -1) {
5851 return map_nt_error_from_unix(errno);
5853 buffer[link_len] = 0;
5854 status = srvstr_push(dstart, flags2,
5856 PTR_DIFF(dend, pdata),
5857 STR_TERMINATE, &len);
5858 if (!NT_STATUS_IS_OK(status)) {
5862 data_size = PTR_DIFF(pdata,(*ppdata));
5867 #if defined(HAVE_POSIX_ACLS)
5868 case SMB_QUERY_POSIX_ACL:
5870 status = smb_query_posix_acl(conn,
5877 if (!NT_STATUS_IS_OK(status)) {
5885 case SMB_QUERY_POSIX_LOCK:
5890 enum brl_type lock_type;
5892 /* We need an open file with a real fd for this. */
5893 if (!fsp || fsp->fh->fd == -1) {
5894 return NT_STATUS_INVALID_LEVEL;
5897 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5898 return NT_STATUS_INVALID_PARAMETER;
5901 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5902 case POSIX_LOCK_TYPE_READ:
5903 lock_type = READ_LOCK;
5905 case POSIX_LOCK_TYPE_WRITE:
5906 lock_type = WRITE_LOCK;
5908 case POSIX_LOCK_TYPE_UNLOCK:
5910 /* There's no point in asking for an unlock... */
5911 return NT_STATUS_INVALID_PARAMETER;
5914 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5915 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5916 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5918 status = query_lock(fsp,
5925 if (ERROR_WAS_LOCK_DENIED(status)) {
5926 /* Here we need to report who has it locked... */
5927 data_size = POSIX_LOCK_DATA_SIZE;
5929 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5930 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5931 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5932 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5933 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5935 } else if (NT_STATUS_IS_OK(status)) {
5936 /* For success we just return a copy of what we sent
5937 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5938 data_size = POSIX_LOCK_DATA_SIZE;
5939 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5940 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5948 return NT_STATUS_INVALID_LEVEL;
5951 *pdata_size = data_size;
5952 return NT_STATUS_OK;
5955 /****************************************************************************
5956 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5957 file name or file id).
5958 ****************************************************************************/
5960 static void call_trans2qfilepathinfo(connection_struct *conn,
5961 struct smb_request *req,
5962 unsigned int tran_call,
5963 char **pparams, int total_params,
5964 char **ppdata, int total_data,
5965 unsigned int max_data_bytes)
5967 char *params = *pparams;
5968 char *pdata = *ppdata;
5969 uint16_t info_level;
5970 unsigned int data_size = 0;
5971 unsigned int param_size = 2;
5972 struct smb_filename *smb_fname = NULL;
5973 bool delete_pending = False;
5974 struct timespec write_time_ts;
5975 files_struct *fsp = NULL;
5976 struct file_id fileid;
5977 struct ea_list *ea_list = NULL;
5978 int lock_data_count = 0;
5979 char *lock_data = NULL;
5980 size_t fixed_portion;
5981 NTSTATUS status = NT_STATUS_OK;
5984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5988 ZERO_STRUCT(write_time_ts);
5990 if (tran_call == TRANSACT2_QFILEINFO) {
5991 if (total_params < 4) {
5992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5997 call_trans2qpipeinfo(conn, req, tran_call,
5998 pparams, total_params,
6004 fsp = file_fsp(req, SVAL(params,0));
6005 info_level = SVAL(params,2);
6007 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6009 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6010 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6014 /* Initial check for valid fsp ptr. */
6015 if (!check_fsp_open(conn, req, fsp)) {
6019 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
6020 if (smb_fname == NULL) {
6021 reply_nterror(req, NT_STATUS_NO_MEMORY);
6025 if(fsp->fake_file_handle) {
6027 * This is actually for the QUOTA_FAKE_FILE --metze
6030 /* We know this name is ok, it's already passed the checks. */
6032 } else if(fsp->fh->fd == -1) {
6034 * This is actually a QFILEINFO on a directory
6035 * handle (returned from an NT SMB). NT5.0 seems
6036 * to do this call. JRA.
6039 if (INFO_LEVEL_IS_UNIX(info_level)) {
6040 /* Always do lstat for UNIX calls. */
6041 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6042 DEBUG(3,("call_trans2qfilepathinfo: "
6043 "SMB_VFS_LSTAT of %s failed "
6045 smb_fname_str_dbg(smb_fname),
6048 map_nt_error_from_unix(errno));
6051 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6052 DEBUG(3,("call_trans2qfilepathinfo: "
6053 "SMB_VFS_STAT of %s failed (%s)\n",
6054 smb_fname_str_dbg(smb_fname),
6057 map_nt_error_from_unix(errno));
6061 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6062 fileid = vfs_file_id_from_sbuf(
6063 conn, &smb_fname->st);
6064 get_file_infos(fileid, fsp->name_hash,
6070 * Original code - this is an open file.
6072 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6073 DEBUG(3, ("fstat of %s failed (%s)\n",
6074 fsp_fnum_dbg(fsp), strerror(errno)));
6076 map_nt_error_from_unix(errno));
6079 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6080 fileid = vfs_file_id_from_sbuf(
6081 conn, &smb_fname->st);
6082 get_file_infos(fileid, fsp->name_hash,
6091 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6094 if (total_params < 7) {
6095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6099 info_level = SVAL(params,0);
6101 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6103 if (INFO_LEVEL_IS_UNIX(info_level)) {
6104 if (!lp_unix_extensions()) {
6105 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6108 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6109 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6110 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6111 req->posix_pathnames) {
6112 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6116 if (req->posix_pathnames) {
6117 srvstr_get_path_posix(req,
6126 srvstr_get_path(req,
6135 if (!NT_STATUS_IS_OK(status)) {
6136 reply_nterror(req, status);
6140 status = filename_convert(req,
6147 if (!NT_STATUS_IS_OK(status)) {
6148 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6149 reply_botherror(req,
6150 NT_STATUS_PATH_NOT_COVERED,
6151 ERRSRV, ERRbadpath);
6154 reply_nterror(req, status);
6158 /* If this is a stream, check if there is a delete_pending. */
6159 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6160 && is_ntfs_stream_smb_fname(smb_fname)) {
6161 struct smb_filename *smb_fname_base;
6163 /* Create an smb_filename with stream_name == NULL. */
6164 smb_fname_base = synthetic_smb_fname(
6166 smb_fname->base_name,
6170 if (smb_fname_base == NULL) {
6171 reply_nterror(req, NT_STATUS_NO_MEMORY);
6175 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6176 /* Always do lstat for UNIX calls. */
6177 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6178 DEBUG(3,("call_trans2qfilepathinfo: "
6179 "SMB_VFS_LSTAT of %s failed "
6181 smb_fname_str_dbg(smb_fname_base),
6183 TALLOC_FREE(smb_fname_base);
6185 map_nt_error_from_unix(errno));
6189 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6190 DEBUG(3,("call_trans2qfilepathinfo: "
6191 "fileinfo of %s failed "
6193 smb_fname_str_dbg(smb_fname_base),
6195 TALLOC_FREE(smb_fname_base);
6197 map_nt_error_from_unix(errno));
6202 status = file_name_hash(conn,
6203 smb_fname_str_dbg(smb_fname_base),
6205 if (!NT_STATUS_IS_OK(status)) {
6206 TALLOC_FREE(smb_fname_base);
6207 reply_nterror(req, status);
6211 fileid = vfs_file_id_from_sbuf(conn,
6212 &smb_fname_base->st);
6213 TALLOC_FREE(smb_fname_base);
6214 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6215 if (delete_pending) {
6216 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6221 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6222 /* Always do lstat for UNIX calls. */
6223 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6224 DEBUG(3,("call_trans2qfilepathinfo: "
6225 "SMB_VFS_LSTAT of %s failed (%s)\n",
6226 smb_fname_str_dbg(smb_fname),
6229 map_nt_error_from_unix(errno));
6234 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6235 DEBUG(3,("call_trans2qfilepathinfo: "
6236 "SMB_VFS_STAT of %s failed (%s)\n",
6237 smb_fname_str_dbg(smb_fname),
6240 map_nt_error_from_unix(errno));
6245 status = file_name_hash(conn,
6246 smb_fname_str_dbg(smb_fname),
6248 if (!NT_STATUS_IS_OK(status)) {
6249 reply_nterror(req, status);
6253 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6254 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6255 get_file_infos(fileid, name_hash, &delete_pending,
6259 if (delete_pending) {
6260 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6265 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6266 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6268 info_level,tran_call,total_data));
6270 /* Pull out any data sent here before we realloc. */
6271 switch (info_level) {
6272 case SMB_INFO_QUERY_EAS_FROM_LIST:
6274 /* Pull any EA list from the data portion. */
6277 if (total_data < 4) {
6279 req, NT_STATUS_INVALID_PARAMETER);
6282 ea_size = IVAL(pdata,0);
6284 if (total_data > 0 && ea_size != total_data) {
6285 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6286 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6288 req, NT_STATUS_INVALID_PARAMETER);
6292 if (!lp_ea_support(SNUM(conn))) {
6293 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6297 /* Pull out the list of names. */
6298 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6301 req, NT_STATUS_INVALID_PARAMETER);
6307 case SMB_QUERY_POSIX_LOCK:
6309 if (fsp == NULL || fsp->fh->fd == -1) {
6310 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6314 if (total_data != POSIX_LOCK_DATA_SIZE) {
6316 req, NT_STATUS_INVALID_PARAMETER);
6320 /* Copy the lock range data. */
6321 lock_data = (char *)talloc_memdup(
6322 req, pdata, total_data);
6324 reply_nterror(req, NT_STATUS_NO_MEMORY);
6327 lock_data_count = total_data;
6333 *pparams = (char *)SMB_REALLOC(*pparams,2);
6334 if (*pparams == NULL) {
6335 reply_nterror(req, NT_STATUS_NO_MEMORY);
6342 * draft-leach-cifs-v1-spec-02.txt
6343 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6346 * The requested information is placed in the Data portion of the
6347 * transaction response. For the information levels greater than 0x100,
6348 * the transaction response has 1 parameter word which should be
6349 * ignored by the client.
6351 * However Windows only follows this rule for the IS_NAME_VALID call.
6353 switch (info_level) {
6354 case SMB_INFO_IS_NAME_VALID:
6359 if ((info_level & 0xFF00) == 0xFF00) {
6361 * We use levels that start with 0xFF00
6362 * internally to represent SMB2 specific levels
6364 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6368 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6370 delete_pending, write_time_ts,
6372 lock_data_count, lock_data,
6373 req->flags2, max_data_bytes,
6375 ppdata, &data_size);
6376 if (!NT_STATUS_IS_OK(status)) {
6377 if (open_was_deferred(req->xconn, req->mid)) {
6378 /* We have re-scheduled this call. */
6381 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6382 bool ok = defer_smb1_sharing_violation(req);
6387 reply_nterror(req, status);
6390 if (fixed_portion > max_data_bytes) {
6391 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6395 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6401 /****************************************************************************
6402 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6404 ****************************************************************************/
6406 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6407 connection_struct *conn,
6408 struct smb_request *req,
6409 bool overwrite_if_exists,
6410 const struct smb_filename *smb_fname_old,
6411 struct smb_filename *smb_fname_new)
6413 NTSTATUS status = NT_STATUS_OK;
6417 /* source must already exist. */
6418 if (!VALID_STAT(smb_fname_old->st)) {
6419 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6422 if (VALID_STAT(smb_fname_new->st)) {
6423 if (overwrite_if_exists) {
6424 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6425 return NT_STATUS_FILE_IS_A_DIRECTORY;
6427 status = unlink_internals(conn,
6429 FILE_ATTRIBUTE_NORMAL,
6432 if (!NT_STATUS_IS_OK(status)) {
6436 /* Disallow if newname already exists. */
6437 return NT_STATUS_OBJECT_NAME_COLLISION;
6441 /* No links from a directory. */
6442 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6443 return NT_STATUS_FILE_IS_A_DIRECTORY;
6446 /* Setting a hardlink to/from a stream isn't currently supported. */
6447 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6449 DBG_DEBUG("Old name has streams\n");
6450 return NT_STATUS_INVALID_PARAMETER;
6452 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6454 DBG_DEBUG("New name has streams\n");
6455 return NT_STATUS_INVALID_PARAMETER;
6458 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6459 smb_fname_old->base_name, smb_fname_new->base_name));
6461 ret = SMB_VFS_LINKAT(conn,
6469 status = map_nt_error_from_unix(errno);
6470 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6471 nt_errstr(status), smb_fname_old->base_name,
6472 smb_fname_new->base_name));
6477 /****************************************************************************
6478 Deal with setting the time from any of the setfilepathinfo functions.
6479 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6480 calling this function.
6481 ****************************************************************************/
6483 NTSTATUS smb_set_file_time(connection_struct *conn,
6485 const struct smb_filename *smb_fname,
6486 struct smb_file_time *ft,
6487 bool setting_write_time)
6489 struct smb_filename smb_fname_base;
6491 FILE_NOTIFY_CHANGE_LAST_ACCESS
6492 |FILE_NOTIFY_CHANGE_LAST_WRITE
6493 |FILE_NOTIFY_CHANGE_CREATION;
6495 if (!VALID_STAT(smb_fname->st)) {
6496 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6499 /* get some defaults (no modifications) if any info is zero or -1. */
6500 if (null_timespec(ft->create_time)) {
6501 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6504 if (null_timespec(ft->atime)) {
6505 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6508 if (null_timespec(ft->mtime)) {
6509 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6512 if (!setting_write_time) {
6513 /* ft->mtime comes from change time, not write time. */
6514 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6517 /* Ensure the resolution is the correct for
6518 * what we can store on this filesystem. */
6520 round_timespec(conn->ts_res, &ft->create_time);
6521 round_timespec(conn->ts_res, &ft->ctime);
6522 round_timespec(conn->ts_res, &ft->atime);
6523 round_timespec(conn->ts_res, &ft->mtime);
6525 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6526 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6527 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6528 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6529 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6530 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6531 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6532 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6534 if (setting_write_time) {
6536 * This was a Windows setfileinfo on an open file.
6537 * NT does this a lot. We also need to
6538 * set the time here, as it can be read by
6539 * FindFirst/FindNext and with the patch for bug #2045
6540 * in smbd/fileio.c it ensures that this timestamp is
6541 * kept sticky even after a write. We save the request
6542 * away and will set it on file close and after a write. JRA.
6545 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6546 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6549 if (fsp->base_fsp) {
6550 set_sticky_write_time_fsp(fsp->base_fsp,
6553 set_sticky_write_time_fsp(fsp, ft->mtime);
6556 set_sticky_write_time_path(
6557 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6562 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6564 /* Always call ntimes on the base, even if a stream was passed in. */
6565 smb_fname_base = *smb_fname;
6566 smb_fname_base.stream_name = NULL;
6568 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6569 return map_nt_error_from_unix(errno);
6572 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6573 smb_fname->base_name);
6574 return NT_STATUS_OK;
6577 /****************************************************************************
6578 Deal with setting the dosmode from any of the setfilepathinfo functions.
6579 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6580 done before calling this function.
6581 ****************************************************************************/
6583 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6584 const struct smb_filename *smb_fname,
6587 struct smb_filename *smb_fname_base;
6590 if (!VALID_STAT(smb_fname->st)) {
6591 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6594 /* Always operate on the base_name, even if a stream was passed in. */
6595 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6596 smb_fname->base_name,
6600 if (smb_fname_base == NULL) {
6601 return NT_STATUS_NO_MEMORY;
6605 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6606 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6608 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6612 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6614 /* check the mode isn't different, before changing it */
6615 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6616 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6617 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6618 (unsigned int)dosmode));
6620 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6622 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6624 smb_fname_str_dbg(smb_fname_base),
6626 status = map_nt_error_from_unix(errno);
6630 status = NT_STATUS_OK;
6632 TALLOC_FREE(smb_fname_base);
6636 /****************************************************************************
6637 Deal with setting the size from any of the setfilepathinfo functions.
6638 ****************************************************************************/
6640 static NTSTATUS smb_set_file_size(connection_struct *conn,
6641 struct smb_request *req,
6643 const struct smb_filename *smb_fname,
6644 const SMB_STRUCT_STAT *psbuf,
6646 bool fail_after_createfile)
6648 NTSTATUS status = NT_STATUS_OK;
6649 struct smb_filename *smb_fname_tmp = NULL;
6650 files_struct *new_fsp = NULL;
6652 if (!VALID_STAT(*psbuf)) {
6653 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6656 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6658 get_file_size_stat(psbuf));
6660 if (size == get_file_size_stat(psbuf)) {
6661 return NT_STATUS_OK;
6664 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6665 smb_fname_str_dbg(smb_fname), (double)size));
6667 if (fsp && fsp->fh->fd != -1) {
6668 /* Handle based call. */
6669 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6670 return NT_STATUS_ACCESS_DENIED;
6673 if (vfs_set_filelen(fsp, size) == -1) {
6674 return map_nt_error_from_unix(errno);
6676 trigger_write_time_update_immediate(fsp);
6677 return NT_STATUS_OK;
6680 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6681 if (smb_fname_tmp == NULL) {
6682 return NT_STATUS_NO_MEMORY;
6685 smb_fname_tmp->st = *psbuf;
6687 status = SMB_VFS_CREATE_FILE(
6690 0, /* root_dir_fid */
6691 smb_fname_tmp, /* fname */
6692 FILE_WRITE_DATA, /* access_mask */
6693 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6695 FILE_OPEN, /* create_disposition*/
6696 0, /* create_options */
6697 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6698 0, /* oplock_request */
6700 0, /* allocation_size */
6701 0, /* private_flags */
6704 &new_fsp, /* result */
6706 NULL, NULL); /* create context */
6708 TALLOC_FREE(smb_fname_tmp);
6710 if (!NT_STATUS_IS_OK(status)) {
6711 /* NB. We check for open_was_deferred in the caller. */
6715 /* See RAW-SFILEINFO-END-OF-FILE */
6716 if (fail_after_createfile) {
6717 close_file(req, new_fsp,NORMAL_CLOSE);
6718 return NT_STATUS_INVALID_LEVEL;
6721 if (vfs_set_filelen(new_fsp, size) == -1) {
6722 status = map_nt_error_from_unix(errno);
6723 close_file(req, new_fsp,NORMAL_CLOSE);
6727 trigger_write_time_update_immediate(new_fsp);
6728 close_file(req, new_fsp,NORMAL_CLOSE);
6729 return NT_STATUS_OK;
6732 /****************************************************************************
6733 Deal with SMB_INFO_SET_EA.
6734 ****************************************************************************/
6736 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6740 const struct smb_filename *smb_fname)
6742 struct ea_list *ea_list = NULL;
6743 TALLOC_CTX *ctx = NULL;
6744 NTSTATUS status = NT_STATUS_OK;
6746 if (total_data < 10) {
6748 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6749 length. They seem to have no effect. Bug #3212. JRA */
6751 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6752 /* We're done. We only get EA info in this call. */
6753 return NT_STATUS_OK;
6756 return NT_STATUS_INVALID_PARAMETER;
6759 if (IVAL(pdata,0) > total_data) {
6760 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6761 IVAL(pdata,0), (unsigned int)total_data));
6762 return NT_STATUS_INVALID_PARAMETER;
6766 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6768 return NT_STATUS_INVALID_PARAMETER;
6771 status = set_ea(conn, fsp, smb_fname, ea_list);
6776 /****************************************************************************
6777 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6778 ****************************************************************************/
6780 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6785 struct ea_list *ea_list = NULL;
6789 return NT_STATUS_INVALID_HANDLE;
6792 if (!lp_ea_support(SNUM(conn))) {
6793 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6794 "EA's not supported.\n",
6795 (unsigned int)total_data));
6796 return NT_STATUS_EAS_NOT_SUPPORTED;
6799 if (total_data < 10) {
6800 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6802 (unsigned int)total_data));
6803 return NT_STATUS_INVALID_PARAMETER;
6806 ea_list = read_nttrans_ea_list(talloc_tos(),
6811 return NT_STATUS_INVALID_PARAMETER;
6814 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6816 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6817 smb_fname_str_dbg(fsp->fsp_name),
6818 nt_errstr(status) ));
6824 /****************************************************************************
6825 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6826 ****************************************************************************/
6828 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6832 struct smb_filename *smb_fname)
6834 NTSTATUS status = NT_STATUS_OK;
6835 bool delete_on_close;
6836 uint32_t dosmode = 0;
6838 if (total_data < 1) {
6839 return NT_STATUS_INVALID_PARAMETER;
6843 return NT_STATUS_INVALID_HANDLE;
6846 delete_on_close = (CVAL(pdata,0) ? True : False);
6847 dosmode = dos_mode(conn, smb_fname);
6849 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6850 "delete_on_close = %u\n",
6851 smb_fname_str_dbg(smb_fname),
6852 (unsigned int)dosmode,
6853 (unsigned int)delete_on_close ));
6855 if (delete_on_close) {
6856 status = can_set_delete_on_close(fsp, dosmode);
6857 if (!NT_STATUS_IS_OK(status)) {
6862 /* The set is across all open files on this dev/inode pair. */
6863 if (!set_delete_on_close(fsp, delete_on_close,
6864 conn->session_info->security_token,
6865 conn->session_info->unix_token)) {
6866 return NT_STATUS_ACCESS_DENIED;
6868 return NT_STATUS_OK;
6871 /****************************************************************************
6872 Deal with SMB_FILE_POSITION_INFORMATION.
6873 ****************************************************************************/
6875 static NTSTATUS smb_file_position_information(connection_struct *conn,
6880 uint64_t position_information;
6882 if (total_data < 8) {
6883 return NT_STATUS_INVALID_PARAMETER;
6887 /* Ignore on pathname based set. */
6888 return NT_STATUS_OK;
6891 position_information = (uint64_t)IVAL(pdata,0);
6892 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6894 DEBUG(10,("smb_file_position_information: Set file position "
6895 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6896 (double)position_information));
6897 fsp->fh->position_information = position_information;
6898 return NT_STATUS_OK;
6901 /****************************************************************************
6902 Deal with SMB_FILE_MODE_INFORMATION.
6903 ****************************************************************************/
6905 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6911 if (total_data < 4) {
6912 return NT_STATUS_INVALID_PARAMETER;
6914 mode = IVAL(pdata,0);
6915 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6916 return NT_STATUS_INVALID_PARAMETER;
6918 return NT_STATUS_OK;
6921 /****************************************************************************
6922 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6923 ****************************************************************************/
6925 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6926 struct smb_request *req,
6929 const struct smb_filename *new_smb_fname)
6931 char *link_target = NULL;
6932 TALLOC_CTX *ctx = talloc_tos();
6935 /* Set a symbolic link. */
6936 /* Don't allow this if follow links is false. */
6938 if (total_data == 0) {
6939 return NT_STATUS_INVALID_PARAMETER;
6942 if (!lp_follow_symlinks(SNUM(conn))) {
6943 return NT_STATUS_ACCESS_DENIED;
6946 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6947 total_data, STR_TERMINATE);
6950 return NT_STATUS_INVALID_PARAMETER;
6953 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6954 new_smb_fname->base_name, link_target ));
6956 ret = SMB_VFS_SYMLINKAT(conn,
6961 return map_nt_error_from_unix(errno);
6964 return NT_STATUS_OK;
6967 /****************************************************************************
6968 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6969 ****************************************************************************/
6971 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6972 struct smb_request *req,
6973 const char *pdata, int total_data,
6974 struct smb_filename *smb_fname_new)
6976 char *oldname = NULL;
6977 struct smb_filename *smb_fname_old = NULL;
6978 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6979 TALLOC_CTX *ctx = talloc_tos();
6980 NTSTATUS status = NT_STATUS_OK;
6982 /* Set a hard link. */
6983 if (total_data == 0) {
6984 return NT_STATUS_INVALID_PARAMETER;
6987 if (req->posix_pathnames) {
6988 srvstr_get_path_posix(ctx,
6997 srvstr_get_path(ctx,
7006 if (!NT_STATUS_IS_OK(status)) {
7010 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7011 smb_fname_str_dbg(smb_fname_new), oldname));
7013 status = filename_convert(ctx,
7020 if (!NT_STATUS_IS_OK(status)) {
7024 return hardlink_internals(ctx, conn, req, false,
7025 smb_fname_old, smb_fname_new);
7028 /****************************************************************************
7029 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7030 ****************************************************************************/
7032 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7033 struct smb_request *req,
7037 struct smb_filename *smb_fname_src)
7041 char *newname = NULL;
7042 struct smb_filename *smb_fname_dst = NULL;
7043 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7044 ucf_flags_from_smb_request(req);
7045 NTSTATUS status = NT_STATUS_OK;
7046 TALLOC_CTX *ctx = talloc_tos();
7049 return NT_STATUS_INVALID_HANDLE;
7052 if (total_data < 20) {
7053 return NT_STATUS_INVALID_PARAMETER;
7056 overwrite = (CVAL(pdata,0) ? True : False);
7057 len = IVAL(pdata,16);
7059 if (len > (total_data - 20) || (len == 0)) {
7060 return NT_STATUS_INVALID_PARAMETER;
7063 if (req->posix_pathnames) {
7064 srvstr_get_path_posix(ctx,
7073 srvstr_get_path(ctx,
7082 if (!NT_STATUS_IS_OK(status)) {
7086 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7089 status = filename_convert(ctx,
7096 if (!NT_STATUS_IS_OK(status)) {
7100 if (fsp->base_fsp) {
7101 /* newname must be a stream name. */
7102 if (newname[0] != ':') {
7103 return NT_STATUS_NOT_SUPPORTED;
7106 /* Create an smb_fname to call rename_internals_fsp() with. */
7107 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7108 fsp->base_fsp->fsp_name->base_name,
7111 fsp->base_fsp->fsp_name->flags);
7112 if (smb_fname_dst == NULL) {
7113 status = NT_STATUS_NO_MEMORY;
7118 * Set the original last component, since
7119 * rename_internals_fsp() requires it.
7121 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7123 if (smb_fname_dst->original_lcomp == NULL) {
7124 status = NT_STATUS_NO_MEMORY;
7130 DEBUG(10,("smb2_file_rename_information: "
7131 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7132 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7133 smb_fname_str_dbg(smb_fname_dst)));
7134 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7135 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7139 TALLOC_FREE(smb_fname_dst);
7143 static NTSTATUS smb_file_link_information(connection_struct *conn,
7144 struct smb_request *req,
7148 struct smb_filename *smb_fname_src)
7152 char *newname = NULL;
7153 struct smb_filename *smb_fname_dst = NULL;
7154 NTSTATUS status = NT_STATUS_OK;
7155 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7156 ucf_flags_from_smb_request(req);
7157 TALLOC_CTX *ctx = talloc_tos();
7160 return NT_STATUS_INVALID_HANDLE;
7163 if (total_data < 20) {
7164 return NT_STATUS_INVALID_PARAMETER;
7167 overwrite = (CVAL(pdata,0) ? true : false);
7168 len = IVAL(pdata,16);
7170 if (len > (total_data - 20) || (len == 0)) {
7171 return NT_STATUS_INVALID_PARAMETER;
7174 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7175 srvstr_get_path_posix(ctx,
7183 ucf_flags |= UCF_POSIX_PATHNAMES;
7185 srvstr_get_path(ctx,
7194 if (!NT_STATUS_IS_OK(status)) {
7198 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7201 status = filename_convert(ctx,
7208 if (!NT_STATUS_IS_OK(status)) {
7212 if (fsp->base_fsp) {
7213 /* No stream names. */
7214 return NT_STATUS_NOT_SUPPORTED;
7217 DEBUG(10,("smb_file_link_information: "
7218 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7219 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7220 smb_fname_str_dbg(smb_fname_dst)));
7221 status = hardlink_internals(ctx,
7228 TALLOC_FREE(smb_fname_dst);
7232 /****************************************************************************
7233 Deal with SMB_FILE_RENAME_INFORMATION.
7234 ****************************************************************************/
7236 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7237 struct smb_request *req,
7241 struct smb_filename *smb_fname_src)
7246 char *newname = NULL;
7247 struct smb_filename *smb_fname_dst = NULL;
7248 bool dest_has_wcard = False;
7249 NTSTATUS status = NT_STATUS_OK;
7251 TALLOC_CTX *ctx = talloc_tos();
7253 if (total_data < 13) {
7254 return NT_STATUS_INVALID_PARAMETER;
7257 overwrite = (CVAL(pdata,0) ? True : False);
7258 root_fid = IVAL(pdata,4);
7259 len = IVAL(pdata,8);
7261 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7262 return NT_STATUS_INVALID_PARAMETER;
7265 if (req->posix_pathnames) {
7266 srvstr_get_path_wcard_posix(ctx,
7276 srvstr_get_path_wcard(ctx,
7286 if (!NT_STATUS_IS_OK(status)) {
7290 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7293 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7294 status = resolve_dfspath_wcard(ctx, conn,
7296 UCF_COND_ALLOW_WCARD_LCOMP,
7297 !conn->sconn->using_smb2,
7300 if (!NT_STATUS_IS_OK(status)) {
7305 /* Check the new name has no '/' characters. */
7306 if (strchr_m(newname, '/')) {
7307 return NT_STATUS_NOT_SUPPORTED;
7310 if (fsp && fsp->base_fsp) {
7311 /* newname must be a stream name. */
7312 if (newname[0] != ':') {
7313 return NT_STATUS_NOT_SUPPORTED;
7316 /* Create an smb_fname to call rename_internals_fsp() with. */
7317 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7318 fsp->base_fsp->fsp_name->base_name,
7321 fsp->base_fsp->fsp_name->flags);
7322 if (smb_fname_dst == NULL) {
7323 status = NT_STATUS_NO_MEMORY;
7328 * Set the original last component, since
7329 * rename_internals_fsp() requires it.
7331 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7333 if (smb_fname_dst->original_lcomp == NULL) {
7334 status = NT_STATUS_NO_MEMORY;
7340 * Build up an smb_fname_dst based on the filename passed in.
7341 * We basically just strip off the last component, and put on
7342 * the newname instead.
7344 char *base_name = NULL;
7345 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7346 ucf_flags_from_smb_request(req);
7348 if (dest_has_wcard) {
7349 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7352 /* newname must *not* be a stream name. */
7353 if (newname[0] == ':') {
7354 return NT_STATUS_NOT_SUPPORTED;
7358 * Strip off the last component (filename) of the path passed
7361 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7363 return NT_STATUS_NO_MEMORY;
7365 p = strrchr_m(base_name, '/');
7369 base_name = talloc_strdup(ctx, "");
7371 return NT_STATUS_NO_MEMORY;
7374 /* Append the new name. */
7375 base_name = talloc_asprintf_append(base_name,
7379 return NT_STATUS_NO_MEMORY;
7382 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7385 /* If an error we expect this to be
7386 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7388 if (!NT_STATUS_IS_OK(status)) {
7389 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7393 /* Create an smb_fname to call rename_internals_fsp() */
7394 smb_fname_dst = synthetic_smb_fname(ctx,
7398 smb_fname_src->flags);
7399 if (smb_fname_dst == NULL) {
7400 status = NT_STATUS_NO_MEMORY;
7407 DEBUG(10,("smb_file_rename_information: "
7408 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7409 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7410 smb_fname_str_dbg(smb_fname_dst)));
7411 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7414 DEBUG(10,("smb_file_rename_information: "
7415 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7416 smb_fname_str_dbg(smb_fname_src),
7417 smb_fname_str_dbg(smb_fname_dst)));
7418 status = rename_internals(ctx, conn, req, smb_fname_src,
7419 smb_fname_dst, 0, overwrite, false,
7421 FILE_WRITE_ATTRIBUTES);
7424 TALLOC_FREE(smb_fname_dst);
7428 /****************************************************************************
7429 Deal with SMB_SET_POSIX_ACL.
7430 ****************************************************************************/
7432 #if defined(HAVE_POSIX_ACLS)
7433 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7434 struct smb_request *req,
7438 const struct smb_filename *smb_fname)
7440 uint16_t posix_acl_version;
7441 uint16_t num_file_acls;
7442 uint16_t num_def_acls;
7443 bool valid_file_acls = true;
7444 bool valid_def_acls = true;
7446 unsigned int size_needed;
7447 unsigned int total_data;
7448 bool close_fsp = false;
7450 if (total_data_in < 0) {
7451 status = NT_STATUS_INVALID_PARAMETER;
7455 total_data = total_data_in;
7457 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7458 status = NT_STATUS_INVALID_PARAMETER;
7461 posix_acl_version = SVAL(pdata,0);
7462 num_file_acls = SVAL(pdata,2);
7463 num_def_acls = SVAL(pdata,4);
7465 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7466 valid_file_acls = false;
7470 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7471 valid_def_acls = false;
7475 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7476 status = NT_STATUS_INVALID_PARAMETER;
7481 if (num_file_acls + num_def_acls < num_file_acls) {
7482 status = NT_STATUS_INVALID_PARAMETER;
7486 size_needed = num_file_acls + num_def_acls;
7489 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7490 * than UINT_MAX, so check by division.
7492 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7493 status = NT_STATUS_INVALID_PARAMETER;
7497 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7498 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7499 status = NT_STATUS_INVALID_PARAMETER;
7502 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7504 if (total_data < size_needed) {
7505 status = NT_STATUS_INVALID_PARAMETER;
7510 * Ensure we always operate on a file descriptor, not just
7514 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7516 SEC_STD_READ_CONTROL|
7517 FILE_READ_ATTRIBUTES|
7518 FILE_WRITE_ATTRIBUTES;
7520 status = get_posix_fsp(conn,
7526 if (!NT_STATUS_IS_OK(status)) {
7532 /* Here we know fsp != NULL */
7533 SMB_ASSERT(fsp != NULL);
7535 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7536 if (!NT_STATUS_IS_OK(status)) {
7540 /* If we have a default acl, this *must* be a directory. */
7541 if (valid_def_acls && !fsp->is_directory) {
7542 DBG_INFO("Can't set default acls on "
7543 "non-directory %s\n",
7545 return NT_STATUS_INVALID_HANDLE;
7548 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7549 "num_def_acls = %"PRIu16"\n",
7554 /* Move pdata to the start of the file ACL entries. */
7555 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7557 if (valid_file_acls) {
7558 status = set_unix_posix_acl(conn,
7562 if (!NT_STATUS_IS_OK(status)) {
7567 /* Move pdata to the start of the default ACL entries. */
7568 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7570 if (valid_def_acls) {
7571 status = set_unix_posix_default_acl(conn,
7575 if (!NT_STATUS_IS_OK(status)) {
7580 status = NT_STATUS_OK;
7585 (void)close_file(req, fsp, NORMAL_CLOSE);
7592 /****************************************************************************
7593 Deal with SMB_SET_POSIX_LOCK.
7594 ****************************************************************************/
7596 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7598 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7599 struct smb_request *req,
7604 struct tevent_req *subreq = NULL;
7605 struct smbd_lock_element *lck = NULL;
7609 bool blocking_lock = False;
7610 enum brl_type lock_type;
7612 NTSTATUS status = NT_STATUS_OK;
7614 if (fsp == NULL || fsp->fh->fd == -1) {
7615 return NT_STATUS_INVALID_HANDLE;
7618 if (total_data != POSIX_LOCK_DATA_SIZE) {
7619 return NT_STATUS_INVALID_PARAMETER;
7622 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7623 case POSIX_LOCK_TYPE_READ:
7624 lock_type = READ_LOCK;
7626 case POSIX_LOCK_TYPE_WRITE:
7627 /* Return the right POSIX-mappable error code for files opened read-only. */
7628 if (!fsp->can_write) {
7629 return NT_STATUS_INVALID_HANDLE;
7631 lock_type = WRITE_LOCK;
7633 case POSIX_LOCK_TYPE_UNLOCK:
7634 lock_type = UNLOCK_LOCK;
7637 return NT_STATUS_INVALID_PARAMETER;
7640 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7641 case POSIX_LOCK_FLAG_NOWAIT:
7642 blocking_lock = false;
7644 case POSIX_LOCK_FLAG_WAIT:
7645 blocking_lock = true;
7648 return NT_STATUS_INVALID_PARAMETER;
7651 if (!lp_blocking_locks(SNUM(conn))) {
7652 blocking_lock = False;
7655 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7656 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7657 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7658 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7659 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7661 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7662 "count = %"PRIu64", offset = %"PRIu64"\n",
7664 (unsigned int)lock_type,
7669 if (lock_type == UNLOCK_LOCK) {
7670 struct smbd_lock_element l = {
7672 .brltype = UNLOCK_LOCK,
7676 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7680 lck = talloc(req, struct smbd_lock_element);
7682 return NT_STATUS_NO_MEMORY;
7685 *lck = (struct smbd_lock_element) {
7687 .brltype = lock_type,
7692 subreq = smbd_smb1_do_locks_send(
7697 blocking_lock ? UINT32_MAX : 0,
7698 true, /* large_offset */
7702 if (subreq == NULL) {
7704 return NT_STATUS_NO_MEMORY;
7706 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7707 return NT_STATUS_EVENT_PENDING;
7710 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7712 struct smb_request *req = NULL;
7716 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7719 status = smbd_smb1_do_locks_recv(subreq);
7720 TALLOC_FREE(subreq);
7722 if (NT_STATUS_IS_OK(status)) {
7723 char params[2] = {0};
7724 /* Fake up max_data_bytes here - we know it fits. */
7725 send_trans2_replies(
7735 reply_nterror(req, status);
7738 (char *)req->outbuf,
7741 IS_CONN_ENCRYPTED(req->conn),
7744 exit_server_cleanly("smb_set_posix_lock_done: "
7745 "srv_send_smb failed.");
7753 /****************************************************************************
7754 Deal with SMB_SET_FILE_BASIC_INFO.
7755 ****************************************************************************/
7757 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7761 const struct smb_filename *smb_fname)
7763 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7764 struct smb_file_time ft;
7765 uint32_t dosmode = 0;
7766 NTSTATUS status = NT_STATUS_OK;
7770 if (total_data < 36) {
7771 return NT_STATUS_INVALID_PARAMETER;
7774 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7775 if (!NT_STATUS_IS_OK(status)) {
7779 /* Set the attributes */
7780 dosmode = IVAL(pdata,32);
7781 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7782 if (!NT_STATUS_IS_OK(status)) {
7787 ft.create_time = interpret_long_date(pdata);
7790 ft.atime = interpret_long_date(pdata+8);
7793 ft.mtime = interpret_long_date(pdata+16);
7796 ft.ctime = interpret_long_date(pdata+24);
7798 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7799 smb_fname_str_dbg(smb_fname)));
7801 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7805 /****************************************************************************
7806 Deal with SMB_INFO_STANDARD.
7807 ****************************************************************************/
7809 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7813 const struct smb_filename *smb_fname)
7816 struct smb_file_time ft;
7820 if (total_data < 12) {
7821 return NT_STATUS_INVALID_PARAMETER;
7825 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7827 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7829 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7831 DEBUG(10,("smb_set_info_standard: file %s\n",
7832 smb_fname_str_dbg(smb_fname)));
7834 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7835 if (!NT_STATUS_IS_OK(status)) {
7839 return smb_set_file_time(conn,
7846 /****************************************************************************
7847 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7848 ****************************************************************************/
7850 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7851 struct smb_request *req,
7855 struct smb_filename *smb_fname)
7857 uint64_t allocation_size = 0;
7858 NTSTATUS status = NT_STATUS_OK;
7859 files_struct *new_fsp = NULL;
7861 if (!VALID_STAT(smb_fname->st)) {
7862 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7865 if (total_data < 8) {
7866 return NT_STATUS_INVALID_PARAMETER;
7869 allocation_size = (uint64_t)IVAL(pdata,0);
7870 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7871 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7872 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7873 (double)allocation_size));
7875 if (allocation_size) {
7876 allocation_size = smb_roundup(conn, allocation_size);
7879 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7880 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7881 (double)allocation_size));
7883 if (fsp && fsp->fh->fd != -1) {
7884 /* Open file handle. */
7885 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7886 return NT_STATUS_ACCESS_DENIED;
7889 /* Only change if needed. */
7890 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7891 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7892 return map_nt_error_from_unix(errno);
7895 /* But always update the time. */
7897 * This is equivalent to a write. Ensure it's seen immediately
7898 * if there are no pending writes.
7900 trigger_write_time_update_immediate(fsp);
7901 return NT_STATUS_OK;
7904 /* Pathname or stat or directory file. */
7905 status = SMB_VFS_CREATE_FILE(
7908 0, /* root_dir_fid */
7909 smb_fname, /* fname */
7910 FILE_WRITE_DATA, /* access_mask */
7911 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7913 FILE_OPEN, /* create_disposition*/
7914 0, /* create_options */
7915 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7916 0, /* oplock_request */
7918 0, /* allocation_size */
7919 0, /* private_flags */
7922 &new_fsp, /* result */
7924 NULL, NULL); /* create context */
7926 if (!NT_STATUS_IS_OK(status)) {
7927 /* NB. We check for open_was_deferred in the caller. */
7931 /* Only change if needed. */
7932 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7933 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7934 status = map_nt_error_from_unix(errno);
7935 close_file(req, new_fsp, NORMAL_CLOSE);
7940 /* Changing the allocation size should set the last mod time. */
7942 * This is equivalent to a write. Ensure it's seen immediately
7943 * if there are no pending writes.
7945 trigger_write_time_update_immediate(new_fsp);
7946 close_file(req, new_fsp, NORMAL_CLOSE);
7947 return NT_STATUS_OK;
7950 /****************************************************************************
7951 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7952 ****************************************************************************/
7954 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7955 struct smb_request *req,
7959 const struct smb_filename *smb_fname,
7960 bool fail_after_createfile)
7964 if (total_data < 8) {
7965 return NT_STATUS_INVALID_PARAMETER;
7968 size = IVAL(pdata,0);
7969 size |= (((off_t)IVAL(pdata,4)) << 32);
7970 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7971 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7974 return smb_set_file_size(conn, req,
7979 fail_after_createfile);
7982 /****************************************************************************
7983 Allow a UNIX info mknod.
7984 ****************************************************************************/
7986 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7989 const struct smb_filename *smb_fname)
7991 uint32_t file_type = IVAL(pdata,56);
7992 #if defined(HAVE_MAKEDEV)
7993 uint32_t dev_major = IVAL(pdata,60);
7994 uint32_t dev_minor = IVAL(pdata,68);
7996 SMB_DEV_T dev = (SMB_DEV_T)0;
7997 uint32_t raw_unixmode = IVAL(pdata,84);
8002 if (total_data < 100) {
8003 return NT_STATUS_INVALID_PARAMETER;
8006 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8007 PERM_NEW_FILE, &unixmode);
8008 if (!NT_STATUS_IS_OK(status)) {
8012 #if defined(HAVE_MAKEDEV)
8013 dev = makedev(dev_major, dev_minor);
8016 switch (file_type) {
8017 #if defined(S_IFIFO)
8018 case UNIX_TYPE_FIFO:
8019 unixmode |= S_IFIFO;
8022 #if defined(S_IFSOCK)
8023 case UNIX_TYPE_SOCKET:
8024 unixmode |= S_IFSOCK;
8027 #if defined(S_IFCHR)
8028 case UNIX_TYPE_CHARDEV:
8029 unixmode |= S_IFCHR;
8032 #if defined(S_IFBLK)
8033 case UNIX_TYPE_BLKDEV:
8034 unixmode |= S_IFBLK;
8038 return NT_STATUS_INVALID_PARAMETER;
8041 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8042 "%.0f mode 0%o for file %s\n", (double)dev,
8043 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8045 /* Ok - do the mknod. */
8046 ret = SMB_VFS_MKNODAT(conn,
8053 return map_nt_error_from_unix(errno);
8056 /* If any of the other "set" calls fail we
8057 * don't want to end up with a half-constructed mknod.
8060 if (lp_inherit_permissions(SNUM(conn))) {
8062 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
8064 return NT_STATUS_NO_MEMORY;
8066 inherit_access_posix_acl(conn, parent, smb_fname,
8068 TALLOC_FREE(parent);
8071 return NT_STATUS_OK;
8074 /****************************************************************************
8075 Deal with SMB_SET_FILE_UNIX_BASIC.
8076 ****************************************************************************/
8078 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8079 struct smb_request *req,
8083 const struct smb_filename *smb_fname)
8085 struct smb_file_time ft;
8086 uint32_t raw_unixmode;
8089 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8090 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8091 NTSTATUS status = NT_STATUS_OK;
8092 bool delete_on_fail = False;
8093 enum perm_type ptype;
8094 files_struct *all_fsps = NULL;
8095 bool modify_mtime = true;
8097 struct smb_filename *smb_fname_tmp = NULL;
8098 SMB_STRUCT_STAT sbuf;
8102 if (total_data < 100) {
8103 return NT_STATUS_INVALID_PARAMETER;
8106 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8107 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8108 size=IVAL(pdata,0); /* first 8 Bytes are size */
8109 size |= (((off_t)IVAL(pdata,4)) << 32);
8112 ft.atime = interpret_long_date(pdata+24); /* access_time */
8113 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
8114 set_owner = (uid_t)IVAL(pdata,40);
8115 set_grp = (gid_t)IVAL(pdata,48);
8116 raw_unixmode = IVAL(pdata,84);
8118 if (VALID_STAT(smb_fname->st)) {
8119 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8120 ptype = PERM_EXISTING_DIR;
8122 ptype = PERM_EXISTING_FILE;
8125 ptype = PERM_NEW_FILE;
8128 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8130 if (!NT_STATUS_IS_OK(status)) {
8134 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8135 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8136 smb_fname_str_dbg(smb_fname), (double)size,
8137 (unsigned int)set_owner, (unsigned int)set_grp,
8138 (int)raw_unixmode));
8140 sbuf = smb_fname->st;
8142 if (!VALID_STAT(sbuf)) {
8144 * The only valid use of this is to create character and block
8145 * devices, and named pipes. This is deprecated (IMHO) and
8146 * a new info level should be used for mknod. JRA.
8149 status = smb_unix_mknod(conn,
8153 if (!NT_STATUS_IS_OK(status)) {
8157 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
8158 if (smb_fname_tmp == NULL) {
8159 return NT_STATUS_NO_MEMORY;
8162 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
8163 status = map_nt_error_from_unix(errno);
8164 TALLOC_FREE(smb_fname_tmp);
8165 SMB_VFS_UNLINK(conn, smb_fname);
8169 sbuf = smb_fname_tmp->st;
8170 smb_fname = smb_fname_tmp;
8172 /* Ensure we don't try and change anything else. */
8173 raw_unixmode = SMB_MODE_NO_CHANGE;
8174 size = get_file_size_stat(&sbuf);
8175 ft.atime = sbuf.st_ex_atime;
8176 ft.mtime = sbuf.st_ex_mtime;
8178 * We continue here as we might want to change the
8181 delete_on_fail = True;
8185 /* Horrible backwards compatibility hack as an old server bug
8186 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8190 size = get_file_size_stat(&sbuf);
8195 * Deal with the UNIX specific mode set.
8198 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8201 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8202 "setting mode 0%o for file %s\n",
8203 (unsigned int)unixmode,
8204 smb_fname_str_dbg(smb_fname)));
8205 if (fsp && fsp->fh->fd != -1) {
8206 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8208 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8211 return map_nt_error_from_unix(errno);
8216 * Deal with the UNIX specific uid set.
8219 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8220 (sbuf.st_ex_uid != set_owner)) {
8223 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8224 "changing owner %u for path %s\n",
8225 (unsigned int)set_owner,
8226 smb_fname_str_dbg(smb_fname)));
8228 if (fsp && fsp->fh->fd != -1) {
8229 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8232 * UNIX extensions calls must always operate
8235 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8236 set_owner, (gid_t)-1);
8240 status = map_nt_error_from_unix(errno);
8241 if (delete_on_fail) {
8242 SMB_VFS_UNLINK(conn, smb_fname);
8249 * Deal with the UNIX specific gid set.
8252 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8253 (sbuf.st_ex_gid != set_grp)) {
8256 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8257 "changing group %u for file %s\n",
8258 (unsigned int)set_grp,
8259 smb_fname_str_dbg(smb_fname)));
8260 if (fsp && fsp->fh->fd != -1) {
8261 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8264 * UNIX extensions calls must always operate
8267 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8271 status = map_nt_error_from_unix(errno);
8272 if (delete_on_fail) {
8273 SMB_VFS_UNLINK(conn, smb_fname);
8279 /* Deal with any size changes. */
8281 status = smb_set_file_size(conn, req,
8287 if (!NT_STATUS_IS_OK(status)) {
8291 /* Deal with any time changes. */
8292 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
8293 /* No change, don't cancel anything. */
8297 id = vfs_file_id_from_sbuf(conn, &sbuf);
8298 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8299 all_fsps = file_find_di_next(all_fsps)) {
8301 * We're setting the time explicitly for UNIX.
8302 * Cancel any pending changes over all handles.
8304 all_fsps->update_write_time_on_close = false;
8305 TALLOC_FREE(all_fsps->update_write_time_event);
8309 * Override the "setting_write_time"
8310 * parameter here as it almost does what
8311 * we need. Just remember if we modified
8312 * mtime and send the notify ourselves.
8314 if (null_timespec(ft.mtime)) {
8315 modify_mtime = false;
8318 status = smb_set_file_time(conn,
8324 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8325 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8330 /****************************************************************************
8331 Deal with SMB_SET_FILE_UNIX_INFO2.
8332 ****************************************************************************/
8334 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8335 struct smb_request *req,
8339 const struct smb_filename *smb_fname)
8342 uint32_t smb_fflags;
8345 if (total_data < 116) {
8346 return NT_STATUS_INVALID_PARAMETER;
8349 /* Start by setting all the fields that are common between UNIX_BASIC
8352 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8354 if (!NT_STATUS_IS_OK(status)) {
8358 smb_fflags = IVAL(pdata, 108);
8359 smb_fmask = IVAL(pdata, 112);
8361 /* NB: We should only attempt to alter the file flags if the client
8362 * sends a non-zero mask.
8364 if (smb_fmask != 0) {
8365 int stat_fflags = 0;
8367 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8368 smb_fmask, &stat_fflags)) {
8369 /* Client asked to alter a flag we don't understand. */
8370 return NT_STATUS_INVALID_PARAMETER;
8373 if (fsp && fsp->fh->fd != -1) {
8374 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8375 return NT_STATUS_NOT_SUPPORTED;
8377 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8378 stat_fflags) != 0) {
8379 return map_nt_error_from_unix(errno);
8384 /* XXX: need to add support for changing the create_time here. You
8385 * can do this for paths on Darwin with setattrlist(2). The right way
8386 * to hook this up is probably by extending the VFS utimes interface.
8389 return NT_STATUS_OK;
8392 /****************************************************************************
8393 Create a directory with POSIX semantics.
8394 ****************************************************************************/
8396 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8397 struct smb_request *req,
8400 struct smb_filename *smb_fname,
8401 int *pdata_return_size)
8403 NTSTATUS status = NT_STATUS_OK;
8404 uint32_t raw_unixmode = 0;
8405 uint32_t mod_unixmode = 0;
8406 mode_t unixmode = (mode_t)0;
8407 files_struct *fsp = NULL;
8408 uint16_t info_level_return = 0;
8410 char *pdata = *ppdata;
8412 if (total_data < 18) {
8413 return NT_STATUS_INVALID_PARAMETER;
8416 raw_unixmode = IVAL(pdata,8);
8417 /* Next 4 bytes are not yet defined. */
8419 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8420 PERM_NEW_DIR, &unixmode);
8421 if (!NT_STATUS_IS_OK(status)) {
8425 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8427 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8428 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8430 status = SMB_VFS_CREATE_FILE(
8433 0, /* root_dir_fid */
8434 smb_fname, /* fname */
8435 FILE_READ_ATTRIBUTES, /* access_mask */
8436 FILE_SHARE_NONE, /* share_access */
8437 FILE_CREATE, /* create_disposition*/
8438 FILE_DIRECTORY_FILE, /* create_options */
8439 mod_unixmode, /* file_attributes */
8440 0, /* oplock_request */
8442 0, /* allocation_size */
8443 0, /* private_flags */
8448 NULL, NULL); /* create context */
8450 if (NT_STATUS_IS_OK(status)) {
8451 close_file(req, fsp, NORMAL_CLOSE);
8454 info_level_return = SVAL(pdata,16);
8456 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8457 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8458 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8459 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8461 *pdata_return_size = 12;
8464 /* Realloc the data size */
8465 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8466 if (*ppdata == NULL) {
8467 *pdata_return_size = 0;
8468 return NT_STATUS_NO_MEMORY;
8472 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8473 SSVAL(pdata,2,0); /* No fnum. */
8474 SIVAL(pdata,4,info); /* Was directory created. */
8476 switch (info_level_return) {
8477 case SMB_QUERY_FILE_UNIX_BASIC:
8478 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8479 SSVAL(pdata,10,0); /* Padding. */
8480 store_file_unix_basic(conn, pdata + 12, fsp,
8483 case SMB_QUERY_FILE_UNIX_INFO2:
8484 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8485 SSVAL(pdata,10,0); /* Padding. */
8486 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8490 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8491 SSVAL(pdata,10,0); /* Padding. */
8498 /****************************************************************************
8499 Open/Create a file with POSIX semantics.
8500 ****************************************************************************/
8502 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8503 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8505 static NTSTATUS smb_posix_open(connection_struct *conn,
8506 struct smb_request *req,
8509 struct smb_filename *smb_fname,
8510 int *pdata_return_size)
8512 bool extended_oplock_granted = False;
8513 char *pdata = *ppdata;
8515 uint32_t wire_open_mode = 0;
8516 uint32_t raw_unixmode = 0;
8517 uint32_t mod_unixmode = 0;
8518 uint32_t create_disp = 0;
8519 uint32_t access_mask = 0;
8520 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8521 NTSTATUS status = NT_STATUS_OK;
8522 mode_t unixmode = (mode_t)0;
8523 files_struct *fsp = NULL;
8524 int oplock_request = 0;
8526 uint16_t info_level_return = 0;
8528 if (total_data < 18) {
8529 return NT_STATUS_INVALID_PARAMETER;
8532 flags = IVAL(pdata,0);
8533 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8534 if (oplock_request) {
8535 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8538 wire_open_mode = IVAL(pdata,4);
8540 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8541 return smb_posix_mkdir(conn, req,
8548 switch (wire_open_mode & SMB_ACCMODE) {
8550 access_mask = SMB_O_RDONLY_MAPPING;
8553 access_mask = SMB_O_WRONLY_MAPPING;
8556 access_mask = (SMB_O_RDONLY_MAPPING|
8557 SMB_O_WRONLY_MAPPING);
8560 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8561 (unsigned int)wire_open_mode ));
8562 return NT_STATUS_INVALID_PARAMETER;
8565 wire_open_mode &= ~SMB_ACCMODE;
8567 /* First take care of O_CREAT|O_EXCL interactions. */
8568 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8569 case (SMB_O_CREAT | SMB_O_EXCL):
8570 /* File exists fail. File not exist create. */
8571 create_disp = FILE_CREATE;
8574 /* File exists open. File not exist create. */
8575 create_disp = FILE_OPEN_IF;
8578 /* O_EXCL on its own without O_CREAT is undefined.
8579 We deliberately ignore it as some versions of
8580 Linux CIFSFS can send a bare O_EXCL on the
8581 wire which other filesystems in the kernel
8582 ignore. See bug 9519 for details. */
8587 /* File exists open. File not exist fail. */
8588 create_disp = FILE_OPEN;
8591 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8592 (unsigned int)wire_open_mode ));
8593 return NT_STATUS_INVALID_PARAMETER;
8596 /* Next factor in the effects of O_TRUNC. */
8597 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8599 if (wire_open_mode & SMB_O_TRUNC) {
8600 switch (create_disp) {
8602 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8603 /* Leave create_disp alone as
8604 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8606 /* File exists fail. File not exist create. */
8609 /* SMB_O_CREAT | SMB_O_TRUNC */
8610 /* File exists overwrite. File not exist create. */
8611 create_disp = FILE_OVERWRITE_IF;
8615 /* File exists overwrite. File not exist fail. */
8616 create_disp = FILE_OVERWRITE;
8619 /* Cannot get here. */
8620 smb_panic("smb_posix_open: logic error");
8621 return NT_STATUS_INVALID_PARAMETER;
8625 raw_unixmode = IVAL(pdata,8);
8626 /* Next 4 bytes are not yet defined. */
8628 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8629 (VALID_STAT(smb_fname->st) ?
8630 PERM_EXISTING_FILE : PERM_NEW_FILE),
8633 if (!NT_STATUS_IS_OK(status)) {
8637 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8639 if (wire_open_mode & SMB_O_SYNC) {
8640 create_options |= FILE_WRITE_THROUGH;
8642 if (wire_open_mode & SMB_O_APPEND) {
8643 access_mask |= FILE_APPEND_DATA;
8645 if (wire_open_mode & SMB_O_DIRECT) {
8646 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8649 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8650 VALID_STAT_OF_DIR(smb_fname->st)) {
8651 if (access_mask != SMB_O_RDONLY_MAPPING) {
8652 return NT_STATUS_FILE_IS_A_DIRECTORY;
8654 create_options &= ~FILE_NON_DIRECTORY_FILE;
8655 create_options |= FILE_DIRECTORY_FILE;
8658 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8659 smb_fname_str_dbg(smb_fname),
8660 (unsigned int)wire_open_mode,
8661 (unsigned int)unixmode ));
8663 status = SMB_VFS_CREATE_FILE(
8666 0, /* root_dir_fid */
8667 smb_fname, /* fname */
8668 access_mask, /* access_mask */
8669 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8671 create_disp, /* create_disposition*/
8672 create_options, /* create_options */
8673 mod_unixmode, /* file_attributes */
8674 oplock_request, /* oplock_request */
8676 0, /* allocation_size */
8677 0, /* private_flags */
8682 NULL, NULL); /* create context */
8684 if (!NT_STATUS_IS_OK(status)) {
8688 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8689 extended_oplock_granted = True;
8692 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8693 extended_oplock_granted = True;
8696 info_level_return = SVAL(pdata,16);
8698 /* Allocate the correct return size. */
8700 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8701 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8702 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8703 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8705 *pdata_return_size = 12;
8708 /* Realloc the data size */
8709 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8710 if (*ppdata == NULL) {
8711 close_file(req, fsp, ERROR_CLOSE);
8712 *pdata_return_size = 0;
8713 return NT_STATUS_NO_MEMORY;
8717 if (extended_oplock_granted) {
8718 if (flags & REQUEST_BATCH_OPLOCK) {
8719 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8721 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8723 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8724 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8726 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8729 SSVAL(pdata,2,fsp->fnum);
8730 SIVAL(pdata,4,info); /* Was file created etc. */
8732 switch (info_level_return) {
8733 case SMB_QUERY_FILE_UNIX_BASIC:
8734 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8735 SSVAL(pdata,10,0); /* padding. */
8736 store_file_unix_basic(conn, pdata + 12, fsp,
8739 case SMB_QUERY_FILE_UNIX_INFO2:
8740 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8741 SSVAL(pdata,10,0); /* padding. */
8742 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8746 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8747 SSVAL(pdata,10,0); /* padding. */
8750 return NT_STATUS_OK;
8753 /****************************************************************************
8754 Delete a file with POSIX semantics.
8755 ****************************************************************************/
8757 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8758 struct smb_request *req,
8761 struct smb_filename *smb_fname)
8763 NTSTATUS status = NT_STATUS_OK;
8764 files_struct *fsp = NULL;
8768 int create_options = 0;
8769 struct share_mode_lock *lck = NULL;
8770 bool other_nonposix_opens;
8772 if (total_data < 2) {
8773 return NT_STATUS_INVALID_PARAMETER;
8776 flags = SVAL(pdata,0);
8778 if (!VALID_STAT(smb_fname->st)) {
8779 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8782 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8783 !VALID_STAT_OF_DIR(smb_fname->st)) {
8784 return NT_STATUS_NOT_A_DIRECTORY;
8787 DEBUG(10,("smb_posix_unlink: %s %s\n",
8788 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8789 smb_fname_str_dbg(smb_fname)));
8791 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8792 create_options |= FILE_DIRECTORY_FILE;
8795 status = SMB_VFS_CREATE_FILE(
8798 0, /* root_dir_fid */
8799 smb_fname, /* fname */
8800 DELETE_ACCESS, /* access_mask */
8801 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8803 FILE_OPEN, /* create_disposition*/
8804 create_options, /* create_options */
8805 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8806 0, /* oplock_request */
8808 0, /* allocation_size */
8809 0, /* private_flags */
8814 NULL, NULL); /* create context */
8816 if (!NT_STATUS_IS_OK(status)) {
8821 * Don't lie to client. If we can't really delete due to
8822 * non-POSIX opens return SHARING_VIOLATION.
8825 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8827 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8828 "lock for file %s\n", fsp_str_dbg(fsp)));
8829 close_file(req, fsp, NORMAL_CLOSE);
8830 return NT_STATUS_INVALID_PARAMETER;
8833 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8834 if (other_nonposix_opens) {
8835 /* Fail with sharing violation. */
8837 close_file(req, fsp, NORMAL_CLOSE);
8838 return NT_STATUS_SHARING_VIOLATION;
8842 * Set the delete on close.
8844 status = smb_set_file_disposition_info(conn,
8852 if (!NT_STATUS_IS_OK(status)) {
8853 close_file(req, fsp, NORMAL_CLOSE);
8856 return close_file(req, fsp, NORMAL_CLOSE);
8859 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8860 struct smb_request *req,
8861 TALLOC_CTX *mem_ctx,
8862 uint16_t info_level,
8864 struct smb_filename *smb_fname,
8865 char **ppdata, int total_data,
8868 char *pdata = *ppdata;
8869 NTSTATUS status = NT_STATUS_OK;
8870 int data_return_size = 0;
8874 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8875 return NT_STATUS_INVALID_LEVEL;
8878 if (!CAN_WRITE(conn)) {
8879 /* Allow POSIX opens. The open path will deny
8880 * any non-readonly opens. */
8881 if (info_level != SMB_POSIX_PATH_OPEN) {
8882 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8886 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8887 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8889 info_level, total_data));
8891 switch (info_level) {
8893 case SMB_INFO_STANDARD:
8895 status = smb_set_info_standard(conn,
8903 case SMB_INFO_SET_EA:
8905 status = smb_info_set_ea(conn,
8913 case SMB_SET_FILE_BASIC_INFO:
8914 case SMB_FILE_BASIC_INFORMATION:
8916 status = smb_set_file_basic_info(conn,
8924 case SMB_FILE_ALLOCATION_INFORMATION:
8925 case SMB_SET_FILE_ALLOCATION_INFO:
8927 status = smb_set_file_allocation_info(conn, req,
8935 case SMB_FILE_END_OF_FILE_INFORMATION:
8936 case SMB_SET_FILE_END_OF_FILE_INFO:
8939 * XP/Win7 both fail after the createfile with
8940 * SMB_SET_FILE_END_OF_FILE_INFO but not
8941 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8942 * The level is known here, so pass it down
8946 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8948 status = smb_set_file_end_of_file_info(conn, req,
8957 case SMB_FILE_DISPOSITION_INFORMATION:
8958 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8961 /* JRA - We used to just ignore this on a path ?
8962 * Shouldn't this be invalid level on a pathname
8965 if (tran_call != TRANSACT2_SETFILEINFO) {
8966 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8969 status = smb_set_file_disposition_info(conn,
8977 case SMB_FILE_POSITION_INFORMATION:
8979 status = smb_file_position_information(conn,
8986 case SMB_FILE_FULL_EA_INFORMATION:
8988 status = smb_set_file_full_ea_info(conn,
8995 /* From tridge Samba4 :
8996 * MODE_INFORMATION in setfileinfo (I have no
8997 * idea what "mode information" on a file is - it takes a value of 0,
8998 * 2, 4 or 6. What could it be?).
9001 case SMB_FILE_MODE_INFORMATION:
9003 status = smb_file_mode_information(conn,
9009 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9010 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9011 case SMB_FILE_SHORT_NAME_INFORMATION:
9012 return NT_STATUS_NOT_SUPPORTED;
9015 * CIFS UNIX extensions.
9018 case SMB_SET_FILE_UNIX_BASIC:
9020 status = smb_set_file_unix_basic(conn, req,
9028 case SMB_SET_FILE_UNIX_INFO2:
9030 status = smb_set_file_unix_info2(conn, req,
9038 case SMB_SET_FILE_UNIX_LINK:
9041 /* We must have a pathname for this. */
9042 return NT_STATUS_INVALID_LEVEL;
9044 status = smb_set_file_unix_link(conn, req, pdata,
9045 total_data, smb_fname);
9049 case SMB_SET_FILE_UNIX_HLINK:
9052 /* We must have a pathname for this. */
9053 return NT_STATUS_INVALID_LEVEL;
9055 status = smb_set_file_unix_hlink(conn, req,
9061 case SMB_FILE_RENAME_INFORMATION:
9063 status = smb_file_rename_information(conn, req,
9069 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9071 /* SMB2 rename information. */
9072 status = smb2_file_rename_information(conn, req,
9078 case SMB_FILE_LINK_INFORMATION:
9080 status = smb_file_link_information(conn, req,
9086 #if defined(HAVE_POSIX_ACLS)
9087 case SMB_SET_POSIX_ACL:
9089 status = smb_set_posix_acl(conn,
9099 case SMB_SET_POSIX_LOCK:
9102 return NT_STATUS_INVALID_LEVEL;
9104 status = smb_set_posix_lock(conn, req,
9105 pdata, total_data, fsp);
9109 case SMB_POSIX_PATH_OPEN:
9112 /* We must have a pathname for this. */
9113 return NT_STATUS_INVALID_LEVEL;
9116 status = smb_posix_open(conn, req,
9124 case SMB_POSIX_PATH_UNLINK:
9127 /* We must have a pathname for this. */
9128 return NT_STATUS_INVALID_LEVEL;
9131 status = smb_posix_unlink(conn, req,
9139 return NT_STATUS_INVALID_LEVEL;
9142 if (!NT_STATUS_IS_OK(status)) {
9146 *ret_data_size = data_return_size;
9147 return NT_STATUS_OK;
9150 /****************************************************************************
9151 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9152 ****************************************************************************/
9154 static void call_trans2setfilepathinfo(connection_struct *conn,
9155 struct smb_request *req,
9156 unsigned int tran_call,
9157 char **pparams, int total_params,
9158 char **ppdata, int total_data,
9159 unsigned int max_data_bytes)
9161 char *params = *pparams;
9162 char *pdata = *ppdata;
9163 uint16_t info_level;
9164 struct smb_filename *smb_fname = NULL;
9165 files_struct *fsp = NULL;
9166 NTSTATUS status = NT_STATUS_OK;
9167 int data_return_size = 0;
9170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9174 if (tran_call == TRANSACT2_SETFILEINFO) {
9175 if (total_params < 4) {
9176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9180 fsp = file_fsp(req, SVAL(params,0));
9181 /* Basic check for non-null fsp. */
9182 if (!check_fsp_open(conn, req, fsp)) {
9185 info_level = SVAL(params,2);
9187 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9188 if (smb_fname == NULL) {
9189 reply_nterror(req, NT_STATUS_NO_MEMORY);
9193 if(fsp->fh->fd == -1) {
9195 * This is actually a SETFILEINFO on a directory
9196 * handle (returned from an NT SMB). NT5.0 seems
9197 * to do this call. JRA.
9199 if (INFO_LEVEL_IS_UNIX(info_level)) {
9200 /* Always do lstat for UNIX calls. */
9201 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9202 DEBUG(3,("call_trans2setfilepathinfo: "
9203 "SMB_VFS_LSTAT of %s failed "
9205 smb_fname_str_dbg(smb_fname),
9207 reply_nterror(req, map_nt_error_from_unix(errno));
9211 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9212 DEBUG(3,("call_trans2setfilepathinfo: "
9213 "fileinfo of %s failed (%s)\n",
9214 smb_fname_str_dbg(smb_fname),
9216 reply_nterror(req, map_nt_error_from_unix(errno));
9220 } else if (fsp->print_file) {
9222 * Doing a DELETE_ON_CLOSE should cancel a print job.
9224 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9225 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9227 DEBUG(3,("call_trans2setfilepathinfo: "
9228 "Cancelling print job (%s)\n",
9232 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9238 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9243 * Original code - this is an open file.
9245 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9246 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9247 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9249 reply_nterror(req, map_nt_error_from_unix(errno));
9255 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9258 if (total_params < 7) {
9259 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9263 info_level = SVAL(params,0);
9264 if (req->posix_pathnames) {
9265 srvstr_get_path_posix(req,
9274 srvstr_get_path(req,
9283 if (!NT_STATUS_IS_OK(status)) {
9284 reply_nterror(req, status);
9288 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9289 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9290 info_level == SMB_FILE_RENAME_INFORMATION ||
9291 info_level == SMB_POSIX_PATH_OPEN ||
9292 info_level == SMB_POSIX_PATH_UNLINK) {
9293 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9296 status = filename_convert(req, conn,
9302 if (!NT_STATUS_IS_OK(status)) {
9303 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9304 reply_botherror(req,
9305 NT_STATUS_PATH_NOT_COVERED,
9306 ERRSRV, ERRbadpath);
9309 reply_nterror(req, status);
9313 if (INFO_LEVEL_IS_UNIX(info_level)) {
9315 * For CIFS UNIX extensions the target name may not exist.
9318 /* Always do lstat for UNIX calls. */
9319 SMB_VFS_LSTAT(conn, smb_fname);
9321 } else if (!VALID_STAT(smb_fname->st) &&
9322 SMB_VFS_STAT(conn, smb_fname)) {
9323 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9325 smb_fname_str_dbg(smb_fname),
9327 reply_nterror(req, map_nt_error_from_unix(errno));
9332 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9333 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9335 info_level,total_data));
9337 /* Realloc the parameter size */
9338 *pparams = (char *)SMB_REALLOC(*pparams,2);
9339 if (*pparams == NULL) {
9340 reply_nterror(req, NT_STATUS_NO_MEMORY);
9347 status = smbd_do_setfilepathinfo(conn, req, req,
9353 if (!NT_STATUS_IS_OK(status)) {
9354 if (open_was_deferred(req->xconn, req->mid)) {
9355 /* We have re-scheduled this call. */
9358 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9359 bool ok = defer_smb1_sharing_violation(req);
9364 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9365 /* We have re-scheduled this call. */
9368 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9369 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9370 ERRSRV, ERRbadpath);
9373 if (info_level == SMB_POSIX_PATH_OPEN) {
9374 reply_openerror(req, status);
9379 * Invalid EA name needs to return 2 param bytes,
9380 * not a zero-length error packet.
9382 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9383 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9386 reply_nterror(req, status);
9391 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9397 /****************************************************************************
9398 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9399 ****************************************************************************/
9401 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9402 char **pparams, int total_params,
9403 char **ppdata, int total_data,
9404 unsigned int max_data_bytes)
9406 struct smb_filename *smb_dname = NULL;
9407 char *params = *pparams;
9408 char *pdata = *ppdata;
9409 char *directory = NULL;
9410 NTSTATUS status = NT_STATUS_OK;
9411 struct ea_list *ea_list = NULL;
9412 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9413 TALLOC_CTX *ctx = talloc_tos();
9415 if (!CAN_WRITE(conn)) {
9416 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9420 if (total_params < 5) {
9421 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9425 if (req->posix_pathnames) {
9426 srvstr_get_path_posix(ctx,
9435 srvstr_get_path(ctx,
9444 if (!NT_STATUS_IS_OK(status)) {
9445 reply_nterror(req, status);
9449 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9451 status = filename_convert(ctx,
9459 if (!NT_STATUS_IS_OK(status)) {
9460 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9461 reply_botherror(req,
9462 NT_STATUS_PATH_NOT_COVERED,
9463 ERRSRV, ERRbadpath);
9466 reply_nterror(req, status);
9471 * OS/2 workplace shell seems to send SET_EA requests of "null"
9472 * length (4 bytes containing IVAL 4).
9473 * They seem to have no effect. Bug #3212. JRA.
9476 if (total_data && (total_data != 4)) {
9477 /* Any data in this call is an EA list. */
9478 if (total_data < 10) {
9479 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9483 if (IVAL(pdata,0) > total_data) {
9484 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9485 IVAL(pdata,0), (unsigned int)total_data));
9486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9490 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9497 if (!lp_ea_support(SNUM(conn))) {
9498 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9502 /* If total_data == 4 Windows doesn't care what values
9503 * are placed in that field, it just ignores them.
9504 * The System i QNTC IBM SMB client puts bad values here,
9505 * so ignore them. */
9507 status = create_directory(conn, req, smb_dname);
9509 if (!NT_STATUS_IS_OK(status)) {
9510 reply_nterror(req, status);
9514 /* Try and set any given EA. */
9516 status = set_ea(conn, NULL, smb_dname, ea_list);
9517 if (!NT_STATUS_IS_OK(status)) {
9518 reply_nterror(req, status);
9523 /* Realloc the parameter and data sizes */
9524 *pparams = (char *)SMB_REALLOC(*pparams,2);
9525 if(*pparams == NULL) {
9526 reply_nterror(req, NT_STATUS_NO_MEMORY);
9533 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9536 TALLOC_FREE(smb_dname);
9540 /****************************************************************************
9541 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9542 We don't actually do this - we just send a null response.
9543 ****************************************************************************/
9545 static void call_trans2findnotifyfirst(connection_struct *conn,
9546 struct smb_request *req,
9547 char **pparams, int total_params,
9548 char **ppdata, int total_data,
9549 unsigned int max_data_bytes)
9551 char *params = *pparams;
9552 uint16_t info_level;
9554 if (total_params < 6) {
9555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9559 info_level = SVAL(params,4);
9560 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9562 switch (info_level) {
9567 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9571 /* Realloc the parameter and data sizes */
9572 *pparams = (char *)SMB_REALLOC(*pparams,6);
9573 if (*pparams == NULL) {
9574 reply_nterror(req, NT_STATUS_NO_MEMORY);
9579 SSVAL(params,0,fnf_handle);
9580 SSVAL(params,2,0); /* No changes */
9581 SSVAL(params,4,0); /* No EA errors */
9588 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9593 /****************************************************************************
9594 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9595 changes). Currently this does nothing.
9596 ****************************************************************************/
9598 static void call_trans2findnotifynext(connection_struct *conn,
9599 struct smb_request *req,
9600 char **pparams, int total_params,
9601 char **ppdata, int total_data,
9602 unsigned int max_data_bytes)
9604 char *params = *pparams;
9606 DEBUG(3,("call_trans2findnotifynext\n"));
9608 /* Realloc the parameter and data sizes */
9609 *pparams = (char *)SMB_REALLOC(*pparams,4);
9610 if (*pparams == NULL) {
9611 reply_nterror(req, NT_STATUS_NO_MEMORY);
9616 SSVAL(params,0,0); /* No changes */
9617 SSVAL(params,2,0); /* No EA errors */
9619 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9624 /****************************************************************************
9625 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9626 ****************************************************************************/
9628 static void call_trans2getdfsreferral(connection_struct *conn,
9629 struct smb_request *req,
9630 char **pparams, int total_params,
9631 char **ppdata, int total_data,
9632 unsigned int max_data_bytes)
9634 char *params = *pparams;
9635 char *pathname = NULL;
9637 int max_referral_level;
9638 NTSTATUS status = NT_STATUS_OK;
9639 TALLOC_CTX *ctx = talloc_tos();
9641 DEBUG(10,("call_trans2getdfsreferral\n"));
9643 if (total_params < 3) {
9644 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9648 max_referral_level = SVAL(params,0);
9650 if(!lp_host_msdfs()) {
9651 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9655 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9656 total_params - 2, STR_TERMINATE);
9658 reply_nterror(req, NT_STATUS_NOT_FOUND);
9661 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9662 ppdata,&status)) < 0) {
9663 reply_nterror(req, status);
9667 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9668 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9669 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9674 #define LMCAT_SPL 0x53
9675 #define LMFUNC_GETJOBID 0x60
9677 /****************************************************************************
9678 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9679 ****************************************************************************/
9681 static void call_trans2ioctl(connection_struct *conn,
9682 struct smb_request *req,
9683 char **pparams, int total_params,
9684 char **ppdata, int total_data,
9685 unsigned int max_data_bytes)
9687 char *pdata = *ppdata;
9688 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9692 /* check for an invalid fid before proceeding */
9695 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9699 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9700 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9701 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9702 if (*ppdata == NULL) {
9703 reply_nterror(req, NT_STATUS_NO_MEMORY);
9708 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9709 CAN ACCEPT THIS IN UNICODE. JRA. */
9712 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9714 status = srvstr_push(pdata, req->flags2, pdata + 2,
9715 lp_netbios_name(), 15,
9716 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9717 if (!NT_STATUS_IS_OK(status)) {
9718 reply_nterror(req, status);
9721 status = srvstr_push(pdata, req->flags2, pdata+18,
9722 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9723 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9724 if (!NT_STATUS_IS_OK(status)) {
9725 reply_nterror(req, status);
9728 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9733 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9734 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9737 /****************************************************************************
9738 Reply to a SMBfindclose (stop trans2 directory search).
9739 ****************************************************************************/
9741 void reply_findclose(struct smb_request *req)
9744 struct smbd_server_connection *sconn = req->sconn;
9745 files_struct *fsp = NULL;
9747 START_PROFILE(SMBfindclose);
9750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9751 END_PROFILE(SMBfindclose);
9755 dptr_num = SVALS(req->vwv+0, 0);
9757 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9760 * OS/2 seems to use -1 to indicate "close all directories"
9761 * This has to mean on this specific connection struct.
9763 if (dptr_num == -1) {
9764 dptr_closecnum(req->conn);
9766 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9769 close_file(NULL, fsp, NORMAL_CLOSE);
9774 reply_outbuf(req, 0, 0);
9776 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9778 END_PROFILE(SMBfindclose);
9782 /****************************************************************************
9783 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9784 ****************************************************************************/
9786 void reply_findnclose(struct smb_request *req)
9790 START_PROFILE(SMBfindnclose);
9793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9794 END_PROFILE(SMBfindnclose);
9798 dptr_num = SVAL(req->vwv+0, 0);
9800 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9802 /* We never give out valid handles for a
9803 findnotifyfirst - so any dptr_num is ok here.
9806 reply_outbuf(req, 0, 0);
9808 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9810 END_PROFILE(SMBfindnclose);
9814 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9815 struct trans_state *state)
9817 if (get_Protocol() >= PROTOCOL_NT1) {
9818 req->flags2 |= 0x40; /* IS_LONG_NAME */
9819 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9822 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9823 if (state->call != TRANSACT2_QFSINFO &&
9824 state->call != TRANSACT2_SETFSINFO) {
9825 DEBUG(0,("handle_trans2: encryption required "
9827 (unsigned int)state->call));
9828 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9833 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9835 /* Now we must call the relevant TRANS2 function */
9836 switch(state->call) {
9837 case TRANSACT2_OPEN:
9839 START_PROFILE(Trans2_open);
9840 call_trans2open(conn, req,
9841 &state->param, state->total_param,
9842 &state->data, state->total_data,
9843 state->max_data_return);
9844 END_PROFILE(Trans2_open);
9848 case TRANSACT2_FINDFIRST:
9850 START_PROFILE(Trans2_findfirst);
9851 call_trans2findfirst(conn, req,
9852 &state->param, state->total_param,
9853 &state->data, state->total_data,
9854 state->max_data_return);
9855 END_PROFILE(Trans2_findfirst);
9859 case TRANSACT2_FINDNEXT:
9861 START_PROFILE(Trans2_findnext);
9862 call_trans2findnext(conn, req,
9863 &state->param, state->total_param,
9864 &state->data, state->total_data,
9865 state->max_data_return);
9866 END_PROFILE(Trans2_findnext);
9870 case TRANSACT2_QFSINFO:
9872 START_PROFILE(Trans2_qfsinfo);
9873 call_trans2qfsinfo(conn, req,
9874 &state->param, state->total_param,
9875 &state->data, state->total_data,
9876 state->max_data_return);
9877 END_PROFILE(Trans2_qfsinfo);
9881 case TRANSACT2_SETFSINFO:
9883 START_PROFILE(Trans2_setfsinfo);
9884 call_trans2setfsinfo(conn, req,
9885 &state->param, state->total_param,
9886 &state->data, state->total_data,
9887 state->max_data_return);
9888 END_PROFILE(Trans2_setfsinfo);
9892 case TRANSACT2_QPATHINFO:
9893 case TRANSACT2_QFILEINFO:
9895 START_PROFILE(Trans2_qpathinfo);
9896 call_trans2qfilepathinfo(conn, req, state->call,
9897 &state->param, state->total_param,
9898 &state->data, state->total_data,
9899 state->max_data_return);
9900 END_PROFILE(Trans2_qpathinfo);
9904 case TRANSACT2_SETPATHINFO:
9905 case TRANSACT2_SETFILEINFO:
9907 START_PROFILE(Trans2_setpathinfo);
9908 call_trans2setfilepathinfo(conn, req, state->call,
9909 &state->param, state->total_param,
9910 &state->data, state->total_data,
9911 state->max_data_return);
9912 END_PROFILE(Trans2_setpathinfo);
9916 case TRANSACT2_FINDNOTIFYFIRST:
9918 START_PROFILE(Trans2_findnotifyfirst);
9919 call_trans2findnotifyfirst(conn, req,
9920 &state->param, state->total_param,
9921 &state->data, state->total_data,
9922 state->max_data_return);
9923 END_PROFILE(Trans2_findnotifyfirst);
9927 case TRANSACT2_FINDNOTIFYNEXT:
9929 START_PROFILE(Trans2_findnotifynext);
9930 call_trans2findnotifynext(conn, req,
9931 &state->param, state->total_param,
9932 &state->data, state->total_data,
9933 state->max_data_return);
9934 END_PROFILE(Trans2_findnotifynext);
9938 case TRANSACT2_MKDIR:
9940 START_PROFILE(Trans2_mkdir);
9941 call_trans2mkdir(conn, req,
9942 &state->param, state->total_param,
9943 &state->data, state->total_data,
9944 state->max_data_return);
9945 END_PROFILE(Trans2_mkdir);
9949 case TRANSACT2_GET_DFS_REFERRAL:
9951 START_PROFILE(Trans2_get_dfs_referral);
9952 call_trans2getdfsreferral(conn, req,
9953 &state->param, state->total_param,
9954 &state->data, state->total_data,
9955 state->max_data_return);
9956 END_PROFILE(Trans2_get_dfs_referral);
9960 case TRANSACT2_IOCTL:
9962 START_PROFILE(Trans2_ioctl);
9963 call_trans2ioctl(conn, req,
9964 &state->param, state->total_param,
9965 &state->data, state->total_data,
9966 state->max_data_return);
9967 END_PROFILE(Trans2_ioctl);
9972 /* Error in request */
9973 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9974 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9978 /****************************************************************************
9979 Reply to a SMBtrans2.
9980 ****************************************************************************/
9982 void reply_trans2(struct smb_request *req)
9984 connection_struct *conn = req->conn;
9989 unsigned int tran_call;
9990 struct trans_state *state;
9993 START_PROFILE(SMBtrans2);
9995 if (req->wct < 14) {
9996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9997 END_PROFILE(SMBtrans2);
10001 dsoff = SVAL(req->vwv+12, 0);
10002 dscnt = SVAL(req->vwv+11, 0);
10003 psoff = SVAL(req->vwv+10, 0);
10004 pscnt = SVAL(req->vwv+9, 0);
10005 tran_call = SVAL(req->vwv+14, 0);
10007 result = allow_new_trans(conn->pending_trans, req->mid);
10008 if (!NT_STATUS_IS_OK(result)) {
10009 DEBUG(2, ("Got invalid trans2 request: %s\n",
10010 nt_errstr(result)));
10011 reply_nterror(req, result);
10012 END_PROFILE(SMBtrans2);
10016 if (IS_IPC(conn)) {
10017 switch (tran_call) {
10018 /* List the allowed trans2 calls on IPC$ */
10019 case TRANSACT2_OPEN:
10020 case TRANSACT2_GET_DFS_REFERRAL:
10021 case TRANSACT2_QFILEINFO:
10022 case TRANSACT2_QFSINFO:
10023 case TRANSACT2_SETFSINFO:
10026 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10027 END_PROFILE(SMBtrans2);
10032 if ((state = talloc(conn, struct trans_state)) == NULL) {
10033 DEBUG(0, ("talloc failed\n"));
10034 reply_nterror(req, NT_STATUS_NO_MEMORY);
10035 END_PROFILE(SMBtrans2);
10039 state->cmd = SMBtrans2;
10041 state->mid = req->mid;
10042 state->vuid = req->vuid;
10043 state->setup_count = SVAL(req->vwv+13, 0);
10044 state->setup = NULL;
10045 state->total_param = SVAL(req->vwv+0, 0);
10046 state->param = NULL;
10047 state->total_data = SVAL(req->vwv+1, 0);
10048 state->data = NULL;
10049 state->max_param_return = SVAL(req->vwv+2, 0);
10050 state->max_data_return = SVAL(req->vwv+3, 0);
10051 state->max_setup_return = SVAL(req->vwv+4, 0);
10052 state->close_on_completion = BITSETW(req->vwv+5, 0);
10053 state->one_way = BITSETW(req->vwv+5, 1);
10055 state->call = tran_call;
10057 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10058 is so as a sanity check */
10059 if (state->setup_count != 1) {
10061 * Need to have rc=0 for ioctl to get job id for OS/2.
10062 * Network printing will fail if function is not successful.
10063 * Similar function in reply.c will be used if protocol
10064 * is LANMAN1.0 instead of LM1.2X002.
10065 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10066 * outbuf doesn't have to be set(only job id is used).
10068 if ( (state->setup_count == 4)
10069 && (tran_call == TRANSACT2_IOCTL)
10070 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10071 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10072 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10074 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10075 DEBUG(2,("Transaction is %d\n",tran_call));
10076 TALLOC_FREE(state);
10077 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10078 END_PROFILE(SMBtrans2);
10083 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10086 if (state->total_data) {
10088 if (trans_oob(state->total_data, 0, dscnt)
10089 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10093 /* Can't use talloc here, the core routines do realloc on the
10094 * params and data. */
10095 state->data = (char *)SMB_MALLOC(state->total_data);
10096 if (state->data == NULL) {
10097 DEBUG(0,("reply_trans2: data malloc fail for %u "
10098 "bytes !\n", (unsigned int)state->total_data));
10099 TALLOC_FREE(state);
10100 reply_nterror(req, NT_STATUS_NO_MEMORY);
10101 END_PROFILE(SMBtrans2);
10105 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10108 if (state->total_param) {
10110 if (trans_oob(state->total_param, 0, pscnt)
10111 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10115 /* Can't use talloc here, the core routines do realloc on the
10116 * params and data. */
10117 state->param = (char *)SMB_MALLOC(state->total_param);
10118 if (state->param == NULL) {
10119 DEBUG(0,("reply_trans: param malloc fail for %u "
10120 "bytes !\n", (unsigned int)state->total_param));
10121 SAFE_FREE(state->data);
10122 TALLOC_FREE(state);
10123 reply_nterror(req, NT_STATUS_NO_MEMORY);
10124 END_PROFILE(SMBtrans2);
10128 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10131 state->received_data = dscnt;
10132 state->received_param = pscnt;
10134 if ((state->received_param == state->total_param) &&
10135 (state->received_data == state->total_data)) {
10137 handle_trans2(conn, req, state);
10139 SAFE_FREE(state->data);
10140 SAFE_FREE(state->param);
10141 TALLOC_FREE(state);
10142 END_PROFILE(SMBtrans2);
10146 DLIST_ADD(conn->pending_trans, state);
10148 /* We need to send an interim response then receive the rest
10149 of the parameter/data bytes */
10150 reply_outbuf(req, 0, 0);
10151 show_msg((char *)req->outbuf);
10152 END_PROFILE(SMBtrans2);
10157 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10158 SAFE_FREE(state->data);
10159 SAFE_FREE(state->param);
10160 TALLOC_FREE(state);
10161 END_PROFILE(SMBtrans2);
10162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10166 /****************************************************************************
10167 Reply to a SMBtranss2
10168 ****************************************************************************/
10170 void reply_transs2(struct smb_request *req)
10172 connection_struct *conn = req->conn;
10173 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10174 struct trans_state *state;
10176 START_PROFILE(SMBtranss2);
10178 show_msg((const char *)req->inbuf);
10180 /* Windows clients expect all replies to
10181 a transact secondary (SMBtranss2 0x33)
10182 to have a command code of transact
10183 (SMBtrans2 0x32). See bug #8989
10184 and also [MS-CIFS] section 2.2.4.47.2
10187 req->cmd = SMBtrans2;
10189 if (req->wct < 8) {
10190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10191 END_PROFILE(SMBtranss2);
10195 for (state = conn->pending_trans; state != NULL;
10196 state = state->next) {
10197 if (state->mid == req->mid) {
10202 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10204 END_PROFILE(SMBtranss2);
10208 /* Revise state->total_param and state->total_data in case they have
10209 changed downwards */
10211 if (SVAL(req->vwv+0, 0) < state->total_param)
10212 state->total_param = SVAL(req->vwv+0, 0);
10213 if (SVAL(req->vwv+1, 0) < state->total_data)
10214 state->total_data = SVAL(req->vwv+1, 0);
10216 pcnt = SVAL(req->vwv+2, 0);
10217 poff = SVAL(req->vwv+3, 0);
10218 pdisp = SVAL(req->vwv+4, 0);
10220 dcnt = SVAL(req->vwv+5, 0);
10221 doff = SVAL(req->vwv+6, 0);
10222 ddisp = SVAL(req->vwv+7, 0);
10224 state->received_param += pcnt;
10225 state->received_data += dcnt;
10227 if ((state->received_data > state->total_data) ||
10228 (state->received_param > state->total_param))
10232 if (trans_oob(state->total_param, pdisp, pcnt)
10233 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10236 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10240 if (trans_oob(state->total_data, ddisp, dcnt)
10241 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10244 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10247 if ((state->received_param < state->total_param) ||
10248 (state->received_data < state->total_data)) {
10249 END_PROFILE(SMBtranss2);
10253 handle_trans2(conn, req, state);
10255 DLIST_REMOVE(conn->pending_trans, state);
10256 SAFE_FREE(state->data);
10257 SAFE_FREE(state->param);
10258 TALLOC_FREE(state);
10260 END_PROFILE(SMBtranss2);
10265 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10266 DLIST_REMOVE(conn->pending_trans, state);
10267 SAFE_FREE(state->data);
10268 SAFE_FREE(state->param);
10269 TALLOC_FREE(state);
10270 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10271 END_PROFILE(SMBtranss2);