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 = {
7671 .req_guid = smbd_request_guid(req, 0),
7673 .brltype = UNLOCK_LOCK,
7677 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7681 lck = talloc(req, struct smbd_lock_element);
7683 return NT_STATUS_NO_MEMORY;
7686 *lck = (struct smbd_lock_element) {
7687 .req_guid = smbd_request_guid(req, 0),
7689 .brltype = lock_type,
7694 subreq = smbd_smb1_do_locks_send(
7699 blocking_lock ? UINT32_MAX : 0,
7700 true, /* large_offset */
7704 if (subreq == NULL) {
7706 return NT_STATUS_NO_MEMORY;
7708 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7709 return NT_STATUS_EVENT_PENDING;
7712 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7714 struct smb_request *req = NULL;
7718 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7721 status = smbd_smb1_do_locks_recv(subreq);
7722 TALLOC_FREE(subreq);
7724 if (NT_STATUS_IS_OK(status)) {
7725 char params[2] = {0};
7726 /* Fake up max_data_bytes here - we know it fits. */
7727 send_trans2_replies(
7737 reply_nterror(req, status);
7740 (char *)req->outbuf,
7743 IS_CONN_ENCRYPTED(req->conn),
7746 exit_server_cleanly("smb_set_posix_lock_done: "
7747 "srv_send_smb failed.");
7755 /****************************************************************************
7756 Deal with SMB_SET_FILE_BASIC_INFO.
7757 ****************************************************************************/
7759 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7763 const struct smb_filename *smb_fname)
7765 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7766 struct smb_file_time ft;
7767 uint32_t dosmode = 0;
7768 NTSTATUS status = NT_STATUS_OK;
7772 if (total_data < 36) {
7773 return NT_STATUS_INVALID_PARAMETER;
7776 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7777 if (!NT_STATUS_IS_OK(status)) {
7781 /* Set the attributes */
7782 dosmode = IVAL(pdata,32);
7783 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7784 if (!NT_STATUS_IS_OK(status)) {
7789 ft.create_time = interpret_long_date(pdata);
7792 ft.atime = interpret_long_date(pdata+8);
7795 ft.mtime = interpret_long_date(pdata+16);
7798 ft.ctime = interpret_long_date(pdata+24);
7800 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7801 smb_fname_str_dbg(smb_fname)));
7803 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7807 /****************************************************************************
7808 Deal with SMB_INFO_STANDARD.
7809 ****************************************************************************/
7811 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7815 const struct smb_filename *smb_fname)
7818 struct smb_file_time ft;
7822 if (total_data < 12) {
7823 return NT_STATUS_INVALID_PARAMETER;
7827 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7829 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7831 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7833 DEBUG(10,("smb_set_info_standard: file %s\n",
7834 smb_fname_str_dbg(smb_fname)));
7836 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7837 if (!NT_STATUS_IS_OK(status)) {
7841 return smb_set_file_time(conn,
7848 /****************************************************************************
7849 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7850 ****************************************************************************/
7852 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7853 struct smb_request *req,
7857 struct smb_filename *smb_fname)
7859 uint64_t allocation_size = 0;
7860 NTSTATUS status = NT_STATUS_OK;
7861 files_struct *new_fsp = NULL;
7863 if (!VALID_STAT(smb_fname->st)) {
7864 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7867 if (total_data < 8) {
7868 return NT_STATUS_INVALID_PARAMETER;
7871 allocation_size = (uint64_t)IVAL(pdata,0);
7872 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7873 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7874 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7875 (double)allocation_size));
7877 if (allocation_size) {
7878 allocation_size = smb_roundup(conn, allocation_size);
7881 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7882 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7883 (double)allocation_size));
7885 if (fsp && fsp->fh->fd != -1) {
7886 /* Open file handle. */
7887 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7888 return NT_STATUS_ACCESS_DENIED;
7891 /* Only change if needed. */
7892 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7893 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7894 return map_nt_error_from_unix(errno);
7897 /* But always update the time. */
7899 * This is equivalent to a write. Ensure it's seen immediately
7900 * if there are no pending writes.
7902 trigger_write_time_update_immediate(fsp);
7903 return NT_STATUS_OK;
7906 /* Pathname or stat or directory file. */
7907 status = SMB_VFS_CREATE_FILE(
7910 0, /* root_dir_fid */
7911 smb_fname, /* fname */
7912 FILE_WRITE_DATA, /* access_mask */
7913 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7915 FILE_OPEN, /* create_disposition*/
7916 0, /* create_options */
7917 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7918 0, /* oplock_request */
7920 0, /* allocation_size */
7921 0, /* private_flags */
7924 &new_fsp, /* result */
7926 NULL, NULL); /* create context */
7928 if (!NT_STATUS_IS_OK(status)) {
7929 /* NB. We check for open_was_deferred in the caller. */
7933 /* Only change if needed. */
7934 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7935 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7936 status = map_nt_error_from_unix(errno);
7937 close_file(req, new_fsp, NORMAL_CLOSE);
7942 /* Changing the allocation size should set the last mod time. */
7944 * This is equivalent to a write. Ensure it's seen immediately
7945 * if there are no pending writes.
7947 trigger_write_time_update_immediate(new_fsp);
7948 close_file(req, new_fsp, NORMAL_CLOSE);
7949 return NT_STATUS_OK;
7952 /****************************************************************************
7953 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7954 ****************************************************************************/
7956 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7957 struct smb_request *req,
7961 const struct smb_filename *smb_fname,
7962 bool fail_after_createfile)
7966 if (total_data < 8) {
7967 return NT_STATUS_INVALID_PARAMETER;
7970 size = IVAL(pdata,0);
7971 size |= (((off_t)IVAL(pdata,4)) << 32);
7972 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7973 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7976 return smb_set_file_size(conn, req,
7981 fail_after_createfile);
7984 /****************************************************************************
7985 Allow a UNIX info mknod.
7986 ****************************************************************************/
7988 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7991 const struct smb_filename *smb_fname)
7993 uint32_t file_type = IVAL(pdata,56);
7994 #if defined(HAVE_MAKEDEV)
7995 uint32_t dev_major = IVAL(pdata,60);
7996 uint32_t dev_minor = IVAL(pdata,68);
7998 SMB_DEV_T dev = (SMB_DEV_T)0;
7999 uint32_t raw_unixmode = IVAL(pdata,84);
8004 if (total_data < 100) {
8005 return NT_STATUS_INVALID_PARAMETER;
8008 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8009 PERM_NEW_FILE, &unixmode);
8010 if (!NT_STATUS_IS_OK(status)) {
8014 #if defined(HAVE_MAKEDEV)
8015 dev = makedev(dev_major, dev_minor);
8018 switch (file_type) {
8019 /* We can't create other objects here. */
8020 case UNIX_TYPE_FILE:
8022 case UNIX_TYPE_SYMLINK:
8023 return NT_STATUS_ACCESS_DENIED;
8024 #if defined(S_IFIFO)
8025 case UNIX_TYPE_FIFO:
8026 unixmode |= S_IFIFO;
8029 #if defined(S_IFSOCK)
8030 case UNIX_TYPE_SOCKET:
8031 unixmode |= S_IFSOCK;
8034 #if defined(S_IFCHR)
8035 case UNIX_TYPE_CHARDEV:
8036 /* This is only allowed for root. */
8037 if (get_current_uid(conn) != sec_initial_uid()) {
8038 return NT_STATUS_ACCESS_DENIED;
8040 unixmode |= S_IFCHR;
8043 #if defined(S_IFBLK)
8044 case UNIX_TYPE_BLKDEV:
8045 if (get_current_uid(conn) != sec_initial_uid()) {
8046 return NT_STATUS_ACCESS_DENIED;
8048 unixmode |= S_IFBLK;
8052 return NT_STATUS_INVALID_PARAMETER;
8055 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8056 "%.0f mode 0%o for file %s\n", (double)dev,
8057 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8059 /* Ok - do the mknod. */
8060 ret = SMB_VFS_MKNODAT(conn,
8067 return map_nt_error_from_unix(errno);
8070 /* If any of the other "set" calls fail we
8071 * don't want to end up with a half-constructed mknod.
8074 if (lp_inherit_permissions(SNUM(conn))) {
8076 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
8078 return NT_STATUS_NO_MEMORY;
8080 inherit_access_posix_acl(conn, parent, smb_fname,
8082 TALLOC_FREE(parent);
8085 return NT_STATUS_OK;
8088 /****************************************************************************
8089 Deal with SMB_SET_FILE_UNIX_BASIC.
8090 ****************************************************************************/
8092 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8093 struct smb_request *req,
8097 const struct smb_filename *smb_fname)
8099 struct smb_file_time ft;
8100 uint32_t raw_unixmode;
8103 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8104 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8105 NTSTATUS status = NT_STATUS_OK;
8106 bool delete_on_fail = False;
8107 enum perm_type ptype;
8108 files_struct *all_fsps = NULL;
8109 bool modify_mtime = true;
8111 struct smb_filename *smb_fname_tmp = NULL;
8112 SMB_STRUCT_STAT sbuf;
8116 if (total_data < 100) {
8117 return NT_STATUS_INVALID_PARAMETER;
8120 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8121 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8122 size=IVAL(pdata,0); /* first 8 Bytes are size */
8123 size |= (((off_t)IVAL(pdata,4)) << 32);
8126 ft.atime = interpret_long_date(pdata+24); /* access_time */
8127 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
8128 set_owner = (uid_t)IVAL(pdata,40);
8129 set_grp = (gid_t)IVAL(pdata,48);
8130 raw_unixmode = IVAL(pdata,84);
8132 if (VALID_STAT(smb_fname->st)) {
8133 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8134 ptype = PERM_EXISTING_DIR;
8136 ptype = PERM_EXISTING_FILE;
8139 ptype = PERM_NEW_FILE;
8142 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8144 if (!NT_STATUS_IS_OK(status)) {
8148 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8149 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8150 smb_fname_str_dbg(smb_fname), (double)size,
8151 (unsigned int)set_owner, (unsigned int)set_grp,
8152 (int)raw_unixmode));
8154 sbuf = smb_fname->st;
8156 if (!VALID_STAT(sbuf)) {
8158 * The only valid use of this is to create character and block
8159 * devices, and named pipes. This is deprecated (IMHO) and
8160 * a new info level should be used for mknod. JRA.
8163 status = smb_unix_mknod(conn,
8167 if (!NT_STATUS_IS_OK(status)) {
8171 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
8172 if (smb_fname_tmp == NULL) {
8173 return NT_STATUS_NO_MEMORY;
8176 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
8177 status = map_nt_error_from_unix(errno);
8178 TALLOC_FREE(smb_fname_tmp);
8179 SMB_VFS_UNLINKAT(conn,
8186 sbuf = smb_fname_tmp->st;
8187 smb_fname = smb_fname_tmp;
8189 /* Ensure we don't try and change anything else. */
8190 raw_unixmode = SMB_MODE_NO_CHANGE;
8191 size = get_file_size_stat(&sbuf);
8192 ft.atime = sbuf.st_ex_atime;
8193 ft.mtime = sbuf.st_ex_mtime;
8195 * We continue here as we might want to change the
8198 delete_on_fail = True;
8202 /* Horrible backwards compatibility hack as an old server bug
8203 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8207 size = get_file_size_stat(&sbuf);
8212 * Deal with the UNIX specific mode set.
8215 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8218 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8219 "setting mode 0%o for file %s\n",
8220 (unsigned int)unixmode,
8221 smb_fname_str_dbg(smb_fname)));
8222 if (fsp && fsp->fh->fd != -1) {
8223 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8225 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8228 return map_nt_error_from_unix(errno);
8233 * Deal with the UNIX specific uid set.
8236 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8237 (sbuf.st_ex_uid != set_owner)) {
8240 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8241 "changing owner %u for path %s\n",
8242 (unsigned int)set_owner,
8243 smb_fname_str_dbg(smb_fname)));
8245 if (fsp && fsp->fh->fd != -1) {
8246 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8249 * UNIX extensions calls must always operate
8252 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8253 set_owner, (gid_t)-1);
8257 status = map_nt_error_from_unix(errno);
8258 if (delete_on_fail) {
8259 SMB_VFS_UNLINKAT(conn,
8269 * Deal with the UNIX specific gid set.
8272 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8273 (sbuf.st_ex_gid != set_grp)) {
8276 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8277 "changing group %u for file %s\n",
8278 (unsigned int)set_grp,
8279 smb_fname_str_dbg(smb_fname)));
8280 if (fsp && fsp->fh->fd != -1) {
8281 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8284 * UNIX extensions calls must always operate
8287 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8291 status = map_nt_error_from_unix(errno);
8292 if (delete_on_fail) {
8293 SMB_VFS_UNLINKAT(conn,
8302 /* Deal with any size changes. */
8304 if (S_ISREG(sbuf.st_ex_mode)) {
8305 status = smb_set_file_size(conn, req,
8311 if (!NT_STATUS_IS_OK(status)) {
8316 /* Deal with any time changes. */
8317 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
8318 /* No change, don't cancel anything. */
8322 id = vfs_file_id_from_sbuf(conn, &sbuf);
8323 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8324 all_fsps = file_find_di_next(all_fsps)) {
8326 * We're setting the time explicitly for UNIX.
8327 * Cancel any pending changes over all handles.
8329 all_fsps->update_write_time_on_close = false;
8330 TALLOC_FREE(all_fsps->update_write_time_event);
8334 * Override the "setting_write_time"
8335 * parameter here as it almost does what
8336 * we need. Just remember if we modified
8337 * mtime and send the notify ourselves.
8339 if (null_timespec(ft.mtime)) {
8340 modify_mtime = false;
8343 status = smb_set_file_time(conn,
8349 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8350 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8355 /****************************************************************************
8356 Deal with SMB_SET_FILE_UNIX_INFO2.
8357 ****************************************************************************/
8359 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8360 struct smb_request *req,
8364 const struct smb_filename *smb_fname)
8367 uint32_t smb_fflags;
8370 if (total_data < 116) {
8371 return NT_STATUS_INVALID_PARAMETER;
8374 /* Start by setting all the fields that are common between UNIX_BASIC
8377 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8379 if (!NT_STATUS_IS_OK(status)) {
8383 smb_fflags = IVAL(pdata, 108);
8384 smb_fmask = IVAL(pdata, 112);
8386 /* NB: We should only attempt to alter the file flags if the client
8387 * sends a non-zero mask.
8389 if (smb_fmask != 0) {
8390 int stat_fflags = 0;
8392 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8393 smb_fmask, &stat_fflags)) {
8394 /* Client asked to alter a flag we don't understand. */
8395 return NT_STATUS_INVALID_PARAMETER;
8398 if (fsp && fsp->fh->fd != -1) {
8399 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8400 return NT_STATUS_NOT_SUPPORTED;
8402 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8403 stat_fflags) != 0) {
8404 return map_nt_error_from_unix(errno);
8409 /* XXX: need to add support for changing the create_time here. You
8410 * can do this for paths on Darwin with setattrlist(2). The right way
8411 * to hook this up is probably by extending the VFS utimes interface.
8414 return NT_STATUS_OK;
8417 /****************************************************************************
8418 Create a directory with POSIX semantics.
8419 ****************************************************************************/
8421 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8422 struct smb_request *req,
8425 struct smb_filename *smb_fname,
8426 int *pdata_return_size)
8428 NTSTATUS status = NT_STATUS_OK;
8429 uint32_t raw_unixmode = 0;
8430 uint32_t mod_unixmode = 0;
8431 mode_t unixmode = (mode_t)0;
8432 files_struct *fsp = NULL;
8433 uint16_t info_level_return = 0;
8435 char *pdata = *ppdata;
8437 if (total_data < 18) {
8438 return NT_STATUS_INVALID_PARAMETER;
8441 raw_unixmode = IVAL(pdata,8);
8442 /* Next 4 bytes are not yet defined. */
8444 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8445 PERM_NEW_DIR, &unixmode);
8446 if (!NT_STATUS_IS_OK(status)) {
8450 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8452 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8453 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8455 status = SMB_VFS_CREATE_FILE(
8458 0, /* root_dir_fid */
8459 smb_fname, /* fname */
8460 FILE_READ_ATTRIBUTES, /* access_mask */
8461 FILE_SHARE_NONE, /* share_access */
8462 FILE_CREATE, /* create_disposition*/
8463 FILE_DIRECTORY_FILE, /* create_options */
8464 mod_unixmode, /* file_attributes */
8465 0, /* oplock_request */
8467 0, /* allocation_size */
8468 0, /* private_flags */
8473 NULL, NULL); /* create context */
8475 if (NT_STATUS_IS_OK(status)) {
8476 close_file(req, fsp, NORMAL_CLOSE);
8479 info_level_return = SVAL(pdata,16);
8481 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8482 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8483 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8484 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8486 *pdata_return_size = 12;
8489 /* Realloc the data size */
8490 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8491 if (*ppdata == NULL) {
8492 *pdata_return_size = 0;
8493 return NT_STATUS_NO_MEMORY;
8497 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8498 SSVAL(pdata,2,0); /* No fnum. */
8499 SIVAL(pdata,4,info); /* Was directory created. */
8501 switch (info_level_return) {
8502 case SMB_QUERY_FILE_UNIX_BASIC:
8503 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8504 SSVAL(pdata,10,0); /* Padding. */
8505 store_file_unix_basic(conn, pdata + 12, fsp,
8508 case SMB_QUERY_FILE_UNIX_INFO2:
8509 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8510 SSVAL(pdata,10,0); /* Padding. */
8511 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8515 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8516 SSVAL(pdata,10,0); /* Padding. */
8523 /****************************************************************************
8524 Open/Create a file with POSIX semantics.
8525 ****************************************************************************/
8527 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8528 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8530 static NTSTATUS smb_posix_open(connection_struct *conn,
8531 struct smb_request *req,
8534 struct smb_filename *smb_fname,
8535 int *pdata_return_size)
8537 bool extended_oplock_granted = False;
8538 char *pdata = *ppdata;
8540 uint32_t wire_open_mode = 0;
8541 uint32_t raw_unixmode = 0;
8542 uint32_t mod_unixmode = 0;
8543 uint32_t create_disp = 0;
8544 uint32_t access_mask = 0;
8545 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8546 NTSTATUS status = NT_STATUS_OK;
8547 mode_t unixmode = (mode_t)0;
8548 files_struct *fsp = NULL;
8549 int oplock_request = 0;
8551 uint16_t info_level_return = 0;
8553 if (total_data < 18) {
8554 return NT_STATUS_INVALID_PARAMETER;
8557 flags = IVAL(pdata,0);
8558 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8559 if (oplock_request) {
8560 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8563 wire_open_mode = IVAL(pdata,4);
8565 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8566 return smb_posix_mkdir(conn, req,
8573 switch (wire_open_mode & SMB_ACCMODE) {
8575 access_mask = SMB_O_RDONLY_MAPPING;
8578 access_mask = SMB_O_WRONLY_MAPPING;
8581 access_mask = (SMB_O_RDONLY_MAPPING|
8582 SMB_O_WRONLY_MAPPING);
8585 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8586 (unsigned int)wire_open_mode ));
8587 return NT_STATUS_INVALID_PARAMETER;
8590 wire_open_mode &= ~SMB_ACCMODE;
8592 /* First take care of O_CREAT|O_EXCL interactions. */
8593 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8594 case (SMB_O_CREAT | SMB_O_EXCL):
8595 /* File exists fail. File not exist create. */
8596 create_disp = FILE_CREATE;
8599 /* File exists open. File not exist create. */
8600 create_disp = FILE_OPEN_IF;
8603 /* O_EXCL on its own without O_CREAT is undefined.
8604 We deliberately ignore it as some versions of
8605 Linux CIFSFS can send a bare O_EXCL on the
8606 wire which other filesystems in the kernel
8607 ignore. See bug 9519 for details. */
8612 /* File exists open. File not exist fail. */
8613 create_disp = FILE_OPEN;
8616 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8617 (unsigned int)wire_open_mode ));
8618 return NT_STATUS_INVALID_PARAMETER;
8621 /* Next factor in the effects of O_TRUNC. */
8622 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8624 if (wire_open_mode & SMB_O_TRUNC) {
8625 switch (create_disp) {
8627 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8628 /* Leave create_disp alone as
8629 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8631 /* File exists fail. File not exist create. */
8634 /* SMB_O_CREAT | SMB_O_TRUNC */
8635 /* File exists overwrite. File not exist create. */
8636 create_disp = FILE_OVERWRITE_IF;
8640 /* File exists overwrite. File not exist fail. */
8641 create_disp = FILE_OVERWRITE;
8644 /* Cannot get here. */
8645 smb_panic("smb_posix_open: logic error");
8646 return NT_STATUS_INVALID_PARAMETER;
8650 raw_unixmode = IVAL(pdata,8);
8651 /* Next 4 bytes are not yet defined. */
8653 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8654 (VALID_STAT(smb_fname->st) ?
8655 PERM_EXISTING_FILE : PERM_NEW_FILE),
8658 if (!NT_STATUS_IS_OK(status)) {
8662 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8664 if (wire_open_mode & SMB_O_SYNC) {
8665 create_options |= FILE_WRITE_THROUGH;
8667 if (wire_open_mode & SMB_O_APPEND) {
8668 access_mask |= FILE_APPEND_DATA;
8670 if (wire_open_mode & SMB_O_DIRECT) {
8671 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8674 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8675 VALID_STAT_OF_DIR(smb_fname->st)) {
8676 if (access_mask != SMB_O_RDONLY_MAPPING) {
8677 return NT_STATUS_FILE_IS_A_DIRECTORY;
8679 create_options &= ~FILE_NON_DIRECTORY_FILE;
8680 create_options |= FILE_DIRECTORY_FILE;
8683 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8684 smb_fname_str_dbg(smb_fname),
8685 (unsigned int)wire_open_mode,
8686 (unsigned int)unixmode ));
8688 status = SMB_VFS_CREATE_FILE(
8691 0, /* root_dir_fid */
8692 smb_fname, /* fname */
8693 access_mask, /* access_mask */
8694 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8696 create_disp, /* create_disposition*/
8697 create_options, /* create_options */
8698 mod_unixmode, /* file_attributes */
8699 oplock_request, /* oplock_request */
8701 0, /* allocation_size */
8702 0, /* private_flags */
8707 NULL, NULL); /* create context */
8709 if (!NT_STATUS_IS_OK(status)) {
8713 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8714 extended_oplock_granted = True;
8717 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8718 extended_oplock_granted = True;
8721 info_level_return = SVAL(pdata,16);
8723 /* Allocate the correct return size. */
8725 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8726 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8727 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8728 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8730 *pdata_return_size = 12;
8733 /* Realloc the data size */
8734 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8735 if (*ppdata == NULL) {
8736 close_file(req, fsp, ERROR_CLOSE);
8737 *pdata_return_size = 0;
8738 return NT_STATUS_NO_MEMORY;
8742 if (extended_oplock_granted) {
8743 if (flags & REQUEST_BATCH_OPLOCK) {
8744 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8746 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8748 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8749 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8751 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8754 SSVAL(pdata,2,fsp->fnum);
8755 SIVAL(pdata,4,info); /* Was file created etc. */
8757 switch (info_level_return) {
8758 case SMB_QUERY_FILE_UNIX_BASIC:
8759 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8760 SSVAL(pdata,10,0); /* padding. */
8761 store_file_unix_basic(conn, pdata + 12, fsp,
8764 case SMB_QUERY_FILE_UNIX_INFO2:
8765 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8766 SSVAL(pdata,10,0); /* padding. */
8767 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8771 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8772 SSVAL(pdata,10,0); /* padding. */
8775 return NT_STATUS_OK;
8778 /****************************************************************************
8779 Delete a file with POSIX semantics.
8780 ****************************************************************************/
8782 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8783 struct smb_request *req,
8786 struct smb_filename *smb_fname)
8788 NTSTATUS status = NT_STATUS_OK;
8789 files_struct *fsp = NULL;
8793 int create_options = 0;
8794 struct share_mode_lock *lck = NULL;
8795 bool other_nonposix_opens;
8797 if (total_data < 2) {
8798 return NT_STATUS_INVALID_PARAMETER;
8801 flags = SVAL(pdata,0);
8803 if (!VALID_STAT(smb_fname->st)) {
8804 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8807 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8808 !VALID_STAT_OF_DIR(smb_fname->st)) {
8809 return NT_STATUS_NOT_A_DIRECTORY;
8812 DEBUG(10,("smb_posix_unlink: %s %s\n",
8813 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8814 smb_fname_str_dbg(smb_fname)));
8816 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8817 create_options |= FILE_DIRECTORY_FILE;
8820 status = SMB_VFS_CREATE_FILE(
8823 0, /* root_dir_fid */
8824 smb_fname, /* fname */
8825 DELETE_ACCESS, /* access_mask */
8826 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8828 FILE_OPEN, /* create_disposition*/
8829 create_options, /* create_options */
8830 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8831 0, /* oplock_request */
8833 0, /* allocation_size */
8834 0, /* private_flags */
8839 NULL, NULL); /* create context */
8841 if (!NT_STATUS_IS_OK(status)) {
8846 * Don't lie to client. If we can't really delete due to
8847 * non-POSIX opens return SHARING_VIOLATION.
8850 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8852 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8853 "lock for file %s\n", fsp_str_dbg(fsp)));
8854 close_file(req, fsp, NORMAL_CLOSE);
8855 return NT_STATUS_INVALID_PARAMETER;
8858 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8859 if (other_nonposix_opens) {
8860 /* Fail with sharing violation. */
8862 close_file(req, fsp, NORMAL_CLOSE);
8863 return NT_STATUS_SHARING_VIOLATION;
8867 * Set the delete on close.
8869 status = smb_set_file_disposition_info(conn,
8877 if (!NT_STATUS_IS_OK(status)) {
8878 close_file(req, fsp, NORMAL_CLOSE);
8881 return close_file(req, fsp, NORMAL_CLOSE);
8884 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8885 struct smb_request *req,
8886 TALLOC_CTX *mem_ctx,
8887 uint16_t info_level,
8889 struct smb_filename *smb_fname,
8890 char **ppdata, int total_data,
8893 char *pdata = *ppdata;
8894 NTSTATUS status = NT_STATUS_OK;
8895 int data_return_size = 0;
8899 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8900 return NT_STATUS_INVALID_LEVEL;
8903 if (!CAN_WRITE(conn)) {
8904 /* Allow POSIX opens. The open path will deny
8905 * any non-readonly opens. */
8906 if (info_level != SMB_POSIX_PATH_OPEN) {
8907 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8911 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8912 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8914 info_level, total_data));
8916 switch (info_level) {
8918 case SMB_INFO_STANDARD:
8920 status = smb_set_info_standard(conn,
8928 case SMB_INFO_SET_EA:
8930 status = smb_info_set_ea(conn,
8938 case SMB_SET_FILE_BASIC_INFO:
8939 case SMB_FILE_BASIC_INFORMATION:
8941 status = smb_set_file_basic_info(conn,
8949 case SMB_FILE_ALLOCATION_INFORMATION:
8950 case SMB_SET_FILE_ALLOCATION_INFO:
8952 status = smb_set_file_allocation_info(conn, req,
8960 case SMB_FILE_END_OF_FILE_INFORMATION:
8961 case SMB_SET_FILE_END_OF_FILE_INFO:
8964 * XP/Win7 both fail after the createfile with
8965 * SMB_SET_FILE_END_OF_FILE_INFO but not
8966 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8967 * The level is known here, so pass it down
8971 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8973 status = smb_set_file_end_of_file_info(conn, req,
8982 case SMB_FILE_DISPOSITION_INFORMATION:
8983 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8986 /* JRA - We used to just ignore this on a path ?
8987 * Shouldn't this be invalid level on a pathname
8990 if (tran_call != TRANSACT2_SETFILEINFO) {
8991 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8994 status = smb_set_file_disposition_info(conn,
9002 case SMB_FILE_POSITION_INFORMATION:
9004 status = smb_file_position_information(conn,
9011 case SMB_FILE_FULL_EA_INFORMATION:
9013 status = smb_set_file_full_ea_info(conn,
9020 /* From tridge Samba4 :
9021 * MODE_INFORMATION in setfileinfo (I have no
9022 * idea what "mode information" on a file is - it takes a value of 0,
9023 * 2, 4 or 6. What could it be?).
9026 case SMB_FILE_MODE_INFORMATION:
9028 status = smb_file_mode_information(conn,
9034 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9035 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9036 case SMB_FILE_SHORT_NAME_INFORMATION:
9037 return NT_STATUS_NOT_SUPPORTED;
9040 * CIFS UNIX extensions.
9043 case SMB_SET_FILE_UNIX_BASIC:
9045 status = smb_set_file_unix_basic(conn, req,
9053 case SMB_SET_FILE_UNIX_INFO2:
9055 status = smb_set_file_unix_info2(conn, req,
9063 case SMB_SET_FILE_UNIX_LINK:
9066 /* We must have a pathname for this. */
9067 return NT_STATUS_INVALID_LEVEL;
9069 status = smb_set_file_unix_link(conn, req, pdata,
9070 total_data, smb_fname);
9074 case SMB_SET_FILE_UNIX_HLINK:
9077 /* We must have a pathname for this. */
9078 return NT_STATUS_INVALID_LEVEL;
9080 status = smb_set_file_unix_hlink(conn, req,
9086 case SMB_FILE_RENAME_INFORMATION:
9088 status = smb_file_rename_information(conn, req,
9094 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9096 /* SMB2 rename information. */
9097 status = smb2_file_rename_information(conn, req,
9103 case SMB_FILE_LINK_INFORMATION:
9105 status = smb_file_link_information(conn, req,
9111 #if defined(HAVE_POSIX_ACLS)
9112 case SMB_SET_POSIX_ACL:
9114 status = smb_set_posix_acl(conn,
9124 case SMB_SET_POSIX_LOCK:
9127 return NT_STATUS_INVALID_LEVEL;
9129 status = smb_set_posix_lock(conn, req,
9130 pdata, total_data, fsp);
9134 case SMB_POSIX_PATH_OPEN:
9137 /* We must have a pathname for this. */
9138 return NT_STATUS_INVALID_LEVEL;
9141 status = smb_posix_open(conn, req,
9149 case SMB_POSIX_PATH_UNLINK:
9152 /* We must have a pathname for this. */
9153 return NT_STATUS_INVALID_LEVEL;
9156 status = smb_posix_unlink(conn, req,
9164 return NT_STATUS_INVALID_LEVEL;
9167 if (!NT_STATUS_IS_OK(status)) {
9171 *ret_data_size = data_return_size;
9172 return NT_STATUS_OK;
9175 /****************************************************************************
9176 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9177 ****************************************************************************/
9179 static void call_trans2setfilepathinfo(connection_struct *conn,
9180 struct smb_request *req,
9181 unsigned int tran_call,
9182 char **pparams, int total_params,
9183 char **ppdata, int total_data,
9184 unsigned int max_data_bytes)
9186 char *params = *pparams;
9187 char *pdata = *ppdata;
9188 uint16_t info_level;
9189 struct smb_filename *smb_fname = NULL;
9190 files_struct *fsp = NULL;
9191 NTSTATUS status = NT_STATUS_OK;
9192 int data_return_size = 0;
9195 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9199 if (tran_call == TRANSACT2_SETFILEINFO) {
9200 if (total_params < 4) {
9201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9205 fsp = file_fsp(req, SVAL(params,0));
9206 /* Basic check for non-null fsp. */
9207 if (!check_fsp_open(conn, req, fsp)) {
9210 info_level = SVAL(params,2);
9212 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9213 if (smb_fname == NULL) {
9214 reply_nterror(req, NT_STATUS_NO_MEMORY);
9218 if(fsp->fh->fd == -1) {
9220 * This is actually a SETFILEINFO on a directory
9221 * handle (returned from an NT SMB). NT5.0 seems
9222 * to do this call. JRA.
9224 if (INFO_LEVEL_IS_UNIX(info_level)) {
9225 /* Always do lstat for UNIX calls. */
9226 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9227 DEBUG(3,("call_trans2setfilepathinfo: "
9228 "SMB_VFS_LSTAT of %s failed "
9230 smb_fname_str_dbg(smb_fname),
9232 reply_nterror(req, map_nt_error_from_unix(errno));
9236 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9237 DEBUG(3,("call_trans2setfilepathinfo: "
9238 "fileinfo of %s failed (%s)\n",
9239 smb_fname_str_dbg(smb_fname),
9241 reply_nterror(req, map_nt_error_from_unix(errno));
9245 } else if (fsp->print_file) {
9247 * Doing a DELETE_ON_CLOSE should cancel a print job.
9249 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9250 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9252 DEBUG(3,("call_trans2setfilepathinfo: "
9253 "Cancelling print job (%s)\n",
9257 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9263 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9268 * Original code - this is an open file.
9270 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9271 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9272 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9274 reply_nterror(req, map_nt_error_from_unix(errno));
9280 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9283 if (total_params < 7) {
9284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9288 info_level = SVAL(params,0);
9289 if (req->posix_pathnames) {
9290 srvstr_get_path_posix(req,
9299 srvstr_get_path(req,
9308 if (!NT_STATUS_IS_OK(status)) {
9309 reply_nterror(req, status);
9313 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9314 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9315 info_level == SMB_FILE_RENAME_INFORMATION ||
9316 info_level == SMB_POSIX_PATH_OPEN ||
9317 info_level == SMB_POSIX_PATH_UNLINK) {
9318 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9321 status = filename_convert(req, conn,
9327 if (!NT_STATUS_IS_OK(status)) {
9328 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9329 reply_botherror(req,
9330 NT_STATUS_PATH_NOT_COVERED,
9331 ERRSRV, ERRbadpath);
9334 reply_nterror(req, status);
9338 if (INFO_LEVEL_IS_UNIX(info_level)) {
9340 * For CIFS UNIX extensions the target name may not exist.
9343 /* Always do lstat for UNIX calls. */
9344 SMB_VFS_LSTAT(conn, smb_fname);
9346 } else if (!VALID_STAT(smb_fname->st) &&
9347 SMB_VFS_STAT(conn, smb_fname)) {
9348 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9350 smb_fname_str_dbg(smb_fname),
9352 reply_nterror(req, map_nt_error_from_unix(errno));
9357 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9358 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9360 info_level,total_data));
9362 /* Realloc the parameter size */
9363 *pparams = (char *)SMB_REALLOC(*pparams,2);
9364 if (*pparams == NULL) {
9365 reply_nterror(req, NT_STATUS_NO_MEMORY);
9372 status = smbd_do_setfilepathinfo(conn, req, req,
9378 if (!NT_STATUS_IS_OK(status)) {
9379 if (open_was_deferred(req->xconn, req->mid)) {
9380 /* We have re-scheduled this call. */
9383 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9384 bool ok = defer_smb1_sharing_violation(req);
9389 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9390 /* We have re-scheduled this call. */
9393 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9394 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9395 ERRSRV, ERRbadpath);
9398 if (info_level == SMB_POSIX_PATH_OPEN) {
9399 reply_openerror(req, status);
9404 * Invalid EA name needs to return 2 param bytes,
9405 * not a zero-length error packet.
9407 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9408 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9411 reply_nterror(req, status);
9416 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9422 /****************************************************************************
9423 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9424 ****************************************************************************/
9426 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9427 char **pparams, int total_params,
9428 char **ppdata, int total_data,
9429 unsigned int max_data_bytes)
9431 struct smb_filename *smb_dname = NULL;
9432 char *params = *pparams;
9433 char *pdata = *ppdata;
9434 char *directory = NULL;
9435 NTSTATUS status = NT_STATUS_OK;
9436 struct ea_list *ea_list = NULL;
9437 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9438 TALLOC_CTX *ctx = talloc_tos();
9440 if (!CAN_WRITE(conn)) {
9441 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9445 if (total_params < 5) {
9446 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9450 if (req->posix_pathnames) {
9451 srvstr_get_path_posix(ctx,
9460 srvstr_get_path(ctx,
9469 if (!NT_STATUS_IS_OK(status)) {
9470 reply_nterror(req, status);
9474 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9476 status = filename_convert(ctx,
9484 if (!NT_STATUS_IS_OK(status)) {
9485 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9486 reply_botherror(req,
9487 NT_STATUS_PATH_NOT_COVERED,
9488 ERRSRV, ERRbadpath);
9491 reply_nterror(req, status);
9496 * OS/2 workplace shell seems to send SET_EA requests of "null"
9497 * length (4 bytes containing IVAL 4).
9498 * They seem to have no effect. Bug #3212. JRA.
9501 if (total_data && (total_data != 4)) {
9502 /* Any data in this call is an EA list. */
9503 if (total_data < 10) {
9504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9508 if (IVAL(pdata,0) > total_data) {
9509 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9510 IVAL(pdata,0), (unsigned int)total_data));
9511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9515 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9522 if (!lp_ea_support(SNUM(conn))) {
9523 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9527 /* If total_data == 4 Windows doesn't care what values
9528 * are placed in that field, it just ignores them.
9529 * The System i QNTC IBM SMB client puts bad values here,
9530 * so ignore them. */
9532 status = create_directory(conn, req, smb_dname);
9534 if (!NT_STATUS_IS_OK(status)) {
9535 reply_nterror(req, status);
9539 /* Try and set any given EA. */
9541 status = set_ea(conn, NULL, smb_dname, ea_list);
9542 if (!NT_STATUS_IS_OK(status)) {
9543 reply_nterror(req, status);
9548 /* Realloc the parameter and data sizes */
9549 *pparams = (char *)SMB_REALLOC(*pparams,2);
9550 if(*pparams == NULL) {
9551 reply_nterror(req, NT_STATUS_NO_MEMORY);
9558 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9561 TALLOC_FREE(smb_dname);
9565 /****************************************************************************
9566 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9567 We don't actually do this - we just send a null response.
9568 ****************************************************************************/
9570 static void call_trans2findnotifyfirst(connection_struct *conn,
9571 struct smb_request *req,
9572 char **pparams, int total_params,
9573 char **ppdata, int total_data,
9574 unsigned int max_data_bytes)
9576 char *params = *pparams;
9577 uint16_t info_level;
9579 if (total_params < 6) {
9580 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9584 info_level = SVAL(params,4);
9585 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9587 switch (info_level) {
9592 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9596 /* Realloc the parameter and data sizes */
9597 *pparams = (char *)SMB_REALLOC(*pparams,6);
9598 if (*pparams == NULL) {
9599 reply_nterror(req, NT_STATUS_NO_MEMORY);
9604 SSVAL(params,0,fnf_handle);
9605 SSVAL(params,2,0); /* No changes */
9606 SSVAL(params,4,0); /* No EA errors */
9613 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9618 /****************************************************************************
9619 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9620 changes). Currently this does nothing.
9621 ****************************************************************************/
9623 static void call_trans2findnotifynext(connection_struct *conn,
9624 struct smb_request *req,
9625 char **pparams, int total_params,
9626 char **ppdata, int total_data,
9627 unsigned int max_data_bytes)
9629 char *params = *pparams;
9631 DEBUG(3,("call_trans2findnotifynext\n"));
9633 /* Realloc the parameter and data sizes */
9634 *pparams = (char *)SMB_REALLOC(*pparams,4);
9635 if (*pparams == NULL) {
9636 reply_nterror(req, NT_STATUS_NO_MEMORY);
9641 SSVAL(params,0,0); /* No changes */
9642 SSVAL(params,2,0); /* No EA errors */
9644 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9649 /****************************************************************************
9650 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9651 ****************************************************************************/
9653 static void call_trans2getdfsreferral(connection_struct *conn,
9654 struct smb_request *req,
9655 char **pparams, int total_params,
9656 char **ppdata, int total_data,
9657 unsigned int max_data_bytes)
9659 char *params = *pparams;
9660 char *pathname = NULL;
9662 int max_referral_level;
9663 NTSTATUS status = NT_STATUS_OK;
9664 TALLOC_CTX *ctx = talloc_tos();
9666 DEBUG(10,("call_trans2getdfsreferral\n"));
9668 if (total_params < 3) {
9669 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9673 max_referral_level = SVAL(params,0);
9675 if(!lp_host_msdfs()) {
9676 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9680 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9681 total_params - 2, STR_TERMINATE);
9683 reply_nterror(req, NT_STATUS_NOT_FOUND);
9686 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9687 ppdata,&status)) < 0) {
9688 reply_nterror(req, status);
9692 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9693 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9694 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9699 #define LMCAT_SPL 0x53
9700 #define LMFUNC_GETJOBID 0x60
9702 /****************************************************************************
9703 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9704 ****************************************************************************/
9706 static void call_trans2ioctl(connection_struct *conn,
9707 struct smb_request *req,
9708 char **pparams, int total_params,
9709 char **ppdata, int total_data,
9710 unsigned int max_data_bytes)
9712 char *pdata = *ppdata;
9713 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9717 /* check for an invalid fid before proceeding */
9720 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9724 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9725 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9726 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9727 if (*ppdata == NULL) {
9728 reply_nterror(req, NT_STATUS_NO_MEMORY);
9733 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9734 CAN ACCEPT THIS IN UNICODE. JRA. */
9737 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9739 status = srvstr_push(pdata, req->flags2, pdata + 2,
9740 lp_netbios_name(), 15,
9741 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9742 if (!NT_STATUS_IS_OK(status)) {
9743 reply_nterror(req, status);
9746 status = srvstr_push(pdata, req->flags2, pdata+18,
9747 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9748 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9749 if (!NT_STATUS_IS_OK(status)) {
9750 reply_nterror(req, status);
9753 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9758 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9759 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9762 /****************************************************************************
9763 Reply to a SMBfindclose (stop trans2 directory search).
9764 ****************************************************************************/
9766 void reply_findclose(struct smb_request *req)
9769 struct smbd_server_connection *sconn = req->sconn;
9770 files_struct *fsp = NULL;
9772 START_PROFILE(SMBfindclose);
9775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9776 END_PROFILE(SMBfindclose);
9780 dptr_num = SVALS(req->vwv+0, 0);
9782 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9785 * OS/2 seems to use -1 to indicate "close all directories"
9786 * This has to mean on this specific connection struct.
9788 if (dptr_num == -1) {
9789 dptr_closecnum(req->conn);
9791 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9794 close_file(NULL, fsp, NORMAL_CLOSE);
9799 reply_outbuf(req, 0, 0);
9801 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9803 END_PROFILE(SMBfindclose);
9807 /****************************************************************************
9808 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9809 ****************************************************************************/
9811 void reply_findnclose(struct smb_request *req)
9815 START_PROFILE(SMBfindnclose);
9818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9819 END_PROFILE(SMBfindnclose);
9823 dptr_num = SVAL(req->vwv+0, 0);
9825 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9827 /* We never give out valid handles for a
9828 findnotifyfirst - so any dptr_num is ok here.
9831 reply_outbuf(req, 0, 0);
9833 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9835 END_PROFILE(SMBfindnclose);
9839 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9840 struct trans_state *state)
9842 if (get_Protocol() >= PROTOCOL_NT1) {
9843 req->flags2 |= 0x40; /* IS_LONG_NAME */
9844 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9847 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9848 if (state->call != TRANSACT2_QFSINFO &&
9849 state->call != TRANSACT2_SETFSINFO) {
9850 DEBUG(0,("handle_trans2: encryption required "
9852 (unsigned int)state->call));
9853 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9858 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9860 /* Now we must call the relevant TRANS2 function */
9861 switch(state->call) {
9862 case TRANSACT2_OPEN:
9864 START_PROFILE(Trans2_open);
9865 call_trans2open(conn, req,
9866 &state->param, state->total_param,
9867 &state->data, state->total_data,
9868 state->max_data_return);
9869 END_PROFILE(Trans2_open);
9873 case TRANSACT2_FINDFIRST:
9875 START_PROFILE(Trans2_findfirst);
9876 call_trans2findfirst(conn, req,
9877 &state->param, state->total_param,
9878 &state->data, state->total_data,
9879 state->max_data_return);
9880 END_PROFILE(Trans2_findfirst);
9884 case TRANSACT2_FINDNEXT:
9886 START_PROFILE(Trans2_findnext);
9887 call_trans2findnext(conn, req,
9888 &state->param, state->total_param,
9889 &state->data, state->total_data,
9890 state->max_data_return);
9891 END_PROFILE(Trans2_findnext);
9895 case TRANSACT2_QFSINFO:
9897 START_PROFILE(Trans2_qfsinfo);
9898 call_trans2qfsinfo(conn, req,
9899 &state->param, state->total_param,
9900 &state->data, state->total_data,
9901 state->max_data_return);
9902 END_PROFILE(Trans2_qfsinfo);
9906 case TRANSACT2_SETFSINFO:
9908 START_PROFILE(Trans2_setfsinfo);
9909 call_trans2setfsinfo(conn, req,
9910 &state->param, state->total_param,
9911 &state->data, state->total_data,
9912 state->max_data_return);
9913 END_PROFILE(Trans2_setfsinfo);
9917 case TRANSACT2_QPATHINFO:
9918 case TRANSACT2_QFILEINFO:
9920 START_PROFILE(Trans2_qpathinfo);
9921 call_trans2qfilepathinfo(conn, req, state->call,
9922 &state->param, state->total_param,
9923 &state->data, state->total_data,
9924 state->max_data_return);
9925 END_PROFILE(Trans2_qpathinfo);
9929 case TRANSACT2_SETPATHINFO:
9930 case TRANSACT2_SETFILEINFO:
9932 START_PROFILE(Trans2_setpathinfo);
9933 call_trans2setfilepathinfo(conn, req, state->call,
9934 &state->param, state->total_param,
9935 &state->data, state->total_data,
9936 state->max_data_return);
9937 END_PROFILE(Trans2_setpathinfo);
9941 case TRANSACT2_FINDNOTIFYFIRST:
9943 START_PROFILE(Trans2_findnotifyfirst);
9944 call_trans2findnotifyfirst(conn, req,
9945 &state->param, state->total_param,
9946 &state->data, state->total_data,
9947 state->max_data_return);
9948 END_PROFILE(Trans2_findnotifyfirst);
9952 case TRANSACT2_FINDNOTIFYNEXT:
9954 START_PROFILE(Trans2_findnotifynext);
9955 call_trans2findnotifynext(conn, req,
9956 &state->param, state->total_param,
9957 &state->data, state->total_data,
9958 state->max_data_return);
9959 END_PROFILE(Trans2_findnotifynext);
9963 case TRANSACT2_MKDIR:
9965 START_PROFILE(Trans2_mkdir);
9966 call_trans2mkdir(conn, req,
9967 &state->param, state->total_param,
9968 &state->data, state->total_data,
9969 state->max_data_return);
9970 END_PROFILE(Trans2_mkdir);
9974 case TRANSACT2_GET_DFS_REFERRAL:
9976 START_PROFILE(Trans2_get_dfs_referral);
9977 call_trans2getdfsreferral(conn, req,
9978 &state->param, state->total_param,
9979 &state->data, state->total_data,
9980 state->max_data_return);
9981 END_PROFILE(Trans2_get_dfs_referral);
9985 case TRANSACT2_IOCTL:
9987 START_PROFILE(Trans2_ioctl);
9988 call_trans2ioctl(conn, req,
9989 &state->param, state->total_param,
9990 &state->data, state->total_data,
9991 state->max_data_return);
9992 END_PROFILE(Trans2_ioctl);
9997 /* Error in request */
9998 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9999 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
10003 /****************************************************************************
10004 Reply to a SMBtrans2.
10005 ****************************************************************************/
10007 void reply_trans2(struct smb_request *req)
10009 connection_struct *conn = req->conn;
10010 unsigned int dsoff;
10011 unsigned int dscnt;
10012 unsigned int psoff;
10013 unsigned int pscnt;
10014 unsigned int tran_call;
10015 struct trans_state *state;
10018 START_PROFILE(SMBtrans2);
10020 if (req->wct < 14) {
10021 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10022 END_PROFILE(SMBtrans2);
10026 dsoff = SVAL(req->vwv+12, 0);
10027 dscnt = SVAL(req->vwv+11, 0);
10028 psoff = SVAL(req->vwv+10, 0);
10029 pscnt = SVAL(req->vwv+9, 0);
10030 tran_call = SVAL(req->vwv+14, 0);
10032 result = allow_new_trans(conn->pending_trans, req->mid);
10033 if (!NT_STATUS_IS_OK(result)) {
10034 DEBUG(2, ("Got invalid trans2 request: %s\n",
10035 nt_errstr(result)));
10036 reply_nterror(req, result);
10037 END_PROFILE(SMBtrans2);
10041 if (IS_IPC(conn)) {
10042 switch (tran_call) {
10043 /* List the allowed trans2 calls on IPC$ */
10044 case TRANSACT2_OPEN:
10045 case TRANSACT2_GET_DFS_REFERRAL:
10046 case TRANSACT2_QFILEINFO:
10047 case TRANSACT2_QFSINFO:
10048 case TRANSACT2_SETFSINFO:
10051 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10052 END_PROFILE(SMBtrans2);
10057 if ((state = talloc(conn, struct trans_state)) == NULL) {
10058 DEBUG(0, ("talloc failed\n"));
10059 reply_nterror(req, NT_STATUS_NO_MEMORY);
10060 END_PROFILE(SMBtrans2);
10064 state->cmd = SMBtrans2;
10066 state->mid = req->mid;
10067 state->vuid = req->vuid;
10068 state->setup_count = SVAL(req->vwv+13, 0);
10069 state->setup = NULL;
10070 state->total_param = SVAL(req->vwv+0, 0);
10071 state->param = NULL;
10072 state->total_data = SVAL(req->vwv+1, 0);
10073 state->data = NULL;
10074 state->max_param_return = SVAL(req->vwv+2, 0);
10075 state->max_data_return = SVAL(req->vwv+3, 0);
10076 state->max_setup_return = SVAL(req->vwv+4, 0);
10077 state->close_on_completion = BITSETW(req->vwv+5, 0);
10078 state->one_way = BITSETW(req->vwv+5, 1);
10080 state->call = tran_call;
10082 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10083 is so as a sanity check */
10084 if (state->setup_count != 1) {
10086 * Need to have rc=0 for ioctl to get job id for OS/2.
10087 * Network printing will fail if function is not successful.
10088 * Similar function in reply.c will be used if protocol
10089 * is LANMAN1.0 instead of LM1.2X002.
10090 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10091 * outbuf doesn't have to be set(only job id is used).
10093 if ( (state->setup_count == 4)
10094 && (tran_call == TRANSACT2_IOCTL)
10095 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10096 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10097 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10099 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10100 DEBUG(2,("Transaction is %d\n",tran_call));
10101 TALLOC_FREE(state);
10102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10103 END_PROFILE(SMBtrans2);
10108 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10111 if (state->total_data) {
10113 if (trans_oob(state->total_data, 0, dscnt)
10114 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10118 /* Can't use talloc here, the core routines do realloc on the
10119 * params and data. */
10120 state->data = (char *)SMB_MALLOC(state->total_data);
10121 if (state->data == NULL) {
10122 DEBUG(0,("reply_trans2: data malloc fail for %u "
10123 "bytes !\n", (unsigned int)state->total_data));
10124 TALLOC_FREE(state);
10125 reply_nterror(req, NT_STATUS_NO_MEMORY);
10126 END_PROFILE(SMBtrans2);
10130 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10133 if (state->total_param) {
10135 if (trans_oob(state->total_param, 0, pscnt)
10136 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10140 /* Can't use talloc here, the core routines do realloc on the
10141 * params and data. */
10142 state->param = (char *)SMB_MALLOC(state->total_param);
10143 if (state->param == NULL) {
10144 DEBUG(0,("reply_trans: param malloc fail for %u "
10145 "bytes !\n", (unsigned int)state->total_param));
10146 SAFE_FREE(state->data);
10147 TALLOC_FREE(state);
10148 reply_nterror(req, NT_STATUS_NO_MEMORY);
10149 END_PROFILE(SMBtrans2);
10153 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10156 state->received_data = dscnt;
10157 state->received_param = pscnt;
10159 if ((state->received_param == state->total_param) &&
10160 (state->received_data == state->total_data)) {
10162 handle_trans2(conn, req, state);
10164 SAFE_FREE(state->data);
10165 SAFE_FREE(state->param);
10166 TALLOC_FREE(state);
10167 END_PROFILE(SMBtrans2);
10171 DLIST_ADD(conn->pending_trans, state);
10173 /* We need to send an interim response then receive the rest
10174 of the parameter/data bytes */
10175 reply_outbuf(req, 0, 0);
10176 show_msg((char *)req->outbuf);
10177 END_PROFILE(SMBtrans2);
10182 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10183 SAFE_FREE(state->data);
10184 SAFE_FREE(state->param);
10185 TALLOC_FREE(state);
10186 END_PROFILE(SMBtrans2);
10187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10191 /****************************************************************************
10192 Reply to a SMBtranss2
10193 ****************************************************************************/
10195 void reply_transs2(struct smb_request *req)
10197 connection_struct *conn = req->conn;
10198 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10199 struct trans_state *state;
10201 START_PROFILE(SMBtranss2);
10203 show_msg((const char *)req->inbuf);
10205 /* Windows clients expect all replies to
10206 a transact secondary (SMBtranss2 0x33)
10207 to have a command code of transact
10208 (SMBtrans2 0x32). See bug #8989
10209 and also [MS-CIFS] section 2.2.4.47.2
10212 req->cmd = SMBtrans2;
10214 if (req->wct < 8) {
10215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10216 END_PROFILE(SMBtranss2);
10220 for (state = conn->pending_trans; state != NULL;
10221 state = state->next) {
10222 if (state->mid == req->mid) {
10227 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10228 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10229 END_PROFILE(SMBtranss2);
10233 /* Revise state->total_param and state->total_data in case they have
10234 changed downwards */
10236 if (SVAL(req->vwv+0, 0) < state->total_param)
10237 state->total_param = SVAL(req->vwv+0, 0);
10238 if (SVAL(req->vwv+1, 0) < state->total_data)
10239 state->total_data = SVAL(req->vwv+1, 0);
10241 pcnt = SVAL(req->vwv+2, 0);
10242 poff = SVAL(req->vwv+3, 0);
10243 pdisp = SVAL(req->vwv+4, 0);
10245 dcnt = SVAL(req->vwv+5, 0);
10246 doff = SVAL(req->vwv+6, 0);
10247 ddisp = SVAL(req->vwv+7, 0);
10249 state->received_param += pcnt;
10250 state->received_data += dcnt;
10252 if ((state->received_data > state->total_data) ||
10253 (state->received_param > state->total_param))
10257 if (trans_oob(state->total_param, pdisp, pcnt)
10258 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10261 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10265 if (trans_oob(state->total_data, ddisp, dcnt)
10266 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10269 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10272 if ((state->received_param < state->total_param) ||
10273 (state->received_data < state->total_data)) {
10274 END_PROFILE(SMBtranss2);
10278 handle_trans2(conn, req, state);
10280 DLIST_REMOVE(conn->pending_trans, state);
10281 SAFE_FREE(state->data);
10282 SAFE_FREE(state->param);
10283 TALLOC_FREE(state);
10285 END_PROFILE(SMBtranss2);
10290 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10291 DLIST_REMOVE(conn->pending_trans, state);
10292 SAFE_FREE(state->data);
10293 SAFE_FREE(state->param);
10294 TALLOC_FREE(state);
10295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10296 END_PROFILE(SMBtranss2);