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(
1458 reply_openerror(req, status);
1461 smb_action = FILE_WAS_OPENED;
1464 size = get_file_size_stat(&smb_fname->st);
1465 fattr = dos_mode(conn, smb_fname);
1466 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1467 inode = smb_fname->st.st_ex_ino;
1468 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1469 close_file(req, fsp, ERROR_CLOSE);
1470 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1474 /* Realloc the size of parameters and data we will return */
1475 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1476 if(*pparams == NULL ) {
1477 reply_nterror(req, NT_STATUS_NO_MEMORY);
1482 SSVAL(params,0,fsp->fnum);
1483 SSVAL(params,2,fattr);
1484 srv_put_dos_date2(params,4, mtime);
1485 SIVAL(params,8, (uint32_t)size);
1486 SSVAL(params,12,deny_mode);
1487 SSVAL(params,14,0); /* open_type - file or directory. */
1488 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1490 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1491 smb_action |= EXTENDED_OPLOCK_GRANTED;
1494 SSVAL(params,18,smb_action);
1497 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1499 SIVAL(params,20,inode);
1500 SSVAL(params,24,0); /* Padding. */
1502 uint32_t ea_size = estimate_ea_size(conn, fsp,
1504 SIVAL(params, 26, ea_size);
1506 SIVAL(params, 26, 0);
1509 /* Send the required number of replies */
1510 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1512 TALLOC_FREE(smb_fname);
1515 /*********************************************************
1516 Routine to check if a given string matches exactly.
1517 as a special case a mask of "." does NOT match. That
1518 is required for correct wildcard semantics
1519 Case can be significant or not.
1520 **********************************************************/
1522 static bool exact_match(bool has_wild,
1523 bool case_sensitive,
1527 if (mask[0] == '.' && mask[1] == 0) {
1535 if (case_sensitive) {
1536 return strcmp(str,mask)==0;
1538 return strcasecmp_m(str,mask) == 0;
1542 /****************************************************************************
1543 Return the filetype for UNIX extensions.
1544 ****************************************************************************/
1546 static uint32_t unix_filetype(mode_t mode)
1549 return UNIX_TYPE_FILE;
1550 else if(S_ISDIR(mode))
1551 return UNIX_TYPE_DIR;
1553 else if(S_ISLNK(mode))
1554 return UNIX_TYPE_SYMLINK;
1557 else if(S_ISCHR(mode))
1558 return UNIX_TYPE_CHARDEV;
1561 else if(S_ISBLK(mode))
1562 return UNIX_TYPE_BLKDEV;
1565 else if(S_ISFIFO(mode))
1566 return UNIX_TYPE_FIFO;
1569 else if(S_ISSOCK(mode))
1570 return UNIX_TYPE_SOCKET;
1573 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1574 return UNIX_TYPE_UNKNOWN;
1577 /****************************************************************************
1578 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1579 ****************************************************************************/
1581 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1583 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1584 const SMB_STRUCT_STAT *psbuf,
1586 enum perm_type ptype,
1591 if (perms == SMB_MODE_NO_CHANGE) {
1592 if (!VALID_STAT(*psbuf)) {
1593 return NT_STATUS_INVALID_PARAMETER;
1595 *ret_perms = psbuf->st_ex_mode;
1596 return NT_STATUS_OK;
1600 ret = wire_perms_to_unix(perms);
1602 if (ptype == PERM_NEW_FILE) {
1604 * "create mask"/"force create mode" are
1605 * only applied to new files, not existing ones.
1607 ret &= lp_create_mask(SNUM(conn));
1608 /* Add in force bits */
1609 ret |= lp_force_create_mode(SNUM(conn));
1610 } else if (ptype == PERM_NEW_DIR) {
1612 * "directory mask"/"force directory mode" are
1613 * only applied to new directories, not existing ones.
1615 ret &= lp_directory_mask(SNUM(conn));
1616 /* Add in force bits */
1617 ret |= lp_force_directory_mode(SNUM(conn));
1621 return NT_STATUS_OK;
1624 /****************************************************************************
1625 Needed to show the msdfs symlinks as directories. Modifies psbuf
1626 to be a directory if it's a msdfs link.
1627 ****************************************************************************/
1629 static bool check_msdfs_link(connection_struct *conn,
1630 struct smb_filename *smb_fname)
1632 int saved_errno = errno;
1633 if(lp_host_msdfs() &&
1634 lp_msdfs_root(SNUM(conn)) &&
1635 is_msdfs_link(conn, smb_fname)) {
1637 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1639 smb_fname->base_name));
1640 smb_fname->st.st_ex_mode =
1641 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1642 errno = saved_errno;
1645 errno = saved_errno;
1650 /****************************************************************************
1651 Get a level dependent lanman2 dir entry.
1652 ****************************************************************************/
1654 struct smbd_dirptr_lanman2_state {
1655 connection_struct *conn;
1656 uint32_t info_level;
1657 bool check_mangled_names;
1659 bool got_exact_match;
1662 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1668 struct smbd_dirptr_lanman2_state *state =
1669 (struct smbd_dirptr_lanman2_state *)private_data;
1671 char mangled_name[13]; /* mangled 8.3 name. */
1675 /* Mangle fname if it's an illegal name. */
1676 if (mangle_must_mangle(dname, state->conn->params)) {
1678 * Slow path - ensure we can push the original name as UCS2. If
1679 * not, then just don't return this name.
1683 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1684 uint8_t *tmp = talloc_array(talloc_tos(),
1688 status = srvstr_push(NULL,
1689 FLAGS2_UNICODE_STRINGS,
1698 if (!NT_STATUS_IS_OK(status)) {
1702 ok = name_to_8_3(dname, mangled_name,
1703 true, state->conn->params);
1707 fname = mangled_name;
1712 got_match = exact_match(state->has_wild,
1713 state->conn->case_sensitive,
1715 state->got_exact_match = got_match;
1717 got_match = mask_match(fname, mask,
1718 state->conn->case_sensitive);
1721 if(!got_match && state->check_mangled_names &&
1722 !mangle_is_8_3(fname, false, state->conn->params)) {
1724 * It turns out that NT matches wildcards against
1725 * both long *and* short names. This may explain some
1726 * of the wildcard wierdness from old DOS clients
1727 * that some people have been seeing.... JRA.
1729 /* Force the mangling into 8.3. */
1730 ok = name_to_8_3(fname, mangled_name,
1731 false, state->conn->params);
1736 got_match = exact_match(state->has_wild,
1737 state->conn->case_sensitive,
1738 mangled_name, mask);
1739 state->got_exact_match = got_match;
1741 got_match = mask_match(mangled_name, mask,
1742 state->conn->case_sensitive);
1750 *_fname = talloc_strdup(ctx, fname);
1751 if (*_fname == NULL) {
1758 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1760 struct smb_filename *smb_fname,
1764 struct smbd_dirptr_lanman2_state *state =
1765 (struct smbd_dirptr_lanman2_state *)private_data;
1766 bool ms_dfs_link = false;
1769 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1770 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1771 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1772 "Couldn't lstat [%s] (%s)\n",
1773 smb_fname_str_dbg(smb_fname),
1777 } else if (!VALID_STAT(smb_fname->st) &&
1778 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1779 /* Needed to show the msdfs symlinks as
1782 ms_dfs_link = check_msdfs_link(state->conn,
1785 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1786 "Couldn't stat [%s] (%s)\n",
1787 smb_fname_str_dbg(smb_fname),
1794 mode = dos_mode_msdfs(state->conn, smb_fname);
1795 } else if (get_dosmode) {
1796 mode = dos_mode(state->conn, smb_fname);
1803 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1804 connection_struct *conn,
1806 uint32_t info_level,
1807 struct ea_list *name_list,
1808 bool check_mangled_names,
1809 bool requires_resume_key,
1812 const struct smb_filename *smb_fname,
1813 int space_remaining,
1819 uint64_t *last_entry_off)
1821 char *p, *q, *pdata = *ppdata;
1823 uint64_t file_size = 0;
1824 uint64_t allocation_size = 0;
1825 uint64_t file_id = 0;
1827 struct timespec mdate_ts = {0};
1828 struct timespec adate_ts = {0};
1829 struct timespec cdate_ts = {0};
1830 struct timespec create_date_ts = {0};
1831 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1833 char *last_entry_ptr;
1838 struct readdir_attr_data *readdir_attr_data = NULL;
1840 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1841 file_size = get_file_size_stat(&smb_fname->st);
1843 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1845 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1846 if (!NT_STATUS_IS_OK(status)) {
1847 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1852 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1854 mdate_ts = smb_fname->st.st_ex_mtime;
1855 adate_ts = smb_fname->st.st_ex_atime;
1856 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1857 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1859 if (lp_dos_filetime_resolution(SNUM(conn))) {
1860 dos_filetime_timespec(&create_date_ts);
1861 dos_filetime_timespec(&mdate_ts);
1862 dos_filetime_timespec(&adate_ts);
1863 dos_filetime_timespec(&cdate_ts);
1866 create_date = convert_timespec_to_time_t(create_date_ts);
1867 mdate = convert_timespec_to_time_t(mdate_ts);
1868 adate = convert_timespec_to_time_t(adate_ts);
1870 /* align the record */
1871 SMB_ASSERT(align >= 1);
1873 off = (int)PTR_DIFF(pdata, base_data);
1874 pad = (off + (align-1)) & ~(align-1);
1877 if (pad && pad > space_remaining) {
1878 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1879 "for padding (wanted %u, had %d)\n",
1882 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1886 /* initialize padding to 0 */
1888 memset(pdata, 0, pad);
1890 space_remaining -= pad;
1892 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1902 switch (info_level) {
1903 case SMB_FIND_INFO_STANDARD:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1905 if(requires_resume_key) {
1909 srv_put_dos_date2(p,0,create_date);
1910 srv_put_dos_date2(p,4,adate);
1911 srv_put_dos_date2(p,8,mdate);
1912 SIVAL(p,12,(uint32_t)file_size);
1913 SIVAL(p,16,(uint32_t)allocation_size);
1917 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1918 p += ucs2_align(base_data, p, 0);
1920 status = srvstr_push(base_data, flags2, p,
1921 fname, PTR_DIFF(end_data, p),
1922 STR_TERMINATE, &len);
1923 if (!NT_STATUS_IS_OK(status)) {
1926 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1928 SCVAL(nameptr, -1, len - 2);
1930 SCVAL(nameptr, -1, 0);
1934 SCVAL(nameptr, -1, len - 1);
1936 SCVAL(nameptr, -1, 0);
1942 case SMB_FIND_EA_SIZE:
1943 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1944 if (requires_resume_key) {
1948 srv_put_dos_date2(p,0,create_date);
1949 srv_put_dos_date2(p,4,adate);
1950 srv_put_dos_date2(p,8,mdate);
1951 SIVAL(p,12,(uint32_t)file_size);
1952 SIVAL(p,16,(uint32_t)allocation_size);
1955 unsigned int ea_size = estimate_ea_size(conn, NULL,
1957 SIVAL(p,22,ea_size); /* Extended attributes */
1961 status = srvstr_push(base_data, flags2,
1962 p, fname, PTR_DIFF(end_data, p),
1963 STR_TERMINATE | STR_NOALIGN, &len);
1964 if (!NT_STATUS_IS_OK(status)) {
1967 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1980 SCVAL(nameptr,0,len);
1982 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1985 case SMB_FIND_EA_LIST:
1987 struct ea_list *file_list = NULL;
1990 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1992 return NT_STATUS_INVALID_PARAMETER;
1994 if (requires_resume_key) {
1998 srv_put_dos_date2(p,0,create_date);
1999 srv_put_dos_date2(p,4,adate);
2000 srv_put_dos_date2(p,8,mdate);
2001 SIVAL(p,12,(uint32_t)file_size);
2002 SIVAL(p,16,(uint32_t)allocation_size);
2004 p += 22; /* p now points to the EA area. */
2006 status = get_ea_list_from_file(ctx, conn, NULL,
2008 &ea_len, &file_list);
2009 if (!NT_STATUS_IS_OK(status)) {
2012 name_list = ea_list_union(name_list, file_list, &ea_len);
2014 /* We need to determine if this entry will fit in the space available. */
2015 /* Max string size is 255 bytes. */
2016 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2017 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2018 "(wanted %u, had %d)\n",
2019 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2021 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2024 /* Push the ea_data followed by the name. */
2025 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2027 status = srvstr_push(base_data, flags2,
2028 p + 1, fname, PTR_DIFF(end_data, p+1),
2029 STR_TERMINATE | STR_NOALIGN, &len);
2030 if (!NT_STATUS_IS_OK(status)) {
2033 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2046 SCVAL(nameptr,0,len);
2048 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2052 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2053 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2054 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2056 SIVAL(p,0,reskey); p += 4;
2057 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2058 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2059 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2060 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2061 SOFF_T(p,0,file_size); p += 8;
2062 SOFF_T(p,0,allocation_size); p += 8;
2063 SIVAL(p,0,mode); p += 4;
2064 q = p; p += 4; /* q is placeholder for name length. */
2065 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2066 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2068 unsigned int ea_size = estimate_ea_size(conn, NULL,
2070 SIVAL(p,0,ea_size); /* Extended attributes */
2073 /* Clear the short name buffer. This is
2074 * IMPORTANT as not doing so will trigger
2075 * a Win2k client bug. JRA.
2077 if (!was_8_3 && check_mangled_names) {
2078 char mangled_name[13]; /* mangled 8.3 name. */
2079 if (!name_to_8_3(fname,mangled_name,True,
2081 /* Error - mangle failed ! */
2082 memset(mangled_name,'\0',12);
2084 mangled_name[12] = 0;
2085 status = srvstr_push(base_data, flags2,
2086 p+2, mangled_name, 24,
2087 STR_UPPER|STR_UNICODE, &len);
2088 if (!NT_STATUS_IS_OK(status)) {
2092 memset(p + 2 + len,'\0',24 - len);
2099 status = srvstr_push(base_data, flags2, p,
2100 fname, PTR_DIFF(end_data, p),
2101 STR_TERMINATE_ASCII, &len);
2102 if (!NT_STATUS_IS_OK(status)) {
2108 len = PTR_DIFF(p, pdata);
2109 pad = (len + (align-1)) & ~(align-1);
2111 * offset to the next entry, the caller
2112 * will overwrite it for the last entry
2113 * that's why we always include the padding
2117 * set padding to zero
2120 memset(p, 0, pad - len);
2127 case SMB_FIND_FILE_DIRECTORY_INFO:
2128 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2130 SIVAL(p,0,reskey); p += 4;
2131 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2132 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2133 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2134 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2135 SOFF_T(p,0,file_size); p += 8;
2136 SOFF_T(p,0,allocation_size); p += 8;
2137 SIVAL(p,0,mode); p += 4;
2138 status = srvstr_push(base_data, flags2,
2139 p + 4, fname, PTR_DIFF(end_data, p+4),
2140 STR_TERMINATE_ASCII, &len);
2141 if (!NT_STATUS_IS_OK(status)) {
2147 len = PTR_DIFF(p, pdata);
2148 pad = (len + (align-1)) & ~(align-1);
2150 * offset to the next entry, the caller
2151 * will overwrite it for the last entry
2152 * that's why we always include the padding
2156 * set padding to zero
2159 memset(p, 0, pad - len);
2166 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2167 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2169 SIVAL(p,0,reskey); p += 4;
2170 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2171 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2172 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2173 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2174 SOFF_T(p,0,file_size); p += 8;
2175 SOFF_T(p,0,allocation_size); p += 8;
2176 SIVAL(p,0,mode); p += 4;
2177 q = p; p += 4; /* q is placeholder for name length. */
2178 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2179 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2181 unsigned int ea_size = estimate_ea_size(conn, NULL,
2183 SIVAL(p,0,ea_size); /* Extended attributes */
2186 status = srvstr_push(base_data, flags2, p,
2187 fname, PTR_DIFF(end_data, p),
2188 STR_TERMINATE_ASCII, &len);
2189 if (!NT_STATUS_IS_OK(status)) {
2195 len = PTR_DIFF(p, pdata);
2196 pad = (len + (align-1)) & ~(align-1);
2198 * offset to the next entry, the caller
2199 * will overwrite it for the last entry
2200 * that's why we always include the padding
2204 * set padding to zero
2207 memset(p, 0, pad - len);
2214 case SMB_FIND_FILE_NAMES_INFO:
2215 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2217 SIVAL(p,0,reskey); p += 4;
2219 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2220 acl on a dir (tridge) */
2221 status = srvstr_push(base_data, flags2, p,
2222 fname, PTR_DIFF(end_data, p),
2223 STR_TERMINATE_ASCII, &len);
2224 if (!NT_STATUS_IS_OK(status)) {
2230 len = PTR_DIFF(p, pdata);
2231 pad = (len + (align-1)) & ~(align-1);
2233 * offset to the next entry, the caller
2234 * will overwrite it for the last entry
2235 * that's why we always include the padding
2239 * set padding to zero
2242 memset(p, 0, pad - len);
2249 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2250 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2252 SIVAL(p,0,reskey); p += 4;
2253 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2254 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2255 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2256 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2257 SOFF_T(p,0,file_size); p += 8;
2258 SOFF_T(p,0,allocation_size); p += 8;
2259 SIVAL(p,0,mode); p += 4;
2260 q = p; p += 4; /* q is placeholder for name length. */
2261 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2262 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2264 unsigned int ea_size = estimate_ea_size(conn, NULL,
2266 SIVAL(p,0,ea_size); /* Extended attributes */
2269 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2270 SBVAL(p,0,file_id); p += 8;
2271 status = srvstr_push(base_data, flags2, p,
2272 fname, PTR_DIFF(end_data, p),
2273 STR_TERMINATE_ASCII, &len);
2274 if (!NT_STATUS_IS_OK(status)) {
2280 len = PTR_DIFF(p, pdata);
2281 pad = (len + (align-1)) & ~(align-1);
2283 * offset to the next entry, the caller
2284 * will overwrite it for the last entry
2285 * that's why we always include the padding
2289 * set padding to zero
2292 memset(p, 0, pad - len);
2299 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2300 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2301 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2303 SIVAL(p,0,reskey); p += 4;
2304 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2305 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2306 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2307 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2308 SOFF_T(p,0,file_size); p += 8;
2309 SOFF_T(p,0,allocation_size); p += 8;
2310 SIVAL(p,0,mode); p += 4;
2311 q = p; p += 4; /* q is placeholder for name length */
2312 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2313 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2314 } else if (readdir_attr_data &&
2315 readdir_attr_data->type == RDATTR_AAPL) {
2317 * OS X specific SMB2 extension negotiated via
2318 * AAPL create context: return max_access in
2321 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2323 unsigned int ea_size = estimate_ea_size(conn, NULL,
2325 SIVAL(p,0,ea_size); /* Extended attributes */
2329 if (readdir_attr_data &&
2330 readdir_attr_data->type == RDATTR_AAPL) {
2332 * OS X specific SMB2 extension negotiated via
2333 * AAPL create context: return resource fork
2334 * length and compressed FinderInfo in
2337 * According to documentation short_name_len
2338 * should be 0, but on the wire behaviour
2339 * shows its set to 24 by clients.
2343 /* Resourefork length */
2344 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2346 /* Compressed FinderInfo */
2347 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2348 } else if (!was_8_3 && check_mangled_names) {
2349 char mangled_name[13]; /* mangled 8.3 name. */
2350 if (!name_to_8_3(fname,mangled_name,True,
2352 /* Error - mangle failed ! */
2353 memset(mangled_name,'\0',12);
2355 mangled_name[12] = 0;
2356 status = srvstr_push(base_data, flags2,
2357 p+2, mangled_name, 24,
2358 STR_UPPER|STR_UNICODE, &len);
2359 if (!NT_STATUS_IS_OK(status)) {
2364 memset(p + 2 + len,'\0',24 - len);
2368 /* Clear the short name buffer. This is
2369 * IMPORTANT as not doing so will trigger
2370 * a Win2k client bug. JRA.
2377 if (readdir_attr_data &&
2378 readdir_attr_data->type == RDATTR_AAPL) {
2380 * OS X specific SMB2 extension negotiated via
2381 * AAPL create context: return UNIX mode in
2384 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2385 SSVAL(p, 0, aapl_mode);
2391 SBVAL(p,0,file_id); p += 8;
2392 status = srvstr_push(base_data, flags2, p,
2393 fname, PTR_DIFF(end_data, p),
2394 STR_TERMINATE_ASCII, &len);
2395 if (!NT_STATUS_IS_OK(status)) {
2401 len = PTR_DIFF(p, pdata);
2402 pad = (len + (align-1)) & ~(align-1);
2404 * offset to the next entry, the caller
2405 * will overwrite it for the last entry
2406 * that's why we always include the padding
2410 * set padding to zero
2413 memset(p, 0, pad - len);
2420 /* CIFS UNIX Extension. */
2422 case SMB_FIND_FILE_UNIX:
2423 case SMB_FIND_FILE_UNIX_INFO2:
2425 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2427 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2429 if (info_level == SMB_FIND_FILE_UNIX) {
2430 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2431 p = store_file_unix_basic(conn, p,
2432 NULL, &smb_fname->st);
2433 status = srvstr_push(base_data, flags2, p,
2434 fname, PTR_DIFF(end_data, p),
2435 STR_TERMINATE, &len);
2436 if (!NT_STATUS_IS_OK(status)) {
2440 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2441 p = store_file_unix_basic_info2(conn, p,
2442 NULL, &smb_fname->st);
2445 status = srvstr_push(base_data, flags2, p, fname,
2446 PTR_DIFF(end_data, p), 0, &len);
2447 if (!NT_STATUS_IS_OK(status)) {
2450 SIVAL(nameptr, 0, len);
2455 len = PTR_DIFF(p, pdata);
2456 pad = (len + (align-1)) & ~(align-1);
2458 * offset to the next entry, the caller
2459 * will overwrite it for the last entry
2460 * that's why we always include the padding
2464 * set padding to zero
2467 memset(p, 0, pad - len);
2472 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2477 return NT_STATUS_INVALID_LEVEL;
2480 if (PTR_DIFF(p,pdata) > space_remaining) {
2481 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2482 "(wanted %u, had %d)\n",
2483 (unsigned int)PTR_DIFF(p,pdata),
2485 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2488 /* Setup the last entry pointer, as an offset from base_data */
2489 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2490 /* Advance the data pointer to the next slot */
2493 return NT_STATUS_OK;
2496 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2497 connection_struct *conn,
2498 struct dptr_struct *dirptr,
2500 const char *path_mask,
2503 int requires_resume_key,
2512 int space_remaining,
2513 struct smb_filename **_smb_fname,
2514 bool *got_exact_match,
2515 int *_last_entry_off,
2516 struct ea_list *name_list,
2517 struct file_id *file_id)
2520 const char *mask = NULL;
2521 long prev_dirpos = 0;
2524 struct smb_filename *smb_fname = NULL;
2525 struct smbd_dirptr_lanman2_state state;
2527 uint64_t last_entry_off = 0;
2529 enum mangled_names_options mangled_names;
2530 bool marshall_with_83_names;
2532 mangled_names = lp_mangled_names(conn->params);
2536 state.info_level = info_level;
2537 if (mangled_names != MANGLED_NAMES_NO) {
2538 state.check_mangled_names = true;
2540 state.has_wild = dptr_has_wild(dirptr);
2541 state.got_exact_match = false;
2543 *got_exact_match = false;
2545 p = strrchr_m(path_mask,'/');
2556 ok = smbd_dirptr_get_entry(ctx,
2563 smbd_dirptr_lanman2_match_fn,
2564 smbd_dirptr_lanman2_mode_fn,
2571 return NT_STATUS_END_OF_FILE;
2574 *got_exact_match = state.got_exact_match;
2576 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2578 status = smbd_marshall_dir_entry(ctx,
2583 marshall_with_83_names,
2584 requires_resume_key,
2595 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2596 DEBUG(1,("Conversion error: illegal character: %s\n",
2597 smb_fname_str_dbg(smb_fname)));
2600 if (file_id != NULL) {
2601 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2604 if (!NT_STATUS_IS_OK(status) &&
2605 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2607 TALLOC_FREE(smb_fname);
2612 if (_smb_fname != NULL) {
2613 struct smb_filename *name = NULL;
2615 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2617 TALLOC_FREE(smb_fname);
2619 return NT_STATUS_NO_MEMORY;
2624 TALLOC_FREE(smb_fname);
2627 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2628 dptr_SeekDir(dirptr, prev_dirpos);
2632 *_last_entry_off = last_entry_off;
2633 return NT_STATUS_OK;
2636 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2637 connection_struct *conn,
2638 struct dptr_struct *dirptr,
2640 const char *path_mask,
2643 bool requires_resume_key,
2649 int space_remaining,
2650 bool *got_exact_match,
2651 int *last_entry_off,
2652 struct ea_list *name_list)
2655 const bool do_pad = true;
2657 if (info_level >= 1 && info_level <= 3) {
2658 /* No alignment on earlier info levels. */
2662 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2663 path_mask, dirtype, info_level,
2664 requires_resume_key, dont_descend, ask_sharemode,
2665 true, align, do_pad,
2666 ppdata, base_data, end_data,
2670 last_entry_off, name_list, NULL);
2673 /****************************************************************************
2674 Reply to a TRANS2_FINDFIRST.
2675 ****************************************************************************/
2677 static void call_trans2findfirst(connection_struct *conn,
2678 struct smb_request *req,
2679 char **pparams, int total_params,
2680 char **ppdata, int total_data,
2681 unsigned int max_data_bytes)
2683 /* We must be careful here that we don't return more than the
2684 allowed number of data bytes. If this means returning fewer than
2685 maxentries then so be it. We assume that the redirector has
2686 enough room for the fixed number of parameter bytes it has
2688 struct smb_filename *smb_dname = NULL;
2689 char *params = *pparams;
2690 char *pdata = *ppdata;
2694 uint16_t findfirst_flags;
2695 bool close_after_first;
2697 bool requires_resume_key;
2699 char *directory = NULL;
2702 int last_entry_off=0;
2706 bool finished = False;
2707 bool dont_descend = False;
2708 bool out_of_space = False;
2709 int space_remaining;
2710 bool mask_contains_wcard = False;
2711 struct ea_list *ea_list = NULL;
2712 NTSTATUS ntstatus = NT_STATUS_OK;
2713 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2714 struct smbd_server_connection *sconn = req->sconn;
2715 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2716 ucf_flags_from_smb_request(req);
2717 bool backup_priv = false;
2718 bool as_root = false;
2719 files_struct *fsp = NULL;
2722 if (total_params < 13) {
2723 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2727 dirtype = SVAL(params,0);
2728 maxentries = SVAL(params,2);
2729 findfirst_flags = SVAL(params,4);
2730 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2731 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2732 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2733 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2734 security_token_has_privilege(get_current_nttok(conn),
2737 info_level = SVAL(params,6);
2739 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2740 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2741 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2743 info_level, max_data_bytes));
2746 /* W2K3 seems to treat zero as 1. */
2750 switch (info_level) {
2751 case SMB_FIND_INFO_STANDARD:
2752 case SMB_FIND_EA_SIZE:
2753 case SMB_FIND_EA_LIST:
2754 case SMB_FIND_FILE_DIRECTORY_INFO:
2755 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2756 case SMB_FIND_FILE_NAMES_INFO:
2757 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2758 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2759 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2761 case SMB_FIND_FILE_UNIX:
2762 case SMB_FIND_FILE_UNIX_INFO2:
2763 /* Always use filesystem for UNIX mtime query. */
2764 ask_sharemode = false;
2765 if (!lp_unix_extensions()) {
2766 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2769 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2772 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2776 if (req->posix_pathnames) {
2777 srvstr_get_path_wcard_posix(talloc_tos(),
2785 &mask_contains_wcard);
2787 srvstr_get_path_wcard(talloc_tos(),
2795 &mask_contains_wcard);
2797 if (!NT_STATUS_IS_OK(ntstatus)) {
2798 reply_nterror(req, ntstatus);
2805 ntstatus = filename_convert_with_privilege(talloc_tos(),
2810 &mask_contains_wcard,
2813 ntstatus = filename_convert(talloc_tos(), conn,
2817 &mask_contains_wcard,
2821 if (!NT_STATUS_IS_OK(ntstatus)) {
2822 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2823 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2824 ERRSRV, ERRbadpath);
2827 reply_nterror(req, ntstatus);
2831 mask = smb_dname->original_lcomp;
2833 directory = smb_dname->base_name;
2835 p = strrchr_m(directory,'/');
2837 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2838 if((directory[0] == '.') && (directory[1] == '\0')) {
2839 mask = talloc_strdup(talloc_tos(),"*");
2841 reply_nterror(req, NT_STATUS_NO_MEMORY);
2844 mask_contains_wcard = True;
2850 if (p == NULL || p == directory) {
2851 /* Ensure we don't have a directory name of "". */
2852 directory = talloc_strdup(talloc_tos(), ".");
2854 reply_nterror(req, NT_STATUS_NO_MEMORY);
2857 /* Ensure smb_dname->base_name matches. */
2858 smb_dname->base_name = directory;
2861 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2863 if (info_level == SMB_FIND_EA_LIST) {
2866 if (total_data < 4) {
2867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2871 ea_size = IVAL(pdata,0);
2872 if (ea_size != total_data) {
2873 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2874 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2879 if (!lp_ea_support(SNUM(conn))) {
2880 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2884 /* Pull out the list of names. */
2885 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2892 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2893 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2897 *ppdata = (char *)SMB_REALLOC(
2898 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2899 if(*ppdata == NULL ) {
2900 reply_nterror(req, NT_STATUS_NO_MEMORY);
2904 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2906 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2909 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2910 /* Realloc the params space */
2911 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2912 if (*pparams == NULL) {
2913 reply_nterror(req, NT_STATUS_NO_MEMORY);
2919 * As we've cut off the last component from
2920 * smb_fname we need to re-stat smb_dname
2921 * so FILE_OPEN disposition knows the directory
2924 if (req->posix_pathnames) {
2925 ret = SMB_VFS_LSTAT(conn, smb_dname);
2927 ret = SMB_VFS_STAT(conn, smb_dname);
2931 ntstatus = map_nt_error_from_unix(errno);
2932 reply_nterror(req, ntstatus);
2937 * Open an fsp on this directory for the dptr.
2939 ntstatus = SMB_VFS_CREATE_FILE(
2942 0, /* root_dir_fid */
2943 smb_dname, /* dname */
2944 FILE_LIST_DIRECTORY, /* access_mask */
2946 FILE_SHARE_WRITE, /* share_access */
2947 FILE_OPEN, /* create_disposition*/
2948 FILE_DIRECTORY_FILE, /* create_options */
2949 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2950 NO_OPLOCK, /* oplock_request */
2952 0, /* allocation_size */
2953 0, /* private_flags */
2958 NULL, /* in_context */
2959 NULL);/* out_context */
2961 if (!NT_STATUS_IS_OK(ntstatus)) {
2962 DBG_ERR("failed to open directory %s\n",
2963 smb_fname_str_dbg(smb_dname));
2964 reply_nterror(req, ntstatus);
2968 /* Save the wildcard match and attribs we are using on this directory -
2969 needed as lanman2 assumes these are being saved between calls */
2971 ntstatus = dptr_create(conn,
2979 mask_contains_wcard,
2983 if (!NT_STATUS_IS_OK(ntstatus)) {
2985 * Use NULL here for the first parameter (req)
2986 * as this is not a client visible handle so
2987 * can'tbe part of an SMB1 chain.
2989 close_file(NULL, fsp, NORMAL_CLOSE);
2991 reply_nterror(req, ntstatus);
2996 /* Remember this in case we have
2997 to do a findnext. */
2998 dptr_set_priv(fsp->dptr);
3001 dptr_num = dptr_dnum(fsp->dptr);
3002 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
3004 /* We don't need to check for VOL here as this is returned by
3005 a different TRANS2 call. */
3007 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3008 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
3009 if (in_list(directory,
3010 lp_dont_descend(talloc_tos(), SNUM(conn)),
3011 conn->case_sensitive)) {
3012 dont_descend = True;
3016 space_remaining = max_data_bytes;
3017 out_of_space = False;
3019 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
3020 bool got_exact_match = False;
3022 /* this is a heuristic to avoid seeking the dirptr except when
3023 absolutely necessary. It allows for a filename of about 40 chars */
3024 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3025 out_of_space = True;
3028 ntstatus = get_lanman2_dir_entry(talloc_tos(),
3032 mask,dirtype,info_level,
3033 requires_resume_key,dont_descend,
3038 &last_entry_off, ea_list);
3039 if (NT_STATUS_EQUAL(ntstatus,
3040 NT_STATUS_ILLEGAL_CHARACTER)) {
3042 * Bad character conversion on name. Ignore this
3047 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3048 out_of_space = true;
3050 finished = !NT_STATUS_IS_OK(ntstatus);
3054 if (!finished && !out_of_space)
3058 * As an optimisation if we know we aren't looking
3059 * for a wildcard name (ie. the name matches the wildcard exactly)
3060 * then we can finish on any (first) match.
3061 * This speeds up large directory searches. JRA.
3067 /* Ensure space_remaining never goes -ve. */
3068 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3069 space_remaining = 0;
3070 out_of_space = true;
3072 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3076 /* Check if we can close the dirptr */
3077 if(close_after_first || (finished && close_if_end)) {
3078 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3080 close_file(NULL, fsp, NORMAL_CLOSE);
3085 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3086 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3087 * the protocol level is less than NT1. Tested with smbclient. JRA.
3088 * This should fix the OS/2 client bug #2335.
3091 if(numentries == 0) {
3094 * We may have already closed the file in the
3095 * close_after_first or finished case above.
3098 close_file(NULL, fsp, NORMAL_CLOSE);
3101 if (get_Protocol() < PROTOCOL_NT1) {
3102 reply_force_doserror(req, ERRDOS, ERRnofiles);
3105 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3106 ERRDOS, ERRbadfile);
3111 /* At this point pdata points to numentries directory entries. */
3113 /* Set up the return parameter block */
3114 SSVAL(params,0,dptr_num);
3115 SSVAL(params,2,numentries);
3116 SSVAL(params,4,finished);
3117 SSVAL(params,6,0); /* Never an EA error */
3118 SSVAL(params,8,last_entry_off);
3120 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3123 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3124 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3126 reply_nterror(req, NT_STATUS_NO_MEMORY);
3130 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3131 smb_fn_name(req->cmd),
3132 mask, directory, dirtype, numentries ) );
3135 * Force a name mangle here to ensure that the
3136 * mask as an 8.3 name is top of the mangled cache.
3137 * The reasons for this are subtle. Don't remove
3138 * this code unless you know what you are doing
3139 * (see PR#13758). JRA.
3142 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3143 char mangled_name[13];
3144 name_to_8_3(mask, mangled_name, True, conn->params);
3152 TALLOC_FREE(smb_dname);
3156 /****************************************************************************
3157 Reply to a TRANS2_FINDNEXT.
3158 ****************************************************************************/
3160 static void call_trans2findnext(connection_struct *conn,
3161 struct smb_request *req,
3162 char **pparams, int total_params,
3163 char **ppdata, int total_data,
3164 unsigned int max_data_bytes)
3166 /* We must be careful here that we don't return more than the
3167 allowed number of data bytes. If this means returning fewer than
3168 maxentries then so be it. We assume that the redirector has
3169 enough room for the fixed number of parameter bytes it has
3171 char *params = *pparams;
3172 char *pdata = *ppdata;
3176 uint16_t info_level;
3177 uint32_t resume_key;
3178 uint16_t findnext_flags;
3179 bool close_after_request;
3181 bool requires_resume_key;
3183 bool mask_contains_wcard = False;
3184 char *resume_name = NULL;
3185 const char *mask = NULL;
3186 const char *directory = NULL;
3190 int i, last_entry_off=0;
3191 bool finished = False;
3192 bool dont_descend = False;
3193 bool out_of_space = False;
3194 int space_remaining;
3195 struct ea_list *ea_list = NULL;
3196 NTSTATUS ntstatus = NT_STATUS_OK;
3197 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3198 TALLOC_CTX *ctx = talloc_tos();
3199 struct smbd_server_connection *sconn = req->sconn;
3200 bool backup_priv = false;
3201 bool as_root = false;
3202 files_struct *fsp = NULL;
3204 if (total_params < 13) {
3205 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3209 dptr_num = SVAL(params,0);
3210 maxentries = SVAL(params,2);
3211 info_level = SVAL(params,4);
3212 resume_key = IVAL(params,6);
3213 findnext_flags = SVAL(params,10);
3214 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3215 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3216 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3217 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3219 if (!continue_bit) {
3220 /* We only need resume_name if continue_bit is zero. */
3221 if (req->posix_pathnames) {
3222 srvstr_get_path_wcard_posix(ctx,
3230 &mask_contains_wcard);
3232 srvstr_get_path_wcard(ctx,
3240 &mask_contains_wcard);
3242 if (!NT_STATUS_IS_OK(ntstatus)) {
3243 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3244 complain (it thinks we're asking for the directory above the shared
3245 path or an invalid name). Catch this as the resume name is only compared, never used in
3246 a file access. JRA. */
3247 srvstr_pull_talloc(ctx, params, req->flags2,
3248 &resume_name, params+12,
3252 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3253 reply_nterror(req, ntstatus);
3259 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3260 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3261 resume_key = %d resume name = %s continue=%d level = %d\n",
3262 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3263 requires_resume_key, resume_key,
3264 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3267 /* W2K3 seems to treat zero as 1. */
3271 switch (info_level) {
3272 case SMB_FIND_INFO_STANDARD:
3273 case SMB_FIND_EA_SIZE:
3274 case SMB_FIND_EA_LIST:
3275 case SMB_FIND_FILE_DIRECTORY_INFO:
3276 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3277 case SMB_FIND_FILE_NAMES_INFO:
3278 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3279 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3280 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3282 case SMB_FIND_FILE_UNIX:
3283 case SMB_FIND_FILE_UNIX_INFO2:
3284 /* Always use filesystem for UNIX mtime query. */
3285 ask_sharemode = false;
3286 if (!lp_unix_extensions()) {
3287 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3292 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3296 if (info_level == SMB_FIND_EA_LIST) {
3299 if (total_data < 4) {
3300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3304 ea_size = IVAL(pdata,0);
3305 if (ea_size != total_data) {
3306 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3307 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3312 if (!lp_ea_support(SNUM(conn))) {
3313 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3317 /* Pull out the list of names. */
3318 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3325 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3330 *ppdata = (char *)SMB_REALLOC(
3331 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3332 if(*ppdata == NULL) {
3333 reply_nterror(req, NT_STATUS_NO_MEMORY);
3338 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3341 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3344 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3345 /* Realloc the params space */
3346 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3347 if(*pparams == NULL ) {
3348 reply_nterror(req, NT_STATUS_NO_MEMORY);
3354 /* Check that the dptr is valid */
3355 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3357 reply_nterror(req, STATUS_NO_MORE_FILES);
3361 directory = dptr_path(sconn, dptr_num);
3363 /* Get the wildcard mask from the dptr */
3364 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3365 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3366 reply_nterror(req, STATUS_NO_MORE_FILES);
3370 /* Get the attr mask from the dptr */
3371 dirtype = dptr_attr(sconn, dptr_num);
3373 backup_priv = dptr_get_priv(fsp->dptr);
3375 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3376 "backup_priv = %d\n",
3377 dptr_num, mask, dirtype,
3379 dptr_TellDir(fsp->dptr),
3382 /* We don't need to check for VOL here as this is returned by
3383 a different TRANS2 call. */
3385 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3386 directory,lp_dont_descend(ctx, SNUM(conn))));
3387 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3388 dont_descend = True;
3391 space_remaining = max_data_bytes;
3392 out_of_space = False;
3400 * Seek to the correct position. We no longer use the resume key but
3401 * depend on the last file name instead.
3404 if(!continue_bit && resume_name && *resume_name) {
3407 long current_pos = 0;
3409 * Remember, name_to_8_3 is called by
3410 * get_lanman2_dir_entry(), so the resume name
3411 * could be mangled. Ensure we check the unmangled name.
3414 if (mangle_is_mangled(resume_name, conn->params)) {
3415 char *new_resume_name = NULL;
3416 mangle_lookup_name_from_8_3(ctx,
3420 if (new_resume_name) {
3421 resume_name = new_resume_name;
3426 * Fix for NT redirector problem triggered by resume key indexes
3427 * changing between directory scans. We now return a resume key of 0
3428 * and instead look for the filename to continue from (also given
3429 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3430 * findfirst/findnext (as is usual) then the directory pointer
3431 * should already be at the correct place.
3434 finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
3435 } /* end if resume_name && !continue_bit */
3437 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3438 bool got_exact_match = False;
3440 /* this is a heuristic to avoid seeking the fsp->dptr except when
3441 absolutely necessary. It allows for a filename of about 40 chars */
3442 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3443 out_of_space = True;
3446 ntstatus = get_lanman2_dir_entry(ctx,
3450 mask,dirtype,info_level,
3451 requires_resume_key,dont_descend,
3456 &last_entry_off, ea_list);
3457 if (NT_STATUS_EQUAL(ntstatus,
3458 NT_STATUS_ILLEGAL_CHARACTER)) {
3460 * Bad character conversion on name. Ignore this
3465 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3466 out_of_space = true;
3468 finished = !NT_STATUS_IS_OK(ntstatus);
3472 if (!finished && !out_of_space)
3476 * As an optimisation if we know we aren't looking
3477 * for a wildcard name (ie. the name matches the wildcard exactly)
3478 * then we can finish on any (first) match.
3479 * This speeds up large directory searches. JRA.
3485 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3488 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3489 smb_fn_name(req->cmd),
3490 mask, directory, dirtype, numentries ) );
3492 /* Check if we can close the fsp->dptr */
3493 if(close_after_request || (finished && close_if_end)) {
3494 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3495 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3496 close_file(NULL, fsp, NORMAL_CLOSE);
3504 /* Set up the return parameter block */
3505 SSVAL(params,0,numentries);
3506 SSVAL(params,2,finished);
3507 SSVAL(params,4,0); /* Never an EA error */
3508 SSVAL(params,6,last_entry_off);
3510 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3516 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3518 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3522 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3524 SMB_ASSERT(extended_info != NULL);
3526 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3527 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3528 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3529 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3530 #ifdef SAMBA_VERSION_REVISION
3531 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3533 extended_info->samba_subversion = 0;
3534 #ifdef SAMBA_VERSION_RC_RELEASE
3535 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3537 #ifdef SAMBA_VERSION_PRE_RELEASE
3538 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3541 #ifdef SAMBA_VERSION_VENDOR_PATCH
3542 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3544 extended_info->samba_gitcommitdate = 0;
3545 #ifdef SAMBA_VERSION_COMMIT_TIME
3546 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3549 memset(extended_info->samba_version_string, 0,
3550 sizeof(extended_info->samba_version_string));
3552 snprintf (extended_info->samba_version_string,
3553 sizeof(extended_info->samba_version_string),
3554 "%s", samba_version_string());
3557 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3558 connection_struct *conn,
3559 TALLOC_CTX *mem_ctx,
3560 uint16_t info_level,
3562 unsigned int max_data_bytes,
3563 size_t *fixed_portion,
3564 struct smb_filename *fname,
3568 char *pdata, *end_data;
3571 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3572 int snum = SNUM(conn);
3573 const char *fstype = lp_fstype(SNUM(conn));
3574 const char *filename = NULL;
3575 const uint64_t bytes_per_sector = 512;
3576 uint32_t additional_flags = 0;
3577 struct smb_filename smb_fname;
3579 NTSTATUS status = NT_STATUS_OK;
3582 if (fname == NULL || fname->base_name == NULL) {
3585 filename = fname->base_name;
3589 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3590 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3591 "info level (0x%x) on IPC$.\n",
3592 (unsigned int)info_level));
3593 return NT_STATUS_ACCESS_DENIED;
3597 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3599 ZERO_STRUCT(smb_fname);
3600 smb_fname.base_name = discard_const_p(char, filename);
3602 if(info_level != SMB_FS_QUOTA_INFORMATION
3603 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3604 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3605 return map_nt_error_from_unix(errno);
3610 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3611 return NT_STATUS_INVALID_PARAMETER;
3614 *ppdata = (char *)SMB_REALLOC(
3615 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3616 if (*ppdata == NULL) {
3617 return NT_STATUS_NO_MEMORY;
3621 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3622 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3626 switch (info_level) {
3627 case SMB_INFO_ALLOCATION:
3629 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3631 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3633 if (df_ret == (uint64_t)-1) {
3634 return map_nt_error_from_unix(errno);
3637 block_size = lp_block_size(snum);
3638 if (bsize < block_size) {
3639 uint64_t factor = block_size/bsize;
3644 if (bsize > block_size) {
3645 uint64_t factor = bsize/block_size;
3650 sectors_per_unit = bsize/bytes_per_sector;
3652 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3653 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3654 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3657 * For large drives, return max values and not modulo.
3659 dsize = MIN(dsize, UINT32_MAX);
3660 dfree = MIN(dfree, UINT32_MAX);
3662 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3663 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3664 SIVAL(pdata,l1_cUnit,dsize);
3665 SIVAL(pdata,l1_cUnitAvail,dfree);
3666 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3670 case SMB_INFO_VOLUME:
3671 /* Return volume name */
3673 * Add volume serial number - hash of a combination of
3674 * the called hostname and the service name.
3676 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3678 * Win2k3 and previous mess this up by sending a name length
3679 * one byte short. I believe only older clients (OS/2 Win9x) use
3680 * this call so try fixing this by adding a terminating null to
3681 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3683 status = srvstr_push(
3685 pdata+l2_vol_szVolLabel, vname,
3686 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3687 STR_NOALIGN|STR_TERMINATE, &len);
3688 if (!NT_STATUS_IS_OK(status)) {
3691 SCVAL(pdata,l2_vol_cch,len);
3692 data_len = l2_vol_szVolLabel + len;
3693 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3694 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3695 (unsigned)len, vname));
3698 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3699 case SMB_FS_ATTRIBUTE_INFORMATION:
3701 additional_flags = 0;
3702 #if defined(HAVE_SYS_QUOTAS)
3703 additional_flags |= FILE_VOLUME_QUOTAS;
3706 if(lp_nt_acl_support(SNUM(conn))) {
3707 additional_flags |= FILE_PERSISTENT_ACLS;
3710 /* Capabilities are filled in at connection time through STATVFS call */
3711 additional_flags |= conn->fs_capabilities;
3712 additional_flags |= lp_parm_int(conn->params->service,
3713 "share", "fake_fscaps",
3716 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3717 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3718 additional_flags); /* FS ATTRIBUTES */
3720 SIVAL(pdata,4,255); /* Max filename component length */
3721 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3722 and will think we can't do long filenames */
3723 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3724 PTR_DIFF(end_data, pdata+12),
3726 if (!NT_STATUS_IS_OK(status)) {
3730 data_len = 12 + len;
3731 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3732 /* the client only requested a portion of the
3734 data_len = max_data_bytes;
3735 status = STATUS_BUFFER_OVERFLOW;
3737 *fixed_portion = 16;
3740 case SMB_QUERY_FS_LABEL_INFO:
3741 case SMB_FS_LABEL_INFORMATION:
3742 status = srvstr_push(pdata, flags2, pdata+4, vname,
3743 PTR_DIFF(end_data, pdata+4), 0, &len);
3744 if (!NT_STATUS_IS_OK(status)) {
3751 case SMB_QUERY_FS_VOLUME_INFO:
3752 case SMB_FS_VOLUME_INFORMATION:
3755 * Add volume serial number - hash of a combination of
3756 * the called hostname and the service name.
3758 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3759 (str_checksum(get_local_machine_name())<<16));
3761 /* Max label len is 32 characters. */
3762 status = srvstr_push(pdata, flags2, pdata+18, vname,
3763 PTR_DIFF(end_data, pdata+18),
3765 if (!NT_STATUS_IS_OK(status)) {
3768 SIVAL(pdata,12,len);
3771 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3772 (int)strlen(vname),vname,
3773 lp_servicename(talloc_tos(), snum)));
3774 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3775 /* the client only requested a portion of the
3777 data_len = max_data_bytes;
3778 status = STATUS_BUFFER_OVERFLOW;
3780 *fixed_portion = 24;
3783 case SMB_QUERY_FS_SIZE_INFO:
3784 case SMB_FS_SIZE_INFORMATION:
3786 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3788 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3790 if (df_ret == (uint64_t)-1) {
3791 return map_nt_error_from_unix(errno);
3793 block_size = lp_block_size(snum);
3794 if (bsize < block_size) {
3795 uint64_t factor = block_size/bsize;
3800 if (bsize > block_size) {
3801 uint64_t factor = bsize/block_size;
3806 sectors_per_unit = bsize/bytes_per_sector;
3807 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3808 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3809 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3810 SBIG_UINT(pdata,0,dsize);
3811 SBIG_UINT(pdata,8,dfree);
3812 SIVAL(pdata,16,sectors_per_unit);
3813 SIVAL(pdata,20,bytes_per_sector);
3814 *fixed_portion = 24;
3818 case SMB_FS_FULL_SIZE_INFORMATION:
3820 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3822 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3824 if (df_ret == (uint64_t)-1) {
3825 return map_nt_error_from_unix(errno);
3827 block_size = lp_block_size(snum);
3828 if (bsize < block_size) {
3829 uint64_t factor = block_size/bsize;
3834 if (bsize > block_size) {
3835 uint64_t factor = bsize/block_size;
3840 sectors_per_unit = bsize/bytes_per_sector;
3841 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3842 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3843 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3844 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3845 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3846 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3847 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3848 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3849 *fixed_portion = 32;
3853 case SMB_QUERY_FS_DEVICE_INFO:
3854 case SMB_FS_DEVICE_INFORMATION:
3856 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3858 if (!CAN_WRITE(conn)) {
3859 characteristics |= FILE_READ_ONLY_DEVICE;
3862 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3863 SIVAL(pdata,4,characteristics);
3868 #ifdef HAVE_SYS_QUOTAS
3869 case SMB_FS_QUOTA_INFORMATION:
3871 * what we have to send --metze:
3873 * Unknown1: 24 NULL bytes
3874 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3875 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3876 * Quota Flags: 2 byte :
3877 * Unknown3: 6 NULL bytes
3881 * details for Quota Flags:
3883 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3884 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3885 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3886 * 0x0001 Enable Quotas: enable quota for this fs
3890 /* we need to fake up a fsp here,
3891 * because its not send in this call
3894 SMB_NTQUOTA_STRUCT quotas;
3897 ZERO_STRUCT(quotas);
3900 fsp.fnum = FNUM_FIELD_INVALID;
3903 if (get_current_uid(conn) != 0) {
3904 DEBUG(0,("get_user_quota: access_denied "
3905 "service [%s] user [%s]\n",
3906 lp_servicename(talloc_tos(), SNUM(conn)),
3907 conn->session_info->unix_info->unix_name));
3908 return NT_STATUS_ACCESS_DENIED;
3911 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3913 if (!NT_STATUS_IS_OK(status)) {
3914 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3920 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3921 lp_servicename(talloc_tos(), SNUM(conn))));
3923 /* Unknown1 24 NULL bytes*/
3924 SBIG_UINT(pdata,0,(uint64_t)0);
3925 SBIG_UINT(pdata,8,(uint64_t)0);
3926 SBIG_UINT(pdata,16,(uint64_t)0);
3928 /* Default Soft Quota 8 bytes */
3929 SBIG_UINT(pdata,24,quotas.softlim);
3931 /* Default Hard Quota 8 bytes */
3932 SBIG_UINT(pdata,32,quotas.hardlim);
3934 /* Quota flag 2 bytes */
3935 SSVAL(pdata,40,quotas.qflags);
3937 /* Unknown3 6 NULL bytes */
3943 #endif /* HAVE_SYS_QUOTAS */
3944 case SMB_FS_OBJECTID_INFORMATION:
3946 unsigned char objid[16];
3947 struct smb_extended_info extended_info;
3948 memcpy(pdata,create_volume_objectid(conn, objid),16);
3949 samba_extended_info_version (&extended_info);
3950 SIVAL(pdata,16,extended_info.samba_magic);
3951 SIVAL(pdata,20,extended_info.samba_version);
3952 SIVAL(pdata,24,extended_info.samba_subversion);
3953 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3954 memcpy(pdata+36,extended_info.samba_version_string,28);
3959 case SMB_FS_SECTOR_SIZE_INFORMATION:
3963 * These values match a physical Windows Server 2012
3964 * share backed by NTFS atop spinning rust.
3966 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3967 /* logical_bytes_per_sector */
3968 SIVAL(pdata, 0, bytes_per_sector);
3969 /* phys_bytes_per_sector_atomic */
3970 SIVAL(pdata, 4, bytes_per_sector);
3971 /* phys_bytes_per_sector_perf */
3972 SIVAL(pdata, 8, bytes_per_sector);
3973 /* fs_effective_phys_bytes_per_sector_atomic */
3974 SIVAL(pdata, 12, bytes_per_sector);
3976 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3977 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3978 /* byte_off_sector_align */
3979 SIVAL(pdata, 20, 0);
3980 /* byte_off_partition_align */
3981 SIVAL(pdata, 24, 0);
3982 *fixed_portion = 28;
3988 * Query the version and capabilities of the CIFS UNIX extensions
3992 case SMB_QUERY_CIFS_UNIX_INFO:
3994 bool large_write = lp_min_receive_file_size() &&
3995 !srv_is_signing_active(xconn);
3996 bool large_read = !srv_is_signing_active(xconn);
3997 int encrypt_caps = 0;
3999 if (!lp_unix_extensions()) {
4000 return NT_STATUS_INVALID_LEVEL;
4003 switch (conn->encrypt_level) {
4004 case SMB_SIGNING_OFF:
4007 case SMB_SIGNING_DESIRED:
4008 case SMB_SIGNING_IF_REQUIRED:
4009 case SMB_SIGNING_DEFAULT:
4010 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
4012 case SMB_SIGNING_REQUIRED:
4013 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
4014 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
4015 large_write = false;
4021 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
4022 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
4024 /* We have POSIX ACLs, pathname, encryption,
4025 * large read/write, and locking capability. */
4027 SBIG_UINT(pdata,4,((uint64_t)(
4028 CIFS_UNIX_POSIX_ACLS_CAP|
4029 CIFS_UNIX_POSIX_PATHNAMES_CAP|
4030 CIFS_UNIX_FCNTL_LOCKS_CAP|
4031 CIFS_UNIX_EXTATTR_CAP|
4032 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
4034 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
4036 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
4040 case SMB_QUERY_POSIX_FS_INFO:
4043 vfs_statvfs_struct svfs;
4045 if (!lp_unix_extensions()) {
4046 return NT_STATUS_INVALID_LEVEL;
4049 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
4053 SIVAL(pdata,0,svfs.OptimalTransferSize);
4054 SIVAL(pdata,4,svfs.BlockSize);
4055 SBIG_UINT(pdata,8,svfs.TotalBlocks);
4056 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4057 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4058 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4059 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4060 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4061 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4063 } else if (rc == EOPNOTSUPP) {
4064 return NT_STATUS_INVALID_LEVEL;
4065 #endif /* EOPNOTSUPP */
4067 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4068 return NT_STATUS_DOS(ERRSRV, ERRerror);
4073 case SMB_QUERY_POSIX_WHOAMI:
4079 if (!lp_unix_extensions()) {
4080 return NT_STATUS_INVALID_LEVEL;
4083 if (max_data_bytes < 40) {
4084 return NT_STATUS_BUFFER_TOO_SMALL;
4087 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4088 flags |= SMB_WHOAMI_GUEST;
4091 /* NOTE: 8 bytes for UID/GID, irrespective of native
4092 * platform size. This matches
4093 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4095 data_len = 4 /* flags */
4102 + 4 /* pad/reserved */
4103 + (conn->session_info->unix_token->ngroups * 8)
4105 + (conn->session_info->security_token->num_sids *
4109 SIVAL(pdata, 0, flags);
4110 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4112 (uint64_t)conn->session_info->unix_token->uid);
4113 SBIG_UINT(pdata, 16,
4114 (uint64_t)conn->session_info->unix_token->gid);
4117 if (data_len >= max_data_bytes) {
4118 /* Potential overflow, skip the GIDs and SIDs. */
4120 SIVAL(pdata, 24, 0); /* num_groups */
4121 SIVAL(pdata, 28, 0); /* num_sids */
4122 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4123 SIVAL(pdata, 36, 0); /* reserved */
4129 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4130 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4132 /* We walk the SID list twice, but this call is fairly
4133 * infrequent, and I don't expect that it's performance
4134 * sensitive -- jpeach
4136 for (i = 0, sid_bytes = 0;
4137 i < conn->session_info->security_token->num_sids; ++i) {
4138 sid_bytes += ndr_size_dom_sid(
4139 &conn->session_info->security_token->sids[i],
4143 /* SID list byte count */
4144 SIVAL(pdata, 32, sid_bytes);
4146 /* 4 bytes pad/reserved - must be zero */
4147 SIVAL(pdata, 36, 0);
4151 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4152 SBIG_UINT(pdata, data_len,
4153 (uint64_t)conn->session_info->unix_token->groups[i]);
4159 i < conn->session_info->security_token->num_sids; ++i) {
4160 int sid_len = ndr_size_dom_sid(
4161 &conn->session_info->security_token->sids[i],
4164 sid_linearize((uint8_t *)(pdata + data_len),
4166 &conn->session_info->security_token->sids[i]);
4167 data_len += sid_len;
4173 case SMB_MAC_QUERY_FS_INFO:
4175 * Thursby MAC extension... ONLY on NTFS filesystems
4176 * once we do streams then we don't need this
4178 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4180 SIVAL(pdata,84,0x100); /* Don't support mac... */
4186 return NT_STATUS_INVALID_LEVEL;
4189 *ret_data_len = data_len;
4193 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4194 struct smb_request *req,
4196 const DATA_BLOB *qdata)
4199 SMB_NTQUOTA_STRUCT quotas;
4201 ZERO_STRUCT(quotas);
4204 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4205 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4206 lp_servicename(talloc_tos(), SNUM(conn)),
4207 conn->session_info->unix_info->unix_name));
4208 return NT_STATUS_ACCESS_DENIED;
4211 if (!check_fsp_ntquota_handle(conn, req,
4213 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4214 return NT_STATUS_INVALID_HANDLE;
4217 /* note: normally there're 48 bytes,
4218 * but we didn't use the last 6 bytes for now
4221 if (qdata->length < 42) {
4222 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4223 (unsigned int)qdata->length));
4224 return NT_STATUS_INVALID_PARAMETER;
4227 /* unknown_1 24 NULL bytes in pdata*/
4229 /* the soft quotas 8 bytes (uint64_t)*/
4230 quotas.softlim = BVAL(qdata->data,24);
4232 /* the hard quotas 8 bytes (uint64_t)*/
4233 quotas.hardlim = BVAL(qdata->data,32);
4235 /* quota_flags 2 bytes **/
4236 quotas.qflags = SVAL(qdata->data,40);
4238 /* unknown_2 6 NULL bytes follow*/
4240 /* now set the quotas */
4241 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4242 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4243 lp_servicename(talloc_tos(), SNUM(conn))));
4244 status = map_nt_error_from_unix(errno);
4246 status = NT_STATUS_OK;
4251 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4252 struct smb_request *req,
4253 TALLOC_CTX *mem_ctx,
4254 uint16_t info_level,
4256 const DATA_BLOB *pdata)
4258 switch (info_level) {
4259 case SMB_FS_QUOTA_INFORMATION:
4261 return smb_set_fsquota(conn,
4270 return NT_STATUS_INVALID_LEVEL;
4273 /****************************************************************************
4274 Reply to a TRANS2_QFSINFO (query filesystem info).
4275 ****************************************************************************/
4277 static void call_trans2qfsinfo(connection_struct *conn,
4278 struct smb_request *req,
4279 char **pparams, int total_params,
4280 char **ppdata, int total_data,
4281 unsigned int max_data_bytes)
4283 char *params = *pparams;
4284 uint16_t info_level;
4286 size_t fixed_portion;
4289 if (total_params < 2) {
4290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4294 info_level = SVAL(params,0);
4296 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4297 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4298 DEBUG(0,("call_trans2qfsinfo: encryption required "
4299 "and info level 0x%x sent.\n",
4300 (unsigned int)info_level));
4301 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4306 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4308 status = smbd_do_qfsinfo(req->xconn, conn, req,
4315 if (!NT_STATUS_IS_OK(status)) {
4316 reply_nterror(req, status);
4320 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4323 DEBUG( 4, ( "%s info_level = %d\n",
4324 smb_fn_name(req->cmd), info_level) );
4329 /****************************************************************************
4330 Reply to a TRANS2_SETFSINFO (set filesystem info).
4331 ****************************************************************************/
4333 static void call_trans2setfsinfo(connection_struct *conn,
4334 struct smb_request *req,
4335 char **pparams, int total_params,
4336 char **ppdata, int total_data,
4337 unsigned int max_data_bytes)
4339 struct smbXsrv_connection *xconn = req->xconn;
4340 char *pdata = *ppdata;
4341 char *params = *pparams;
4342 uint16_t info_level;
4344 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4345 lp_servicename(talloc_tos(), SNUM(conn))));
4348 if (total_params < 4) {
4349 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4355 info_level = SVAL(params,2);
4358 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4359 info_level != SMB_SET_CIFS_UNIX_INFO) {
4360 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4361 "info level (0x%x) on IPC$.\n",
4362 (unsigned int)info_level));
4363 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4368 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4369 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4370 DEBUG(0,("call_trans2setfsinfo: encryption required "
4371 "and info level 0x%x sent.\n",
4372 (unsigned int)info_level));
4373 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4378 switch(info_level) {
4379 case SMB_SET_CIFS_UNIX_INFO:
4380 if (!lp_unix_extensions()) {
4381 DEBUG(2,("call_trans2setfsinfo: "
4382 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4383 "unix extensions off\n"));
4385 NT_STATUS_INVALID_LEVEL);
4389 /* There should be 12 bytes of capabilities set. */
4390 if (total_data < 12) {
4393 NT_STATUS_INVALID_PARAMETER);
4396 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4397 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4398 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4399 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4400 /* Just print these values for now. */
4401 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4402 "major = %u, minor = %u cap_low = 0x%x, "
4404 (unsigned int)xconn->
4405 smb1.unix_info.client_major,
4406 (unsigned int)xconn->
4407 smb1.unix_info.client_minor,
4408 (unsigned int)xconn->
4409 smb1.unix_info.client_cap_low,
4410 (unsigned int)xconn->
4411 smb1.unix_info.client_cap_high));
4413 /* Here is where we must switch to posix pathname processing... */
4414 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4415 lp_set_posix_pathnames();
4416 mangle_change_to_posix();
4419 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4420 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4421 /* Client that knows how to do posix locks,
4422 * but not posix open/mkdir operations. Set a
4423 * default type for read/write checks. */
4425 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4430 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4433 size_t param_len = 0;
4434 size_t data_len = total_data;
4436 if (!lp_unix_extensions()) {
4439 NT_STATUS_INVALID_LEVEL);
4443 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4446 NT_STATUS_NOT_SUPPORTED);
4450 if (xconn->smb1.echo_handler.trusted_fde) {
4451 DEBUG( 2,("call_trans2setfsinfo: "
4452 "request transport encryption disabled"
4453 "with 'fork echo handler = yes'\n"));
4456 NT_STATUS_NOT_SUPPORTED);
4460 DEBUG( 4,("call_trans2setfsinfo: "
4461 "request transport encryption.\n"));
4463 status = srv_request_encryption_setup(conn,
4464 (unsigned char **)ppdata,
4466 (unsigned char **)pparams,
4469 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4470 !NT_STATUS_IS_OK(status)) {
4471 reply_nterror(req, status);
4475 send_trans2_replies(conn, req,
4483 if (NT_STATUS_IS_OK(status)) {
4484 /* Server-side transport
4485 * encryption is now *on*. */
4486 status = srv_encryption_start(conn);
4487 if (!NT_STATUS_IS_OK(status)) {
4488 char *reason = talloc_asprintf(talloc_tos(),
4489 "Failure in setting "
4490 "up encrypted transport: %s",
4492 exit_server_cleanly(reason);
4498 case SMB_FS_QUOTA_INFORMATION:
4502 .data = (uint8_t *)pdata,
4503 .length = total_data
4505 files_struct *fsp = NULL;
4506 fsp = file_fsp(req, SVAL(params,0));
4508 status = smb_set_fsquota(conn,
4512 if (!NT_STATUS_IS_OK(status)) {
4513 reply_nterror(req, status);
4519 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4521 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4527 * sending this reply works fine,
4528 * but I'm not sure it's the same
4529 * like windows do...
4532 reply_outbuf(req, 10, 0);
4535 #if defined(HAVE_POSIX_ACLS)
4536 /****************************************************************************
4537 Utility function to count the number of entries in a POSIX acl.
4538 ****************************************************************************/
4540 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4542 unsigned int ace_count = 0;
4543 int entry_id = SMB_ACL_FIRST_ENTRY;
4544 SMB_ACL_ENTRY_T entry;
4546 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4548 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4549 entry_id = SMB_ACL_NEXT_ENTRY;
4556 /****************************************************************************
4557 Utility function to marshall a POSIX acl into wire format.
4558 ****************************************************************************/
4560 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4562 int entry_id = SMB_ACL_FIRST_ENTRY;
4563 SMB_ACL_ENTRY_T entry;
4565 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4566 SMB_ACL_TAG_T tagtype;
4567 SMB_ACL_PERMSET_T permset;
4568 unsigned char perms = 0;
4569 unsigned int own_grp;
4572 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4573 entry_id = SMB_ACL_NEXT_ENTRY;
4576 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4577 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4581 if (sys_acl_get_permset(entry, &permset) == -1) {
4582 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4586 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4587 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4588 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4590 SCVAL(pdata,1,perms);
4593 case SMB_ACL_USER_OBJ:
4594 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4595 own_grp = (unsigned int)pst->st_ex_uid;
4596 SIVAL(pdata,2,own_grp);
4601 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4603 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4606 own_grp = (unsigned int)*puid;
4607 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4608 SIVAL(pdata,2,own_grp);
4612 case SMB_ACL_GROUP_OBJ:
4613 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4614 own_grp = (unsigned int)pst->st_ex_gid;
4615 SIVAL(pdata,2,own_grp);
4620 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4622 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4625 own_grp = (unsigned int)*pgid;
4626 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4627 SIVAL(pdata,2,own_grp);
4632 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4633 SIVAL(pdata,2,0xFFFFFFFF);
4634 SIVAL(pdata,6,0xFFFFFFFF);
4637 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4638 SIVAL(pdata,2,0xFFFFFFFF);
4639 SIVAL(pdata,6,0xFFFFFFFF);
4642 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4645 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4652 /****************************************************************************
4653 Store the FILE_UNIX_BASIC info.
4654 ****************************************************************************/
4656 static char *store_file_unix_basic(connection_struct *conn,
4659 const SMB_STRUCT_STAT *psbuf)
4663 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4664 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4666 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4669 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4672 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4673 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4674 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4677 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4681 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4685 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4688 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4689 devno = psbuf->st_ex_rdev;
4691 devno = psbuf->st_ex_dev;
4694 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4698 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4702 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4705 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4709 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4716 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4717 * the chflags(2) (or equivalent) flags.
4719 * XXX: this really should be behind the VFS interface. To do this, we would
4720 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4721 * Each VFS module could then implement its own mapping as appropriate for the
4722 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4724 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4728 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4732 { UF_IMMUTABLE, EXT_IMMUTABLE },
4736 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4740 { UF_HIDDEN, EXT_HIDDEN },
4743 /* Do not remove. We need to guarantee that this array has at least one
4744 * entry to build on HP-UX.
4750 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4751 uint32_t *smb_fflags, uint32_t *smb_fmask)
4755 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4756 *smb_fmask |= info2_flags_map[i].smb_fflag;
4757 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4758 *smb_fflags |= info2_flags_map[i].smb_fflag;
4763 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4764 const uint32_t smb_fflags,
4765 const uint32_t smb_fmask,
4768 uint32_t max_fmask = 0;
4771 *stat_fflags = psbuf->st_ex_flags;
4773 /* For each flags requested in smb_fmask, check the state of the
4774 * corresponding flag in smb_fflags and set or clear the matching
4778 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4779 max_fmask |= info2_flags_map[i].smb_fflag;
4780 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4781 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4782 *stat_fflags |= info2_flags_map[i].stat_fflag;
4784 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4789 /* If smb_fmask is asking to set any bits that are not supported by
4790 * our flag mappings, we should fail.
4792 if ((smb_fmask & max_fmask) != smb_fmask) {
4800 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4801 * of file flags and birth (create) time.
4803 static char *store_file_unix_basic_info2(connection_struct *conn,
4806 const SMB_STRUCT_STAT *psbuf)
4808 uint32_t file_flags = 0;
4809 uint32_t flags_mask = 0;
4811 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4813 /* Create (birth) time 64 bit */
4814 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4817 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4818 SIVAL(pdata, 0, file_flags); /* flags */
4819 SIVAL(pdata, 4, flags_mask); /* mask */
4825 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4826 const struct stream_struct *streams,
4828 unsigned int max_data_bytes,
4829 unsigned int *data_size)
4832 unsigned int ofs = 0;
4834 if (max_data_bytes < 32) {
4835 return NT_STATUS_INFO_LENGTH_MISMATCH;
4838 for (i = 0; i < num_streams; i++) {
4839 unsigned int next_offset;
4841 smb_ucs2_t *namebuf;
4843 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4844 streams[i].name, &namelen) ||
4847 return NT_STATUS_INVALID_PARAMETER;
4851 * name_buf is now null-terminated, we need to marshall as not
4858 * We cannot overflow ...
4860 if ((ofs + 24 + namelen) > max_data_bytes) {
4861 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4863 TALLOC_FREE(namebuf);
4864 return STATUS_BUFFER_OVERFLOW;
4867 SIVAL(data, ofs+4, namelen);
4868 SOFF_T(data, ofs+8, streams[i].size);
4869 SOFF_T(data, ofs+16, streams[i].alloc_size);
4870 memcpy(data+ofs+24, namebuf, namelen);
4871 TALLOC_FREE(namebuf);
4873 next_offset = ofs + 24 + namelen;
4875 if (i == num_streams-1) {
4876 SIVAL(data, ofs, 0);
4879 unsigned int align = ndr_align_size(next_offset, 8);
4881 if ((next_offset + align) > max_data_bytes) {
4882 DEBUG(10, ("refusing to overflow align "
4883 "reply at stream %u\n",
4885 TALLOC_FREE(namebuf);
4886 return STATUS_BUFFER_OVERFLOW;
4889 memset(data+next_offset, 0, align);
4890 next_offset += align;
4892 SIVAL(data, ofs, next_offset - ofs);
4899 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4903 return NT_STATUS_OK;
4906 #if defined(HAVE_POSIX_ACLS)
4907 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4908 struct smb_request *req,
4910 struct smb_filename *smb_fname,
4912 unsigned int data_size_in,
4913 unsigned int *pdata_size_out)
4915 SMB_ACL_T file_acl = NULL;
4916 SMB_ACL_T def_acl = NULL;
4917 uint16_t num_file_acls = 0;
4918 uint16_t num_def_acls = 0;
4919 unsigned int size_needed = 0;
4925 * Ensure we always operate on a file descriptor, not just
4929 uint32_t access_mask = SEC_STD_READ_CONTROL|
4930 FILE_READ_ATTRIBUTES|
4931 FILE_WRITE_ATTRIBUTES;
4933 status = get_posix_fsp(conn,
4939 if (!NT_STATUS_IS_OK(status)) {
4945 SMB_ASSERT(fsp != NULL);
4947 status = refuse_symlink(conn,
4950 if (!NT_STATUS_IS_OK(status)) {
4954 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4957 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4958 DBG_INFO("ACLs not implemented on "
4959 "filesystem containing %s\n",
4961 status = NT_STATUS_NOT_IMPLEMENTED;
4965 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4967 * We can only have default POSIX ACLs on
4970 if (!fsp->is_directory) {
4971 DBG_INFO("Non-directory open %s\n",
4973 status = NT_STATUS_INVALID_HANDLE;
4976 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
4978 SMB_ACL_TYPE_DEFAULT,
4980 def_acl = free_empty_sys_acl(conn, def_acl);
4983 num_file_acls = count_acl_entries(conn, file_acl);
4984 num_def_acls = count_acl_entries(conn, def_acl);
4987 if (num_file_acls + num_def_acls < num_file_acls) {
4988 status = NT_STATUS_INVALID_PARAMETER;
4992 size_needed = num_file_acls + num_def_acls;
4995 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4996 * than UINT_MAX, so check by division.
4998 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4999 status = NT_STATUS_INVALID_PARAMETER;
5003 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5004 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5005 status = NT_STATUS_INVALID_PARAMETER;
5008 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5010 if ( data_size_in < size_needed) {
5011 DBG_INFO("data_size too small (%u) need %u\n",
5014 status = NT_STATUS_BUFFER_TOO_SMALL;
5018 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5019 SSVAL(pdata,2,num_file_acls);
5020 SSVAL(pdata,4,num_def_acls);
5021 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5023 ok = marshall_posix_acl(conn,
5028 status = NT_STATUS_INTERNAL_ERROR;
5031 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5033 ok = marshall_posix_acl(conn,
5038 status = NT_STATUS_INTERNAL_ERROR;
5042 *pdata_size_out = size_needed;
5043 status = NT_STATUS_OK;
5049 * Ensure the stat struct in smb_fname is up to
5050 * date. Structure copy.
5052 smb_fname->st = fsp->fsp_name->st;
5053 (void)close_file(req, fsp, NORMAL_CLOSE);
5057 TALLOC_FREE(file_acl);
5058 TALLOC_FREE(def_acl);
5063 /****************************************************************************
5064 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5065 ****************************************************************************/
5067 static void call_trans2qpipeinfo(connection_struct *conn,
5068 struct smb_request *req,
5069 unsigned int tran_call,
5070 char **pparams, int total_params,
5071 char **ppdata, int total_data,
5072 unsigned int max_data_bytes)
5074 char *params = *pparams;
5075 char *pdata = *ppdata;
5076 unsigned int data_size = 0;
5077 unsigned int param_size = 2;
5078 uint16_t info_level;
5082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5086 if (total_params < 4) {
5087 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5091 fsp = file_fsp(req, SVAL(params,0));
5092 if (!fsp_is_np(fsp)) {
5093 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5097 info_level = SVAL(params,2);
5099 *pparams = (char *)SMB_REALLOC(*pparams,2);
5100 if (*pparams == NULL) {
5101 reply_nterror(req, NT_STATUS_NO_MEMORY);
5106 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5107 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5110 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5111 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5112 if (*ppdata == NULL ) {
5113 reply_nterror(req, NT_STATUS_NO_MEMORY);
5118 switch (info_level) {
5119 case SMB_FILE_STANDARD_INFORMATION:
5121 SOFF_T(pdata,0,4096LL);
5128 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5132 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5138 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5139 TALLOC_CTX *mem_ctx,
5140 struct smb_request *req,
5141 uint16_t info_level,
5143 struct smb_filename *smb_fname,
5144 bool delete_pending,
5145 struct timespec write_time_ts,
5146 struct ea_list *ea_list,
5147 int lock_data_count,
5150 unsigned int max_data_bytes,
5151 size_t *fixed_portion,
5153 unsigned int *pdata_size)
5155 char *pdata = *ppdata;
5156 char *dstart, *dend;
5157 unsigned int data_size;
5158 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5159 time_t create_time, mtime, atime, c_time;
5160 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5167 uint64_t file_size = 0;
5169 uint64_t allocation_size = 0;
5170 uint64_t file_id = 0;
5171 uint32_t access_mask = 0;
5174 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5175 return NT_STATUS_INVALID_LEVEL;
5178 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5179 smb_fname_str_dbg(smb_fname),
5181 info_level, max_data_bytes));
5183 mode = dos_mode(conn, smb_fname);
5184 nlink = psbuf->st_ex_nlink;
5186 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5190 if ((nlink > 0) && delete_pending) {
5194 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5195 return NT_STATUS_INVALID_PARAMETER;
5198 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5199 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5200 if (*ppdata == NULL) {
5201 return NT_STATUS_NO_MEMORY;
5205 dend = dstart + data_size - 1;
5207 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
5208 update_stat_ex_mtime(psbuf, write_time_ts);
5211 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5212 mtime_ts = psbuf->st_ex_mtime;
5213 atime_ts = psbuf->st_ex_atime;
5214 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5216 if (lp_dos_filetime_resolution(SNUM(conn))) {
5217 dos_filetime_timespec(&create_time_ts);
5218 dos_filetime_timespec(&mtime_ts);
5219 dos_filetime_timespec(&atime_ts);
5220 dos_filetime_timespec(&ctime_ts);
5223 create_time = convert_timespec_to_time_t(create_time_ts);
5224 mtime = convert_timespec_to_time_t(mtime_ts);
5225 atime = convert_timespec_to_time_t(atime_ts);
5226 c_time = convert_timespec_to_time_t(ctime_ts);
5228 p = strrchr_m(smb_fname->base_name,'/');
5230 base_name = smb_fname->base_name;
5234 /* NT expects the name to be in an exact form of the *full*
5235 filename. See the trans2 torture test */
5236 if (ISDOT(base_name)) {
5237 dos_fname = talloc_strdup(mem_ctx, "\\");
5239 return NT_STATUS_NO_MEMORY;
5242 dos_fname = talloc_asprintf(mem_ctx,
5244 smb_fname->base_name);
5246 return NT_STATUS_NO_MEMORY;
5248 if (is_ntfs_stream_smb_fname(smb_fname)) {
5249 dos_fname = talloc_asprintf(dos_fname, "%s",
5250 smb_fname->stream_name);
5252 return NT_STATUS_NO_MEMORY;
5256 string_replace(dos_fname, '/', '\\');
5259 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5262 /* Do we have this path open ? */
5264 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5265 fsp1 = file_find_di_first(conn->sconn, fileid);
5266 if (fsp1 && fsp1->initial_allocation_size) {
5267 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5271 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5272 file_size = get_file_size_stat(psbuf);
5276 pos = fsp->fh->position_information;
5280 access_mask = fsp->access_mask;
5282 /* GENERIC_EXECUTE mapping from Windows */
5283 access_mask = 0x12019F;
5286 /* This should be an index number - looks like
5289 I think this causes us to fail the IFSKIT
5290 BasicFileInformationTest. -tpot */
5291 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5295 switch (info_level) {
5296 case SMB_INFO_STANDARD:
5297 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5299 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5300 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5301 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5302 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5303 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5304 SSVAL(pdata,l1_attrFile,mode);
5307 case SMB_INFO_QUERY_EA_SIZE:
5309 unsigned int ea_size =
5310 estimate_ea_size(conn, fsp,
5312 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5314 srv_put_dos_date2(pdata,0,create_time);
5315 srv_put_dos_date2(pdata,4,atime);
5316 srv_put_dos_date2(pdata,8,mtime); /* write time */
5317 SIVAL(pdata,12,(uint32_t)file_size);
5318 SIVAL(pdata,16,(uint32_t)allocation_size);
5319 SSVAL(pdata,20,mode);
5320 SIVAL(pdata,22,ea_size);
5324 case SMB_INFO_IS_NAME_VALID:
5325 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5327 /* os/2 needs this ? really ?*/
5328 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5330 /* This is only reached for qpathinfo */
5334 case SMB_INFO_QUERY_EAS_FROM_LIST:
5336 size_t total_ea_len = 0;
5337 struct ea_list *ea_file_list = NULL;
5338 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5341 get_ea_list_from_file(mem_ctx, conn, fsp,
5343 &total_ea_len, &ea_file_list);
5344 if (!NT_STATUS_IS_OK(status)) {
5348 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5350 if (!ea_list || (total_ea_len > data_size)) {
5352 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5356 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5360 case SMB_INFO_QUERY_ALL_EAS:
5362 /* We have data_size bytes to put EA's into. */
5363 size_t total_ea_len = 0;
5364 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5366 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5368 &total_ea_len, &ea_list);
5369 if (!NT_STATUS_IS_OK(status)) {
5373 if (!ea_list || (total_ea_len > data_size)) {
5375 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5379 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5383 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5385 /* This is FileFullEaInformation - 0xF which maps to
5386 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5388 /* We have data_size bytes to put EA's into. */
5389 size_t total_ea_len = 0;
5390 struct ea_list *ea_file_list = NULL;
5392 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5394 /*TODO: add filtering and index handling */
5397 get_ea_list_from_file(mem_ctx, conn, fsp,
5399 &total_ea_len, &ea_file_list);
5400 if (!NT_STATUS_IS_OK(status)) {
5403 if (!ea_file_list) {
5404 return NT_STATUS_NO_EAS_ON_FILE;
5407 status = fill_ea_chained_buffer(mem_ctx,
5411 conn, ea_file_list);
5412 if (!NT_STATUS_IS_OK(status)) {
5418 case SMB_FILE_BASIC_INFORMATION:
5419 case SMB_QUERY_FILE_BASIC_INFO:
5421 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5423 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5429 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5430 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5431 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5432 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5433 SIVAL(pdata,32,mode);
5435 DEBUG(5,("SMB_QFBI - "));
5436 DEBUG(5,("create: %s ", ctime(&create_time)));
5437 DEBUG(5,("access: %s ", ctime(&atime)));
5438 DEBUG(5,("write: %s ", ctime(&mtime)));
5439 DEBUG(5,("change: %s ", ctime(&c_time)));
5440 DEBUG(5,("mode: %x\n", mode));
5441 *fixed_portion = data_size;
5444 case SMB_FILE_STANDARD_INFORMATION:
5445 case SMB_QUERY_FILE_STANDARD_INFO:
5447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5449 SOFF_T(pdata,0,allocation_size);
5450 SOFF_T(pdata,8,file_size);
5451 SIVAL(pdata,16,nlink);
5452 SCVAL(pdata,20,delete_pending?1:0);
5453 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5454 SSVAL(pdata,22,0); /* Padding. */
5455 *fixed_portion = 24;
5458 case SMB_FILE_EA_INFORMATION:
5459 case SMB_QUERY_FILE_EA_INFO:
5461 unsigned int ea_size =
5462 estimate_ea_size(conn, fsp, smb_fname);
5463 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5466 SIVAL(pdata,0,ea_size);
5470 /* Get the 8.3 name - used if NT SMB was negotiated. */
5471 case SMB_QUERY_FILE_ALT_NAME_INFO:
5472 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5474 char mangled_name[13];
5475 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5476 if (!name_to_8_3(base_name,mangled_name,
5477 True,conn->params)) {
5478 return NT_STATUS_NO_MEMORY;
5480 status = srvstr_push(dstart, flags2,
5481 pdata+4, mangled_name,
5482 PTR_DIFF(dend, pdata+4),
5484 if (!NT_STATUS_IS_OK(status)) {
5487 data_size = 4 + len;
5493 case SMB_QUERY_FILE_NAME_INFO:
5496 this must be *exactly* right for ACLs on mapped drives to work
5498 status = srvstr_push(dstart, flags2,
5500 PTR_DIFF(dend, pdata+4),
5502 if (!NT_STATUS_IS_OK(status)) {
5505 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5506 data_size = 4 + len;
5511 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5513 char *nfname = NULL;
5515 if (!fsp->conn->sconn->using_smb2) {
5516 return NT_STATUS_INVALID_LEVEL;
5519 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5520 if (nfname == NULL) {
5521 return NT_STATUS_NO_MEMORY;
5524 if (ISDOT(nfname)) {
5527 string_replace(nfname, '/', '\\');
5529 if (smb_fname->stream_name != NULL) {
5530 const char *s = smb_fname->stream_name;
5531 const char *e = NULL;
5534 SMB_ASSERT(s[0] != '\0');
5537 * smb_fname->stream_name is in form
5538 * of ':StrEam:$DATA', but we should only
5539 * append ':StrEam' here.
5542 e = strchr(&s[1], ':');
5548 nfname = talloc_strndup_append(nfname, s, n);
5549 if (nfname == NULL) {
5550 return NT_STATUS_NO_MEMORY;
5554 status = srvstr_push(dstart, flags2,
5556 PTR_DIFF(dend, pdata+4),
5558 if (!NT_STATUS_IS_OK(status)) {
5561 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5562 data_size = 4 + len;
5568 case SMB_FILE_ALLOCATION_INFORMATION:
5569 case SMB_QUERY_FILE_ALLOCATION_INFO:
5570 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5572 SOFF_T(pdata,0,allocation_size);
5575 case SMB_FILE_END_OF_FILE_INFORMATION:
5576 case SMB_QUERY_FILE_END_OF_FILEINFO:
5577 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5579 SOFF_T(pdata,0,file_size);
5582 case SMB_QUERY_FILE_ALL_INFO:
5583 case SMB_FILE_ALL_INFORMATION:
5585 unsigned int ea_size =
5586 estimate_ea_size(conn, fsp, smb_fname);
5587 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5588 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5589 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5590 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5591 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5592 SIVAL(pdata,32,mode);
5593 SIVAL(pdata,36,0); /* padding. */
5595 SOFF_T(pdata,0,allocation_size);
5596 SOFF_T(pdata,8,file_size);
5597 SIVAL(pdata,16,nlink);
5598 SCVAL(pdata,20,delete_pending);
5599 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5602 SIVAL(pdata,0,ea_size);
5603 pdata += 4; /* EA info */
5604 status = srvstr_push(dstart, flags2,
5606 PTR_DIFF(dend, pdata+4),
5608 if (!NT_STATUS_IS_OK(status)) {
5613 data_size = PTR_DIFF(pdata,(*ppdata));
5614 *fixed_portion = 10;
5618 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5620 unsigned int ea_size =
5621 estimate_ea_size(conn, fsp, smb_fname);
5622 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5623 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5624 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5625 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5626 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5627 SIVAL(pdata, 0x20, mode);
5628 SIVAL(pdata, 0x24, 0); /* padding. */
5629 SBVAL(pdata, 0x28, allocation_size);
5630 SBVAL(pdata, 0x30, file_size);
5631 SIVAL(pdata, 0x38, nlink);
5632 SCVAL(pdata, 0x3C, delete_pending);
5633 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5634 SSVAL(pdata, 0x3E, 0); /* padding */
5635 SBVAL(pdata, 0x40, file_id);
5636 SIVAL(pdata, 0x48, ea_size);
5637 SIVAL(pdata, 0x4C, access_mask);
5638 SBVAL(pdata, 0x50, pos);
5639 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5640 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5644 status = srvstr_push(dstart, flags2,
5646 PTR_DIFF(dend, pdata+4),
5648 if (!NT_STATUS_IS_OK(status)) {
5653 data_size = PTR_DIFF(pdata,(*ppdata));
5654 *fixed_portion = 104;
5657 case SMB_FILE_INTERNAL_INFORMATION:
5659 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5660 SBVAL(pdata, 0, file_id);
5665 case SMB_FILE_ACCESS_INFORMATION:
5666 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5667 SIVAL(pdata, 0, access_mask);
5672 case SMB_FILE_NAME_INFORMATION:
5673 /* Pathname with leading '\'. */
5676 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5677 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5678 SIVAL(pdata,0,byte_len);
5679 data_size = 4 + byte_len;
5683 case SMB_FILE_DISPOSITION_INFORMATION:
5684 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5686 SCVAL(pdata,0,delete_pending);
5690 case SMB_FILE_POSITION_INFORMATION:
5691 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5693 SOFF_T(pdata,0,pos);
5697 case SMB_FILE_MODE_INFORMATION:
5698 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5699 SIVAL(pdata,0,mode);
5704 case SMB_FILE_ALIGNMENT_INFORMATION:
5705 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5706 SIVAL(pdata,0,0); /* No alignment needed. */
5712 * NT4 server just returns "invalid query" to this - if we try
5713 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5716 /* The first statement above is false - verified using Thursby
5717 * client against NT4 -- gcolley.
5719 case SMB_QUERY_FILE_STREAM_INFO:
5720 case SMB_FILE_STREAM_INFORMATION: {
5721 unsigned int num_streams = 0;
5722 struct stream_struct *streams = NULL;
5724 DEBUG(10,("smbd_do_qfilepathinfo: "
5725 "SMB_FILE_STREAM_INFORMATION\n"));
5727 if (is_ntfs_stream_smb_fname(smb_fname)) {
5728 return NT_STATUS_INVALID_PARAMETER;
5731 status = vfs_streaminfo(conn,
5738 if (!NT_STATUS_IS_OK(status)) {
5739 DEBUG(10, ("could not get stream info: %s\n",
5740 nt_errstr(status)));
5744 status = marshall_stream_info(num_streams, streams,
5745 pdata, max_data_bytes,
5748 if (!NT_STATUS_IS_OK(status)) {
5749 DEBUG(10, ("marshall_stream_info failed: %s\n",
5750 nt_errstr(status)));
5751 TALLOC_FREE(streams);
5755 TALLOC_FREE(streams);
5757 *fixed_portion = 32;
5761 case SMB_QUERY_COMPRESSION_INFO:
5762 case SMB_FILE_COMPRESSION_INFORMATION:
5763 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5764 SOFF_T(pdata,0,file_size);
5765 SIVAL(pdata,8,0); /* ??? */
5766 SIVAL(pdata,12,0); /* ??? */
5768 *fixed_portion = 16;
5771 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5772 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5773 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5774 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5775 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5776 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5777 SOFF_T(pdata,32,allocation_size);
5778 SOFF_T(pdata,40,file_size);
5779 SIVAL(pdata,48,mode);
5780 SIVAL(pdata,52,0); /* ??? */
5782 *fixed_portion = 56;
5785 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5786 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5787 SIVAL(pdata,0,mode);
5794 * CIFS UNIX Extensions.
5797 case SMB_QUERY_FILE_UNIX_BASIC:
5799 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5800 data_size = PTR_DIFF(pdata,(*ppdata));
5802 DEBUG(4,("smbd_do_qfilepathinfo: "
5803 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5804 dump_data(4, (uint8_t *)(*ppdata), data_size);
5808 case SMB_QUERY_FILE_UNIX_INFO2:
5810 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5811 data_size = PTR_DIFF(pdata,(*ppdata));
5815 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5817 for (i=0; i<100; i++)
5818 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5824 case SMB_QUERY_FILE_UNIX_LINK:
5827 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5830 return NT_STATUS_NO_MEMORY;
5833 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5835 if(!S_ISLNK(psbuf->st_ex_mode)) {
5836 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5839 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5841 link_len = SMB_VFS_READLINK(conn,
5844 if (link_len == -1) {
5845 return map_nt_error_from_unix(errno);
5847 buffer[link_len] = 0;
5848 status = srvstr_push(dstart, flags2,
5850 PTR_DIFF(dend, pdata),
5851 STR_TERMINATE, &len);
5852 if (!NT_STATUS_IS_OK(status)) {
5856 data_size = PTR_DIFF(pdata,(*ppdata));
5861 #if defined(HAVE_POSIX_ACLS)
5862 case SMB_QUERY_POSIX_ACL:
5864 status = smb_query_posix_acl(conn,
5871 if (!NT_STATUS_IS_OK(status)) {
5879 case SMB_QUERY_POSIX_LOCK:
5884 enum brl_type lock_type;
5886 /* We need an open file with a real fd for this. */
5887 if (!fsp || fsp->fh->fd == -1) {
5888 return NT_STATUS_INVALID_LEVEL;
5891 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5892 return NT_STATUS_INVALID_PARAMETER;
5895 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5896 case POSIX_LOCK_TYPE_READ:
5897 lock_type = READ_LOCK;
5899 case POSIX_LOCK_TYPE_WRITE:
5900 lock_type = WRITE_LOCK;
5902 case POSIX_LOCK_TYPE_UNLOCK:
5904 /* There's no point in asking for an unlock... */
5905 return NT_STATUS_INVALID_PARAMETER;
5908 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5909 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5910 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5912 status = query_lock(fsp,
5919 if (ERROR_WAS_LOCK_DENIED(status)) {
5920 /* Here we need to report who has it locked... */
5921 data_size = POSIX_LOCK_DATA_SIZE;
5923 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5924 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5925 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5926 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5927 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5929 } else if (NT_STATUS_IS_OK(status)) {
5930 /* For success we just return a copy of what we sent
5931 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5932 data_size = POSIX_LOCK_DATA_SIZE;
5933 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5934 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5942 return NT_STATUS_INVALID_LEVEL;
5945 *pdata_size = data_size;
5946 return NT_STATUS_OK;
5949 /****************************************************************************
5950 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5951 file name or file id).
5952 ****************************************************************************/
5954 static void call_trans2qfilepathinfo(connection_struct *conn,
5955 struct smb_request *req,
5956 unsigned int tran_call,
5957 char **pparams, int total_params,
5958 char **ppdata, int total_data,
5959 unsigned int max_data_bytes)
5961 char *params = *pparams;
5962 char *pdata = *ppdata;
5963 uint16_t info_level;
5964 unsigned int data_size = 0;
5965 unsigned int param_size = 2;
5966 struct smb_filename *smb_fname = NULL;
5967 bool delete_pending = False;
5968 struct timespec write_time_ts;
5969 files_struct *fsp = NULL;
5970 struct file_id fileid;
5971 struct ea_list *ea_list = NULL;
5972 int lock_data_count = 0;
5973 char *lock_data = NULL;
5974 size_t fixed_portion;
5975 NTSTATUS status = NT_STATUS_OK;
5978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5982 ZERO_STRUCT(write_time_ts);
5984 if (tran_call == TRANSACT2_QFILEINFO) {
5985 if (total_params < 4) {
5986 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5991 call_trans2qpipeinfo(conn, req, tran_call,
5992 pparams, total_params,
5998 fsp = file_fsp(req, SVAL(params,0));
5999 info_level = SVAL(params,2);
6001 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6003 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6004 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6008 /* Initial check for valid fsp ptr. */
6009 if (!check_fsp_open(conn, req, fsp)) {
6013 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
6014 if (smb_fname == NULL) {
6015 reply_nterror(req, NT_STATUS_NO_MEMORY);
6019 if(fsp->fake_file_handle) {
6021 * This is actually for the QUOTA_FAKE_FILE --metze
6024 /* We know this name is ok, it's already passed the checks. */
6026 } else if(fsp->fh->fd == -1) {
6028 * This is actually a QFILEINFO on a directory
6029 * handle (returned from an NT SMB). NT5.0 seems
6030 * to do this call. JRA.
6033 if (INFO_LEVEL_IS_UNIX(info_level)) {
6034 /* Always do lstat for UNIX calls. */
6035 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6036 DEBUG(3,("call_trans2qfilepathinfo: "
6037 "SMB_VFS_LSTAT of %s failed "
6039 smb_fname_str_dbg(smb_fname),
6042 map_nt_error_from_unix(errno));
6045 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6046 DEBUG(3,("call_trans2qfilepathinfo: "
6047 "SMB_VFS_STAT of %s failed (%s)\n",
6048 smb_fname_str_dbg(smb_fname),
6051 map_nt_error_from_unix(errno));
6055 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6056 fileid = vfs_file_id_from_sbuf(
6057 conn, &smb_fname->st);
6058 get_file_infos(fileid, fsp->name_hash,
6064 * Original code - this is an open file.
6066 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6067 DEBUG(3, ("fstat of %s failed (%s)\n",
6068 fsp_fnum_dbg(fsp), strerror(errno)));
6070 map_nt_error_from_unix(errno));
6073 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6074 fileid = vfs_file_id_from_sbuf(
6075 conn, &smb_fname->st);
6076 get_file_infos(fileid, fsp->name_hash,
6085 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6088 if (total_params < 7) {
6089 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6093 info_level = SVAL(params,0);
6095 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6097 if (INFO_LEVEL_IS_UNIX(info_level)) {
6098 if (!lp_unix_extensions()) {
6099 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6102 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6103 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6104 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6105 req->posix_pathnames) {
6106 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6110 if (req->posix_pathnames) {
6111 srvstr_get_path_posix(req,
6120 srvstr_get_path(req,
6129 if (!NT_STATUS_IS_OK(status)) {
6130 reply_nterror(req, status);
6134 status = filename_convert(req,
6141 if (!NT_STATUS_IS_OK(status)) {
6142 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6143 reply_botherror(req,
6144 NT_STATUS_PATH_NOT_COVERED,
6145 ERRSRV, ERRbadpath);
6148 reply_nterror(req, status);
6152 /* If this is a stream, check if there is a delete_pending. */
6153 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6154 && is_ntfs_stream_smb_fname(smb_fname)) {
6155 struct smb_filename *smb_fname_base;
6157 /* Create an smb_filename with stream_name == NULL. */
6158 smb_fname_base = synthetic_smb_fname(
6160 smb_fname->base_name,
6164 if (smb_fname_base == NULL) {
6165 reply_nterror(req, NT_STATUS_NO_MEMORY);
6169 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6170 /* Always do lstat for UNIX calls. */
6171 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6172 DEBUG(3,("call_trans2qfilepathinfo: "
6173 "SMB_VFS_LSTAT of %s failed "
6175 smb_fname_str_dbg(smb_fname_base),
6177 TALLOC_FREE(smb_fname_base);
6179 map_nt_error_from_unix(errno));
6183 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6184 DEBUG(3,("call_trans2qfilepathinfo: "
6185 "fileinfo of %s failed "
6187 smb_fname_str_dbg(smb_fname_base),
6189 TALLOC_FREE(smb_fname_base);
6191 map_nt_error_from_unix(errno));
6196 status = file_name_hash(conn,
6197 smb_fname_str_dbg(smb_fname_base),
6199 if (!NT_STATUS_IS_OK(status)) {
6200 TALLOC_FREE(smb_fname_base);
6201 reply_nterror(req, status);
6205 fileid = vfs_file_id_from_sbuf(conn,
6206 &smb_fname_base->st);
6207 TALLOC_FREE(smb_fname_base);
6208 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6209 if (delete_pending) {
6210 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6215 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6216 /* Always do lstat for UNIX calls. */
6217 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6218 DEBUG(3,("call_trans2qfilepathinfo: "
6219 "SMB_VFS_LSTAT of %s failed (%s)\n",
6220 smb_fname_str_dbg(smb_fname),
6223 map_nt_error_from_unix(errno));
6228 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6229 DEBUG(3,("call_trans2qfilepathinfo: "
6230 "SMB_VFS_STAT of %s failed (%s)\n",
6231 smb_fname_str_dbg(smb_fname),
6234 map_nt_error_from_unix(errno));
6239 status = file_name_hash(conn,
6240 smb_fname_str_dbg(smb_fname),
6242 if (!NT_STATUS_IS_OK(status)) {
6243 reply_nterror(req, status);
6247 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6248 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6249 get_file_infos(fileid, name_hash, &delete_pending,
6253 if (delete_pending) {
6254 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6259 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6260 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6262 info_level,tran_call,total_data));
6264 /* Pull out any data sent here before we realloc. */
6265 switch (info_level) {
6266 case SMB_INFO_QUERY_EAS_FROM_LIST:
6268 /* Pull any EA list from the data portion. */
6271 if (total_data < 4) {
6273 req, NT_STATUS_INVALID_PARAMETER);
6276 ea_size = IVAL(pdata,0);
6278 if (total_data > 0 && ea_size != total_data) {
6279 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6280 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6282 req, NT_STATUS_INVALID_PARAMETER);
6286 if (!lp_ea_support(SNUM(conn))) {
6287 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6291 /* Pull out the list of names. */
6292 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6295 req, NT_STATUS_INVALID_PARAMETER);
6301 case SMB_QUERY_POSIX_LOCK:
6303 if (fsp == NULL || fsp->fh->fd == -1) {
6304 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6308 if (total_data != POSIX_LOCK_DATA_SIZE) {
6310 req, NT_STATUS_INVALID_PARAMETER);
6314 /* Copy the lock range data. */
6315 lock_data = (char *)talloc_memdup(
6316 req, pdata, total_data);
6318 reply_nterror(req, NT_STATUS_NO_MEMORY);
6321 lock_data_count = total_data;
6327 *pparams = (char *)SMB_REALLOC(*pparams,2);
6328 if (*pparams == NULL) {
6329 reply_nterror(req, NT_STATUS_NO_MEMORY);
6336 * draft-leach-cifs-v1-spec-02.txt
6337 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6340 * The requested information is placed in the Data portion of the
6341 * transaction response. For the information levels greater than 0x100,
6342 * the transaction response has 1 parameter word which should be
6343 * ignored by the client.
6345 * However Windows only follows this rule for the IS_NAME_VALID call.
6347 switch (info_level) {
6348 case SMB_INFO_IS_NAME_VALID:
6353 if ((info_level & 0xFF00) == 0xFF00) {
6355 * We use levels that start with 0xFF00
6356 * internally to represent SMB2 specific levels
6358 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6362 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6364 delete_pending, write_time_ts,
6366 lock_data_count, lock_data,
6367 req->flags2, max_data_bytes,
6369 ppdata, &data_size);
6370 if (!NT_STATUS_IS_OK(status)) {
6371 if (open_was_deferred(req->xconn, req->mid)) {
6372 /* We have re-scheduled this call. */
6375 reply_nterror(req, status);
6378 if (fixed_portion > max_data_bytes) {
6379 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6383 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6389 /****************************************************************************
6390 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6392 ****************************************************************************/
6394 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6395 connection_struct *conn,
6396 struct smb_request *req,
6397 bool overwrite_if_exists,
6398 const struct smb_filename *smb_fname_old,
6399 struct smb_filename *smb_fname_new)
6401 NTSTATUS status = NT_STATUS_OK;
6404 /* source must already exist. */
6405 if (!VALID_STAT(smb_fname_old->st)) {
6406 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6409 if (VALID_STAT(smb_fname_new->st)) {
6410 if (overwrite_if_exists) {
6411 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6412 return NT_STATUS_FILE_IS_A_DIRECTORY;
6414 status = unlink_internals(conn,
6416 FILE_ATTRIBUTE_NORMAL,
6419 if (!NT_STATUS_IS_OK(status)) {
6423 /* Disallow if newname already exists. */
6424 return NT_STATUS_OBJECT_NAME_COLLISION;
6428 /* No links from a directory. */
6429 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6430 return NT_STATUS_FILE_IS_A_DIRECTORY;
6433 /* Setting a hardlink to/from a stream isn't currently supported. */
6434 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6436 DBG_DEBUG("Old name has streams\n");
6437 return NT_STATUS_INVALID_PARAMETER;
6439 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6441 DBG_DEBUG("New name has streams\n");
6442 return NT_STATUS_INVALID_PARAMETER;
6445 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6446 smb_fname_old->base_name, smb_fname_new->base_name));
6448 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6449 status = map_nt_error_from_unix(errno);
6450 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6451 nt_errstr(status), smb_fname_old->base_name,
6452 smb_fname_new->base_name));
6457 /****************************************************************************
6458 Deal with setting the time from any of the setfilepathinfo functions.
6459 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6460 calling this function.
6461 ****************************************************************************/
6463 NTSTATUS smb_set_file_time(connection_struct *conn,
6465 const struct smb_filename *smb_fname,
6466 struct smb_file_time *ft,
6467 bool setting_write_time)
6469 struct smb_filename smb_fname_base;
6471 FILE_NOTIFY_CHANGE_LAST_ACCESS
6472 |FILE_NOTIFY_CHANGE_LAST_WRITE
6473 |FILE_NOTIFY_CHANGE_CREATION;
6475 if (!VALID_STAT(smb_fname->st)) {
6476 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6479 /* get some defaults (no modifications) if any info is zero or -1. */
6480 if (null_timespec(ft->create_time)) {
6481 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6484 if (null_timespec(ft->atime)) {
6485 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6488 if (null_timespec(ft->mtime)) {
6489 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6492 if (!setting_write_time) {
6493 /* ft->mtime comes from change time, not write time. */
6494 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6497 /* Ensure the resolution is the correct for
6498 * what we can store on this filesystem. */
6500 round_timespec(conn->ts_res, &ft->create_time);
6501 round_timespec(conn->ts_res, &ft->ctime);
6502 round_timespec(conn->ts_res, &ft->atime);
6503 round_timespec(conn->ts_res, &ft->mtime);
6505 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6506 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6507 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6508 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6509 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6510 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6511 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6512 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6514 if (setting_write_time) {
6516 * This was a Windows setfileinfo on an open file.
6517 * NT does this a lot. We also need to
6518 * set the time here, as it can be read by
6519 * FindFirst/FindNext and with the patch for bug #2045
6520 * in smbd/fileio.c it ensures that this timestamp is
6521 * kept sticky even after a write. We save the request
6522 * away and will set it on file close and after a write. JRA.
6525 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6526 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6529 if (fsp->base_fsp) {
6530 set_sticky_write_time_fsp(fsp->base_fsp,
6533 set_sticky_write_time_fsp(fsp, ft->mtime);
6536 set_sticky_write_time_path(
6537 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6542 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6544 /* Always call ntimes on the base, even if a stream was passed in. */
6545 smb_fname_base = *smb_fname;
6546 smb_fname_base.stream_name = NULL;
6548 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6549 return map_nt_error_from_unix(errno);
6552 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6553 smb_fname->base_name);
6554 return NT_STATUS_OK;
6557 /****************************************************************************
6558 Deal with setting the dosmode from any of the setfilepathinfo functions.
6559 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6560 done before calling this function.
6561 ****************************************************************************/
6563 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6564 const struct smb_filename *smb_fname,
6567 struct smb_filename *smb_fname_base;
6570 if (!VALID_STAT(smb_fname->st)) {
6571 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6574 /* Always operate on the base_name, even if a stream was passed in. */
6575 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6576 smb_fname->base_name,
6580 if (smb_fname_base == NULL) {
6581 return NT_STATUS_NO_MEMORY;
6585 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6586 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6588 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6592 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6594 /* check the mode isn't different, before changing it */
6595 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6596 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6597 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6598 (unsigned int)dosmode));
6600 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6602 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6604 smb_fname_str_dbg(smb_fname_base),
6606 status = map_nt_error_from_unix(errno);
6610 status = NT_STATUS_OK;
6612 TALLOC_FREE(smb_fname_base);
6616 /****************************************************************************
6617 Deal with setting the size from any of the setfilepathinfo functions.
6618 ****************************************************************************/
6620 static NTSTATUS smb_set_file_size(connection_struct *conn,
6621 struct smb_request *req,
6623 const struct smb_filename *smb_fname,
6624 const SMB_STRUCT_STAT *psbuf,
6626 bool fail_after_createfile)
6628 NTSTATUS status = NT_STATUS_OK;
6629 struct smb_filename *smb_fname_tmp = NULL;
6630 files_struct *new_fsp = NULL;
6632 if (!VALID_STAT(*psbuf)) {
6633 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6636 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6638 get_file_size_stat(psbuf));
6640 if (size == get_file_size_stat(psbuf)) {
6641 return NT_STATUS_OK;
6644 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6645 smb_fname_str_dbg(smb_fname), (double)size));
6647 if (fsp && fsp->fh->fd != -1) {
6648 /* Handle based call. */
6649 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6650 return NT_STATUS_ACCESS_DENIED;
6653 if (vfs_set_filelen(fsp, size) == -1) {
6654 return map_nt_error_from_unix(errno);
6656 trigger_write_time_update_immediate(fsp);
6657 return NT_STATUS_OK;
6660 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6661 if (smb_fname_tmp == NULL) {
6662 return NT_STATUS_NO_MEMORY;
6665 smb_fname_tmp->st = *psbuf;
6667 status = SMB_VFS_CREATE_FILE(
6670 0, /* root_dir_fid */
6671 smb_fname_tmp, /* fname */
6672 FILE_WRITE_DATA, /* access_mask */
6673 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6675 FILE_OPEN, /* create_disposition*/
6676 0, /* create_options */
6677 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6678 0, /* oplock_request */
6680 0, /* allocation_size */
6681 0, /* private_flags */
6684 &new_fsp, /* result */
6686 NULL, NULL); /* create context */
6688 TALLOC_FREE(smb_fname_tmp);
6690 if (!NT_STATUS_IS_OK(status)) {
6691 /* NB. We check for open_was_deferred in the caller. */
6695 /* See RAW-SFILEINFO-END-OF-FILE */
6696 if (fail_after_createfile) {
6697 close_file(req, new_fsp,NORMAL_CLOSE);
6698 return NT_STATUS_INVALID_LEVEL;
6701 if (vfs_set_filelen(new_fsp, size) == -1) {
6702 status = map_nt_error_from_unix(errno);
6703 close_file(req, new_fsp,NORMAL_CLOSE);
6707 trigger_write_time_update_immediate(new_fsp);
6708 close_file(req, new_fsp,NORMAL_CLOSE);
6709 return NT_STATUS_OK;
6712 /****************************************************************************
6713 Deal with SMB_INFO_SET_EA.
6714 ****************************************************************************/
6716 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6720 const struct smb_filename *smb_fname)
6722 struct ea_list *ea_list = NULL;
6723 TALLOC_CTX *ctx = NULL;
6724 NTSTATUS status = NT_STATUS_OK;
6726 if (total_data < 10) {
6728 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6729 length. They seem to have no effect. Bug #3212. JRA */
6731 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6732 /* We're done. We only get EA info in this call. */
6733 return NT_STATUS_OK;
6736 return NT_STATUS_INVALID_PARAMETER;
6739 if (IVAL(pdata,0) > total_data) {
6740 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6741 IVAL(pdata,0), (unsigned int)total_data));
6742 return NT_STATUS_INVALID_PARAMETER;
6746 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6748 return NT_STATUS_INVALID_PARAMETER;
6751 status = set_ea(conn, fsp, smb_fname, ea_list);
6756 /****************************************************************************
6757 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6758 ****************************************************************************/
6760 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6765 struct ea_list *ea_list = NULL;
6769 return NT_STATUS_INVALID_HANDLE;
6772 if (!lp_ea_support(SNUM(conn))) {
6773 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6774 "EA's not supported.\n",
6775 (unsigned int)total_data));
6776 return NT_STATUS_EAS_NOT_SUPPORTED;
6779 if (total_data < 10) {
6780 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6782 (unsigned int)total_data));
6783 return NT_STATUS_INVALID_PARAMETER;
6786 ea_list = read_nttrans_ea_list(talloc_tos(),
6791 return NT_STATUS_INVALID_PARAMETER;
6794 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6796 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6797 smb_fname_str_dbg(fsp->fsp_name),
6798 nt_errstr(status) ));
6804 /****************************************************************************
6805 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6806 ****************************************************************************/
6808 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6812 struct smb_filename *smb_fname)
6814 NTSTATUS status = NT_STATUS_OK;
6815 bool delete_on_close;
6816 uint32_t dosmode = 0;
6818 if (total_data < 1) {
6819 return NT_STATUS_INVALID_PARAMETER;
6823 return NT_STATUS_INVALID_HANDLE;
6826 delete_on_close = (CVAL(pdata,0) ? True : False);
6827 dosmode = dos_mode(conn, smb_fname);
6829 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6830 "delete_on_close = %u\n",
6831 smb_fname_str_dbg(smb_fname),
6832 (unsigned int)dosmode,
6833 (unsigned int)delete_on_close ));
6835 if (delete_on_close) {
6836 status = can_set_delete_on_close(fsp, dosmode);
6837 if (!NT_STATUS_IS_OK(status)) {
6842 /* The set is across all open files on this dev/inode pair. */
6843 if (!set_delete_on_close(fsp, delete_on_close,
6844 conn->session_info->security_token,
6845 conn->session_info->unix_token)) {
6846 return NT_STATUS_ACCESS_DENIED;
6848 return NT_STATUS_OK;
6851 /****************************************************************************
6852 Deal with SMB_FILE_POSITION_INFORMATION.
6853 ****************************************************************************/
6855 static NTSTATUS smb_file_position_information(connection_struct *conn,
6860 uint64_t position_information;
6862 if (total_data < 8) {
6863 return NT_STATUS_INVALID_PARAMETER;
6867 /* Ignore on pathname based set. */
6868 return NT_STATUS_OK;
6871 position_information = (uint64_t)IVAL(pdata,0);
6872 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6874 DEBUG(10,("smb_file_position_information: Set file position "
6875 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6876 (double)position_information));
6877 fsp->fh->position_information = position_information;
6878 return NT_STATUS_OK;
6881 /****************************************************************************
6882 Deal with SMB_FILE_MODE_INFORMATION.
6883 ****************************************************************************/
6885 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6891 if (total_data < 4) {
6892 return NT_STATUS_INVALID_PARAMETER;
6894 mode = IVAL(pdata,0);
6895 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6896 return NT_STATUS_INVALID_PARAMETER;
6898 return NT_STATUS_OK;
6901 /****************************************************************************
6902 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6903 ****************************************************************************/
6905 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6906 struct smb_request *req,
6909 const struct smb_filename *new_smb_fname)
6911 char *link_target = NULL;
6912 TALLOC_CTX *ctx = talloc_tos();
6914 /* Set a symbolic link. */
6915 /* Don't allow this if follow links is false. */
6917 if (total_data == 0) {
6918 return NT_STATUS_INVALID_PARAMETER;
6921 if (!lp_follow_symlinks(SNUM(conn))) {
6922 return NT_STATUS_ACCESS_DENIED;
6925 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6926 total_data, STR_TERMINATE);
6929 return NT_STATUS_INVALID_PARAMETER;
6932 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6933 new_smb_fname->base_name, link_target ));
6935 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6936 return map_nt_error_from_unix(errno);
6939 return NT_STATUS_OK;
6942 /****************************************************************************
6943 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6944 ****************************************************************************/
6946 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6947 struct smb_request *req,
6948 const char *pdata, int total_data,
6949 struct smb_filename *smb_fname_new)
6951 char *oldname = NULL;
6952 struct smb_filename *smb_fname_old = NULL;
6953 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6954 TALLOC_CTX *ctx = talloc_tos();
6955 NTSTATUS status = NT_STATUS_OK;
6957 /* Set a hard link. */
6958 if (total_data == 0) {
6959 return NT_STATUS_INVALID_PARAMETER;
6962 if (req->posix_pathnames) {
6963 srvstr_get_path_posix(ctx,
6972 srvstr_get_path(ctx,
6981 if (!NT_STATUS_IS_OK(status)) {
6985 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6986 smb_fname_str_dbg(smb_fname_new), oldname));
6988 status = filename_convert(ctx,
6995 if (!NT_STATUS_IS_OK(status)) {
6999 return hardlink_internals(ctx, conn, req, false,
7000 smb_fname_old, smb_fname_new);
7003 /****************************************************************************
7004 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7005 ****************************************************************************/
7007 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7008 struct smb_request *req,
7012 struct smb_filename *smb_fname_src)
7016 char *newname = NULL;
7017 struct smb_filename *smb_fname_dst = NULL;
7018 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7019 ucf_flags_from_smb_request(req);
7020 NTSTATUS status = NT_STATUS_OK;
7021 TALLOC_CTX *ctx = talloc_tos();
7024 return NT_STATUS_INVALID_HANDLE;
7027 if (total_data < 20) {
7028 return NT_STATUS_INVALID_PARAMETER;
7031 overwrite = (CVAL(pdata,0) ? True : False);
7032 len = IVAL(pdata,16);
7034 if (len > (total_data - 20) || (len == 0)) {
7035 return NT_STATUS_INVALID_PARAMETER;
7038 if (req->posix_pathnames) {
7039 srvstr_get_path_posix(ctx,
7048 srvstr_get_path(ctx,
7057 if (!NT_STATUS_IS_OK(status)) {
7061 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7064 status = filename_convert(ctx,
7071 if (!NT_STATUS_IS_OK(status)) {
7075 if (fsp->base_fsp) {
7076 /* newname must be a stream name. */
7077 if (newname[0] != ':') {
7078 return NT_STATUS_NOT_SUPPORTED;
7081 /* Create an smb_fname to call rename_internals_fsp() with. */
7082 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7083 fsp->base_fsp->fsp_name->base_name,
7086 fsp->base_fsp->fsp_name->flags);
7087 if (smb_fname_dst == NULL) {
7088 status = NT_STATUS_NO_MEMORY;
7093 * Set the original last component, since
7094 * rename_internals_fsp() requires it.
7096 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7098 if (smb_fname_dst->original_lcomp == NULL) {
7099 status = NT_STATUS_NO_MEMORY;
7105 DEBUG(10,("smb2_file_rename_information: "
7106 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7107 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7108 smb_fname_str_dbg(smb_fname_dst)));
7109 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7110 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7114 TALLOC_FREE(smb_fname_dst);
7118 static NTSTATUS smb_file_link_information(connection_struct *conn,
7119 struct smb_request *req,
7123 struct smb_filename *smb_fname_src)
7127 char *newname = NULL;
7128 struct smb_filename *smb_fname_dst = NULL;
7129 NTSTATUS status = NT_STATUS_OK;
7130 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7131 ucf_flags_from_smb_request(req);
7132 TALLOC_CTX *ctx = talloc_tos();
7135 return NT_STATUS_INVALID_HANDLE;
7138 if (total_data < 20) {
7139 return NT_STATUS_INVALID_PARAMETER;
7142 overwrite = (CVAL(pdata,0) ? true : false);
7143 len = IVAL(pdata,16);
7145 if (len > (total_data - 20) || (len == 0)) {
7146 return NT_STATUS_INVALID_PARAMETER;
7149 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7150 srvstr_get_path_posix(ctx,
7158 ucf_flags |= UCF_POSIX_PATHNAMES;
7160 srvstr_get_path(ctx,
7169 if (!NT_STATUS_IS_OK(status)) {
7173 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7176 status = filename_convert(ctx,
7183 if (!NT_STATUS_IS_OK(status)) {
7187 if (fsp->base_fsp) {
7188 /* No stream names. */
7189 return NT_STATUS_NOT_SUPPORTED;
7192 DEBUG(10,("smb_file_link_information: "
7193 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7194 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7195 smb_fname_str_dbg(smb_fname_dst)));
7196 status = hardlink_internals(ctx,
7203 TALLOC_FREE(smb_fname_dst);
7207 /****************************************************************************
7208 Deal with SMB_FILE_RENAME_INFORMATION.
7209 ****************************************************************************/
7211 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7212 struct smb_request *req,
7216 struct smb_filename *smb_fname_src)
7221 char *newname = NULL;
7222 struct smb_filename *smb_fname_dst = NULL;
7223 bool dest_has_wcard = False;
7224 NTSTATUS status = NT_STATUS_OK;
7226 TALLOC_CTX *ctx = talloc_tos();
7228 if (total_data < 13) {
7229 return NT_STATUS_INVALID_PARAMETER;
7232 overwrite = (CVAL(pdata,0) ? True : False);
7233 root_fid = IVAL(pdata,4);
7234 len = IVAL(pdata,8);
7236 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7237 return NT_STATUS_INVALID_PARAMETER;
7240 if (req->posix_pathnames) {
7241 srvstr_get_path_wcard_posix(ctx,
7251 srvstr_get_path_wcard(ctx,
7261 if (!NT_STATUS_IS_OK(status)) {
7265 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7268 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7269 status = resolve_dfspath_wcard(ctx, conn,
7271 UCF_COND_ALLOW_WCARD_LCOMP,
7272 !conn->sconn->using_smb2,
7275 if (!NT_STATUS_IS_OK(status)) {
7280 /* Check the new name has no '/' characters. */
7281 if (strchr_m(newname, '/')) {
7282 return NT_STATUS_NOT_SUPPORTED;
7285 if (fsp && fsp->base_fsp) {
7286 /* newname must be a stream name. */
7287 if (newname[0] != ':') {
7288 return NT_STATUS_NOT_SUPPORTED;
7291 /* Create an smb_fname to call rename_internals_fsp() with. */
7292 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7293 fsp->base_fsp->fsp_name->base_name,
7296 fsp->base_fsp->fsp_name->flags);
7297 if (smb_fname_dst == NULL) {
7298 status = NT_STATUS_NO_MEMORY;
7303 * Set the original last component, since
7304 * rename_internals_fsp() requires it.
7306 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7308 if (smb_fname_dst->original_lcomp == NULL) {
7309 status = NT_STATUS_NO_MEMORY;
7315 * Build up an smb_fname_dst based on the filename passed in.
7316 * We basically just strip off the last component, and put on
7317 * the newname instead.
7319 char *base_name = NULL;
7320 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7321 ucf_flags_from_smb_request(req);
7323 if (dest_has_wcard) {
7324 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7327 /* newname must *not* be a stream name. */
7328 if (newname[0] == ':') {
7329 return NT_STATUS_NOT_SUPPORTED;
7333 * Strip off the last component (filename) of the path passed
7336 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7338 return NT_STATUS_NO_MEMORY;
7340 p = strrchr_m(base_name, '/');
7344 base_name = talloc_strdup(ctx, "");
7346 return NT_STATUS_NO_MEMORY;
7349 /* Append the new name. */
7350 base_name = talloc_asprintf_append(base_name,
7354 return NT_STATUS_NO_MEMORY;
7357 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7360 /* If an error we expect this to be
7361 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7363 if (!NT_STATUS_IS_OK(status)) {
7364 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7368 /* Create an smb_fname to call rename_internals_fsp() */
7369 smb_fname_dst = synthetic_smb_fname(ctx,
7373 smb_fname_src->flags);
7374 if (smb_fname_dst == NULL) {
7375 status = NT_STATUS_NO_MEMORY;
7382 DEBUG(10,("smb_file_rename_information: "
7383 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7384 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7385 smb_fname_str_dbg(smb_fname_dst)));
7386 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7389 DEBUG(10,("smb_file_rename_information: "
7390 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7391 smb_fname_str_dbg(smb_fname_src),
7392 smb_fname_str_dbg(smb_fname_dst)));
7393 status = rename_internals(ctx, conn, req, smb_fname_src,
7394 smb_fname_dst, 0, overwrite, false,
7396 FILE_WRITE_ATTRIBUTES);
7399 TALLOC_FREE(smb_fname_dst);
7403 /****************************************************************************
7404 Deal with SMB_SET_POSIX_ACL.
7405 ****************************************************************************/
7407 #if defined(HAVE_POSIX_ACLS)
7408 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7409 struct smb_request *req,
7413 const struct smb_filename *smb_fname)
7415 uint16_t posix_acl_version;
7416 uint16_t num_file_acls;
7417 uint16_t num_def_acls;
7418 bool valid_file_acls = true;
7419 bool valid_def_acls = true;
7421 unsigned int size_needed;
7422 unsigned int total_data;
7423 bool close_fsp = false;
7425 if (total_data_in < 0) {
7426 status = NT_STATUS_INVALID_PARAMETER;
7430 total_data = total_data_in;
7432 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7433 status = NT_STATUS_INVALID_PARAMETER;
7436 posix_acl_version = SVAL(pdata,0);
7437 num_file_acls = SVAL(pdata,2);
7438 num_def_acls = SVAL(pdata,4);
7440 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7441 valid_file_acls = false;
7445 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7446 valid_def_acls = false;
7450 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7451 status = NT_STATUS_INVALID_PARAMETER;
7456 if (num_file_acls + num_def_acls < num_file_acls) {
7457 status = NT_STATUS_INVALID_PARAMETER;
7461 size_needed = num_file_acls + num_def_acls;
7464 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7465 * than UINT_MAX, so check by division.
7467 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7468 status = NT_STATUS_INVALID_PARAMETER;
7472 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7473 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7474 status = NT_STATUS_INVALID_PARAMETER;
7477 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7479 if (total_data < size_needed) {
7480 status = NT_STATUS_INVALID_PARAMETER;
7485 * Ensure we always operate on a file descriptor, not just
7489 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7491 SEC_STD_READ_CONTROL|
7492 FILE_READ_ATTRIBUTES|
7493 FILE_WRITE_ATTRIBUTES;
7495 status = get_posix_fsp(conn,
7501 if (!NT_STATUS_IS_OK(status)) {
7507 /* Here we know fsp != NULL */
7508 SMB_ASSERT(fsp != NULL);
7510 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7511 if (!NT_STATUS_IS_OK(status)) {
7515 /* If we have a default acl, this *must* be a directory. */
7516 if (valid_def_acls && !fsp->is_directory) {
7517 DBG_INFO("Can't set default acls on "
7518 "non-directory %s\n",
7520 return NT_STATUS_INVALID_HANDLE;
7523 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7524 "num_def_acls = %"PRIu16"\n",
7529 /* Move pdata to the start of the file ACL entries. */
7530 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7532 if (valid_file_acls) {
7533 status = set_unix_posix_acl(conn,
7537 if (!NT_STATUS_IS_OK(status)) {
7542 /* Move pdata to the start of the default ACL entries. */
7543 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7545 if (valid_def_acls) {
7546 status = set_unix_posix_default_acl(conn,
7550 if (!NT_STATUS_IS_OK(status)) {
7555 status = NT_STATUS_OK;
7560 (void)close_file(req, fsp, NORMAL_CLOSE);
7567 /****************************************************************************
7568 Deal with SMB_SET_POSIX_LOCK.
7569 ****************************************************************************/
7571 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7573 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7574 struct smb_request *req,
7579 struct tevent_req *subreq = NULL;
7580 struct smbd_lock_element *lck = NULL;
7584 bool blocking_lock = False;
7585 enum brl_type lock_type;
7587 NTSTATUS status = NT_STATUS_OK;
7589 if (fsp == NULL || fsp->fh->fd == -1) {
7590 return NT_STATUS_INVALID_HANDLE;
7593 if (total_data != POSIX_LOCK_DATA_SIZE) {
7594 return NT_STATUS_INVALID_PARAMETER;
7597 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7598 case POSIX_LOCK_TYPE_READ:
7599 lock_type = READ_LOCK;
7601 case POSIX_LOCK_TYPE_WRITE:
7602 /* Return the right POSIX-mappable error code for files opened read-only. */
7603 if (!fsp->can_write) {
7604 return NT_STATUS_INVALID_HANDLE;
7606 lock_type = WRITE_LOCK;
7608 case POSIX_LOCK_TYPE_UNLOCK:
7609 lock_type = UNLOCK_LOCK;
7612 return NT_STATUS_INVALID_PARAMETER;
7615 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7616 case POSIX_LOCK_FLAG_NOWAIT:
7617 blocking_lock = false;
7619 case POSIX_LOCK_FLAG_WAIT:
7620 blocking_lock = true;
7623 return NT_STATUS_INVALID_PARAMETER;
7626 if (!lp_blocking_locks(SNUM(conn))) {
7627 blocking_lock = False;
7630 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7631 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7632 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7633 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7634 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7636 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7637 "count = %"PRIu64", offset = %"PRIu64"\n",
7639 (unsigned int)lock_type,
7644 if (lock_type == UNLOCK_LOCK) {
7645 struct smbd_lock_element l = {
7647 .brltype = UNLOCK_LOCK,
7651 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7655 lck = talloc(req, struct smbd_lock_element);
7657 return NT_STATUS_NO_MEMORY;
7660 *lck = (struct smbd_lock_element) {
7662 .brltype = lock_type,
7667 subreq = smbd_smb1_do_locks_send(
7672 blocking_lock ? UINT32_MAX : 0,
7673 true, /* large_offset */
7677 if (subreq == NULL) {
7679 return NT_STATUS_NO_MEMORY;
7681 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7682 return NT_STATUS_EVENT_PENDING;
7685 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7687 struct smb_request *req = NULL;
7691 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7694 status = smbd_smb1_do_locks_recv(subreq);
7695 TALLOC_FREE(subreq);
7697 if (NT_STATUS_IS_OK(status)) {
7698 char params[2] = {0};
7699 /* Fake up max_data_bytes here - we know it fits. */
7700 send_trans2_replies(
7710 reply_nterror(req, status);
7713 (char *)req->outbuf,
7716 IS_CONN_ENCRYPTED(req->conn),
7719 exit_server_cleanly("smb_set_posix_lock_done: "
7720 "srv_send_smb failed.");
7728 /****************************************************************************
7729 Deal with SMB_SET_FILE_BASIC_INFO.
7730 ****************************************************************************/
7732 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7736 const struct smb_filename *smb_fname)
7738 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7739 struct smb_file_time ft;
7740 uint32_t dosmode = 0;
7741 NTSTATUS status = NT_STATUS_OK;
7745 if (total_data < 36) {
7746 return NT_STATUS_INVALID_PARAMETER;
7749 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7750 if (!NT_STATUS_IS_OK(status)) {
7754 /* Set the attributes */
7755 dosmode = IVAL(pdata,32);
7756 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7757 if (!NT_STATUS_IS_OK(status)) {
7762 ft.create_time = interpret_long_date(pdata);
7765 ft.atime = interpret_long_date(pdata+8);
7768 ft.mtime = interpret_long_date(pdata+16);
7771 ft.ctime = interpret_long_date(pdata+24);
7773 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7774 smb_fname_str_dbg(smb_fname)));
7776 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7780 /****************************************************************************
7781 Deal with SMB_INFO_STANDARD.
7782 ****************************************************************************/
7784 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7788 const struct smb_filename *smb_fname)
7791 struct smb_file_time ft;
7795 if (total_data < 12) {
7796 return NT_STATUS_INVALID_PARAMETER;
7800 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7802 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7804 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7806 DEBUG(10,("smb_set_info_standard: file %s\n",
7807 smb_fname_str_dbg(smb_fname)));
7809 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7810 if (!NT_STATUS_IS_OK(status)) {
7814 return smb_set_file_time(conn,
7821 /****************************************************************************
7822 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7823 ****************************************************************************/
7825 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7826 struct smb_request *req,
7830 struct smb_filename *smb_fname)
7832 uint64_t allocation_size = 0;
7833 NTSTATUS status = NT_STATUS_OK;
7834 files_struct *new_fsp = NULL;
7836 if (!VALID_STAT(smb_fname->st)) {
7837 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7840 if (total_data < 8) {
7841 return NT_STATUS_INVALID_PARAMETER;
7844 allocation_size = (uint64_t)IVAL(pdata,0);
7845 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7846 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7847 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7848 (double)allocation_size));
7850 if (allocation_size) {
7851 allocation_size = smb_roundup(conn, allocation_size);
7854 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7855 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7856 (double)allocation_size));
7858 if (fsp && fsp->fh->fd != -1) {
7859 /* Open file handle. */
7860 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7861 return NT_STATUS_ACCESS_DENIED;
7864 /* Only change if needed. */
7865 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7866 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7867 return map_nt_error_from_unix(errno);
7870 /* But always update the time. */
7872 * This is equivalent to a write. Ensure it's seen immediately
7873 * if there are no pending writes.
7875 trigger_write_time_update_immediate(fsp);
7876 return NT_STATUS_OK;
7879 /* Pathname or stat or directory file. */
7880 status = SMB_VFS_CREATE_FILE(
7883 0, /* root_dir_fid */
7884 smb_fname, /* fname */
7885 FILE_WRITE_DATA, /* access_mask */
7886 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7888 FILE_OPEN, /* create_disposition*/
7889 0, /* create_options */
7890 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7891 0, /* oplock_request */
7893 0, /* allocation_size */
7894 0, /* private_flags */
7897 &new_fsp, /* result */
7899 NULL, NULL); /* create context */
7901 if (!NT_STATUS_IS_OK(status)) {
7902 /* NB. We check for open_was_deferred in the caller. */
7906 /* Only change if needed. */
7907 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7908 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7909 status = map_nt_error_from_unix(errno);
7910 close_file(req, new_fsp, NORMAL_CLOSE);
7915 /* Changing the allocation size should set the last mod time. */
7917 * This is equivalent to a write. Ensure it's seen immediately
7918 * if there are no pending writes.
7920 trigger_write_time_update_immediate(new_fsp);
7921 close_file(req, new_fsp, NORMAL_CLOSE);
7922 return NT_STATUS_OK;
7925 /****************************************************************************
7926 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7927 ****************************************************************************/
7929 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7930 struct smb_request *req,
7934 const struct smb_filename *smb_fname,
7935 bool fail_after_createfile)
7939 if (total_data < 8) {
7940 return NT_STATUS_INVALID_PARAMETER;
7943 size = IVAL(pdata,0);
7944 size |= (((off_t)IVAL(pdata,4)) << 32);
7945 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7946 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7949 return smb_set_file_size(conn, req,
7954 fail_after_createfile);
7957 /****************************************************************************
7958 Allow a UNIX info mknod.
7959 ****************************************************************************/
7961 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7964 const struct smb_filename *smb_fname)
7966 uint32_t file_type = IVAL(pdata,56);
7967 #if defined(HAVE_MAKEDEV)
7968 uint32_t dev_major = IVAL(pdata,60);
7969 uint32_t dev_minor = IVAL(pdata,68);
7971 SMB_DEV_T dev = (SMB_DEV_T)0;
7972 uint32_t raw_unixmode = IVAL(pdata,84);
7976 if (total_data < 100) {
7977 return NT_STATUS_INVALID_PARAMETER;
7980 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7981 PERM_NEW_FILE, &unixmode);
7982 if (!NT_STATUS_IS_OK(status)) {
7986 #if defined(HAVE_MAKEDEV)
7987 dev = makedev(dev_major, dev_minor);
7990 switch (file_type) {
7991 #if defined(S_IFIFO)
7992 case UNIX_TYPE_FIFO:
7993 unixmode |= S_IFIFO;
7996 #if defined(S_IFSOCK)
7997 case UNIX_TYPE_SOCKET:
7998 unixmode |= S_IFSOCK;
8001 #if defined(S_IFCHR)
8002 case UNIX_TYPE_CHARDEV:
8003 unixmode |= S_IFCHR;
8006 #if defined(S_IFBLK)
8007 case UNIX_TYPE_BLKDEV:
8008 unixmode |= S_IFBLK;
8012 return NT_STATUS_INVALID_PARAMETER;
8015 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8016 "%.0f mode 0%o for file %s\n", (double)dev,
8017 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8019 /* Ok - do the mknod. */
8020 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
8021 return map_nt_error_from_unix(errno);
8024 /* If any of the other "set" calls fail we
8025 * don't want to end up with a half-constructed mknod.
8028 if (lp_inherit_permissions(SNUM(conn))) {
8030 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
8032 return NT_STATUS_NO_MEMORY;
8034 inherit_access_posix_acl(conn, parent, smb_fname,
8036 TALLOC_FREE(parent);
8039 return NT_STATUS_OK;
8042 /****************************************************************************
8043 Deal with SMB_SET_FILE_UNIX_BASIC.
8044 ****************************************************************************/
8046 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8047 struct smb_request *req,
8051 const struct smb_filename *smb_fname)
8053 struct smb_file_time ft;
8054 uint32_t raw_unixmode;
8057 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8058 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8059 NTSTATUS status = NT_STATUS_OK;
8060 bool delete_on_fail = False;
8061 enum perm_type ptype;
8062 files_struct *all_fsps = NULL;
8063 bool modify_mtime = true;
8065 struct smb_filename *smb_fname_tmp = NULL;
8066 SMB_STRUCT_STAT sbuf;
8070 if (total_data < 100) {
8071 return NT_STATUS_INVALID_PARAMETER;
8074 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8075 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8076 size=IVAL(pdata,0); /* first 8 Bytes are size */
8077 size |= (((off_t)IVAL(pdata,4)) << 32);
8080 ft.atime = interpret_long_date(pdata+24); /* access_time */
8081 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
8082 set_owner = (uid_t)IVAL(pdata,40);
8083 set_grp = (gid_t)IVAL(pdata,48);
8084 raw_unixmode = IVAL(pdata,84);
8086 if (VALID_STAT(smb_fname->st)) {
8087 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8088 ptype = PERM_EXISTING_DIR;
8090 ptype = PERM_EXISTING_FILE;
8093 ptype = PERM_NEW_FILE;
8096 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8098 if (!NT_STATUS_IS_OK(status)) {
8102 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8103 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8104 smb_fname_str_dbg(smb_fname), (double)size,
8105 (unsigned int)set_owner, (unsigned int)set_grp,
8106 (int)raw_unixmode));
8108 sbuf = smb_fname->st;
8110 if (!VALID_STAT(sbuf)) {
8112 * The only valid use of this is to create character and block
8113 * devices, and named pipes. This is deprecated (IMHO) and
8114 * a new info level should be used for mknod. JRA.
8117 status = smb_unix_mknod(conn,
8121 if (!NT_STATUS_IS_OK(status)) {
8125 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
8126 if (smb_fname_tmp == NULL) {
8127 return NT_STATUS_NO_MEMORY;
8130 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
8131 status = map_nt_error_from_unix(errno);
8132 TALLOC_FREE(smb_fname_tmp);
8133 SMB_VFS_UNLINK(conn, smb_fname);
8137 sbuf = smb_fname_tmp->st;
8138 smb_fname = smb_fname_tmp;
8140 /* Ensure we don't try and change anything else. */
8141 raw_unixmode = SMB_MODE_NO_CHANGE;
8142 size = get_file_size_stat(&sbuf);
8143 ft.atime = sbuf.st_ex_atime;
8144 ft.mtime = sbuf.st_ex_mtime;
8146 * We continue here as we might want to change the
8149 delete_on_fail = True;
8153 /* Horrible backwards compatibility hack as an old server bug
8154 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8158 size = get_file_size_stat(&sbuf);
8163 * Deal with the UNIX specific mode set.
8166 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8169 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8170 "setting mode 0%o for file %s\n",
8171 (unsigned int)unixmode,
8172 smb_fname_str_dbg(smb_fname)));
8173 if (fsp && fsp->fh->fd != -1) {
8174 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8176 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8179 return map_nt_error_from_unix(errno);
8184 * Deal with the UNIX specific uid set.
8187 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8188 (sbuf.st_ex_uid != set_owner)) {
8191 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8192 "changing owner %u for path %s\n",
8193 (unsigned int)set_owner,
8194 smb_fname_str_dbg(smb_fname)));
8196 if (fsp && fsp->fh->fd != -1) {
8197 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8200 * UNIX extensions calls must always operate
8203 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8204 set_owner, (gid_t)-1);
8208 status = map_nt_error_from_unix(errno);
8209 if (delete_on_fail) {
8210 SMB_VFS_UNLINK(conn, smb_fname);
8217 * Deal with the UNIX specific gid set.
8220 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8221 (sbuf.st_ex_gid != set_grp)) {
8224 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8225 "changing group %u for file %s\n",
8226 (unsigned int)set_grp,
8227 smb_fname_str_dbg(smb_fname)));
8228 if (fsp && fsp->fh->fd != -1) {
8229 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8232 * UNIX extensions calls must always operate
8235 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8239 status = map_nt_error_from_unix(errno);
8240 if (delete_on_fail) {
8241 SMB_VFS_UNLINK(conn, smb_fname);
8247 /* Deal with any size changes. */
8249 status = smb_set_file_size(conn, req,
8255 if (!NT_STATUS_IS_OK(status)) {
8259 /* Deal with any time changes. */
8260 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
8261 /* No change, don't cancel anything. */
8265 id = vfs_file_id_from_sbuf(conn, &sbuf);
8266 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8267 all_fsps = file_find_di_next(all_fsps)) {
8269 * We're setting the time explicitly for UNIX.
8270 * Cancel any pending changes over all handles.
8272 all_fsps->update_write_time_on_close = false;
8273 TALLOC_FREE(all_fsps->update_write_time_event);
8277 * Override the "setting_write_time"
8278 * parameter here as it almost does what
8279 * we need. Just remember if we modified
8280 * mtime and send the notify ourselves.
8282 if (null_timespec(ft.mtime)) {
8283 modify_mtime = false;
8286 status = smb_set_file_time(conn,
8292 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8293 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8298 /****************************************************************************
8299 Deal with SMB_SET_FILE_UNIX_INFO2.
8300 ****************************************************************************/
8302 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8303 struct smb_request *req,
8307 const struct smb_filename *smb_fname)
8310 uint32_t smb_fflags;
8313 if (total_data < 116) {
8314 return NT_STATUS_INVALID_PARAMETER;
8317 /* Start by setting all the fields that are common between UNIX_BASIC
8320 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8322 if (!NT_STATUS_IS_OK(status)) {
8326 smb_fflags = IVAL(pdata, 108);
8327 smb_fmask = IVAL(pdata, 112);
8329 /* NB: We should only attempt to alter the file flags if the client
8330 * sends a non-zero mask.
8332 if (smb_fmask != 0) {
8333 int stat_fflags = 0;
8335 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8336 smb_fmask, &stat_fflags)) {
8337 /* Client asked to alter a flag we don't understand. */
8338 return NT_STATUS_INVALID_PARAMETER;
8341 if (fsp && fsp->fh->fd != -1) {
8342 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8343 return NT_STATUS_NOT_SUPPORTED;
8345 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8346 stat_fflags) != 0) {
8347 return map_nt_error_from_unix(errno);
8352 /* XXX: need to add support for changing the create_time here. You
8353 * can do this for paths on Darwin with setattrlist(2). The right way
8354 * to hook this up is probably by extending the VFS utimes interface.
8357 return NT_STATUS_OK;
8360 /****************************************************************************
8361 Create a directory with POSIX semantics.
8362 ****************************************************************************/
8364 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8365 struct smb_request *req,
8368 struct smb_filename *smb_fname,
8369 int *pdata_return_size)
8371 NTSTATUS status = NT_STATUS_OK;
8372 uint32_t raw_unixmode = 0;
8373 uint32_t mod_unixmode = 0;
8374 mode_t unixmode = (mode_t)0;
8375 files_struct *fsp = NULL;
8376 uint16_t info_level_return = 0;
8378 char *pdata = *ppdata;
8380 if (total_data < 18) {
8381 return NT_STATUS_INVALID_PARAMETER;
8384 raw_unixmode = IVAL(pdata,8);
8385 /* Next 4 bytes are not yet defined. */
8387 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8388 PERM_NEW_DIR, &unixmode);
8389 if (!NT_STATUS_IS_OK(status)) {
8393 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8395 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8396 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8398 status = SMB_VFS_CREATE_FILE(
8401 0, /* root_dir_fid */
8402 smb_fname, /* fname */
8403 FILE_READ_ATTRIBUTES, /* access_mask */
8404 FILE_SHARE_NONE, /* share_access */
8405 FILE_CREATE, /* create_disposition*/
8406 FILE_DIRECTORY_FILE, /* create_options */
8407 mod_unixmode, /* file_attributes */
8408 0, /* oplock_request */
8410 0, /* allocation_size */
8411 0, /* private_flags */
8416 NULL, NULL); /* create context */
8418 if (NT_STATUS_IS_OK(status)) {
8419 close_file(req, fsp, NORMAL_CLOSE);
8422 info_level_return = SVAL(pdata,16);
8424 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8425 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8426 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8427 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8429 *pdata_return_size = 12;
8432 /* Realloc the data size */
8433 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8434 if (*ppdata == NULL) {
8435 *pdata_return_size = 0;
8436 return NT_STATUS_NO_MEMORY;
8440 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8441 SSVAL(pdata,2,0); /* No fnum. */
8442 SIVAL(pdata,4,info); /* Was directory created. */
8444 switch (info_level_return) {
8445 case SMB_QUERY_FILE_UNIX_BASIC:
8446 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8447 SSVAL(pdata,10,0); /* Padding. */
8448 store_file_unix_basic(conn, pdata + 12, fsp,
8451 case SMB_QUERY_FILE_UNIX_INFO2:
8452 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8453 SSVAL(pdata,10,0); /* Padding. */
8454 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8458 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8459 SSVAL(pdata,10,0); /* Padding. */
8466 /****************************************************************************
8467 Open/Create a file with POSIX semantics.
8468 ****************************************************************************/
8470 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8471 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8473 static NTSTATUS smb_posix_open(connection_struct *conn,
8474 struct smb_request *req,
8477 struct smb_filename *smb_fname,
8478 int *pdata_return_size)
8480 bool extended_oplock_granted = False;
8481 char *pdata = *ppdata;
8483 uint32_t wire_open_mode = 0;
8484 uint32_t raw_unixmode = 0;
8485 uint32_t mod_unixmode = 0;
8486 uint32_t create_disp = 0;
8487 uint32_t access_mask = 0;
8488 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8489 NTSTATUS status = NT_STATUS_OK;
8490 mode_t unixmode = (mode_t)0;
8491 files_struct *fsp = NULL;
8492 int oplock_request = 0;
8494 uint16_t info_level_return = 0;
8496 if (total_data < 18) {
8497 return NT_STATUS_INVALID_PARAMETER;
8500 flags = IVAL(pdata,0);
8501 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8502 if (oplock_request) {
8503 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8506 wire_open_mode = IVAL(pdata,4);
8508 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8509 return smb_posix_mkdir(conn, req,
8516 switch (wire_open_mode & SMB_ACCMODE) {
8518 access_mask = SMB_O_RDONLY_MAPPING;
8521 access_mask = SMB_O_WRONLY_MAPPING;
8524 access_mask = (SMB_O_RDONLY_MAPPING|
8525 SMB_O_WRONLY_MAPPING);
8528 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8529 (unsigned int)wire_open_mode ));
8530 return NT_STATUS_INVALID_PARAMETER;
8533 wire_open_mode &= ~SMB_ACCMODE;
8535 /* First take care of O_CREAT|O_EXCL interactions. */
8536 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8537 case (SMB_O_CREAT | SMB_O_EXCL):
8538 /* File exists fail. File not exist create. */
8539 create_disp = FILE_CREATE;
8542 /* File exists open. File not exist create. */
8543 create_disp = FILE_OPEN_IF;
8546 /* O_EXCL on its own without O_CREAT is undefined.
8547 We deliberately ignore it as some versions of
8548 Linux CIFSFS can send a bare O_EXCL on the
8549 wire which other filesystems in the kernel
8550 ignore. See bug 9519 for details. */
8555 /* File exists open. File not exist fail. */
8556 create_disp = FILE_OPEN;
8559 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8560 (unsigned int)wire_open_mode ));
8561 return NT_STATUS_INVALID_PARAMETER;
8564 /* Next factor in the effects of O_TRUNC. */
8565 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8567 if (wire_open_mode & SMB_O_TRUNC) {
8568 switch (create_disp) {
8570 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8571 /* Leave create_disp alone as
8572 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8574 /* File exists fail. File not exist create. */
8577 /* SMB_O_CREAT | SMB_O_TRUNC */
8578 /* File exists overwrite. File not exist create. */
8579 create_disp = FILE_OVERWRITE_IF;
8583 /* File exists overwrite. File not exist fail. */
8584 create_disp = FILE_OVERWRITE;
8587 /* Cannot get here. */
8588 smb_panic("smb_posix_open: logic error");
8589 return NT_STATUS_INVALID_PARAMETER;
8593 raw_unixmode = IVAL(pdata,8);
8594 /* Next 4 bytes are not yet defined. */
8596 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8597 (VALID_STAT(smb_fname->st) ?
8598 PERM_EXISTING_FILE : PERM_NEW_FILE),
8601 if (!NT_STATUS_IS_OK(status)) {
8605 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8607 if (wire_open_mode & SMB_O_SYNC) {
8608 create_options |= FILE_WRITE_THROUGH;
8610 if (wire_open_mode & SMB_O_APPEND) {
8611 access_mask |= FILE_APPEND_DATA;
8613 if (wire_open_mode & SMB_O_DIRECT) {
8614 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8617 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8618 VALID_STAT_OF_DIR(smb_fname->st)) {
8619 if (access_mask != SMB_O_RDONLY_MAPPING) {
8620 return NT_STATUS_FILE_IS_A_DIRECTORY;
8622 create_options &= ~FILE_NON_DIRECTORY_FILE;
8623 create_options |= FILE_DIRECTORY_FILE;
8626 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8627 smb_fname_str_dbg(smb_fname),
8628 (unsigned int)wire_open_mode,
8629 (unsigned int)unixmode ));
8631 status = SMB_VFS_CREATE_FILE(
8634 0, /* root_dir_fid */
8635 smb_fname, /* fname */
8636 access_mask, /* access_mask */
8637 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8639 create_disp, /* create_disposition*/
8640 create_options, /* create_options */
8641 mod_unixmode, /* file_attributes */
8642 oplock_request, /* oplock_request */
8644 0, /* allocation_size */
8645 0, /* private_flags */
8650 NULL, NULL); /* create context */
8652 if (!NT_STATUS_IS_OK(status)) {
8656 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8657 extended_oplock_granted = True;
8660 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8661 extended_oplock_granted = True;
8664 info_level_return = SVAL(pdata,16);
8666 /* Allocate the correct return size. */
8668 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8669 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8670 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8671 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8673 *pdata_return_size = 12;
8676 /* Realloc the data size */
8677 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8678 if (*ppdata == NULL) {
8679 close_file(req, fsp, ERROR_CLOSE);
8680 *pdata_return_size = 0;
8681 return NT_STATUS_NO_MEMORY;
8685 if (extended_oplock_granted) {
8686 if (flags & REQUEST_BATCH_OPLOCK) {
8687 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8689 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8691 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8692 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8694 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8697 SSVAL(pdata,2,fsp->fnum);
8698 SIVAL(pdata,4,info); /* Was file created etc. */
8700 switch (info_level_return) {
8701 case SMB_QUERY_FILE_UNIX_BASIC:
8702 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8703 SSVAL(pdata,10,0); /* padding. */
8704 store_file_unix_basic(conn, pdata + 12, fsp,
8707 case SMB_QUERY_FILE_UNIX_INFO2:
8708 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8709 SSVAL(pdata,10,0); /* padding. */
8710 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8714 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8715 SSVAL(pdata,10,0); /* padding. */
8718 return NT_STATUS_OK;
8721 /****************************************************************************
8722 Delete a file with POSIX semantics.
8723 ****************************************************************************/
8725 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8726 struct smb_request *req,
8729 struct smb_filename *smb_fname)
8731 struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
8732 NTSTATUS status = NT_STATUS_OK;
8733 files_struct *fsp = NULL;
8737 int create_options = 0;
8738 struct share_mode_lock *lck = NULL;
8739 bool other_nonposix_opens;
8741 if (total_data < 2) {
8742 return NT_STATUS_INVALID_PARAMETER;
8745 flags = SVAL(pdata,0);
8747 if (!VALID_STAT(smb_fname->st)) {
8748 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8751 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8752 !VALID_STAT_OF_DIR(smb_fname->st)) {
8753 return NT_STATUS_NOT_A_DIRECTORY;
8756 DEBUG(10,("smb_posix_unlink: %s %s\n",
8757 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8758 smb_fname_str_dbg(smb_fname)));
8760 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8761 create_options |= FILE_DIRECTORY_FILE;
8764 status = SMB_VFS_CREATE_FILE(
8767 0, /* root_dir_fid */
8768 smb_fname, /* fname */
8769 DELETE_ACCESS, /* access_mask */
8770 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8772 FILE_OPEN, /* create_disposition*/
8773 create_options, /* create_options */
8774 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8775 0, /* oplock_request */
8777 0, /* allocation_size */
8778 0, /* private_flags */
8783 NULL, NULL); /* create context */
8785 if (!NT_STATUS_IS_OK(status)) {
8790 * Don't lie to client. If we can't really delete due to
8791 * non-POSIX opens return SHARING_VIOLATION.
8794 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8796 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8797 "lock for file %s\n", fsp_str_dbg(fsp)));
8798 close_file(req, fsp, NORMAL_CLOSE);
8799 return NT_STATUS_INVALID_PARAMETER;
8802 other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
8803 if (other_nonposix_opens) {
8804 /* Fail with sharing violation. */
8806 close_file(req, fsp, NORMAL_CLOSE);
8807 return NT_STATUS_SHARING_VIOLATION;
8811 * Set the delete on close.
8813 status = smb_set_file_disposition_info(conn,
8821 if (!NT_STATUS_IS_OK(status)) {
8822 close_file(req, fsp, NORMAL_CLOSE);
8825 return close_file(req, fsp, NORMAL_CLOSE);
8828 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8829 struct smb_request *req,
8830 TALLOC_CTX *mem_ctx,
8831 uint16_t info_level,
8833 struct smb_filename *smb_fname,
8834 char **ppdata, int total_data,
8837 char *pdata = *ppdata;
8838 NTSTATUS status = NT_STATUS_OK;
8839 int data_return_size = 0;
8843 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8844 return NT_STATUS_INVALID_LEVEL;
8847 if (!CAN_WRITE(conn)) {
8848 /* Allow POSIX opens. The open path will deny
8849 * any non-readonly opens. */
8850 if (info_level != SMB_POSIX_PATH_OPEN) {
8851 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8855 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8856 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8858 info_level, total_data));
8860 switch (info_level) {
8862 case SMB_INFO_STANDARD:
8864 status = smb_set_info_standard(conn,
8872 case SMB_INFO_SET_EA:
8874 status = smb_info_set_ea(conn,
8882 case SMB_SET_FILE_BASIC_INFO:
8883 case SMB_FILE_BASIC_INFORMATION:
8885 status = smb_set_file_basic_info(conn,
8893 case SMB_FILE_ALLOCATION_INFORMATION:
8894 case SMB_SET_FILE_ALLOCATION_INFO:
8896 status = smb_set_file_allocation_info(conn, req,
8904 case SMB_FILE_END_OF_FILE_INFORMATION:
8905 case SMB_SET_FILE_END_OF_FILE_INFO:
8908 * XP/Win7 both fail after the createfile with
8909 * SMB_SET_FILE_END_OF_FILE_INFO but not
8910 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8911 * The level is known here, so pass it down
8915 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8917 status = smb_set_file_end_of_file_info(conn, req,
8926 case SMB_FILE_DISPOSITION_INFORMATION:
8927 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8930 /* JRA - We used to just ignore this on a path ?
8931 * Shouldn't this be invalid level on a pathname
8934 if (tran_call != TRANSACT2_SETFILEINFO) {
8935 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8938 status = smb_set_file_disposition_info(conn,
8946 case SMB_FILE_POSITION_INFORMATION:
8948 status = smb_file_position_information(conn,
8955 case SMB_FILE_FULL_EA_INFORMATION:
8957 status = smb_set_file_full_ea_info(conn,
8964 /* From tridge Samba4 :
8965 * MODE_INFORMATION in setfileinfo (I have no
8966 * idea what "mode information" on a file is - it takes a value of 0,
8967 * 2, 4 or 6. What could it be?).
8970 case SMB_FILE_MODE_INFORMATION:
8972 status = smb_file_mode_information(conn,
8978 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8979 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8980 case SMB_FILE_SHORT_NAME_INFORMATION:
8981 return NT_STATUS_NOT_SUPPORTED;
8984 * CIFS UNIX extensions.
8987 case SMB_SET_FILE_UNIX_BASIC:
8989 status = smb_set_file_unix_basic(conn, req,
8997 case SMB_SET_FILE_UNIX_INFO2:
8999 status = smb_set_file_unix_info2(conn, req,
9007 case SMB_SET_FILE_UNIX_LINK:
9010 /* We must have a pathname for this. */
9011 return NT_STATUS_INVALID_LEVEL;
9013 status = smb_set_file_unix_link(conn, req, pdata,
9014 total_data, smb_fname);
9018 case SMB_SET_FILE_UNIX_HLINK:
9021 /* We must have a pathname for this. */
9022 return NT_STATUS_INVALID_LEVEL;
9024 status = smb_set_file_unix_hlink(conn, req,
9030 case SMB_FILE_RENAME_INFORMATION:
9032 status = smb_file_rename_information(conn, req,
9038 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9040 /* SMB2 rename information. */
9041 status = smb2_file_rename_information(conn, req,
9047 case SMB_FILE_LINK_INFORMATION:
9049 status = smb_file_link_information(conn, req,
9055 #if defined(HAVE_POSIX_ACLS)
9056 case SMB_SET_POSIX_ACL:
9058 status = smb_set_posix_acl(conn,
9068 case SMB_SET_POSIX_LOCK:
9071 return NT_STATUS_INVALID_LEVEL;
9073 status = smb_set_posix_lock(conn, req,
9074 pdata, total_data, fsp);
9078 case SMB_POSIX_PATH_OPEN:
9081 /* We must have a pathname for this. */
9082 return NT_STATUS_INVALID_LEVEL;
9085 status = smb_posix_open(conn, req,
9093 case SMB_POSIX_PATH_UNLINK:
9096 /* We must have a pathname for this. */
9097 return NT_STATUS_INVALID_LEVEL;
9100 status = smb_posix_unlink(conn, req,
9108 return NT_STATUS_INVALID_LEVEL;
9111 if (!NT_STATUS_IS_OK(status)) {
9115 *ret_data_size = data_return_size;
9116 return NT_STATUS_OK;
9119 /****************************************************************************
9120 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9121 ****************************************************************************/
9123 static void call_trans2setfilepathinfo(connection_struct *conn,
9124 struct smb_request *req,
9125 unsigned int tran_call,
9126 char **pparams, int total_params,
9127 char **ppdata, int total_data,
9128 unsigned int max_data_bytes)
9130 char *params = *pparams;
9131 char *pdata = *ppdata;
9132 uint16_t info_level;
9133 struct smb_filename *smb_fname = NULL;
9134 files_struct *fsp = NULL;
9135 NTSTATUS status = NT_STATUS_OK;
9136 int data_return_size = 0;
9139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9143 if (tran_call == TRANSACT2_SETFILEINFO) {
9144 if (total_params < 4) {
9145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9149 fsp = file_fsp(req, SVAL(params,0));
9150 /* Basic check for non-null fsp. */
9151 if (!check_fsp_open(conn, req, fsp)) {
9154 info_level = SVAL(params,2);
9156 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9157 if (smb_fname == NULL) {
9158 reply_nterror(req, NT_STATUS_NO_MEMORY);
9162 if(fsp->fh->fd == -1) {
9164 * This is actually a SETFILEINFO on a directory
9165 * handle (returned from an NT SMB). NT5.0 seems
9166 * to do this call. JRA.
9168 if (INFO_LEVEL_IS_UNIX(info_level)) {
9169 /* Always do lstat for UNIX calls. */
9170 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9171 DEBUG(3,("call_trans2setfilepathinfo: "
9172 "SMB_VFS_LSTAT of %s failed "
9174 smb_fname_str_dbg(smb_fname),
9176 reply_nterror(req, map_nt_error_from_unix(errno));
9180 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9181 DEBUG(3,("call_trans2setfilepathinfo: "
9182 "fileinfo of %s failed (%s)\n",
9183 smb_fname_str_dbg(smb_fname),
9185 reply_nterror(req, map_nt_error_from_unix(errno));
9189 } else if (fsp->print_file) {
9191 * Doing a DELETE_ON_CLOSE should cancel a print job.
9193 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9194 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9196 DEBUG(3,("call_trans2setfilepathinfo: "
9197 "Cancelling print job (%s)\n",
9201 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9207 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9212 * Original code - this is an open file.
9214 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9215 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9216 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9218 reply_nterror(req, map_nt_error_from_unix(errno));
9224 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9227 if (total_params < 7) {
9228 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9232 info_level = SVAL(params,0);
9233 if (req->posix_pathnames) {
9234 srvstr_get_path_posix(req,
9243 srvstr_get_path(req,
9252 if (!NT_STATUS_IS_OK(status)) {
9253 reply_nterror(req, status);
9257 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9258 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9259 info_level == SMB_FILE_RENAME_INFORMATION ||
9260 info_level == SMB_POSIX_PATH_OPEN ||
9261 info_level == SMB_POSIX_PATH_UNLINK) {
9262 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9265 status = filename_convert(req, conn,
9271 if (!NT_STATUS_IS_OK(status)) {
9272 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9273 reply_botherror(req,
9274 NT_STATUS_PATH_NOT_COVERED,
9275 ERRSRV, ERRbadpath);
9278 reply_nterror(req, status);
9282 if (INFO_LEVEL_IS_UNIX(info_level)) {
9284 * For CIFS UNIX extensions the target name may not exist.
9287 /* Always do lstat for UNIX calls. */
9288 SMB_VFS_LSTAT(conn, smb_fname);
9290 } else if (!VALID_STAT(smb_fname->st) &&
9291 SMB_VFS_STAT(conn, smb_fname)) {
9292 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9294 smb_fname_str_dbg(smb_fname),
9296 reply_nterror(req, map_nt_error_from_unix(errno));
9301 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9302 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9304 info_level,total_data));
9306 /* Realloc the parameter size */
9307 *pparams = (char *)SMB_REALLOC(*pparams,2);
9308 if (*pparams == NULL) {
9309 reply_nterror(req, NT_STATUS_NO_MEMORY);
9316 status = smbd_do_setfilepathinfo(conn, req, req,
9322 if (!NT_STATUS_IS_OK(status)) {
9323 if (open_was_deferred(req->xconn, req->mid)) {
9324 /* We have re-scheduled this call. */
9327 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9328 /* We have re-scheduled this call. */
9331 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9332 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9333 ERRSRV, ERRbadpath);
9336 if (info_level == SMB_POSIX_PATH_OPEN) {
9337 reply_openerror(req, status);
9342 * Invalid EA name needs to return 2 param bytes,
9343 * not a zero-length error packet.
9345 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9346 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9349 reply_nterror(req, status);
9354 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9360 /****************************************************************************
9361 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9362 ****************************************************************************/
9364 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9365 char **pparams, int total_params,
9366 char **ppdata, int total_data,
9367 unsigned int max_data_bytes)
9369 struct smb_filename *smb_dname = NULL;
9370 char *params = *pparams;
9371 char *pdata = *ppdata;
9372 char *directory = NULL;
9373 NTSTATUS status = NT_STATUS_OK;
9374 struct ea_list *ea_list = NULL;
9375 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9376 TALLOC_CTX *ctx = talloc_tos();
9378 if (!CAN_WRITE(conn)) {
9379 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9383 if (total_params < 5) {
9384 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9388 if (req->posix_pathnames) {
9389 srvstr_get_path_posix(ctx,
9398 srvstr_get_path(ctx,
9407 if (!NT_STATUS_IS_OK(status)) {
9408 reply_nterror(req, status);
9412 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9414 status = filename_convert(ctx,
9422 if (!NT_STATUS_IS_OK(status)) {
9423 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9424 reply_botherror(req,
9425 NT_STATUS_PATH_NOT_COVERED,
9426 ERRSRV, ERRbadpath);
9429 reply_nterror(req, status);
9434 * OS/2 workplace shell seems to send SET_EA requests of "null"
9435 * length (4 bytes containing IVAL 4).
9436 * They seem to have no effect. Bug #3212. JRA.
9439 if (total_data && (total_data != 4)) {
9440 /* Any data in this call is an EA list. */
9441 if (total_data < 10) {
9442 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9446 if (IVAL(pdata,0) > total_data) {
9447 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9448 IVAL(pdata,0), (unsigned int)total_data));
9449 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9453 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9460 if (!lp_ea_support(SNUM(conn))) {
9461 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9465 /* If total_data == 4 Windows doesn't care what values
9466 * are placed in that field, it just ignores them.
9467 * The System i QNTC IBM SMB client puts bad values here,
9468 * so ignore them. */
9470 status = create_directory(conn, req, smb_dname);
9472 if (!NT_STATUS_IS_OK(status)) {
9473 reply_nterror(req, status);
9477 /* Try and set any given EA. */
9479 status = set_ea(conn, NULL, smb_dname, ea_list);
9480 if (!NT_STATUS_IS_OK(status)) {
9481 reply_nterror(req, status);
9486 /* Realloc the parameter and data sizes */
9487 *pparams = (char *)SMB_REALLOC(*pparams,2);
9488 if(*pparams == NULL) {
9489 reply_nterror(req, NT_STATUS_NO_MEMORY);
9496 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9499 TALLOC_FREE(smb_dname);
9503 /****************************************************************************
9504 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9505 We don't actually do this - we just send a null response.
9506 ****************************************************************************/
9508 static void call_trans2findnotifyfirst(connection_struct *conn,
9509 struct smb_request *req,
9510 char **pparams, int total_params,
9511 char **ppdata, int total_data,
9512 unsigned int max_data_bytes)
9514 char *params = *pparams;
9515 uint16_t info_level;
9517 if (total_params < 6) {
9518 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9522 info_level = SVAL(params,4);
9523 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9525 switch (info_level) {
9530 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9534 /* Realloc the parameter and data sizes */
9535 *pparams = (char *)SMB_REALLOC(*pparams,6);
9536 if (*pparams == NULL) {
9537 reply_nterror(req, NT_STATUS_NO_MEMORY);
9542 SSVAL(params,0,fnf_handle);
9543 SSVAL(params,2,0); /* No changes */
9544 SSVAL(params,4,0); /* No EA errors */
9551 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9556 /****************************************************************************
9557 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9558 changes). Currently this does nothing.
9559 ****************************************************************************/
9561 static void call_trans2findnotifynext(connection_struct *conn,
9562 struct smb_request *req,
9563 char **pparams, int total_params,
9564 char **ppdata, int total_data,
9565 unsigned int max_data_bytes)
9567 char *params = *pparams;
9569 DEBUG(3,("call_trans2findnotifynext\n"));
9571 /* Realloc the parameter and data sizes */
9572 *pparams = (char *)SMB_REALLOC(*pparams,4);
9573 if (*pparams == NULL) {
9574 reply_nterror(req, NT_STATUS_NO_MEMORY);
9579 SSVAL(params,0,0); /* No changes */
9580 SSVAL(params,2,0); /* No EA errors */
9582 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9587 /****************************************************************************
9588 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9589 ****************************************************************************/
9591 static void call_trans2getdfsreferral(connection_struct *conn,
9592 struct smb_request *req,
9593 char **pparams, int total_params,
9594 char **ppdata, int total_data,
9595 unsigned int max_data_bytes)
9597 char *params = *pparams;
9598 char *pathname = NULL;
9600 int max_referral_level;
9601 NTSTATUS status = NT_STATUS_OK;
9602 TALLOC_CTX *ctx = talloc_tos();
9604 DEBUG(10,("call_trans2getdfsreferral\n"));
9606 if (total_params < 3) {
9607 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9611 max_referral_level = SVAL(params,0);
9613 if(!lp_host_msdfs()) {
9614 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9618 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9619 total_params - 2, STR_TERMINATE);
9621 reply_nterror(req, NT_STATUS_NOT_FOUND);
9624 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9625 ppdata,&status)) < 0) {
9626 reply_nterror(req, status);
9630 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9631 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9632 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9637 #define LMCAT_SPL 0x53
9638 #define LMFUNC_GETJOBID 0x60
9640 /****************************************************************************
9641 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9642 ****************************************************************************/
9644 static void call_trans2ioctl(connection_struct *conn,
9645 struct smb_request *req,
9646 char **pparams, int total_params,
9647 char **ppdata, int total_data,
9648 unsigned int max_data_bytes)
9650 char *pdata = *ppdata;
9651 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9655 /* check for an invalid fid before proceeding */
9658 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9662 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9663 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9664 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9665 if (*ppdata == NULL) {
9666 reply_nterror(req, NT_STATUS_NO_MEMORY);
9671 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9672 CAN ACCEPT THIS IN UNICODE. JRA. */
9675 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9677 status = srvstr_push(pdata, req->flags2, pdata + 2,
9678 lp_netbios_name(), 15,
9679 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9680 if (!NT_STATUS_IS_OK(status)) {
9681 reply_nterror(req, status);
9684 status = srvstr_push(pdata, req->flags2, pdata+18,
9685 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9686 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9687 if (!NT_STATUS_IS_OK(status)) {
9688 reply_nterror(req, status);
9691 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9696 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9697 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9700 /****************************************************************************
9701 Reply to a SMBfindclose (stop trans2 directory search).
9702 ****************************************************************************/
9704 void reply_findclose(struct smb_request *req)
9707 struct smbd_server_connection *sconn = req->sconn;
9708 files_struct *fsp = NULL;
9710 START_PROFILE(SMBfindclose);
9713 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9714 END_PROFILE(SMBfindclose);
9718 dptr_num = SVALS(req->vwv+0, 0);
9720 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9723 * OS/2 seems to use -1 to indicate "close all directories"
9724 * This has to mean on this specific connection struct.
9726 if (dptr_num == -1) {
9727 dptr_closecnum(req->conn);
9729 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9730 dptr_close(sconn, &dptr_num);
9732 close_file(NULL, fsp, NORMAL_CLOSE);
9737 reply_outbuf(req, 0, 0);
9739 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9741 END_PROFILE(SMBfindclose);
9745 /****************************************************************************
9746 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9747 ****************************************************************************/
9749 void reply_findnclose(struct smb_request *req)
9753 START_PROFILE(SMBfindnclose);
9756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9757 END_PROFILE(SMBfindnclose);
9761 dptr_num = SVAL(req->vwv+0, 0);
9763 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9765 /* We never give out valid handles for a
9766 findnotifyfirst - so any dptr_num is ok here.
9769 reply_outbuf(req, 0, 0);
9771 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9773 END_PROFILE(SMBfindnclose);
9777 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9778 struct trans_state *state)
9780 if (get_Protocol() >= PROTOCOL_NT1) {
9781 req->flags2 |= 0x40; /* IS_LONG_NAME */
9782 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9785 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9786 if (state->call != TRANSACT2_QFSINFO &&
9787 state->call != TRANSACT2_SETFSINFO) {
9788 DEBUG(0,("handle_trans2: encryption required "
9790 (unsigned int)state->call));
9791 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9796 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9798 /* Now we must call the relevant TRANS2 function */
9799 switch(state->call) {
9800 case TRANSACT2_OPEN:
9802 START_PROFILE(Trans2_open);
9803 call_trans2open(conn, req,
9804 &state->param, state->total_param,
9805 &state->data, state->total_data,
9806 state->max_data_return);
9807 END_PROFILE(Trans2_open);
9811 case TRANSACT2_FINDFIRST:
9813 START_PROFILE(Trans2_findfirst);
9814 call_trans2findfirst(conn, req,
9815 &state->param, state->total_param,
9816 &state->data, state->total_data,
9817 state->max_data_return);
9818 END_PROFILE(Trans2_findfirst);
9822 case TRANSACT2_FINDNEXT:
9824 START_PROFILE(Trans2_findnext);
9825 call_trans2findnext(conn, req,
9826 &state->param, state->total_param,
9827 &state->data, state->total_data,
9828 state->max_data_return);
9829 END_PROFILE(Trans2_findnext);
9833 case TRANSACT2_QFSINFO:
9835 START_PROFILE(Trans2_qfsinfo);
9836 call_trans2qfsinfo(conn, req,
9837 &state->param, state->total_param,
9838 &state->data, state->total_data,
9839 state->max_data_return);
9840 END_PROFILE(Trans2_qfsinfo);
9844 case TRANSACT2_SETFSINFO:
9846 START_PROFILE(Trans2_setfsinfo);
9847 call_trans2setfsinfo(conn, req,
9848 &state->param, state->total_param,
9849 &state->data, state->total_data,
9850 state->max_data_return);
9851 END_PROFILE(Trans2_setfsinfo);
9855 case TRANSACT2_QPATHINFO:
9856 case TRANSACT2_QFILEINFO:
9858 START_PROFILE(Trans2_qpathinfo);
9859 call_trans2qfilepathinfo(conn, req, state->call,
9860 &state->param, state->total_param,
9861 &state->data, state->total_data,
9862 state->max_data_return);
9863 END_PROFILE(Trans2_qpathinfo);
9867 case TRANSACT2_SETPATHINFO:
9868 case TRANSACT2_SETFILEINFO:
9870 START_PROFILE(Trans2_setpathinfo);
9871 call_trans2setfilepathinfo(conn, req, state->call,
9872 &state->param, state->total_param,
9873 &state->data, state->total_data,
9874 state->max_data_return);
9875 END_PROFILE(Trans2_setpathinfo);
9879 case TRANSACT2_FINDNOTIFYFIRST:
9881 START_PROFILE(Trans2_findnotifyfirst);
9882 call_trans2findnotifyfirst(conn, req,
9883 &state->param, state->total_param,
9884 &state->data, state->total_data,
9885 state->max_data_return);
9886 END_PROFILE(Trans2_findnotifyfirst);
9890 case TRANSACT2_FINDNOTIFYNEXT:
9892 START_PROFILE(Trans2_findnotifynext);
9893 call_trans2findnotifynext(conn, req,
9894 &state->param, state->total_param,
9895 &state->data, state->total_data,
9896 state->max_data_return);
9897 END_PROFILE(Trans2_findnotifynext);
9901 case TRANSACT2_MKDIR:
9903 START_PROFILE(Trans2_mkdir);
9904 call_trans2mkdir(conn, req,
9905 &state->param, state->total_param,
9906 &state->data, state->total_data,
9907 state->max_data_return);
9908 END_PROFILE(Trans2_mkdir);
9912 case TRANSACT2_GET_DFS_REFERRAL:
9914 START_PROFILE(Trans2_get_dfs_referral);
9915 call_trans2getdfsreferral(conn, req,
9916 &state->param, state->total_param,
9917 &state->data, state->total_data,
9918 state->max_data_return);
9919 END_PROFILE(Trans2_get_dfs_referral);
9923 case TRANSACT2_IOCTL:
9925 START_PROFILE(Trans2_ioctl);
9926 call_trans2ioctl(conn, req,
9927 &state->param, state->total_param,
9928 &state->data, state->total_data,
9929 state->max_data_return);
9930 END_PROFILE(Trans2_ioctl);
9935 /* Error in request */
9936 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9937 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9941 /****************************************************************************
9942 Reply to a SMBtrans2.
9943 ****************************************************************************/
9945 void reply_trans2(struct smb_request *req)
9947 connection_struct *conn = req->conn;
9952 unsigned int tran_call;
9953 struct trans_state *state;
9956 START_PROFILE(SMBtrans2);
9958 if (req->wct < 14) {
9959 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9960 END_PROFILE(SMBtrans2);
9964 dsoff = SVAL(req->vwv+12, 0);
9965 dscnt = SVAL(req->vwv+11, 0);
9966 psoff = SVAL(req->vwv+10, 0);
9967 pscnt = SVAL(req->vwv+9, 0);
9968 tran_call = SVAL(req->vwv+14, 0);
9970 result = allow_new_trans(conn->pending_trans, req->mid);
9971 if (!NT_STATUS_IS_OK(result)) {
9972 DEBUG(2, ("Got invalid trans2 request: %s\n",
9973 nt_errstr(result)));
9974 reply_nterror(req, result);
9975 END_PROFILE(SMBtrans2);
9980 switch (tran_call) {
9981 /* List the allowed trans2 calls on IPC$ */
9982 case TRANSACT2_OPEN:
9983 case TRANSACT2_GET_DFS_REFERRAL:
9984 case TRANSACT2_QFILEINFO:
9985 case TRANSACT2_QFSINFO:
9986 case TRANSACT2_SETFSINFO:
9989 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9990 END_PROFILE(SMBtrans2);
9995 if ((state = talloc(conn, struct trans_state)) == NULL) {
9996 DEBUG(0, ("talloc failed\n"));
9997 reply_nterror(req, NT_STATUS_NO_MEMORY);
9998 END_PROFILE(SMBtrans2);
10002 state->cmd = SMBtrans2;
10004 state->mid = req->mid;
10005 state->vuid = req->vuid;
10006 state->setup_count = SVAL(req->vwv+13, 0);
10007 state->setup = NULL;
10008 state->total_param = SVAL(req->vwv+0, 0);
10009 state->param = NULL;
10010 state->total_data = SVAL(req->vwv+1, 0);
10011 state->data = NULL;
10012 state->max_param_return = SVAL(req->vwv+2, 0);
10013 state->max_data_return = SVAL(req->vwv+3, 0);
10014 state->max_setup_return = SVAL(req->vwv+4, 0);
10015 state->close_on_completion = BITSETW(req->vwv+5, 0);
10016 state->one_way = BITSETW(req->vwv+5, 1);
10018 state->call = tran_call;
10020 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10021 is so as a sanity check */
10022 if (state->setup_count != 1) {
10024 * Need to have rc=0 for ioctl to get job id for OS/2.
10025 * Network printing will fail if function is not successful.
10026 * Similar function in reply.c will be used if protocol
10027 * is LANMAN1.0 instead of LM1.2X002.
10028 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10029 * outbuf doesn't have to be set(only job id is used).
10031 if ( (state->setup_count == 4)
10032 && (tran_call == TRANSACT2_IOCTL)
10033 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10034 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10035 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10037 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10038 DEBUG(2,("Transaction is %d\n",tran_call));
10039 TALLOC_FREE(state);
10040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10041 END_PROFILE(SMBtrans2);
10046 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10049 if (state->total_data) {
10051 if (trans_oob(state->total_data, 0, dscnt)
10052 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10056 /* Can't use talloc here, the core routines do realloc on the
10057 * params and data. */
10058 state->data = (char *)SMB_MALLOC(state->total_data);
10059 if (state->data == NULL) {
10060 DEBUG(0,("reply_trans2: data malloc fail for %u "
10061 "bytes !\n", (unsigned int)state->total_data));
10062 TALLOC_FREE(state);
10063 reply_nterror(req, NT_STATUS_NO_MEMORY);
10064 END_PROFILE(SMBtrans2);
10068 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10071 if (state->total_param) {
10073 if (trans_oob(state->total_param, 0, pscnt)
10074 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10078 /* Can't use talloc here, the core routines do realloc on the
10079 * params and data. */
10080 state->param = (char *)SMB_MALLOC(state->total_param);
10081 if (state->param == NULL) {
10082 DEBUG(0,("reply_trans: param malloc fail for %u "
10083 "bytes !\n", (unsigned int)state->total_param));
10084 SAFE_FREE(state->data);
10085 TALLOC_FREE(state);
10086 reply_nterror(req, NT_STATUS_NO_MEMORY);
10087 END_PROFILE(SMBtrans2);
10091 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10094 state->received_data = dscnt;
10095 state->received_param = pscnt;
10097 if ((state->received_param == state->total_param) &&
10098 (state->received_data == state->total_data)) {
10100 handle_trans2(conn, req, state);
10102 SAFE_FREE(state->data);
10103 SAFE_FREE(state->param);
10104 TALLOC_FREE(state);
10105 END_PROFILE(SMBtrans2);
10109 DLIST_ADD(conn->pending_trans, state);
10111 /* We need to send an interim response then receive the rest
10112 of the parameter/data bytes */
10113 reply_outbuf(req, 0, 0);
10114 show_msg((char *)req->outbuf);
10115 END_PROFILE(SMBtrans2);
10120 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10121 SAFE_FREE(state->data);
10122 SAFE_FREE(state->param);
10123 TALLOC_FREE(state);
10124 END_PROFILE(SMBtrans2);
10125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10129 /****************************************************************************
10130 Reply to a SMBtranss2
10131 ****************************************************************************/
10133 void reply_transs2(struct smb_request *req)
10135 connection_struct *conn = req->conn;
10136 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10137 struct trans_state *state;
10139 START_PROFILE(SMBtranss2);
10141 show_msg((const char *)req->inbuf);
10143 /* Windows clients expect all replies to
10144 a transact secondary (SMBtranss2 0x33)
10145 to have a command code of transact
10146 (SMBtrans2 0x32). See bug #8989
10147 and also [MS-CIFS] section 2.2.4.47.2
10150 req->cmd = SMBtrans2;
10152 if (req->wct < 8) {
10153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10154 END_PROFILE(SMBtranss2);
10158 for (state = conn->pending_trans; state != NULL;
10159 state = state->next) {
10160 if (state->mid == req->mid) {
10165 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10167 END_PROFILE(SMBtranss2);
10171 /* Revise state->total_param and state->total_data in case they have
10172 changed downwards */
10174 if (SVAL(req->vwv+0, 0) < state->total_param)
10175 state->total_param = SVAL(req->vwv+0, 0);
10176 if (SVAL(req->vwv+1, 0) < state->total_data)
10177 state->total_data = SVAL(req->vwv+1, 0);
10179 pcnt = SVAL(req->vwv+2, 0);
10180 poff = SVAL(req->vwv+3, 0);
10181 pdisp = SVAL(req->vwv+4, 0);
10183 dcnt = SVAL(req->vwv+5, 0);
10184 doff = SVAL(req->vwv+6, 0);
10185 ddisp = SVAL(req->vwv+7, 0);
10187 state->received_param += pcnt;
10188 state->received_data += dcnt;
10190 if ((state->received_data > state->total_data) ||
10191 (state->received_param > state->total_param))
10195 if (trans_oob(state->total_param, pdisp, pcnt)
10196 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10199 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10203 if (trans_oob(state->total_data, ddisp, dcnt)
10204 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10207 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10210 if ((state->received_param < state->total_param) ||
10211 (state->received_data < state->total_data)) {
10212 END_PROFILE(SMBtranss2);
10216 handle_trans2(conn, req, state);
10218 DLIST_REMOVE(conn->pending_trans, state);
10219 SAFE_FREE(state->data);
10220 SAFE_FREE(state->param);
10221 TALLOC_FREE(state);
10223 END_PROFILE(SMBtranss2);
10228 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10229 DLIST_REMOVE(conn->pending_trans, state);
10230 SAFE_FREE(state->data);
10231 SAFE_FREE(state->param);
10232 TALLOC_FREE(state);
10233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10234 END_PROFILE(SMBtranss2);