2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #include "smb1_utils.h"
46 #include "libcli/smb/smb2_posix.h"
48 #define DIR_ENTRY_SAFETY_MARGIN 4096
50 static char *store_file_unix_basic(connection_struct *conn,
53 const SMB_STRUCT_STAT *psbuf);
55 static char *store_file_unix_basic_info2(connection_struct *conn,
58 const SMB_STRUCT_STAT *psbuf);
60 /****************************************************************************
61 Check if an open file handle or smb_fname is a symlink.
62 ****************************************************************************/
64 static NTSTATUS refuse_symlink(connection_struct *conn,
65 const files_struct *fsp,
66 const struct smb_filename *smb_fname)
69 const SMB_STRUCT_STAT *pst = NULL;
72 pst = &fsp->fsp_name->st;
77 if (!VALID_STAT(*pst)) {
78 int ret = vfs_stat_smb_basename(conn,
81 if (ret == -1 && errno != ENOENT) {
82 return map_nt_error_from_unix(errno);
83 } else if (ret == -1) {
84 /* it's not a symlink.. */
90 if (S_ISLNK(pst->st_ex_mode)) {
91 return NT_STATUS_ACCESS_DENIED;
96 NTSTATUS check_access_fsp(const struct files_struct *fsp,
99 if (!(fsp->access_mask & access_mask)) {
100 return NT_STATUS_ACCESS_DENIED;
105 #if defined(HAVE_POSIX_ACLS)
106 /****************************************************************************
107 Utility function to open a fsp for a POSIX handle operation.
108 ****************************************************************************/
110 static NTSTATUS get_posix_fsp(connection_struct *conn,
111 struct smb_request *req,
112 const struct smb_filename *smb_fname,
113 uint32_t access_mask,
114 files_struct **ret_fsp)
117 struct smb_filename *smb_fname_tmp = NULL;
118 uint32_t create_disposition = FILE_OPEN;
119 uint32_t share_access = FILE_SHARE_READ|
122 struct smb2_create_blobs *posx = NULL;
125 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
126 * but set reasonable defaults.
128 uint32_t file_attributes = 0664;
129 uint32_t oplock = NO_OPLOCK;
130 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
132 /* File or directory must exist. */
133 if (!VALID_STAT(smb_fname->st)) {
134 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
136 /* Cannot be a symlink. */
137 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
138 return NT_STATUS_ACCESS_DENIED;
140 /* Set options correctly for directory open. */
141 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
143 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
144 * directories, but set reasonable defaults.
146 file_attributes = 0775;
147 create_options = FILE_DIRECTORY_FILE;
150 /* Createfile uses a non-const smb_fname. */
151 smb_fname_tmp = cp_smb_filename(talloc_tos(),
153 if (smb_fname_tmp == NULL) {
154 status = NT_STATUS_NO_MEMORY;
158 status = make_smb2_posix_create_ctx(
159 talloc_tos(), &posx, file_attributes);
160 if (!NT_STATUS_IS_OK(status)) {
161 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
166 status = SMB_VFS_CREATE_FILE(
169 0, /* root_dir_fid */
170 smb_fname_tmp, /* fname */
171 access_mask, /* access_mask */
172 share_access, /* share_access */
173 create_disposition,/* create_disposition*/
174 create_options, /* create_options */
175 file_attributes,/* file_attributes */
176 oplock, /* oplock_request */
178 0, /* allocation_size */
179 0, /* private_flags */
182 ret_fsp, /* result */
184 posx, /* in_context */
185 NULL); /* out_context */
189 TALLOC_FREE(smb_fname_tmp);
194 /********************************************************************
195 The canonical "check access" based on object handle or path function.
196 ********************************************************************/
198 static NTSTATUS check_access(connection_struct *conn,
200 const struct smb_filename *smb_fname,
201 uint32_t access_mask)
206 status = check_access_fsp(fsp, access_mask);
208 status = smbd_check_access_rights(conn, smb_fname,
215 /********************************************************************
216 Roundup a value to the nearest allocation roundup size boundary.
217 Only do this for Windows clients.
218 ********************************************************************/
220 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
222 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
224 /* Only roundup for Windows clients. */
225 enum remote_arch_types ra_type = get_remote_arch();
226 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
227 val = SMB_ROUNDUP(val,rval);
232 /****************************************************************************
233 Utility functions for dealing with extended attributes.
234 ****************************************************************************/
236 /****************************************************************************
237 Refuse to allow clients to overwrite our private xattrs.
238 ****************************************************************************/
240 bool samba_private_attr_name(const char *unix_ea_name)
242 static const char * const prohibited_ea_names[] = {
243 SAMBA_POSIX_INHERITANCE_EA_NAME,
244 SAMBA_XATTR_DOS_ATTRIB,
252 for (i = 0; prohibited_ea_names[i]; i++) {
253 if (strequal( prohibited_ea_names[i], unix_ea_name))
256 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
257 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
263 /****************************************************************************
264 Get one EA value. Fill in a struct ea_struct.
265 ****************************************************************************/
267 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
268 connection_struct *conn,
270 const struct smb_filename *smb_fname,
272 struct ea_struct *pea)
274 /* Get the value of this xattr. Max size is 64k. */
275 size_t attr_size = 256;
281 val = talloc_realloc(mem_ctx, val, char, attr_size);
283 return NT_STATUS_NO_MEMORY;
286 if (fsp && fsp->fh->fd != -1) {
287 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
289 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
290 ea_name, val, attr_size);
293 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
299 return map_nt_error_from_unix(errno);
302 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
303 dump_data(10, (uint8_t *)val, sizeret);
306 if (strnequal(ea_name, "user.", 5)) {
307 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
309 pea->name = talloc_strdup(mem_ctx, ea_name);
311 if (pea->name == NULL) {
313 return NT_STATUS_NO_MEMORY;
315 pea->value.data = (unsigned char *)val;
316 pea->value.length = (size_t)sizeret;
320 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
321 connection_struct *conn,
323 const struct smb_filename *smb_fname,
328 /* Get a list of all xattrs. Max namesize is 64k. */
329 size_t ea_namelist_size = 1024;
330 char *ea_namelist = smallbuf;
331 char *to_free = NULL;
336 ssize_t sizeret = -1;
344 status = refuse_symlink(conn, fsp, smb_fname);
345 if (!NT_STATUS_IS_OK(status)) {
347 * Just return no EA's on a symlink.
352 if (fsp && fsp->fh->fd != -1) {
353 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
356 sizeret = SMB_VFS_LISTXATTR(conn,
362 if ((sizeret == -1) && (errno == ERANGE)) {
363 ea_namelist_size = 65536;
364 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
365 if (ea_namelist == NULL) {
366 return NT_STATUS_NO_MEMORY;
368 to_free = ea_namelist;
370 if (fsp && fsp->fh->fd != -1) {
371 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
374 sizeret = SMB_VFS_LISTXATTR(conn,
382 status = map_nt_error_from_unix(errno);
383 TALLOC_FREE(to_free);
387 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
390 TALLOC_FREE(to_free);
395 * Ensure the result is 0-terminated
398 if (ea_namelist[sizeret-1] != '\0') {
399 TALLOC_FREE(to_free);
400 return NT_STATUS_INTERNAL_ERROR;
408 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
412 *pnum_names = num_names;
414 if (pnames == NULL) {
415 TALLOC_FREE(to_free);
419 names = talloc_array(mem_ctx, char *, num_names);
421 DEBUG(0, ("talloc failed\n"));
422 TALLOC_FREE(to_free);
423 return NT_STATUS_NO_MEMORY;
426 if (ea_namelist == smallbuf) {
427 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
428 if (ea_namelist == NULL) {
430 return NT_STATUS_NO_MEMORY;
433 talloc_steal(names, ea_namelist);
435 ea_namelist = talloc_realloc(names, ea_namelist, char,
437 if (ea_namelist == NULL) {
439 return NT_STATUS_NO_MEMORY;
445 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
446 names[num_names++] = p;
454 /****************************************************************************
455 Return a linked list of the total EA's. Plus the total size
456 ****************************************************************************/
458 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
459 connection_struct *conn,
461 const struct smb_filename *smb_fname,
462 size_t *pea_total_len,
463 struct ea_list **ea_list)
465 /* Get a list of all xattrs. Max namesize is 64k. */
468 struct ea_list *ea_list_head = NULL;
469 bool posix_pathnames = false;
475 if (!lp_ea_support(SNUM(conn))) {
481 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
483 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
486 status = get_ea_names_from_file(talloc_tos(),
493 if (!NT_STATUS_IS_OK(status)) {
497 if (num_names == 0) {
501 for (i=0; i<num_names; i++) {
502 struct ea_list *listp;
505 if (strnequal(names[i], "system.", 7)
506 || samba_private_attr_name(names[i]))
510 * Filter out any underlying POSIX EA names
511 * that a Windows client can't handle.
513 if (!posix_pathnames &&
514 is_invalid_windows_ea_name(names[i])) {
518 listp = talloc(mem_ctx, struct ea_list);
520 return NT_STATUS_NO_MEMORY;
523 status = get_ea_value(listp,
530 if (!NT_STATUS_IS_OK(status)) {
535 if (listp->ea.value.length == 0) {
537 * We can never return a zero length EA.
538 * Windows reports the EA's as corrupted.
544 push_ascii_fstring(dos_ea_name, listp->ea.name);
547 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
549 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
550 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
551 (unsigned int)listp->ea.value.length));
553 DLIST_ADD_END(ea_list_head, listp);
557 /* Add on 4 for total length. */
558 if (*pea_total_len) {
562 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
563 (unsigned int)*pea_total_len));
565 *ea_list = ea_list_head;
569 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
570 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
575 if (!lp_ea_support(SNUM(conn))) {
579 if (is_ntfs_stream_smb_fname(smb_fname)) {
580 return NT_STATUS_INVALID_PARAMETER;
583 return get_ea_list_from_file_path(mem_ctx,
591 /****************************************************************************
592 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
594 ****************************************************************************/
596 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
597 connection_struct *conn, struct ea_list *ea_list)
599 unsigned int ret_data_size = 4;
602 SMB_ASSERT(total_data_size >= 4);
604 if (!lp_ea_support(SNUM(conn))) {
609 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
612 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
613 dos_namelen = strlen(dos_ea_name);
614 if (dos_namelen > 255 || dos_namelen == 0) {
617 if (ea_list->ea.value.length > 65535) {
620 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
624 /* We know we have room. */
625 SCVAL(p,0,ea_list->ea.flags);
626 SCVAL(p,1,dos_namelen);
627 SSVAL(p,2,ea_list->ea.value.length);
628 strlcpy(p+4, dos_ea_name, dos_namelen+1);
629 if (ea_list->ea.value.length > 0) {
630 memcpy(p + 4 + dos_namelen + 1,
631 ea_list->ea.value.data,
632 ea_list->ea.value.length);
635 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
636 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
639 ret_data_size = PTR_DIFF(p, pdata);
640 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
641 SIVAL(pdata,0,ret_data_size);
642 return ret_data_size;
645 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
647 unsigned int total_data_size,
648 unsigned int *ret_data_size,
649 connection_struct *conn,
650 struct ea_list *ea_list)
652 uint8_t *p = (uint8_t *)pdata;
653 uint8_t *last_start = NULL;
654 bool do_store_data = (pdata != NULL);
658 if (!lp_ea_support(SNUM(conn))) {
659 return NT_STATUS_NO_EAS_ON_FILE;
662 for (; ea_list; ea_list = ea_list->next) {
668 if (last_start != NULL && do_store_data) {
669 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
673 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
674 dos_namelen = strlen(dos_ea_name);
675 if (dos_namelen > 255 || dos_namelen == 0) {
676 return NT_STATUS_INTERNAL_ERROR;
678 if (ea_list->ea.value.length > 65535) {
679 return NT_STATUS_INTERNAL_ERROR;
682 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
685 pad = (4 - (this_size % 4)) % 4;
690 if (this_size > total_data_size) {
691 return NT_STATUS_INFO_LENGTH_MISMATCH;
694 /* We know we have room. */
695 SIVAL(p, 0x00, 0); /* next offset */
696 SCVAL(p, 0x04, ea_list->ea.flags);
697 SCVAL(p, 0x05, dos_namelen);
698 SSVAL(p, 0x06, ea_list->ea.value.length);
699 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
700 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
702 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
706 total_data_size -= this_size;
712 *ret_data_size = PTR_DIFF(p, pdata);
713 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
717 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
719 size_t total_ea_len = 0;
721 struct ea_list *ea_list = NULL;
723 if (!lp_ea_support(SNUM(conn))) {
726 mem_ctx = talloc_stackframe();
728 /* If this is a stream fsp, then we need to instead find the
729 * estimated ea len from the main file, not the stream
730 * (streams cannot have EAs), but the estimate isn't just 0 in
732 if (is_ntfs_stream_smb_fname(smb_fname)) {
735 (void)get_ea_list_from_file_path(mem_ctx,
741 if(conn->sconn->using_smb2) {
743 unsigned int ret_data_size;
745 * We're going to be using fill_ea_chained_buffer() to
746 * marshall EA's - this size is significantly larger
747 * than the SMB1 buffer. Re-calculate the size without
750 status = fill_ea_chained_buffer(mem_ctx,
756 if (!NT_STATUS_IS_OK(status)) {
759 total_ea_len = ret_data_size;
761 TALLOC_FREE(mem_ctx);
765 /****************************************************************************
766 Ensure the EA name is case insensitive by matching any existing EA name.
767 ****************************************************************************/
769 static void canonicalize_ea_name(connection_struct *conn,
771 const struct smb_filename *smb_fname,
772 fstring unix_ea_name)
775 TALLOC_CTX *mem_ctx = talloc_tos();
776 struct ea_list *ea_list;
777 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
783 if (!NT_STATUS_IS_OK(status)) {
787 for (; ea_list; ea_list = ea_list->next) {
788 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
789 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
790 &unix_ea_name[5], ea_list->ea.name));
791 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
797 /****************************************************************************
798 Set or delete an extended attribute.
799 ****************************************************************************/
801 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
802 const struct smb_filename *smb_fname, struct ea_list *ea_list)
805 bool posix_pathnames = false;
807 if (!lp_ea_support(SNUM(conn))) {
808 return NT_STATUS_EAS_NOT_SUPPORTED;
813 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
815 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
818 status = refuse_symlink(conn, fsp, smb_fname);
819 if (!NT_STATUS_IS_OK(status)) {
823 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
824 if (!NT_STATUS_IS_OK(status)) {
828 /* Setting EAs on streams isn't supported. */
829 if (is_ntfs_stream_smb_fname(smb_fname)) {
830 return NT_STATUS_INVALID_PARAMETER;
834 * Filter out invalid Windows EA names - before
835 * we set *any* of them.
838 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
839 return STATUS_INVALID_EA_NAME;
842 for (;ea_list; ea_list = ea_list->next) {
844 fstring unix_ea_name;
846 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
847 fstrcat(unix_ea_name, ea_list->ea.name);
849 canonicalize_ea_name(conn,
854 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
856 if (samba_private_attr_name(unix_ea_name)) {
857 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
858 return NT_STATUS_ACCESS_DENIED;
861 if (ea_list->ea.value.length == 0) {
862 /* Remove the attribute. */
863 if (fsp && (fsp->fh->fd != -1)) {
864 DEBUG(10,("set_ea: deleting ea name %s on "
865 "file %s by file descriptor.\n",
866 unix_ea_name, fsp_str_dbg(fsp)));
867 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
869 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
870 unix_ea_name, smb_fname->base_name));
871 ret = SMB_VFS_REMOVEXATTR(conn,
876 /* Removing a non existent attribute always succeeds. */
877 if (ret == -1 && errno == ENOATTR) {
878 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
884 if (fsp && (fsp->fh->fd != -1)) {
885 DEBUG(10,("set_ea: setting ea name %s on file "
886 "%s by file descriptor.\n",
887 unix_ea_name, fsp_str_dbg(fsp)));
888 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
889 ea_list->ea.value.data, ea_list->ea.value.length, 0);
891 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
892 unix_ea_name, smb_fname->base_name));
893 ret = SMB_VFS_SETXATTR(conn,
896 ea_list->ea.value.data,
897 ea_list->ea.value.length,
904 if (errno == ENOTSUP) {
905 return NT_STATUS_EAS_NOT_SUPPORTED;
908 return map_nt_error_from_unix(errno);
914 /****************************************************************************
915 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
916 ****************************************************************************/
918 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
920 struct ea_list *ea_list_head = NULL;
921 size_t converted_size, offset = 0;
923 while (offset + 2 < data_size) {
924 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
925 unsigned int namelen = CVAL(pdata,offset);
927 offset++; /* Go past the namelen byte. */
929 /* integer wrap paranioa. */
930 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
931 (offset > data_size) || (namelen > data_size) ||
932 (offset + namelen >= data_size)) {
935 /* Ensure the name is null terminated. */
936 if (pdata[offset + namelen] != '\0') {
939 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
941 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
942 "failed: %s", strerror(errno)));
948 offset += (namelen + 1); /* Go past the name + terminating zero. */
949 DLIST_ADD_END(ea_list_head, eal);
950 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
956 /****************************************************************************
957 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
958 ****************************************************************************/
960 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
962 struct ea_list *ea_list_head = NULL;
964 size_t bytes_used = 0;
966 while (offset < data_size) {
967 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
973 DLIST_ADD_END(ea_list_head, eal);
974 offset += bytes_used;
980 /****************************************************************************
981 Count the total EA size needed.
982 ****************************************************************************/
984 static size_t ea_list_size(struct ea_list *ealist)
987 struct ea_list *listp;
990 for (listp = ealist; listp; listp = listp->next) {
991 push_ascii_fstring(dos_ea_name, listp->ea.name);
992 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
994 /* Add on 4 for total length. */
1002 /****************************************************************************
1003 Return a union of EA's from a file list and a list of names.
1004 The TALLOC context for the two lists *MUST* be identical as we steal
1005 memory from one list to add to another. JRA.
1006 ****************************************************************************/
1008 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
1010 struct ea_list *nlistp, *flistp;
1012 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
1013 for (flistp = file_list; flistp; flistp = flistp->next) {
1014 if (strequal(nlistp->ea.name, flistp->ea.name)) {
1020 /* Copy the data from this entry. */
1021 nlistp->ea.flags = flistp->ea.flags;
1022 nlistp->ea.value = flistp->ea.value;
1025 nlistp->ea.flags = 0;
1026 ZERO_STRUCT(nlistp->ea.value);
1030 *total_ea_len = ea_list_size(name_list);
1034 /****************************************************************************
1035 Send the required number of replies back.
1036 We assume all fields other than the data fields are
1037 set correctly for the type of call.
1038 HACK ! Always assumes smb_setup field is zero.
1039 ****************************************************************************/
1041 void send_trans2_replies(connection_struct *conn,
1042 struct smb_request *req,
1050 /* As we are using a protocol > LANMAN1 then the max_send
1051 variable must have been set in the sessetupX call.
1052 This takes precedence over the max_xmit field in the
1053 global struct. These different max_xmit variables should
1054 be merged as this is now too confusing */
1056 int data_to_send = datasize;
1057 int params_to_send = paramsize;
1059 const char *pp = params;
1060 const char *pd = pdata;
1061 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1062 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1063 int data_alignment_offset = 0;
1064 bool overflow = False;
1065 struct smbXsrv_connection *xconn = req->xconn;
1066 int max_send = xconn->smb1.sessions.max_send;
1068 /* Modify the data_to_send and datasize and set the error if
1069 we're trying to send more than max_data_bytes. We still send
1070 the part of the packet(s) that fit. Strange, but needed
1073 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1074 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1075 max_data_bytes, datasize ));
1076 datasize = data_to_send = max_data_bytes;
1080 /* If there genuinely are no parameters or data to send just send the empty packet */
1082 if(params_to_send == 0 && data_to_send == 0) {
1083 reply_outbuf(req, 10, 0);
1084 if (NT_STATUS_V(status)) {
1087 ntstatus_to_dos(status, &eclass, &ecode);
1088 error_packet_set((char *)req->outbuf,
1089 eclass, ecode, status,
1092 show_msg((char *)req->outbuf);
1093 if (!srv_send_smb(xconn,
1094 (char *)req->outbuf,
1095 true, req->seqnum+1,
1096 IS_CONN_ENCRYPTED(conn),
1098 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1100 TALLOC_FREE(req->outbuf);
1104 /* When sending params and data ensure that both are nicely aligned */
1105 /* Only do this alignment when there is also data to send - else
1106 can cause NT redirector problems. */
1108 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1109 data_alignment_offset = 4 - (params_to_send % 4);
1111 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1112 /* The alignment_offset is to align the param bytes on an even byte
1113 boundary. NT 4.0 Beta needs this to work correctly. */
1115 useable_space = max_send - (smb_size
1118 + data_alignment_offset);
1120 if (useable_space < 0) {
1121 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1122 "= %d!!!", useable_space));
1123 exit_server_cleanly("send_trans2_replies: Not enough space");
1126 while (params_to_send || data_to_send) {
1127 /* Calculate whether we will totally or partially fill this packet */
1129 total_sent_thistime = params_to_send + data_to_send;
1131 /* We can never send more than useable_space */
1133 * Note that 'useable_space' does not include the alignment offsets,
1134 * but we must include the alignment offsets in the calculation of
1135 * the length of the data we send over the wire, as the alignment offsets
1136 * are sent here. Fix from Marc_Jacobsen@hp.com.
1139 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1141 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1142 + data_alignment_offset);
1144 /* Set total params and data to be sent */
1145 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1146 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1148 /* Calculate how many parameters and data we can fit into
1149 * this packet. Parameters get precedence
1152 params_sent_thistime = MIN(params_to_send,useable_space);
1153 data_sent_thistime = useable_space - params_sent_thistime;
1154 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1156 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1158 /* smb_proff is the offset from the start of the SMB header to the
1159 parameter bytes, however the first 4 bytes of outbuf are
1160 the Netbios over TCP header. Thus use smb_base() to subtract
1161 them from the calculation */
1163 SSVAL(req->outbuf,smb_proff,
1164 ((smb_buf(req->outbuf)+alignment_offset)
1165 - smb_base(req->outbuf)));
1167 if(params_sent_thistime == 0)
1168 SSVAL(req->outbuf,smb_prdisp,0);
1170 /* Absolute displacement of param bytes sent in this packet */
1171 SSVAL(req->outbuf,smb_prdisp,pp - params);
1173 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1174 if(data_sent_thistime == 0) {
1175 SSVAL(req->outbuf,smb_droff,0);
1176 SSVAL(req->outbuf,smb_drdisp, 0);
1178 /* The offset of the data bytes is the offset of the
1179 parameter bytes plus the number of parameters being sent this time */
1180 SSVAL(req->outbuf, smb_droff,
1181 ((smb_buf(req->outbuf)+alignment_offset)
1182 - smb_base(req->outbuf))
1183 + params_sent_thistime + data_alignment_offset);
1184 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1187 /* Initialize the padding for alignment */
1189 if (alignment_offset != 0) {
1190 memset(smb_buf(req->outbuf), 0, alignment_offset);
1193 /* Copy the param bytes into the packet */
1195 if(params_sent_thistime) {
1196 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1197 params_sent_thistime);
1200 /* Copy in the data bytes */
1201 if(data_sent_thistime) {
1202 if (data_alignment_offset != 0) {
1203 memset((smb_buf(req->outbuf)+alignment_offset+
1204 params_sent_thistime), 0,
1205 data_alignment_offset);
1207 memcpy(smb_buf(req->outbuf)+alignment_offset
1208 +params_sent_thistime+data_alignment_offset,
1209 pd,data_sent_thistime);
1212 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1213 params_sent_thistime, data_sent_thistime, useable_space));
1214 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1215 params_to_send, data_to_send, paramsize, datasize));
1218 error_packet_set((char *)req->outbuf,
1219 ERRDOS,ERRbufferoverflow,
1220 STATUS_BUFFER_OVERFLOW,
1222 } else if (NT_STATUS_V(status)) {
1225 ntstatus_to_dos(status, &eclass, &ecode);
1226 error_packet_set((char *)req->outbuf,
1227 eclass, ecode, status,
1231 /* Send the packet */
1232 show_msg((char *)req->outbuf);
1233 if (!srv_send_smb(xconn,
1234 (char *)req->outbuf,
1235 true, req->seqnum+1,
1236 IS_CONN_ENCRYPTED(conn),
1238 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1240 TALLOC_FREE(req->outbuf);
1242 pp += params_sent_thistime;
1243 pd += data_sent_thistime;
1245 params_to_send -= params_sent_thistime;
1246 data_to_send -= data_sent_thistime;
1249 if(params_to_send < 0 || data_to_send < 0) {
1250 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1251 params_to_send, data_to_send));
1259 /****************************************************************************
1260 Reply to a TRANSACT2_OPEN.
1261 ****************************************************************************/
1263 static void call_trans2open(connection_struct *conn,
1264 struct smb_request *req,
1265 char **pparams, int total_params,
1266 char **ppdata, int total_data,
1267 unsigned int max_data_bytes)
1269 struct smb_filename *smb_fname = NULL;
1270 char *params = *pparams;
1271 char *pdata = *ppdata;
1274 bool oplock_request;
1276 bool return_additional_info;
1285 int fattr=0,mtime=0;
1286 SMB_INO_T inode = 0;
1289 struct ea_list *ea_list = NULL;
1292 uint32_t access_mask;
1293 uint32_t share_mode;
1294 uint32_t create_disposition;
1295 uint32_t create_options = 0;
1296 uint32_t private_flags = 0;
1297 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1298 TALLOC_CTX *ctx = talloc_tos();
1301 * Ensure we have enough parameters to perform the operation.
1304 if (total_params < 29) {
1305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1309 flags = SVAL(params, 0);
1310 deny_mode = SVAL(params, 2);
1311 open_attr = SVAL(params,6);
1312 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1313 if (oplock_request) {
1314 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1318 return_additional_info = BITSETW(params,0);
1319 open_sattr = SVAL(params, 4);
1320 open_time = make_unix_date3(params+8);
1322 open_ofun = SVAL(params,12);
1323 open_size = IVAL(params,14);
1324 pname = ¶ms[28];
1327 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1331 if (req->posix_pathnames) {
1332 srvstr_get_path_posix(ctx,
1341 srvstr_get_path(ctx,
1350 if (!NT_STATUS_IS_OK(status)) {
1351 reply_nterror(req, status);
1355 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1356 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1357 (unsigned int)open_ofun, open_size));
1359 status = filename_convert(ctx,
1366 if (!NT_STATUS_IS_OK(status)) {
1367 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1368 reply_botherror(req,
1369 NT_STATUS_PATH_NOT_COVERED,
1370 ERRSRV, ERRbadpath);
1373 reply_nterror(req, status);
1377 if (open_ofun == 0) {
1378 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1382 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1384 &access_mask, &share_mode,
1385 &create_disposition,
1388 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1392 /* Any data in this call is an EA list. */
1393 if (total_data && (total_data != 4)) {
1394 if (total_data < 10) {
1395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1399 if (IVAL(pdata,0) > total_data) {
1400 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1401 IVAL(pdata,0), (unsigned int)total_data));
1402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1406 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1413 if (!lp_ea_support(SNUM(conn))) {
1414 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1418 if (!req->posix_pathnames &&
1419 ea_list_has_invalid_name(ea_list)) {
1421 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1422 if(*pparams == NULL ) {
1423 reply_nterror(req, NT_STATUS_NO_MEMORY);
1427 memset(params, '\0', param_len);
1428 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1429 params, param_len, NULL, 0, max_data_bytes);
1434 status = SMB_VFS_CREATE_FILE(
1437 0, /* root_dir_fid */
1438 smb_fname, /* fname */
1439 access_mask, /* access_mask */
1440 share_mode, /* share_access */
1441 create_disposition, /* create_disposition*/
1442 create_options, /* create_options */
1443 open_attr, /* file_attributes */
1444 oplock_request, /* oplock_request */
1446 open_size, /* allocation_size */
1449 ea_list, /* ea_list */
1451 &smb_action, /* psbuf */
1452 NULL, NULL); /* create context */
1454 if (!NT_STATUS_IS_OK(status)) {
1455 if (open_was_deferred(req->xconn, req->mid)) {
1456 /* We have re-scheduled this call. */
1460 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1461 reply_openerror(req, status);
1465 fsp = fcb_or_dos_open(
1472 bool ok = defer_smb1_sharing_violation(req);
1476 reply_openerror(req, status);
1480 smb_action = FILE_WAS_OPENED;
1483 size = get_file_size_stat(&smb_fname->st);
1484 fattr = dos_mode(conn, smb_fname);
1485 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1486 inode = smb_fname->st.st_ex_ino;
1487 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1488 close_file(req, fsp, ERROR_CLOSE);
1489 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1493 /* Realloc the size of parameters and data we will return */
1494 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1495 if(*pparams == NULL ) {
1496 reply_nterror(req, NT_STATUS_NO_MEMORY);
1501 SSVAL(params,0,fsp->fnum);
1502 SSVAL(params,2,fattr);
1503 srv_put_dos_date2(params,4, mtime);
1504 SIVAL(params,8, (uint32_t)size);
1505 SSVAL(params,12,deny_mode);
1506 SSVAL(params,14,0); /* open_type - file or directory. */
1507 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1509 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1510 smb_action |= EXTENDED_OPLOCK_GRANTED;
1513 SSVAL(params,18,smb_action);
1516 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1518 SIVAL(params,20,inode);
1519 SSVAL(params,24,0); /* Padding. */
1521 uint32_t ea_size = estimate_ea_size(conn, fsp,
1523 SIVAL(params, 26, ea_size);
1525 SIVAL(params, 26, 0);
1528 /* Send the required number of replies */
1529 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1531 TALLOC_FREE(smb_fname);
1534 /*********************************************************
1535 Routine to check if a given string matches exactly.
1536 as a special case a mask of "." does NOT match. That
1537 is required for correct wildcard semantics
1538 Case can be significant or not.
1539 **********************************************************/
1541 static bool exact_match(bool has_wild,
1542 bool case_sensitive,
1546 if (mask[0] == '.' && mask[1] == 0) {
1554 if (case_sensitive) {
1555 return strcmp(str,mask)==0;
1557 return strcasecmp_m(str,mask) == 0;
1561 /****************************************************************************
1562 Return the filetype for UNIX extensions.
1563 ****************************************************************************/
1565 static uint32_t unix_filetype(mode_t mode)
1568 return UNIX_TYPE_FILE;
1569 else if(S_ISDIR(mode))
1570 return UNIX_TYPE_DIR;
1572 else if(S_ISLNK(mode))
1573 return UNIX_TYPE_SYMLINK;
1576 else if(S_ISCHR(mode))
1577 return UNIX_TYPE_CHARDEV;
1580 else if(S_ISBLK(mode))
1581 return UNIX_TYPE_BLKDEV;
1584 else if(S_ISFIFO(mode))
1585 return UNIX_TYPE_FIFO;
1588 else if(S_ISSOCK(mode))
1589 return UNIX_TYPE_SOCKET;
1592 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1593 return UNIX_TYPE_UNKNOWN;
1596 /****************************************************************************
1597 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1598 ****************************************************************************/
1600 NTSTATUS unix_perms_from_wire(connection_struct *conn,
1601 const SMB_STRUCT_STAT *psbuf,
1603 enum perm_type ptype,
1608 if (perms == SMB_MODE_NO_CHANGE) {
1609 if (!VALID_STAT(*psbuf)) {
1610 return NT_STATUS_INVALID_PARAMETER;
1612 *ret_perms = psbuf->st_ex_mode;
1613 return NT_STATUS_OK;
1617 ret = wire_perms_to_unix(perms);
1619 if (ptype == PERM_NEW_FILE) {
1621 * "create mask"/"force create mode" are
1622 * only applied to new files, not existing ones.
1624 ret &= lp_create_mask(SNUM(conn));
1625 /* Add in force bits */
1626 ret |= lp_force_create_mode(SNUM(conn));
1627 } else if (ptype == PERM_NEW_DIR) {
1629 * "directory mask"/"force directory mode" are
1630 * only applied to new directories, not existing ones.
1632 ret &= lp_directory_mask(SNUM(conn));
1633 /* Add in force bits */
1634 ret |= lp_force_directory_mode(SNUM(conn));
1638 return NT_STATUS_OK;
1641 /****************************************************************************
1642 Needed to show the msdfs symlinks as directories. Modifies psbuf
1643 to be a directory if it's a msdfs link.
1644 ****************************************************************************/
1646 static bool check_msdfs_link(connection_struct *conn,
1647 struct smb_filename *smb_fname)
1649 int saved_errno = errno;
1650 if(lp_host_msdfs() &&
1651 lp_msdfs_root(SNUM(conn)) &&
1652 is_msdfs_link(conn, smb_fname)) {
1654 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1656 smb_fname->base_name));
1657 smb_fname->st.st_ex_mode =
1658 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1659 errno = saved_errno;
1662 errno = saved_errno;
1667 /****************************************************************************
1668 Get a level dependent lanman2 dir entry.
1669 ****************************************************************************/
1671 struct smbd_dirptr_lanman2_state {
1672 connection_struct *conn;
1673 uint32_t info_level;
1674 bool check_mangled_names;
1676 bool got_exact_match;
1679 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1685 struct smbd_dirptr_lanman2_state *state =
1686 (struct smbd_dirptr_lanman2_state *)private_data;
1688 char mangled_name[13]; /* mangled 8.3 name. */
1692 /* Mangle fname if it's an illegal name. */
1693 if (mangle_must_mangle(dname, state->conn->params)) {
1695 * Slow path - ensure we can push the original name as UCS2. If
1696 * not, then just don't return this name.
1700 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1701 uint8_t *tmp = talloc_array(talloc_tos(),
1705 status = srvstr_push(NULL,
1706 FLAGS2_UNICODE_STRINGS,
1715 if (!NT_STATUS_IS_OK(status)) {
1719 ok = name_to_8_3(dname, mangled_name,
1720 true, state->conn->params);
1724 fname = mangled_name;
1729 got_match = exact_match(state->has_wild,
1730 state->conn->case_sensitive,
1732 state->got_exact_match = got_match;
1734 got_match = mask_match(fname, mask,
1735 state->conn->case_sensitive);
1738 if(!got_match && state->check_mangled_names &&
1739 !mangle_is_8_3(fname, false, state->conn->params)) {
1741 * It turns out that NT matches wildcards against
1742 * both long *and* short names. This may explain some
1743 * of the wildcard wierdness from old DOS clients
1744 * that some people have been seeing.... JRA.
1746 /* Force the mangling into 8.3. */
1747 ok = name_to_8_3(fname, mangled_name,
1748 false, state->conn->params);
1753 got_match = exact_match(state->has_wild,
1754 state->conn->case_sensitive,
1755 mangled_name, mask);
1756 state->got_exact_match = got_match;
1758 got_match = mask_match(mangled_name, mask,
1759 state->conn->case_sensitive);
1767 *_fname = talloc_strdup(ctx, fname);
1768 if (*_fname == NULL) {
1775 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1777 struct smb_filename *smb_fname,
1781 struct smbd_dirptr_lanman2_state *state =
1782 (struct smbd_dirptr_lanman2_state *)private_data;
1783 bool ms_dfs_link = false;
1786 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1787 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1788 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1789 "Couldn't lstat [%s] (%s)\n",
1790 smb_fname_str_dbg(smb_fname),
1794 } else if (!VALID_STAT(smb_fname->st) &&
1795 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1796 /* Needed to show the msdfs symlinks as
1799 ms_dfs_link = check_msdfs_link(state->conn,
1802 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1803 "Couldn't stat [%s] (%s)\n",
1804 smb_fname_str_dbg(smb_fname),
1811 mode = dos_mode_msdfs(state->conn, smb_fname);
1812 } else if (get_dosmode) {
1813 mode = dos_mode(state->conn, smb_fname);
1820 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1821 connection_struct *conn,
1823 uint32_t info_level,
1824 struct ea_list *name_list,
1825 bool check_mangled_names,
1826 bool requires_resume_key,
1829 const struct smb_filename *smb_fname,
1830 int space_remaining,
1836 uint64_t *last_entry_off)
1838 char *p, *q, *pdata = *ppdata;
1840 uint64_t file_size = 0;
1841 uint64_t allocation_size = 0;
1842 uint64_t file_id = 0;
1844 struct timespec mdate_ts = {0};
1845 struct timespec adate_ts = {0};
1846 struct timespec cdate_ts = {0};
1847 struct timespec create_date_ts = {0};
1848 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1850 char *last_entry_ptr;
1855 struct readdir_attr_data *readdir_attr_data = NULL;
1857 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1858 file_size = get_file_size_stat(&smb_fname->st);
1860 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1862 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1863 if (!NT_STATUS_IS_OK(status)) {
1864 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1869 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1871 mdate_ts = smb_fname->st.st_ex_mtime;
1872 adate_ts = smb_fname->st.st_ex_atime;
1873 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1874 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1876 if (lp_dos_filetime_resolution(SNUM(conn))) {
1877 dos_filetime_timespec(&create_date_ts);
1878 dos_filetime_timespec(&mdate_ts);
1879 dos_filetime_timespec(&adate_ts);
1880 dos_filetime_timespec(&cdate_ts);
1883 create_date = convert_timespec_to_time_t(create_date_ts);
1884 mdate = convert_timespec_to_time_t(mdate_ts);
1885 adate = convert_timespec_to_time_t(adate_ts);
1887 /* align the record */
1888 SMB_ASSERT(align >= 1);
1890 off = (int)PTR_DIFF(pdata, base_data);
1891 pad = (off + (align-1)) & ~(align-1);
1894 if (pad && pad > space_remaining) {
1895 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1896 "for padding (wanted %u, had %d)\n",
1899 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1903 /* initialize padding to 0 */
1905 memset(pdata, 0, pad);
1907 space_remaining -= pad;
1909 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1919 switch (info_level) {
1920 case SMB_FIND_INFO_STANDARD:
1921 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1922 if(requires_resume_key) {
1926 srv_put_dos_date2(p,0,create_date);
1927 srv_put_dos_date2(p,4,adate);
1928 srv_put_dos_date2(p,8,mdate);
1929 SIVAL(p,12,(uint32_t)file_size);
1930 SIVAL(p,16,(uint32_t)allocation_size);
1934 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1935 p += ucs2_align(base_data, p, 0);
1937 status = srvstr_push(base_data, flags2, p,
1938 fname, PTR_DIFF(end_data, p),
1939 STR_TERMINATE, &len);
1940 if (!NT_STATUS_IS_OK(status)) {
1943 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1945 SCVAL(nameptr, -1, len - 2);
1947 SCVAL(nameptr, -1, 0);
1951 SCVAL(nameptr, -1, len - 1);
1953 SCVAL(nameptr, -1, 0);
1959 case SMB_FIND_EA_SIZE:
1960 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1961 if (requires_resume_key) {
1965 srv_put_dos_date2(p,0,create_date);
1966 srv_put_dos_date2(p,4,adate);
1967 srv_put_dos_date2(p,8,mdate);
1968 SIVAL(p,12,(uint32_t)file_size);
1969 SIVAL(p,16,(uint32_t)allocation_size);
1972 unsigned int ea_size = estimate_ea_size(conn, NULL,
1974 SIVAL(p,22,ea_size); /* Extended attributes */
1978 status = srvstr_push(base_data, flags2,
1979 p, fname, PTR_DIFF(end_data, p),
1980 STR_TERMINATE | STR_NOALIGN, &len);
1981 if (!NT_STATUS_IS_OK(status)) {
1984 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1997 SCVAL(nameptr,0,len);
1999 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2002 case SMB_FIND_EA_LIST:
2004 struct ea_list *file_list = NULL;
2007 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
2009 return NT_STATUS_INVALID_PARAMETER;
2011 if (requires_resume_key) {
2015 srv_put_dos_date2(p,0,create_date);
2016 srv_put_dos_date2(p,4,adate);
2017 srv_put_dos_date2(p,8,mdate);
2018 SIVAL(p,12,(uint32_t)file_size);
2019 SIVAL(p,16,(uint32_t)allocation_size);
2021 p += 22; /* p now points to the EA area. */
2023 status = get_ea_list_from_file(ctx, conn, NULL,
2025 &ea_len, &file_list);
2026 if (!NT_STATUS_IS_OK(status)) {
2029 name_list = ea_list_union(name_list, file_list, &ea_len);
2031 /* We need to determine if this entry will fit in the space available. */
2032 /* Max string size is 255 bytes. */
2033 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2034 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2035 "(wanted %u, had %d)\n",
2036 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2038 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2041 /* Push the ea_data followed by the name. */
2042 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2044 status = srvstr_push(base_data, flags2,
2045 p + 1, fname, PTR_DIFF(end_data, p+1),
2046 STR_TERMINATE | STR_NOALIGN, &len);
2047 if (!NT_STATUS_IS_OK(status)) {
2050 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2063 SCVAL(nameptr,0,len);
2065 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2069 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2070 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2071 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2073 SIVAL(p,0,reskey); p += 4;
2074 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2075 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2076 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2077 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2078 SOFF_T(p,0,file_size); p += 8;
2079 SOFF_T(p,0,allocation_size); p += 8;
2080 SIVAL(p,0,mode); p += 4;
2081 q = p; p += 4; /* q is placeholder for name length. */
2082 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2083 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2085 unsigned int ea_size = estimate_ea_size(conn, NULL,
2087 SIVAL(p,0,ea_size); /* Extended attributes */
2090 /* Clear the short name buffer. This is
2091 * IMPORTANT as not doing so will trigger
2092 * a Win2k client bug. JRA.
2094 if (!was_8_3 && check_mangled_names) {
2095 char mangled_name[13]; /* mangled 8.3 name. */
2096 if (!name_to_8_3(fname,mangled_name,True,
2098 /* Error - mangle failed ! */
2099 memset(mangled_name,'\0',12);
2101 mangled_name[12] = 0;
2102 status = srvstr_push(base_data, flags2,
2103 p+2, mangled_name, 24,
2104 STR_UPPER|STR_UNICODE, &len);
2105 if (!NT_STATUS_IS_OK(status)) {
2109 memset(p + 2 + len,'\0',24 - len);
2116 status = srvstr_push(base_data, flags2, p,
2117 fname, PTR_DIFF(end_data, p),
2118 STR_TERMINATE_ASCII, &len);
2119 if (!NT_STATUS_IS_OK(status)) {
2125 len = PTR_DIFF(p, pdata);
2126 pad = (len + (align-1)) & ~(align-1);
2128 * offset to the next entry, the caller
2129 * will overwrite it for the last entry
2130 * that's why we always include the padding
2134 * set padding to zero
2137 memset(p, 0, pad - len);
2144 case SMB_FIND_FILE_DIRECTORY_INFO:
2145 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2147 SIVAL(p,0,reskey); p += 4;
2148 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2149 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2150 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2151 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2152 SOFF_T(p,0,file_size); p += 8;
2153 SOFF_T(p,0,allocation_size); p += 8;
2154 SIVAL(p,0,mode); p += 4;
2155 status = srvstr_push(base_data, flags2,
2156 p + 4, fname, PTR_DIFF(end_data, p+4),
2157 STR_TERMINATE_ASCII, &len);
2158 if (!NT_STATUS_IS_OK(status)) {
2164 len = PTR_DIFF(p, pdata);
2165 pad = (len + (align-1)) & ~(align-1);
2167 * offset to the next entry, the caller
2168 * will overwrite it for the last entry
2169 * that's why we always include the padding
2173 * set padding to zero
2176 memset(p, 0, pad - len);
2183 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2184 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2186 SIVAL(p,0,reskey); p += 4;
2187 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2188 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2189 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2190 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2191 SOFF_T(p,0,file_size); p += 8;
2192 SOFF_T(p,0,allocation_size); p += 8;
2193 SIVAL(p,0,mode); p += 4;
2194 q = p; p += 4; /* q is placeholder for name length. */
2195 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2196 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2198 unsigned int ea_size = estimate_ea_size(conn, NULL,
2200 SIVAL(p,0,ea_size); /* Extended attributes */
2203 status = srvstr_push(base_data, flags2, p,
2204 fname, PTR_DIFF(end_data, p),
2205 STR_TERMINATE_ASCII, &len);
2206 if (!NT_STATUS_IS_OK(status)) {
2212 len = PTR_DIFF(p, pdata);
2213 pad = (len + (align-1)) & ~(align-1);
2215 * offset to the next entry, the caller
2216 * will overwrite it for the last entry
2217 * that's why we always include the padding
2221 * set padding to zero
2224 memset(p, 0, pad - len);
2231 case SMB_FIND_FILE_NAMES_INFO:
2232 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2234 SIVAL(p,0,reskey); p += 4;
2236 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2237 acl on a dir (tridge) */
2238 status = srvstr_push(base_data, flags2, p,
2239 fname, PTR_DIFF(end_data, p),
2240 STR_TERMINATE_ASCII, &len);
2241 if (!NT_STATUS_IS_OK(status)) {
2247 len = PTR_DIFF(p, pdata);
2248 pad = (len + (align-1)) & ~(align-1);
2250 * offset to the next entry, the caller
2251 * will overwrite it for the last entry
2252 * that's why we always include the padding
2256 * set padding to zero
2259 memset(p, 0, pad - len);
2266 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2267 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2269 SIVAL(p,0,reskey); p += 4;
2270 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2271 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2272 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2273 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2274 SOFF_T(p,0,file_size); p += 8;
2275 SOFF_T(p,0,allocation_size); p += 8;
2276 SIVAL(p,0,mode); p += 4;
2277 q = p; p += 4; /* q is placeholder for name length. */
2278 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2279 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2281 unsigned int ea_size = estimate_ea_size(conn, NULL,
2283 SIVAL(p,0,ea_size); /* Extended attributes */
2286 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2287 SBVAL(p,0,file_id); p += 8;
2288 status = srvstr_push(base_data, flags2, p,
2289 fname, PTR_DIFF(end_data, p),
2290 STR_TERMINATE_ASCII, &len);
2291 if (!NT_STATUS_IS_OK(status)) {
2297 len = PTR_DIFF(p, pdata);
2298 pad = (len + (align-1)) & ~(align-1);
2300 * offset to the next entry, the caller
2301 * will overwrite it for the last entry
2302 * that's why we always include the padding
2306 * set padding to zero
2309 memset(p, 0, pad - len);
2316 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2317 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2318 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2320 SIVAL(p,0,reskey); p += 4;
2321 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2322 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2323 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2324 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2325 SOFF_T(p,0,file_size); p += 8;
2326 SOFF_T(p,0,allocation_size); p += 8;
2327 SIVAL(p,0,mode); p += 4;
2328 q = p; p += 4; /* q is placeholder for name length */
2329 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2330 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2331 } else if (readdir_attr_data &&
2332 readdir_attr_data->type == RDATTR_AAPL) {
2334 * OS X specific SMB2 extension negotiated via
2335 * AAPL create context: return max_access in
2338 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2340 unsigned int ea_size = estimate_ea_size(conn, NULL,
2342 SIVAL(p,0,ea_size); /* Extended attributes */
2346 if (readdir_attr_data &&
2347 readdir_attr_data->type == RDATTR_AAPL) {
2349 * OS X specific SMB2 extension negotiated via
2350 * AAPL create context: return resource fork
2351 * length and compressed FinderInfo in
2354 * According to documentation short_name_len
2355 * should be 0, but on the wire behaviour
2356 * shows its set to 24 by clients.
2360 /* Resourefork length */
2361 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2363 /* Compressed FinderInfo */
2364 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2365 } else if (!was_8_3 && check_mangled_names) {
2366 char mangled_name[13]; /* mangled 8.3 name. */
2367 if (!name_to_8_3(fname,mangled_name,True,
2369 /* Error - mangle failed ! */
2370 memset(mangled_name,'\0',12);
2372 mangled_name[12] = 0;
2373 status = srvstr_push(base_data, flags2,
2374 p+2, mangled_name, 24,
2375 STR_UPPER|STR_UNICODE, &len);
2376 if (!NT_STATUS_IS_OK(status)) {
2381 memset(p + 2 + len,'\0',24 - len);
2385 /* Clear the short name buffer. This is
2386 * IMPORTANT as not doing so will trigger
2387 * a Win2k client bug. JRA.
2394 if (readdir_attr_data &&
2395 readdir_attr_data->type == RDATTR_AAPL) {
2397 * OS X specific SMB2 extension negotiated via
2398 * AAPL create context: return UNIX mode in
2401 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2402 SSVAL(p, 0, aapl_mode);
2408 SBVAL(p,0,file_id); p += 8;
2409 status = srvstr_push(base_data, flags2, p,
2410 fname, PTR_DIFF(end_data, p),
2411 STR_TERMINATE_ASCII, &len);
2412 if (!NT_STATUS_IS_OK(status)) {
2418 len = PTR_DIFF(p, pdata);
2419 pad = (len + (align-1)) & ~(align-1);
2421 * offset to the next entry, the caller
2422 * will overwrite it for the last entry
2423 * that's why we always include the padding
2427 * set padding to zero
2430 memset(p, 0, pad - len);
2437 /* CIFS UNIX Extension. */
2439 case SMB_FIND_FILE_UNIX:
2440 case SMB_FIND_FILE_UNIX_INFO2:
2442 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2444 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2446 if (info_level == SMB_FIND_FILE_UNIX) {
2447 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2448 p = store_file_unix_basic(conn, p,
2449 NULL, &smb_fname->st);
2450 status = srvstr_push(base_data, flags2, p,
2451 fname, PTR_DIFF(end_data, p),
2452 STR_TERMINATE, &len);
2453 if (!NT_STATUS_IS_OK(status)) {
2457 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2458 p = store_file_unix_basic_info2(conn, p,
2459 NULL, &smb_fname->st);
2462 status = srvstr_push(base_data, flags2, p, fname,
2463 PTR_DIFF(end_data, p), 0, &len);
2464 if (!NT_STATUS_IS_OK(status)) {
2467 SIVAL(nameptr, 0, len);
2472 len = PTR_DIFF(p, pdata);
2473 pad = (len + (align-1)) & ~(align-1);
2475 * offset to the next entry, the caller
2476 * will overwrite it for the last entry
2477 * that's why we always include the padding
2481 * set padding to zero
2484 memset(p, 0, pad - len);
2489 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2494 return NT_STATUS_INVALID_LEVEL;
2497 if (PTR_DIFF(p,pdata) > space_remaining) {
2498 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2499 "(wanted %u, had %d)\n",
2500 (unsigned int)PTR_DIFF(p,pdata),
2502 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2505 /* Setup the last entry pointer, as an offset from base_data */
2506 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2507 /* Advance the data pointer to the next slot */
2510 return NT_STATUS_OK;
2513 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2514 connection_struct *conn,
2515 struct dptr_struct *dirptr,
2517 const char *path_mask,
2520 int requires_resume_key,
2529 int space_remaining,
2530 struct smb_filename **_smb_fname,
2531 bool *got_exact_match,
2532 int *_last_entry_off,
2533 struct ea_list *name_list,
2534 struct file_id *file_id)
2537 const char *mask = NULL;
2538 long prev_dirpos = 0;
2541 struct smb_filename *smb_fname = NULL;
2542 struct smbd_dirptr_lanman2_state state;
2544 uint64_t last_entry_off = 0;
2546 enum mangled_names_options mangled_names;
2547 bool marshall_with_83_names;
2549 mangled_names = lp_mangled_names(conn->params);
2553 state.info_level = info_level;
2554 if (mangled_names != MANGLED_NAMES_NO) {
2555 state.check_mangled_names = true;
2557 state.has_wild = dptr_has_wild(dirptr);
2558 state.got_exact_match = false;
2560 *got_exact_match = false;
2562 p = strrchr_m(path_mask,'/');
2573 ok = smbd_dirptr_get_entry(ctx,
2580 smbd_dirptr_lanman2_match_fn,
2581 smbd_dirptr_lanman2_mode_fn,
2588 return NT_STATUS_END_OF_FILE;
2591 *got_exact_match = state.got_exact_match;
2593 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2595 status = smbd_marshall_dir_entry(ctx,
2600 marshall_with_83_names,
2601 requires_resume_key,
2612 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2613 DEBUG(1,("Conversion error: illegal character: %s\n",
2614 smb_fname_str_dbg(smb_fname)));
2617 if (file_id != NULL) {
2618 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2621 if (!NT_STATUS_IS_OK(status) &&
2622 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2624 TALLOC_FREE(smb_fname);
2629 if (_smb_fname != NULL) {
2630 struct smb_filename *name = NULL;
2632 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2634 TALLOC_FREE(smb_fname);
2636 return NT_STATUS_NO_MEMORY;
2641 TALLOC_FREE(smb_fname);
2644 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2645 dptr_SeekDir(dirptr, prev_dirpos);
2649 *_last_entry_off = last_entry_off;
2650 return NT_STATUS_OK;
2653 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2654 connection_struct *conn,
2655 struct dptr_struct *dirptr,
2657 const char *path_mask,
2660 bool requires_resume_key,
2666 int space_remaining,
2667 bool *got_exact_match,
2668 int *last_entry_off,
2669 struct ea_list *name_list)
2672 const bool do_pad = true;
2674 if (info_level >= 1 && info_level <= 3) {
2675 /* No alignment on earlier info levels. */
2679 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2680 path_mask, dirtype, info_level,
2681 requires_resume_key, dont_descend, ask_sharemode,
2682 true, align, do_pad,
2683 ppdata, base_data, end_data,
2687 last_entry_off, name_list, NULL);
2690 /****************************************************************************
2691 Reply to a TRANS2_FINDFIRST.
2692 ****************************************************************************/
2694 static void call_trans2findfirst(connection_struct *conn,
2695 struct smb_request *req,
2696 char **pparams, int total_params,
2697 char **ppdata, int total_data,
2698 unsigned int max_data_bytes)
2700 /* We must be careful here that we don't return more than the
2701 allowed number of data bytes. If this means returning fewer than
2702 maxentries then so be it. We assume that the redirector has
2703 enough room for the fixed number of parameter bytes it has
2705 struct smb_filename *smb_dname = NULL;
2706 char *params = *pparams;
2707 char *pdata = *ppdata;
2711 uint16_t findfirst_flags;
2712 bool close_after_first;
2714 bool requires_resume_key;
2716 char *directory = NULL;
2719 int last_entry_off=0;
2723 bool finished = False;
2724 bool dont_descend = False;
2725 bool out_of_space = False;
2726 int space_remaining;
2727 bool mask_contains_wcard = False;
2728 struct ea_list *ea_list = NULL;
2729 NTSTATUS ntstatus = NT_STATUS_OK;
2730 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
2731 struct smbd_server_connection *sconn = req->sconn;
2732 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2733 ucf_flags_from_smb_request(req);
2734 bool backup_priv = false;
2735 bool as_root = false;
2736 files_struct *fsp = NULL;
2737 const struct loadparm_substitution *lp_sub =
2738 loadparm_s3_global_substitution();
2741 if (total_params < 13) {
2742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2746 dirtype = SVAL(params,0);
2747 maxentries = SVAL(params,2);
2748 findfirst_flags = SVAL(params,4);
2749 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2750 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2751 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2752 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2753 security_token_has_privilege(get_current_nttok(conn),
2756 info_level = SVAL(params,6);
2758 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2759 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2760 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2762 info_level, max_data_bytes));
2765 /* W2K3 seems to treat zero as 1. */
2769 switch (info_level) {
2770 case SMB_FIND_INFO_STANDARD:
2771 case SMB_FIND_EA_SIZE:
2772 case SMB_FIND_EA_LIST:
2773 case SMB_FIND_FILE_DIRECTORY_INFO:
2774 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2775 case SMB_FIND_FILE_NAMES_INFO:
2776 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2777 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2778 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2780 case SMB_FIND_FILE_UNIX:
2781 case SMB_FIND_FILE_UNIX_INFO2:
2782 /* Always use filesystem for UNIX mtime query. */
2783 ask_sharemode = false;
2784 if (!lp_unix_extensions()) {
2785 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2788 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2791 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2795 if (req->posix_pathnames) {
2796 srvstr_get_path_wcard_posix(talloc_tos(),
2804 &mask_contains_wcard);
2806 srvstr_get_path_wcard(talloc_tos(),
2814 &mask_contains_wcard);
2816 if (!NT_STATUS_IS_OK(ntstatus)) {
2817 reply_nterror(req, ntstatus);
2824 ntstatus = filename_convert_with_privilege(talloc_tos(),
2829 &mask_contains_wcard,
2832 ntstatus = filename_convert(talloc_tos(), conn,
2836 &mask_contains_wcard,
2840 if (!NT_STATUS_IS_OK(ntstatus)) {
2841 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2842 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2843 ERRSRV, ERRbadpath);
2846 reply_nterror(req, ntstatus);
2850 mask = smb_dname->original_lcomp;
2852 directory = smb_dname->base_name;
2854 p = strrchr_m(directory,'/');
2856 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2857 if((directory[0] == '.') && (directory[1] == '\0')) {
2858 mask = talloc_strdup(talloc_tos(),"*");
2860 reply_nterror(req, NT_STATUS_NO_MEMORY);
2863 mask_contains_wcard = True;
2869 if (p == NULL || p == directory) {
2870 /* Ensure we don't have a directory name of "". */
2871 directory = talloc_strdup(talloc_tos(), ".");
2873 reply_nterror(req, NT_STATUS_NO_MEMORY);
2876 /* Ensure smb_dname->base_name matches. */
2877 smb_dname->base_name = directory;
2880 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2882 if (info_level == SMB_FIND_EA_LIST) {
2885 if (total_data < 4) {
2886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2890 ea_size = IVAL(pdata,0);
2891 if (ea_size != total_data) {
2892 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2893 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2898 if (!lp_ea_support(SNUM(conn))) {
2899 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2903 /* Pull out the list of names. */
2904 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2911 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2912 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2916 *ppdata = (char *)SMB_REALLOC(
2917 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2918 if(*ppdata == NULL ) {
2919 reply_nterror(req, NT_STATUS_NO_MEMORY);
2923 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2925 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2928 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2929 /* Realloc the params space */
2930 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2931 if (*pparams == NULL) {
2932 reply_nterror(req, NT_STATUS_NO_MEMORY);
2938 * As we've cut off the last component from
2939 * smb_fname we need to re-stat smb_dname
2940 * so FILE_OPEN disposition knows the directory
2943 if (req->posix_pathnames) {
2944 ret = SMB_VFS_LSTAT(conn, smb_dname);
2946 ret = SMB_VFS_STAT(conn, smb_dname);
2950 ntstatus = map_nt_error_from_unix(errno);
2951 reply_nterror(req, ntstatus);
2956 * Open an fsp on this directory for the dptr.
2958 ntstatus = SMB_VFS_CREATE_FILE(
2961 0, /* root_dir_fid */
2962 smb_dname, /* dname */
2963 FILE_LIST_DIRECTORY, /* access_mask */
2965 FILE_SHARE_WRITE, /* share_access */
2966 FILE_OPEN, /* create_disposition*/
2967 FILE_DIRECTORY_FILE, /* create_options */
2968 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2969 NO_OPLOCK, /* oplock_request */
2971 0, /* allocation_size */
2972 0, /* private_flags */
2977 NULL, /* in_context */
2978 NULL);/* out_context */
2980 if (!NT_STATUS_IS_OK(ntstatus)) {
2981 DBG_ERR("failed to open directory %s\n",
2982 smb_fname_str_dbg(smb_dname));
2983 reply_nterror(req, ntstatus);
2987 /* Save the wildcard match and attribs we are using on this directory -
2988 needed as lanman2 assumes these are being saved between calls */
2990 ntstatus = dptr_create(conn,
2997 mask_contains_wcard,
3001 if (!NT_STATUS_IS_OK(ntstatus)) {
3003 * Use NULL here for the first parameter (req)
3004 * as this is not a client visible handle so
3005 * can'tbe part of an SMB1 chain.
3007 close_file(NULL, fsp, NORMAL_CLOSE);
3009 reply_nterror(req, ntstatus);
3014 /* Remember this in case we have
3015 to do a findnext. */
3016 dptr_set_priv(fsp->dptr);
3019 dptr_num = dptr_dnum(fsp->dptr);
3020 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
3022 /* We don't need to check for VOL here as this is returned by
3023 a different TRANS2 call. */
3025 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3026 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
3027 if (in_list(directory,
3028 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
3029 conn->case_sensitive)) {
3030 dont_descend = True;
3034 space_remaining = max_data_bytes;
3035 out_of_space = False;
3037 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
3038 bool got_exact_match = False;
3040 /* this is a heuristic to avoid seeking the dirptr except when
3041 absolutely necessary. It allows for a filename of about 40 chars */
3042 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3043 out_of_space = True;
3046 ntstatus = get_lanman2_dir_entry(talloc_tos(),
3050 mask,dirtype,info_level,
3051 requires_resume_key,dont_descend,
3056 &last_entry_off, ea_list);
3057 if (NT_STATUS_EQUAL(ntstatus,
3058 NT_STATUS_ILLEGAL_CHARACTER)) {
3060 * Bad character conversion on name. Ignore this
3065 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3066 out_of_space = true;
3068 finished = !NT_STATUS_IS_OK(ntstatus);
3072 if (!finished && !out_of_space)
3076 * As an optimisation if we know we aren't looking
3077 * for a wildcard name (ie. the name matches the wildcard exactly)
3078 * then we can finish on any (first) match.
3079 * This speeds up large directory searches. JRA.
3085 /* Ensure space_remaining never goes -ve. */
3086 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3087 space_remaining = 0;
3088 out_of_space = true;
3090 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3094 /* Check if we can close the dirptr */
3095 if(close_after_first || (finished && close_if_end)) {
3096 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3098 close_file(NULL, fsp, NORMAL_CLOSE);
3103 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3104 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3105 * the protocol level is less than NT1. Tested with smbclient. JRA.
3106 * This should fix the OS/2 client bug #2335.
3109 if(numentries == 0) {
3112 * We may have already closed the file in the
3113 * close_after_first or finished case above.
3116 close_file(NULL, fsp, NORMAL_CLOSE);
3119 if (get_Protocol() < PROTOCOL_NT1) {
3120 reply_force_doserror(req, ERRDOS, ERRnofiles);
3123 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3124 ERRDOS, ERRbadfile);
3129 /* At this point pdata points to numentries directory entries. */
3131 /* Set up the return parameter block */
3132 SSVAL(params,0,dptr_num);
3133 SSVAL(params,2,numentries);
3134 SSVAL(params,4,finished);
3135 SSVAL(params,6,0); /* Never an EA error */
3136 SSVAL(params,8,last_entry_off);
3138 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3141 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3142 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3144 reply_nterror(req, NT_STATUS_NO_MEMORY);
3148 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3149 smb_fn_name(req->cmd),
3150 mask, directory, dirtype, numentries ) );
3153 * Force a name mangle here to ensure that the
3154 * mask as an 8.3 name is top of the mangled cache.
3155 * The reasons for this are subtle. Don't remove
3156 * this code unless you know what you are doing
3157 * (see PR#13758). JRA.
3160 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3161 char mangled_name[13];
3162 name_to_8_3(mask, mangled_name, True, conn->params);
3170 TALLOC_FREE(smb_dname);
3174 /****************************************************************************
3175 Reply to a TRANS2_FINDNEXT.
3176 ****************************************************************************/
3178 static void call_trans2findnext(connection_struct *conn,
3179 struct smb_request *req,
3180 char **pparams, int total_params,
3181 char **ppdata, int total_data,
3182 unsigned int max_data_bytes)
3184 /* We must be careful here that we don't return more than the
3185 allowed number of data bytes. If this means returning fewer than
3186 maxentries then so be it. We assume that the redirector has
3187 enough room for the fixed number of parameter bytes it has
3189 char *params = *pparams;
3190 char *pdata = *ppdata;
3194 uint16_t info_level;
3195 uint32_t resume_key;
3196 uint16_t findnext_flags;
3197 bool close_after_request;
3199 bool requires_resume_key;
3201 bool mask_contains_wcard = False;
3202 char *resume_name = NULL;
3203 const char *mask = NULL;
3204 const char *directory = NULL;
3208 int i, last_entry_off=0;
3209 bool finished = False;
3210 bool dont_descend = False;
3211 bool out_of_space = False;
3212 int space_remaining;
3213 struct ea_list *ea_list = NULL;
3214 NTSTATUS ntstatus = NT_STATUS_OK;
3215 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3216 TALLOC_CTX *ctx = talloc_tos();
3217 struct smbd_server_connection *sconn = req->sconn;
3218 bool backup_priv = false;
3219 bool as_root = false;
3220 files_struct *fsp = NULL;
3221 const struct loadparm_substitution *lp_sub =
3222 loadparm_s3_global_substitution();
3224 if (total_params < 13) {
3225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3229 dptr_num = SVAL(params,0);
3230 maxentries = SVAL(params,2);
3231 info_level = SVAL(params,4);
3232 resume_key = IVAL(params,6);
3233 findnext_flags = SVAL(params,10);
3234 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3235 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3236 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3237 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3239 if (!continue_bit) {
3240 /* We only need resume_name if continue_bit is zero. */
3241 if (req->posix_pathnames) {
3242 srvstr_get_path_wcard_posix(ctx,
3250 &mask_contains_wcard);
3252 srvstr_get_path_wcard(ctx,
3260 &mask_contains_wcard);
3262 if (!NT_STATUS_IS_OK(ntstatus)) {
3263 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3264 complain (it thinks we're asking for the directory above the shared
3265 path or an invalid name). Catch this as the resume name is only compared, never used in
3266 a file access. JRA. */
3267 srvstr_pull_talloc(ctx, params, req->flags2,
3268 &resume_name, params+12,
3272 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3273 reply_nterror(req, ntstatus);
3279 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3280 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3281 resume_key = %d resume name = %s continue=%d level = %d\n",
3282 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3283 requires_resume_key, resume_key,
3284 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3287 /* W2K3 seems to treat zero as 1. */
3291 switch (info_level) {
3292 case SMB_FIND_INFO_STANDARD:
3293 case SMB_FIND_EA_SIZE:
3294 case SMB_FIND_EA_LIST:
3295 case SMB_FIND_FILE_DIRECTORY_INFO:
3296 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3297 case SMB_FIND_FILE_NAMES_INFO:
3298 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3299 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3300 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3302 case SMB_FIND_FILE_UNIX:
3303 case SMB_FIND_FILE_UNIX_INFO2:
3304 /* Always use filesystem for UNIX mtime query. */
3305 ask_sharemode = false;
3306 if (!lp_unix_extensions()) {
3307 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3312 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3316 if (info_level == SMB_FIND_EA_LIST) {
3319 if (total_data < 4) {
3320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3324 ea_size = IVAL(pdata,0);
3325 if (ea_size != total_data) {
3326 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3327 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3332 if (!lp_ea_support(SNUM(conn))) {
3333 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3337 /* Pull out the list of names. */
3338 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3345 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3350 *ppdata = (char *)SMB_REALLOC(
3351 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3352 if(*ppdata == NULL) {
3353 reply_nterror(req, NT_STATUS_NO_MEMORY);
3358 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3361 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3364 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3365 /* Realloc the params space */
3366 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3367 if(*pparams == NULL ) {
3368 reply_nterror(req, NT_STATUS_NO_MEMORY);
3374 /* Check that the dptr is valid */
3375 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3377 reply_nterror(req, STATUS_NO_MORE_FILES);
3381 directory = dptr_path(sconn, dptr_num);
3383 /* Get the wildcard mask from the dptr */
3384 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3385 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3386 reply_nterror(req, STATUS_NO_MORE_FILES);
3390 /* Get the attr mask from the dptr */
3391 dirtype = dptr_attr(sconn, dptr_num);
3393 backup_priv = dptr_get_priv(fsp->dptr);
3395 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3396 "backup_priv = %d\n",
3397 dptr_num, mask, dirtype,
3399 dptr_TellDir(fsp->dptr),
3402 /* We don't need to check for VOL here as this is returned by
3403 a different TRANS2 call. */
3405 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3406 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
3407 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
3408 dont_descend = True;
3411 space_remaining = max_data_bytes;
3412 out_of_space = False;
3420 * Seek to the correct position. We no longer use the resume key but
3421 * depend on the last file name instead.
3424 if(!continue_bit && resume_name && *resume_name) {
3427 long current_pos = 0;
3429 * Remember, name_to_8_3 is called by
3430 * get_lanman2_dir_entry(), so the resume name
3431 * could be mangled. Ensure we check the unmangled name.
3434 if (mangle_is_mangled(resume_name, conn->params)) {
3435 char *new_resume_name = NULL;
3436 mangle_lookup_name_from_8_3(ctx,
3440 if (new_resume_name) {
3441 resume_name = new_resume_name;
3446 * Fix for NT redirector problem triggered by resume key indexes
3447 * changing between directory scans. We now return a resume key of 0
3448 * and instead look for the filename to continue from (also given
3449 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3450 * findfirst/findnext (as is usual) then the directory pointer
3451 * should already be at the correct place.
3454 finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
3455 } /* end if resume_name && !continue_bit */
3457 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3458 bool got_exact_match = False;
3460 /* this is a heuristic to avoid seeking the fsp->dptr except when
3461 absolutely necessary. It allows for a filename of about 40 chars */
3462 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3463 out_of_space = True;
3466 ntstatus = get_lanman2_dir_entry(ctx,
3470 mask,dirtype,info_level,
3471 requires_resume_key,dont_descend,
3476 &last_entry_off, ea_list);
3477 if (NT_STATUS_EQUAL(ntstatus,
3478 NT_STATUS_ILLEGAL_CHARACTER)) {
3480 * Bad character conversion on name. Ignore this
3485 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3486 out_of_space = true;
3488 finished = !NT_STATUS_IS_OK(ntstatus);
3492 if (!finished && !out_of_space)
3496 * As an optimisation if we know we aren't looking
3497 * for a wildcard name (ie. the name matches the wildcard exactly)
3498 * then we can finish on any (first) match.
3499 * This speeds up large directory searches. JRA.
3505 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3508 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3509 smb_fn_name(req->cmd),
3510 mask, directory, dirtype, numentries ) );
3512 /* Check if we can close the fsp->dptr */
3513 if(close_after_request || (finished && close_if_end)) {
3514 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3516 close_file(NULL, fsp, NORMAL_CLOSE);
3524 /* Set up the return parameter block */
3525 SSVAL(params,0,numentries);
3526 SSVAL(params,2,finished);
3527 SSVAL(params,4,0); /* Never an EA error */
3528 SSVAL(params,6,last_entry_off);
3530 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3536 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3538 const struct loadparm_substitution *lp_sub =
3539 loadparm_s3_global_substitution();
3541 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
3545 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3547 SMB_ASSERT(extended_info != NULL);
3549 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3550 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3551 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3552 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3553 #ifdef SAMBA_VERSION_REVISION
3554 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3556 extended_info->samba_subversion = 0;
3557 #ifdef SAMBA_VERSION_RC_RELEASE
3558 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3560 #ifdef SAMBA_VERSION_PRE_RELEASE
3561 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3564 #ifdef SAMBA_VERSION_VENDOR_PATCH
3565 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3567 extended_info->samba_gitcommitdate = 0;
3568 #ifdef SAMBA_VERSION_COMMIT_TIME
3569 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3572 memset(extended_info->samba_version_string, 0,
3573 sizeof(extended_info->samba_version_string));
3575 snprintf (extended_info->samba_version_string,
3576 sizeof(extended_info->samba_version_string),
3577 "%s", samba_version_string());
3580 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3581 connection_struct *conn,
3582 TALLOC_CTX *mem_ctx,
3583 uint16_t info_level,
3585 unsigned int max_data_bytes,
3586 size_t *fixed_portion,
3587 struct smb_filename *fname,
3591 const struct loadparm_substitution *lp_sub =
3592 loadparm_s3_global_substitution();
3593 char *pdata, *end_data;
3596 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3597 int snum = SNUM(conn);
3598 const char *fstype = lp_fstype(SNUM(conn));
3599 const char *filename = NULL;
3600 const uint64_t bytes_per_sector = 512;
3601 uint32_t additional_flags = 0;
3602 struct smb_filename smb_fname;
3604 NTSTATUS status = NT_STATUS_OK;
3607 if (fname == NULL || fname->base_name == NULL) {
3610 filename = fname->base_name;
3614 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3615 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3616 "info level (0x%x) on IPC$.\n",
3617 (unsigned int)info_level));
3618 return NT_STATUS_ACCESS_DENIED;
3622 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3624 ZERO_STRUCT(smb_fname);
3625 smb_fname.base_name = discard_const_p(char, filename);
3627 if(info_level != SMB_FS_QUOTA_INFORMATION
3628 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3629 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3630 return map_nt_error_from_unix(errno);
3635 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3636 return NT_STATUS_INVALID_PARAMETER;
3639 *ppdata = (char *)SMB_REALLOC(
3640 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3641 if (*ppdata == NULL) {
3642 return NT_STATUS_NO_MEMORY;
3646 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3647 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3651 switch (info_level) {
3652 case SMB_INFO_ALLOCATION:
3654 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3656 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3658 if (df_ret == (uint64_t)-1) {
3659 return map_nt_error_from_unix(errno);
3662 block_size = lp_block_size(snum);
3663 if (bsize < block_size) {
3664 uint64_t factor = block_size/bsize;
3669 if (bsize > block_size) {
3670 uint64_t factor = bsize/block_size;
3675 sectors_per_unit = bsize/bytes_per_sector;
3677 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3678 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3679 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3682 * For large drives, return max values and not modulo.
3684 dsize = MIN(dsize, UINT32_MAX);
3685 dfree = MIN(dfree, UINT32_MAX);
3687 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3688 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3689 SIVAL(pdata,l1_cUnit,dsize);
3690 SIVAL(pdata,l1_cUnitAvail,dfree);
3691 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3695 case SMB_INFO_VOLUME:
3696 /* Return volume name */
3698 * Add volume serial number - hash of a combination of
3699 * the called hostname and the service name.
3701 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3703 * Win2k3 and previous mess this up by sending a name length
3704 * one byte short. I believe only older clients (OS/2 Win9x) use
3705 * this call so try fixing this by adding a terminating null to
3706 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3708 status = srvstr_push(
3710 pdata+l2_vol_szVolLabel, vname,
3711 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3712 STR_NOALIGN|STR_TERMINATE, &len);
3713 if (!NT_STATUS_IS_OK(status)) {
3716 SCVAL(pdata,l2_vol_cch,len);
3717 data_len = l2_vol_szVolLabel + len;
3718 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3719 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3720 (unsigned)len, vname));
3723 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3724 case SMB_FS_ATTRIBUTE_INFORMATION:
3726 additional_flags = 0;
3727 #if defined(HAVE_SYS_QUOTAS)
3728 additional_flags |= FILE_VOLUME_QUOTAS;
3731 if(lp_nt_acl_support(SNUM(conn))) {
3732 additional_flags |= FILE_PERSISTENT_ACLS;
3735 /* Capabilities are filled in at connection time through STATVFS call */
3736 additional_flags |= conn->fs_capabilities;
3737 additional_flags |= lp_parm_int(conn->params->service,
3738 "share", "fake_fscaps",
3741 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3742 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3743 additional_flags); /* FS ATTRIBUTES */
3745 SIVAL(pdata,4,255); /* Max filename component length */
3746 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3747 and will think we can't do long filenames */
3748 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3749 PTR_DIFF(end_data, pdata+12),
3751 if (!NT_STATUS_IS_OK(status)) {
3755 data_len = 12 + len;
3756 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3757 /* the client only requested a portion of the
3759 data_len = max_data_bytes;
3760 status = STATUS_BUFFER_OVERFLOW;
3762 *fixed_portion = 16;
3765 case SMB_QUERY_FS_LABEL_INFO:
3766 case SMB_FS_LABEL_INFORMATION:
3767 status = srvstr_push(pdata, flags2, pdata+4, vname,
3768 PTR_DIFF(end_data, pdata+4), 0, &len);
3769 if (!NT_STATUS_IS_OK(status)) {
3776 case SMB_QUERY_FS_VOLUME_INFO:
3777 case SMB_FS_VOLUME_INFORMATION:
3780 * Add volume serial number - hash of a combination of
3781 * the called hostname and the service name.
3783 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
3784 (str_checksum(get_local_machine_name())<<16));
3786 /* Max label len is 32 characters. */
3787 status = srvstr_push(pdata, flags2, pdata+18, vname,
3788 PTR_DIFF(end_data, pdata+18),
3790 if (!NT_STATUS_IS_OK(status)) {
3793 SIVAL(pdata,12,len);
3796 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3797 (int)strlen(vname),vname,
3798 lp_servicename(talloc_tos(), lp_sub, snum)));
3799 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3800 /* the client only requested a portion of the
3802 data_len = max_data_bytes;
3803 status = STATUS_BUFFER_OVERFLOW;
3805 *fixed_portion = 24;
3808 case SMB_QUERY_FS_SIZE_INFO:
3809 case SMB_FS_SIZE_INFORMATION:
3811 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3813 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3815 if (df_ret == (uint64_t)-1) {
3816 return map_nt_error_from_unix(errno);
3818 block_size = lp_block_size(snum);
3819 if (bsize < block_size) {
3820 uint64_t factor = block_size/bsize;
3825 if (bsize > block_size) {
3826 uint64_t factor = bsize/block_size;
3831 sectors_per_unit = bsize/bytes_per_sector;
3832 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3833 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3834 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3835 SBIG_UINT(pdata,0,dsize);
3836 SBIG_UINT(pdata,8,dfree);
3837 SIVAL(pdata,16,sectors_per_unit);
3838 SIVAL(pdata,20,bytes_per_sector);
3839 *fixed_portion = 24;
3843 case SMB_FS_FULL_SIZE_INFORMATION:
3845 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3847 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3849 if (df_ret == (uint64_t)-1) {
3850 return map_nt_error_from_unix(errno);
3852 block_size = lp_block_size(snum);
3853 if (bsize < block_size) {
3854 uint64_t factor = block_size/bsize;
3859 if (bsize > block_size) {
3860 uint64_t factor = bsize/block_size;
3865 sectors_per_unit = bsize/bytes_per_sector;
3866 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3867 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3868 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3869 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3870 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3871 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3872 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3873 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3874 *fixed_portion = 32;
3878 case SMB_QUERY_FS_DEVICE_INFO:
3879 case SMB_FS_DEVICE_INFORMATION:
3881 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3883 if (!CAN_WRITE(conn)) {
3884 characteristics |= FILE_READ_ONLY_DEVICE;
3887 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3888 SIVAL(pdata,4,characteristics);
3893 #ifdef HAVE_SYS_QUOTAS
3894 case SMB_FS_QUOTA_INFORMATION:
3896 * what we have to send --metze:
3898 * Unknown1: 24 NULL bytes
3899 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3900 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3901 * Quota Flags: 2 byte :
3902 * Unknown3: 6 NULL bytes
3906 * details for Quota Flags:
3908 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3909 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3910 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3911 * 0x0001 Enable Quotas: enable quota for this fs
3915 /* we need to fake up a fsp here,
3916 * because its not send in this call
3919 SMB_NTQUOTA_STRUCT quotas;
3922 ZERO_STRUCT(quotas);
3925 fsp.fnum = FNUM_FIELD_INVALID;
3928 if (get_current_uid(conn) != 0) {
3929 DEBUG(0,("get_user_quota: access_denied "
3930 "service [%s] user [%s]\n",
3931 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
3932 conn->session_info->unix_info->unix_name));
3933 return NT_STATUS_ACCESS_DENIED;
3936 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3938 if (!NT_STATUS_IS_OK(status)) {
3939 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3945 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3946 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3948 /* Unknown1 24 NULL bytes*/
3949 SBIG_UINT(pdata,0,(uint64_t)0);
3950 SBIG_UINT(pdata,8,(uint64_t)0);
3951 SBIG_UINT(pdata,16,(uint64_t)0);
3953 /* Default Soft Quota 8 bytes */
3954 SBIG_UINT(pdata,24,quotas.softlim);
3956 /* Default Hard Quota 8 bytes */
3957 SBIG_UINT(pdata,32,quotas.hardlim);
3959 /* Quota flag 2 bytes */
3960 SSVAL(pdata,40,quotas.qflags);
3962 /* Unknown3 6 NULL bytes */
3968 #endif /* HAVE_SYS_QUOTAS */
3969 case SMB_FS_OBJECTID_INFORMATION:
3971 unsigned char objid[16];
3972 struct smb_extended_info extended_info;
3973 memcpy(pdata,create_volume_objectid(conn, objid),16);
3974 samba_extended_info_version (&extended_info);
3975 SIVAL(pdata,16,extended_info.samba_magic);
3976 SIVAL(pdata,20,extended_info.samba_version);
3977 SIVAL(pdata,24,extended_info.samba_subversion);
3978 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3979 memcpy(pdata+36,extended_info.samba_version_string,28);
3984 case SMB_FS_SECTOR_SIZE_INFORMATION:
3988 * These values match a physical Windows Server 2012
3989 * share backed by NTFS atop spinning rust.
3991 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3992 /* logical_bytes_per_sector */
3993 SIVAL(pdata, 0, bytes_per_sector);
3994 /* phys_bytes_per_sector_atomic */
3995 SIVAL(pdata, 4, bytes_per_sector);
3996 /* phys_bytes_per_sector_perf */
3997 SIVAL(pdata, 8, bytes_per_sector);
3998 /* fs_effective_phys_bytes_per_sector_atomic */
3999 SIVAL(pdata, 12, bytes_per_sector);
4001 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
4002 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
4003 /* byte_off_sector_align */
4004 SIVAL(pdata, 20, 0);
4005 /* byte_off_partition_align */
4006 SIVAL(pdata, 24, 0);
4007 *fixed_portion = 28;
4013 * Query the version and capabilities of the CIFS UNIX extensions
4017 case SMB_QUERY_CIFS_UNIX_INFO:
4019 bool large_write = lp_min_receive_file_size() &&
4020 !srv_is_signing_active(xconn);
4021 bool large_read = !srv_is_signing_active(xconn);
4022 int encrypt_caps = 0;
4024 if (!lp_unix_extensions()) {
4025 return NT_STATUS_INVALID_LEVEL;
4028 switch (conn->encrypt_level) {
4029 case SMB_SIGNING_OFF:
4032 case SMB_SIGNING_DESIRED:
4033 case SMB_SIGNING_IF_REQUIRED:
4034 case SMB_SIGNING_DEFAULT:
4035 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
4037 case SMB_SIGNING_REQUIRED:
4038 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
4039 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
4040 large_write = false;
4046 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
4047 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
4049 /* We have POSIX ACLs, pathname, encryption,
4050 * large read/write, and locking capability. */
4052 SBIG_UINT(pdata,4,((uint64_t)(
4053 CIFS_UNIX_POSIX_ACLS_CAP|
4054 CIFS_UNIX_POSIX_PATHNAMES_CAP|
4055 CIFS_UNIX_FCNTL_LOCKS_CAP|
4056 CIFS_UNIX_EXTATTR_CAP|
4057 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
4059 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
4061 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
4065 case SMB_QUERY_POSIX_FS_INFO:
4068 vfs_statvfs_struct svfs;
4070 if (!lp_unix_extensions()) {
4071 return NT_STATUS_INVALID_LEVEL;
4074 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
4078 SIVAL(pdata,0,svfs.OptimalTransferSize);
4079 SIVAL(pdata,4,svfs.BlockSize);
4080 SBIG_UINT(pdata,8,svfs.TotalBlocks);
4081 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4082 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4083 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4084 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4085 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4086 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4088 } else if (rc == EOPNOTSUPP) {
4089 return NT_STATUS_INVALID_LEVEL;
4090 #endif /* EOPNOTSUPP */
4092 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4093 return NT_STATUS_DOS(ERRSRV, ERRerror);
4098 case SMB_QUERY_POSIX_WHOAMI:
4104 if (!lp_unix_extensions()) {
4105 return NT_STATUS_INVALID_LEVEL;
4108 if (max_data_bytes < 40) {
4109 return NT_STATUS_BUFFER_TOO_SMALL;
4112 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4113 flags |= SMB_WHOAMI_GUEST;
4116 /* NOTE: 8 bytes for UID/GID, irrespective of native
4117 * platform size. This matches
4118 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4120 data_len = 4 /* flags */
4127 + 4 /* pad/reserved */
4128 + (conn->session_info->unix_token->ngroups * 8)
4130 + (conn->session_info->security_token->num_sids *
4134 SIVAL(pdata, 0, flags);
4135 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4137 (uint64_t)conn->session_info->unix_token->uid);
4138 SBIG_UINT(pdata, 16,
4139 (uint64_t)conn->session_info->unix_token->gid);
4142 if (data_len >= max_data_bytes) {
4143 /* Potential overflow, skip the GIDs and SIDs. */
4145 SIVAL(pdata, 24, 0); /* num_groups */
4146 SIVAL(pdata, 28, 0); /* num_sids */
4147 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4148 SIVAL(pdata, 36, 0); /* reserved */
4154 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4155 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4157 /* We walk the SID list twice, but this call is fairly
4158 * infrequent, and I don't expect that it's performance
4159 * sensitive -- jpeach
4161 for (i = 0, sid_bytes = 0;
4162 i < conn->session_info->security_token->num_sids; ++i) {
4163 sid_bytes += ndr_size_dom_sid(
4164 &conn->session_info->security_token->sids[i],
4168 /* SID list byte count */
4169 SIVAL(pdata, 32, sid_bytes);
4171 /* 4 bytes pad/reserved - must be zero */
4172 SIVAL(pdata, 36, 0);
4176 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4177 SBIG_UINT(pdata, data_len,
4178 (uint64_t)conn->session_info->unix_token->groups[i]);
4184 i < conn->session_info->security_token->num_sids; ++i) {
4185 int sid_len = ndr_size_dom_sid(
4186 &conn->session_info->security_token->sids[i],
4189 sid_linearize((uint8_t *)(pdata + data_len),
4191 &conn->session_info->security_token->sids[i]);
4192 data_len += sid_len;
4198 case SMB_MAC_QUERY_FS_INFO:
4200 * Thursby MAC extension... ONLY on NTFS filesystems
4201 * once we do streams then we don't need this
4203 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4205 SIVAL(pdata,84,0x100); /* Don't support mac... */
4211 return NT_STATUS_INVALID_LEVEL;
4214 *ret_data_len = data_len;
4218 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4219 struct smb_request *req,
4221 const DATA_BLOB *qdata)
4223 const struct loadparm_substitution *lp_sub =
4224 loadparm_s3_global_substitution();
4226 SMB_NTQUOTA_STRUCT quotas;
4228 ZERO_STRUCT(quotas);
4231 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4232 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4233 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
4234 conn->session_info->unix_info->unix_name));
4235 return NT_STATUS_ACCESS_DENIED;
4238 if (!check_fsp_ntquota_handle(conn, req,
4240 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4241 return NT_STATUS_INVALID_HANDLE;
4244 /* note: normally there're 48 bytes,
4245 * but we didn't use the last 6 bytes for now
4248 if (qdata->length < 42) {
4249 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4250 (unsigned int)qdata->length));
4251 return NT_STATUS_INVALID_PARAMETER;
4254 /* unknown_1 24 NULL bytes in pdata*/
4256 /* the soft quotas 8 bytes (uint64_t)*/
4257 quotas.softlim = BVAL(qdata->data,24);
4259 /* the hard quotas 8 bytes (uint64_t)*/
4260 quotas.hardlim = BVAL(qdata->data,32);
4262 /* quota_flags 2 bytes **/
4263 quotas.qflags = SVAL(qdata->data,40);
4265 /* unknown_2 6 NULL bytes follow*/
4267 /* now set the quotas */
4268 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4269 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4270 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4271 status = map_nt_error_from_unix(errno);
4273 status = NT_STATUS_OK;
4278 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4279 struct smb_request *req,
4280 TALLOC_CTX *mem_ctx,
4281 uint16_t info_level,
4283 const DATA_BLOB *pdata)
4285 switch (info_level) {
4286 case SMB_FS_QUOTA_INFORMATION:
4288 return smb_set_fsquota(conn,
4297 return NT_STATUS_INVALID_LEVEL;
4300 /****************************************************************************
4301 Reply to a TRANS2_QFSINFO (query filesystem info).
4302 ****************************************************************************/
4304 static void call_trans2qfsinfo(connection_struct *conn,
4305 struct smb_request *req,
4306 char **pparams, int total_params,
4307 char **ppdata, int total_data,
4308 unsigned int max_data_bytes)
4310 char *params = *pparams;
4311 uint16_t info_level;
4313 size_t fixed_portion;
4316 if (total_params < 2) {
4317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4321 info_level = SVAL(params,0);
4323 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4324 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4325 DEBUG(0,("call_trans2qfsinfo: encryption required "
4326 "and info level 0x%x sent.\n",
4327 (unsigned int)info_level));
4328 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4333 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4335 status = smbd_do_qfsinfo(req->xconn, conn, req,
4342 if (!NT_STATUS_IS_OK(status)) {
4343 reply_nterror(req, status);
4347 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4350 DEBUG( 4, ( "%s info_level = %d\n",
4351 smb_fn_name(req->cmd), info_level) );
4356 /****************************************************************************
4357 Reply to a TRANS2_SETFSINFO (set filesystem info).
4358 ****************************************************************************/
4360 static void call_trans2setfsinfo(connection_struct *conn,
4361 struct smb_request *req,
4362 char **pparams, int total_params,
4363 char **ppdata, int total_data,
4364 unsigned int max_data_bytes)
4366 const struct loadparm_substitution *lp_sub =
4367 loadparm_s3_global_substitution();
4368 struct smbXsrv_connection *xconn = req->xconn;
4369 char *pdata = *ppdata;
4370 char *params = *pparams;
4371 uint16_t info_level;
4373 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4374 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4377 if (total_params < 4) {
4378 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4380 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4384 info_level = SVAL(params,2);
4387 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4388 info_level != SMB_SET_CIFS_UNIX_INFO) {
4389 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4390 "info level (0x%x) on IPC$.\n",
4391 (unsigned int)info_level));
4392 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4397 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4398 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4399 DEBUG(0,("call_trans2setfsinfo: encryption required "
4400 "and info level 0x%x sent.\n",
4401 (unsigned int)info_level));
4402 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4407 switch(info_level) {
4408 case SMB_SET_CIFS_UNIX_INFO:
4409 if (!lp_unix_extensions()) {
4410 DEBUG(2,("call_trans2setfsinfo: "
4411 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4412 "unix extensions off\n"));
4414 NT_STATUS_INVALID_LEVEL);
4418 /* There should be 12 bytes of capabilities set. */
4419 if (total_data < 12) {
4422 NT_STATUS_INVALID_PARAMETER);
4425 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4426 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4427 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4428 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4429 /* Just print these values for now. */
4430 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4431 "major = %u, minor = %u cap_low = 0x%x, "
4433 (unsigned int)xconn->
4434 smb1.unix_info.client_major,
4435 (unsigned int)xconn->
4436 smb1.unix_info.client_minor,
4437 (unsigned int)xconn->
4438 smb1.unix_info.client_cap_low,
4439 (unsigned int)xconn->
4440 smb1.unix_info.client_cap_high));
4442 /* Here is where we must switch to posix pathname processing... */
4443 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4444 lp_set_posix_pathnames();
4445 mangle_change_to_posix();
4448 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4449 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4450 /* Client that knows how to do posix locks,
4451 * but not posix open/mkdir operations. Set a
4452 * default type for read/write checks. */
4454 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4459 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4462 size_t param_len = 0;
4463 size_t data_len = total_data;
4465 if (!lp_unix_extensions()) {
4468 NT_STATUS_INVALID_LEVEL);
4472 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4475 NT_STATUS_NOT_SUPPORTED);
4479 if (xconn->smb1.echo_handler.trusted_fde) {
4480 DEBUG( 2,("call_trans2setfsinfo: "
4481 "request transport encryption disabled"
4482 "with 'fork echo handler = yes'\n"));
4485 NT_STATUS_NOT_SUPPORTED);
4489 DEBUG( 4,("call_trans2setfsinfo: "
4490 "request transport encryption.\n"));
4492 status = srv_request_encryption_setup(conn,
4493 (unsigned char **)ppdata,
4495 (unsigned char **)pparams,
4498 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4499 !NT_STATUS_IS_OK(status)) {
4500 reply_nterror(req, status);
4504 send_trans2_replies(conn, req,
4512 if (NT_STATUS_IS_OK(status)) {
4513 /* Server-side transport
4514 * encryption is now *on*. */
4515 status = srv_encryption_start(conn);
4516 if (!NT_STATUS_IS_OK(status)) {
4517 char *reason = talloc_asprintf(talloc_tos(),
4518 "Failure in setting "
4519 "up encrypted transport: %s",
4521 exit_server_cleanly(reason);
4527 case SMB_FS_QUOTA_INFORMATION:
4531 .data = (uint8_t *)pdata,
4532 .length = total_data
4534 files_struct *fsp = NULL;
4535 fsp = file_fsp(req, SVAL(params,0));
4537 status = smb_set_fsquota(conn,
4541 if (!NT_STATUS_IS_OK(status)) {
4542 reply_nterror(req, status);
4548 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4550 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4556 * sending this reply works fine,
4557 * but I'm not sure it's the same
4558 * like windows do...
4561 reply_outbuf(req, 10, 0);
4564 #if defined(HAVE_POSIX_ACLS)
4565 /****************************************************************************
4566 Utility function to count the number of entries in a POSIX acl.
4567 ****************************************************************************/
4569 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4571 unsigned int ace_count = 0;
4572 int entry_id = SMB_ACL_FIRST_ENTRY;
4573 SMB_ACL_ENTRY_T entry;
4575 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4577 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4578 entry_id = SMB_ACL_NEXT_ENTRY;
4585 /****************************************************************************
4586 Utility function to marshall a POSIX acl into wire format.
4587 ****************************************************************************/
4589 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4591 int entry_id = SMB_ACL_FIRST_ENTRY;
4592 SMB_ACL_ENTRY_T entry;
4594 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4595 SMB_ACL_TAG_T tagtype;
4596 SMB_ACL_PERMSET_T permset;
4597 unsigned char perms = 0;
4598 unsigned int own_grp;
4601 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4602 entry_id = SMB_ACL_NEXT_ENTRY;
4605 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4606 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4610 if (sys_acl_get_permset(entry, &permset) == -1) {
4611 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4615 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4616 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4617 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4619 SCVAL(pdata,1,perms);
4622 case SMB_ACL_USER_OBJ:
4623 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4624 own_grp = (unsigned int)pst->st_ex_uid;
4625 SIVAL(pdata,2,own_grp);
4630 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4632 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4635 own_grp = (unsigned int)*puid;
4636 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4637 SIVAL(pdata,2,own_grp);
4641 case SMB_ACL_GROUP_OBJ:
4642 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4643 own_grp = (unsigned int)pst->st_ex_gid;
4644 SIVAL(pdata,2,own_grp);
4649 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4651 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4654 own_grp = (unsigned int)*pgid;
4655 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4656 SIVAL(pdata,2,own_grp);
4661 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4662 SIVAL(pdata,2,0xFFFFFFFF);
4663 SIVAL(pdata,6,0xFFFFFFFF);
4666 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4667 SIVAL(pdata,2,0xFFFFFFFF);
4668 SIVAL(pdata,6,0xFFFFFFFF);
4671 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4674 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4681 /****************************************************************************
4682 Store the FILE_UNIX_BASIC info.
4683 ****************************************************************************/
4685 static char *store_file_unix_basic(connection_struct *conn,
4688 const SMB_STRUCT_STAT *psbuf)
4692 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4693 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4695 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4698 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4701 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
4702 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
4703 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4706 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4710 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4714 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4717 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4718 devno = psbuf->st_ex_rdev;
4720 devno = psbuf->st_ex_dev;
4723 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4727 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4731 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4734 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4738 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4745 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4746 * the chflags(2) (or equivalent) flags.
4748 * XXX: this really should be behind the VFS interface. To do this, we would
4749 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4750 * Each VFS module could then implement its own mapping as appropriate for the
4751 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4753 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4757 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4761 { UF_IMMUTABLE, EXT_IMMUTABLE },
4765 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4769 { UF_HIDDEN, EXT_HIDDEN },
4772 /* Do not remove. We need to guarantee that this array has at least one
4773 * entry to build on HP-UX.
4779 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4780 uint32_t *smb_fflags, uint32_t *smb_fmask)
4784 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4785 *smb_fmask |= info2_flags_map[i].smb_fflag;
4786 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4787 *smb_fflags |= info2_flags_map[i].smb_fflag;
4792 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4793 const uint32_t smb_fflags,
4794 const uint32_t smb_fmask,
4797 uint32_t max_fmask = 0;
4800 *stat_fflags = psbuf->st_ex_flags;
4802 /* For each flags requested in smb_fmask, check the state of the
4803 * corresponding flag in smb_fflags and set or clear the matching
4807 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4808 max_fmask |= info2_flags_map[i].smb_fflag;
4809 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4810 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4811 *stat_fflags |= info2_flags_map[i].stat_fflag;
4813 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4818 /* If smb_fmask is asking to set any bits that are not supported by
4819 * our flag mappings, we should fail.
4821 if ((smb_fmask & max_fmask) != smb_fmask) {
4829 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4830 * of file flags and birth (create) time.
4832 static char *store_file_unix_basic_info2(connection_struct *conn,
4835 const SMB_STRUCT_STAT *psbuf)
4837 uint32_t file_flags = 0;
4838 uint32_t flags_mask = 0;
4840 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4842 /* Create (birth) time 64 bit */
4843 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
4846 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4847 SIVAL(pdata, 0, file_flags); /* flags */
4848 SIVAL(pdata, 4, flags_mask); /* mask */
4854 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4855 const struct stream_struct *streams,
4857 unsigned int max_data_bytes,
4858 unsigned int *data_size)
4861 unsigned int ofs = 0;
4863 if (max_data_bytes < 32) {
4864 return NT_STATUS_INFO_LENGTH_MISMATCH;
4867 for (i = 0; i < num_streams; i++) {
4868 unsigned int next_offset;
4870 smb_ucs2_t *namebuf;
4872 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4873 streams[i].name, &namelen) ||
4876 return NT_STATUS_INVALID_PARAMETER;
4880 * name_buf is now null-terminated, we need to marshall as not
4887 * We cannot overflow ...
4889 if ((ofs + 24 + namelen) > max_data_bytes) {
4890 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4892 TALLOC_FREE(namebuf);
4893 return STATUS_BUFFER_OVERFLOW;
4896 SIVAL(data, ofs+4, namelen);
4897 SOFF_T(data, ofs+8, streams[i].size);
4898 SOFF_T(data, ofs+16, streams[i].alloc_size);
4899 memcpy(data+ofs+24, namebuf, namelen);
4900 TALLOC_FREE(namebuf);
4902 next_offset = ofs + 24 + namelen;
4904 if (i == num_streams-1) {
4905 SIVAL(data, ofs, 0);
4908 unsigned int align = ndr_align_size(next_offset, 8);
4910 if ((next_offset + align) > max_data_bytes) {
4911 DEBUG(10, ("refusing to overflow align "
4912 "reply at stream %u\n",
4914 TALLOC_FREE(namebuf);
4915 return STATUS_BUFFER_OVERFLOW;
4918 memset(data+next_offset, 0, align);
4919 next_offset += align;
4921 SIVAL(data, ofs, next_offset - ofs);
4928 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4932 return NT_STATUS_OK;
4935 #if defined(HAVE_POSIX_ACLS)
4936 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4937 struct smb_request *req,
4939 struct smb_filename *smb_fname,
4941 unsigned int data_size_in,
4942 unsigned int *pdata_size_out)
4944 SMB_ACL_T file_acl = NULL;
4945 SMB_ACL_T def_acl = NULL;
4946 uint16_t num_file_acls = 0;
4947 uint16_t num_def_acls = 0;
4948 unsigned int size_needed = 0;
4951 bool close_fsp = false;
4954 * Ensure we always operate on a file descriptor, not just
4958 uint32_t access_mask = SEC_STD_READ_CONTROL|
4959 FILE_READ_ATTRIBUTES|
4960 FILE_WRITE_ATTRIBUTES;
4962 status = get_posix_fsp(conn,
4968 if (!NT_STATUS_IS_OK(status)) {
4974 SMB_ASSERT(fsp != NULL);
4976 status = refuse_symlink(conn,
4979 if (!NT_STATUS_IS_OK(status)) {
4983 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4986 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4987 DBG_INFO("ACLs not implemented on "
4988 "filesystem containing %s\n",
4990 status = NT_STATUS_NOT_IMPLEMENTED;
4994 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4996 * We can only have default POSIX ACLs on
4999 if (!fsp->is_directory) {
5000 DBG_INFO("Non-directory open %s\n",
5002 status = NT_STATUS_INVALID_HANDLE;
5005 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
5007 SMB_ACL_TYPE_DEFAULT,
5009 def_acl = free_empty_sys_acl(conn, def_acl);
5012 num_file_acls = count_acl_entries(conn, file_acl);
5013 num_def_acls = count_acl_entries(conn, def_acl);
5016 if (num_file_acls + num_def_acls < num_file_acls) {
5017 status = NT_STATUS_INVALID_PARAMETER;
5021 size_needed = num_file_acls + num_def_acls;
5024 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5025 * than UINT_MAX, so check by division.
5027 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5028 status = NT_STATUS_INVALID_PARAMETER;
5032 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5033 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5034 status = NT_STATUS_INVALID_PARAMETER;
5037 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5039 if ( data_size_in < size_needed) {
5040 DBG_INFO("data_size too small (%u) need %u\n",
5043 status = NT_STATUS_BUFFER_TOO_SMALL;
5047 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5048 SSVAL(pdata,2,num_file_acls);
5049 SSVAL(pdata,4,num_def_acls);
5050 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5052 ok = marshall_posix_acl(conn,
5057 status = NT_STATUS_INTERNAL_ERROR;
5060 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5062 ok = marshall_posix_acl(conn,
5067 status = NT_STATUS_INTERNAL_ERROR;
5071 *pdata_size_out = size_needed;
5072 status = NT_STATUS_OK;
5078 * Ensure the stat struct in smb_fname is up to
5079 * date. Structure copy.
5081 smb_fname->st = fsp->fsp_name->st;
5082 (void)close_file(req, fsp, NORMAL_CLOSE);
5086 TALLOC_FREE(file_acl);
5087 TALLOC_FREE(def_acl);
5092 /****************************************************************************
5093 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5094 ****************************************************************************/
5096 static void call_trans2qpipeinfo(connection_struct *conn,
5097 struct smb_request *req,
5098 unsigned int tran_call,
5099 char **pparams, int total_params,
5100 char **ppdata, int total_data,
5101 unsigned int max_data_bytes)
5103 char *params = *pparams;
5104 char *pdata = *ppdata;
5105 unsigned int data_size = 0;
5106 unsigned int param_size = 2;
5107 uint16_t info_level;
5111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5115 if (total_params < 4) {
5116 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5120 fsp = file_fsp(req, SVAL(params,0));
5121 if (!fsp_is_np(fsp)) {
5122 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5126 info_level = SVAL(params,2);
5128 *pparams = (char *)SMB_REALLOC(*pparams,2);
5129 if (*pparams == NULL) {
5130 reply_nterror(req, NT_STATUS_NO_MEMORY);
5135 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5139 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5140 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5141 if (*ppdata == NULL ) {
5142 reply_nterror(req, NT_STATUS_NO_MEMORY);
5147 switch (info_level) {
5148 case SMB_FILE_STANDARD_INFORMATION:
5150 SOFF_T(pdata,0,4096LL);
5157 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5161 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5167 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5168 TALLOC_CTX *mem_ctx,
5169 struct smb_request *req,
5170 uint16_t info_level,
5172 struct smb_filename *smb_fname,
5173 bool delete_pending,
5174 struct timespec write_time_ts,
5175 struct ea_list *ea_list,
5176 int lock_data_count,
5179 unsigned int max_data_bytes,
5180 size_t *fixed_portion,
5182 unsigned int *pdata_size)
5184 char *pdata = *ppdata;
5185 char *dstart, *dend;
5186 unsigned int data_size;
5187 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5188 time_t create_time, mtime, atime, c_time;
5189 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5196 uint64_t file_size = 0;
5198 uint64_t allocation_size = 0;
5199 uint64_t file_id = 0;
5200 uint32_t access_mask = 0;
5203 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5204 return NT_STATUS_INVALID_LEVEL;
5207 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5208 smb_fname_str_dbg(smb_fname),
5210 info_level, max_data_bytes));
5212 mode = dos_mode(conn, smb_fname);
5213 nlink = psbuf->st_ex_nlink;
5215 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5219 if ((nlink > 0) && delete_pending) {
5223 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5224 return NT_STATUS_INVALID_PARAMETER;
5227 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5228 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5229 if (*ppdata == NULL) {
5230 return NT_STATUS_NO_MEMORY;
5234 dend = dstart + data_size - 1;
5236 if (!is_omit_timespec(&write_time_ts) &&
5237 !INFO_LEVEL_IS_UNIX(info_level))
5239 update_stat_ex_mtime(psbuf, write_time_ts);
5242 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5243 mtime_ts = psbuf->st_ex_mtime;
5244 atime_ts = psbuf->st_ex_atime;
5245 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5247 if (lp_dos_filetime_resolution(SNUM(conn))) {
5248 dos_filetime_timespec(&create_time_ts);
5249 dos_filetime_timespec(&mtime_ts);
5250 dos_filetime_timespec(&atime_ts);
5251 dos_filetime_timespec(&ctime_ts);
5254 create_time = convert_timespec_to_time_t(create_time_ts);
5255 mtime = convert_timespec_to_time_t(mtime_ts);
5256 atime = convert_timespec_to_time_t(atime_ts);
5257 c_time = convert_timespec_to_time_t(ctime_ts);
5259 p = strrchr_m(smb_fname->base_name,'/');
5261 base_name = smb_fname->base_name;
5265 /* NT expects the name to be in an exact form of the *full*
5266 filename. See the trans2 torture test */
5267 if (ISDOT(base_name)) {
5268 dos_fname = talloc_strdup(mem_ctx, "\\");
5270 return NT_STATUS_NO_MEMORY;
5273 dos_fname = talloc_asprintf(mem_ctx,
5275 smb_fname->base_name);
5277 return NT_STATUS_NO_MEMORY;
5279 if (is_ntfs_stream_smb_fname(smb_fname)) {
5280 dos_fname = talloc_asprintf(dos_fname, "%s",
5281 smb_fname->stream_name);
5283 return NT_STATUS_NO_MEMORY;
5287 string_replace(dos_fname, '/', '\\');
5290 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5293 /* Do we have this path open ? */
5295 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5296 fsp1 = file_find_di_first(conn->sconn, fileid);
5297 if (fsp1 && fsp1->initial_allocation_size) {
5298 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5302 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5303 file_size = get_file_size_stat(psbuf);
5307 pos = fsp->fh->position_information;
5311 access_mask = fsp->access_mask;
5313 /* GENERIC_EXECUTE mapping from Windows */
5314 access_mask = 0x12019F;
5317 /* This should be an index number - looks like
5320 I think this causes us to fail the IFSKIT
5321 BasicFileInformationTest. -tpot */
5322 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5326 switch (info_level) {
5327 case SMB_INFO_STANDARD:
5328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5330 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5331 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5332 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5333 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5334 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5335 SSVAL(pdata,l1_attrFile,mode);
5338 case SMB_INFO_QUERY_EA_SIZE:
5340 unsigned int ea_size =
5341 estimate_ea_size(conn, fsp,
5343 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5345 srv_put_dos_date2(pdata,0,create_time);
5346 srv_put_dos_date2(pdata,4,atime);
5347 srv_put_dos_date2(pdata,8,mtime); /* write time */
5348 SIVAL(pdata,12,(uint32_t)file_size);
5349 SIVAL(pdata,16,(uint32_t)allocation_size);
5350 SSVAL(pdata,20,mode);
5351 SIVAL(pdata,22,ea_size);
5355 case SMB_INFO_IS_NAME_VALID:
5356 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5358 /* os/2 needs this ? really ?*/
5359 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5361 /* This is only reached for qpathinfo */
5365 case SMB_INFO_QUERY_EAS_FROM_LIST:
5367 size_t total_ea_len = 0;
5368 struct ea_list *ea_file_list = NULL;
5369 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5372 get_ea_list_from_file(mem_ctx, conn, fsp,
5374 &total_ea_len, &ea_file_list);
5375 if (!NT_STATUS_IS_OK(status)) {
5379 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5381 if (!ea_list || (total_ea_len > data_size)) {
5383 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5387 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5391 case SMB_INFO_QUERY_ALL_EAS:
5393 /* We have data_size bytes to put EA's into. */
5394 size_t total_ea_len = 0;
5395 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5397 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5399 &total_ea_len, &ea_list);
5400 if (!NT_STATUS_IS_OK(status)) {
5404 if (!ea_list || (total_ea_len > data_size)) {
5406 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5410 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5414 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5416 /* This is FileFullEaInformation - 0xF which maps to
5417 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5419 /* We have data_size bytes to put EA's into. */
5420 size_t total_ea_len = 0;
5421 struct ea_list *ea_file_list = NULL;
5423 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5425 /*TODO: add filtering and index handling */
5428 get_ea_list_from_file(mem_ctx, conn, fsp,
5430 &total_ea_len, &ea_file_list);
5431 if (!NT_STATUS_IS_OK(status)) {
5434 if (!ea_file_list) {
5435 return NT_STATUS_NO_EAS_ON_FILE;
5438 status = fill_ea_chained_buffer(mem_ctx,
5442 conn, ea_file_list);
5443 if (!NT_STATUS_IS_OK(status)) {
5449 case SMB_FILE_BASIC_INFORMATION:
5450 case SMB_QUERY_FILE_BASIC_INFO:
5452 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5453 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5454 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5456 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5460 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5461 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5462 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5463 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5464 SIVAL(pdata,32,mode);
5466 DEBUG(5,("SMB_QFBI - "));
5467 DEBUG(5,("create: %s ", ctime(&create_time)));
5468 DEBUG(5,("access: %s ", ctime(&atime)));
5469 DEBUG(5,("write: %s ", ctime(&mtime)));
5470 DEBUG(5,("change: %s ", ctime(&c_time)));
5471 DEBUG(5,("mode: %x\n", mode));
5472 *fixed_portion = data_size;
5475 case SMB_FILE_STANDARD_INFORMATION:
5476 case SMB_QUERY_FILE_STANDARD_INFO:
5478 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5480 SOFF_T(pdata,0,allocation_size);
5481 SOFF_T(pdata,8,file_size);
5482 SIVAL(pdata,16,nlink);
5483 SCVAL(pdata,20,delete_pending?1:0);
5484 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5485 SSVAL(pdata,22,0); /* Padding. */
5486 *fixed_portion = 24;
5489 case SMB_FILE_EA_INFORMATION:
5490 case SMB_QUERY_FILE_EA_INFO:
5492 unsigned int ea_size =
5493 estimate_ea_size(conn, fsp, smb_fname);
5494 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5497 SIVAL(pdata,0,ea_size);
5501 /* Get the 8.3 name - used if NT SMB was negotiated. */
5502 case SMB_QUERY_FILE_ALT_NAME_INFO:
5503 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5505 char mangled_name[13];
5506 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5507 if (!name_to_8_3(base_name,mangled_name,
5508 True,conn->params)) {
5509 return NT_STATUS_NO_MEMORY;
5511 status = srvstr_push(dstart, flags2,
5512 pdata+4, mangled_name,
5513 PTR_DIFF(dend, pdata+4),
5515 if (!NT_STATUS_IS_OK(status)) {
5518 data_size = 4 + len;
5524 case SMB_QUERY_FILE_NAME_INFO:
5527 this must be *exactly* right for ACLs on mapped drives to work
5529 status = srvstr_push(dstart, flags2,
5531 PTR_DIFF(dend, pdata+4),
5533 if (!NT_STATUS_IS_OK(status)) {
5536 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5537 data_size = 4 + len;
5542 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5544 char *nfname = NULL;
5546 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
5547 return NT_STATUS_INVALID_LEVEL;
5550 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5551 if (nfname == NULL) {
5552 return NT_STATUS_NO_MEMORY;
5555 if (ISDOT(nfname)) {
5558 string_replace(nfname, '/', '\\');
5560 if (smb_fname->stream_name != NULL) {
5561 const char *s = smb_fname->stream_name;
5562 const char *e = NULL;
5565 SMB_ASSERT(s[0] != '\0');
5568 * smb_fname->stream_name is in form
5569 * of ':StrEam:$DATA', but we should only
5570 * append ':StrEam' here.
5573 e = strchr(&s[1], ':');
5579 nfname = talloc_strndup_append(nfname, s, n);
5580 if (nfname == NULL) {
5581 return NT_STATUS_NO_MEMORY;
5585 status = srvstr_push(dstart, flags2,
5587 PTR_DIFF(dend, pdata+4),
5589 if (!NT_STATUS_IS_OK(status)) {
5592 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5593 data_size = 4 + len;
5599 case SMB_FILE_ALLOCATION_INFORMATION:
5600 case SMB_QUERY_FILE_ALLOCATION_INFO:
5601 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5603 SOFF_T(pdata,0,allocation_size);
5606 case SMB_FILE_END_OF_FILE_INFORMATION:
5607 case SMB_QUERY_FILE_END_OF_FILEINFO:
5608 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5610 SOFF_T(pdata,0,file_size);
5613 case SMB_QUERY_FILE_ALL_INFO:
5614 case SMB_FILE_ALL_INFORMATION:
5616 unsigned int ea_size =
5617 estimate_ea_size(conn, fsp, smb_fname);
5618 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5619 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5620 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5621 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5622 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5623 SIVAL(pdata,32,mode);
5624 SIVAL(pdata,36,0); /* padding. */
5626 SOFF_T(pdata,0,allocation_size);
5627 SOFF_T(pdata,8,file_size);
5628 SIVAL(pdata,16,nlink);
5629 SCVAL(pdata,20,delete_pending);
5630 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5633 SIVAL(pdata,0,ea_size);
5634 pdata += 4; /* EA info */
5635 status = srvstr_push(dstart, flags2,
5637 PTR_DIFF(dend, pdata+4),
5639 if (!NT_STATUS_IS_OK(status)) {
5644 data_size = PTR_DIFF(pdata,(*ppdata));
5645 *fixed_portion = 10;
5649 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5651 unsigned int ea_size =
5652 estimate_ea_size(conn, fsp, smb_fname);
5653 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5654 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
5655 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
5656 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
5657 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
5658 SIVAL(pdata, 0x20, mode);
5659 SIVAL(pdata, 0x24, 0); /* padding. */
5660 SBVAL(pdata, 0x28, allocation_size);
5661 SBVAL(pdata, 0x30, file_size);
5662 SIVAL(pdata, 0x38, nlink);
5663 SCVAL(pdata, 0x3C, delete_pending);
5664 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5665 SSVAL(pdata, 0x3E, 0); /* padding */
5666 SBVAL(pdata, 0x40, file_id);
5667 SIVAL(pdata, 0x48, ea_size);
5668 SIVAL(pdata, 0x4C, access_mask);
5669 SBVAL(pdata, 0x50, pos);
5670 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5671 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5675 status = srvstr_push(dstart, flags2,
5677 PTR_DIFF(dend, pdata+4),
5679 if (!NT_STATUS_IS_OK(status)) {
5684 data_size = PTR_DIFF(pdata,(*ppdata));
5685 *fixed_portion = 104;
5688 case SMB_FILE_INTERNAL_INFORMATION:
5690 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5691 SBVAL(pdata, 0, file_id);
5696 case SMB_FILE_ACCESS_INFORMATION:
5697 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5698 SIVAL(pdata, 0, access_mask);
5703 case SMB_FILE_NAME_INFORMATION:
5704 /* Pathname with leading '\'. */
5707 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5709 SIVAL(pdata,0,byte_len);
5710 data_size = 4 + byte_len;
5714 case SMB_FILE_DISPOSITION_INFORMATION:
5715 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5717 SCVAL(pdata,0,delete_pending);
5721 case SMB_FILE_POSITION_INFORMATION:
5722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5724 SOFF_T(pdata,0,pos);
5728 case SMB_FILE_MODE_INFORMATION:
5729 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5730 SIVAL(pdata,0,mode);
5735 case SMB_FILE_ALIGNMENT_INFORMATION:
5736 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5737 SIVAL(pdata,0,0); /* No alignment needed. */
5743 * NT4 server just returns "invalid query" to this - if we try
5744 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5747 /* The first statement above is false - verified using Thursby
5748 * client against NT4 -- gcolley.
5750 case SMB_QUERY_FILE_STREAM_INFO:
5751 case SMB_FILE_STREAM_INFORMATION: {
5752 unsigned int num_streams = 0;
5753 struct stream_struct *streams = NULL;
5755 DEBUG(10,("smbd_do_qfilepathinfo: "
5756 "SMB_FILE_STREAM_INFORMATION\n"));
5758 if (is_ntfs_stream_smb_fname(smb_fname)) {
5759 return NT_STATUS_INVALID_PARAMETER;
5762 status = vfs_streaminfo(conn,
5769 if (!NT_STATUS_IS_OK(status)) {
5770 DEBUG(10, ("could not get stream info: %s\n",
5771 nt_errstr(status)));
5775 status = marshall_stream_info(num_streams, streams,
5776 pdata, max_data_bytes,
5779 if (!NT_STATUS_IS_OK(status)) {
5780 DEBUG(10, ("marshall_stream_info failed: %s\n",
5781 nt_errstr(status)));
5782 TALLOC_FREE(streams);
5786 TALLOC_FREE(streams);
5788 *fixed_portion = 32;
5792 case SMB_QUERY_COMPRESSION_INFO:
5793 case SMB_FILE_COMPRESSION_INFORMATION:
5794 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5795 SOFF_T(pdata,0,file_size);
5796 SIVAL(pdata,8,0); /* ??? */
5797 SIVAL(pdata,12,0); /* ??? */
5799 *fixed_portion = 16;
5802 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5803 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5804 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5805 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5806 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5807 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5808 SOFF_T(pdata,32,allocation_size);
5809 SOFF_T(pdata,40,file_size);
5810 SIVAL(pdata,48,mode);
5811 SIVAL(pdata,52,0); /* ??? */
5813 *fixed_portion = 56;
5816 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5817 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5818 SIVAL(pdata,0,mode);
5825 * CIFS UNIX Extensions.
5828 case SMB_QUERY_FILE_UNIX_BASIC:
5830 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5831 data_size = PTR_DIFF(pdata,(*ppdata));
5833 DEBUG(4,("smbd_do_qfilepathinfo: "
5834 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5835 dump_data(4, (uint8_t *)(*ppdata), data_size);
5839 case SMB_QUERY_FILE_UNIX_INFO2:
5841 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5842 data_size = PTR_DIFF(pdata,(*ppdata));
5846 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5848 for (i=0; i<100; i++)
5849 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5855 case SMB_QUERY_FILE_UNIX_LINK:
5858 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5861 return NT_STATUS_NO_MEMORY;
5864 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5866 if(!S_ISLNK(psbuf->st_ex_mode)) {
5867 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5870 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5872 link_len = SMB_VFS_READLINKAT(conn,
5878 if (link_len == -1) {
5879 return map_nt_error_from_unix(errno);
5881 buffer[link_len] = 0;
5882 status = srvstr_push(dstart, flags2,
5884 PTR_DIFF(dend, pdata),
5885 STR_TERMINATE, &len);
5886 if (!NT_STATUS_IS_OK(status)) {
5890 data_size = PTR_DIFF(pdata,(*ppdata));
5895 #if defined(HAVE_POSIX_ACLS)
5896 case SMB_QUERY_POSIX_ACL:
5898 status = smb_query_posix_acl(conn,
5905 if (!NT_STATUS_IS_OK(status)) {
5913 case SMB_QUERY_POSIX_LOCK:
5918 enum brl_type lock_type;
5920 /* We need an open file with a real fd for this. */
5921 if (!fsp || fsp->fh->fd == -1) {
5922 return NT_STATUS_INVALID_LEVEL;
5925 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5926 return NT_STATUS_INVALID_PARAMETER;
5929 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5930 case POSIX_LOCK_TYPE_READ:
5931 lock_type = READ_LOCK;
5933 case POSIX_LOCK_TYPE_WRITE:
5934 lock_type = WRITE_LOCK;
5936 case POSIX_LOCK_TYPE_UNLOCK:
5938 /* There's no point in asking for an unlock... */
5939 return NT_STATUS_INVALID_PARAMETER;
5942 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5943 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5944 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5946 status = query_lock(fsp,
5953 if (ERROR_WAS_LOCK_DENIED(status)) {
5954 /* Here we need to report who has it locked... */
5955 data_size = POSIX_LOCK_DATA_SIZE;
5957 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5958 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5959 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5960 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5961 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5963 } else if (NT_STATUS_IS_OK(status)) {
5964 /* For success we just return a copy of what we sent
5965 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5966 data_size = POSIX_LOCK_DATA_SIZE;
5967 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5968 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5976 return NT_STATUS_INVALID_LEVEL;
5979 *pdata_size = data_size;
5980 return NT_STATUS_OK;
5983 /****************************************************************************
5984 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5985 file name or file id).
5986 ****************************************************************************/
5988 static void call_trans2qfilepathinfo(connection_struct *conn,
5989 struct smb_request *req,
5990 unsigned int tran_call,
5991 char **pparams, int total_params,
5992 char **ppdata, int total_data,
5993 unsigned int max_data_bytes)
5995 char *params = *pparams;
5996 char *pdata = *ppdata;
5997 uint16_t info_level;
5998 unsigned int data_size = 0;
5999 unsigned int param_size = 2;
6000 struct smb_filename *smb_fname = NULL;
6001 bool delete_pending = False;
6002 struct timespec write_time_ts;
6003 files_struct *fsp = NULL;
6004 struct file_id fileid;
6005 struct ea_list *ea_list = NULL;
6006 int lock_data_count = 0;
6007 char *lock_data = NULL;
6008 size_t fixed_portion;
6009 NTSTATUS status = NT_STATUS_OK;
6012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6016 ZERO_STRUCT(write_time_ts);
6018 if (tran_call == TRANSACT2_QFILEINFO) {
6019 if (total_params < 4) {
6020 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6025 call_trans2qpipeinfo(conn, req, tran_call,
6026 pparams, total_params,
6032 fsp = file_fsp(req, SVAL(params,0));
6033 info_level = SVAL(params,2);
6035 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6037 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6038 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6042 /* Initial check for valid fsp ptr. */
6043 if (!check_fsp_open(conn, req, fsp)) {
6047 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
6048 if (smb_fname == NULL) {
6049 reply_nterror(req, NT_STATUS_NO_MEMORY);
6053 if(fsp->fake_file_handle) {
6055 * This is actually for the QUOTA_FAKE_FILE --metze
6058 /* We know this name is ok, it's already passed the checks. */
6060 } else if(fsp->fh->fd == -1) {
6062 * This is actually a QFILEINFO on a directory
6063 * handle (returned from an NT SMB). NT5.0 seems
6064 * to do this call. JRA.
6067 if (INFO_LEVEL_IS_UNIX(info_level)) {
6068 /* Always do lstat for UNIX calls. */
6069 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6070 DEBUG(3,("call_trans2qfilepathinfo: "
6071 "SMB_VFS_LSTAT of %s failed "
6073 smb_fname_str_dbg(smb_fname),
6076 map_nt_error_from_unix(errno));
6079 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6080 DEBUG(3,("call_trans2qfilepathinfo: "
6081 "SMB_VFS_STAT of %s failed (%s)\n",
6082 smb_fname_str_dbg(smb_fname),
6085 map_nt_error_from_unix(errno));
6089 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6090 fileid = vfs_file_id_from_sbuf(
6091 conn, &smb_fname->st);
6092 get_file_infos(fileid, fsp->name_hash,
6098 * Original code - this is an open file.
6100 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6101 DEBUG(3, ("fstat of %s failed (%s)\n",
6102 fsp_fnum_dbg(fsp), strerror(errno)));
6104 map_nt_error_from_unix(errno));
6107 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6108 fileid = vfs_file_id_from_sbuf(
6109 conn, &smb_fname->st);
6110 get_file_infos(fileid, fsp->name_hash,
6119 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6122 if (total_params < 7) {
6123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6127 info_level = SVAL(params,0);
6129 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6131 if (INFO_LEVEL_IS_UNIX(info_level)) {
6132 if (!lp_unix_extensions()) {
6133 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6136 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6137 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6138 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6139 req->posix_pathnames) {
6140 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6144 if (req->posix_pathnames) {
6145 srvstr_get_path_posix(req,
6154 srvstr_get_path(req,
6163 if (!NT_STATUS_IS_OK(status)) {
6164 reply_nterror(req, status);
6168 status = filename_convert(req,
6175 if (!NT_STATUS_IS_OK(status)) {
6176 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6177 reply_botherror(req,
6178 NT_STATUS_PATH_NOT_COVERED,
6179 ERRSRV, ERRbadpath);
6182 reply_nterror(req, status);
6186 /* If this is a stream, check if there is a delete_pending. */
6187 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6188 && is_ntfs_stream_smb_fname(smb_fname)) {
6189 struct smb_filename *smb_fname_base;
6191 /* Create an smb_filename with stream_name == NULL. */
6192 smb_fname_base = synthetic_smb_fname(
6194 smb_fname->base_name,
6198 if (smb_fname_base == NULL) {
6199 reply_nterror(req, NT_STATUS_NO_MEMORY);
6203 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6204 /* Always do lstat for UNIX calls. */
6205 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6206 DEBUG(3,("call_trans2qfilepathinfo: "
6207 "SMB_VFS_LSTAT of %s failed "
6209 smb_fname_str_dbg(smb_fname_base),
6211 TALLOC_FREE(smb_fname_base);
6213 map_nt_error_from_unix(errno));
6217 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6218 DEBUG(3,("call_trans2qfilepathinfo: "
6219 "fileinfo of %s failed "
6221 smb_fname_str_dbg(smb_fname_base),
6223 TALLOC_FREE(smb_fname_base);
6225 map_nt_error_from_unix(errno));
6230 status = file_name_hash(conn,
6231 smb_fname_str_dbg(smb_fname_base),
6233 if (!NT_STATUS_IS_OK(status)) {
6234 TALLOC_FREE(smb_fname_base);
6235 reply_nterror(req, status);
6239 fileid = vfs_file_id_from_sbuf(conn,
6240 &smb_fname_base->st);
6241 TALLOC_FREE(smb_fname_base);
6242 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6243 if (delete_pending) {
6244 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6249 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6250 /* Always do lstat for UNIX calls. */
6251 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6252 DEBUG(3,("call_trans2qfilepathinfo: "
6253 "SMB_VFS_LSTAT of %s failed (%s)\n",
6254 smb_fname_str_dbg(smb_fname),
6257 map_nt_error_from_unix(errno));
6262 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6263 DEBUG(3,("call_trans2qfilepathinfo: "
6264 "SMB_VFS_STAT of %s failed (%s)\n",
6265 smb_fname_str_dbg(smb_fname),
6268 map_nt_error_from_unix(errno));
6273 status = file_name_hash(conn,
6274 smb_fname_str_dbg(smb_fname),
6276 if (!NT_STATUS_IS_OK(status)) {
6277 reply_nterror(req, status);
6281 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6282 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6283 get_file_infos(fileid, name_hash, &delete_pending,
6287 if (delete_pending) {
6288 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6293 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6294 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6296 info_level,tran_call,total_data));
6298 /* Pull out any data sent here before we realloc. */
6299 switch (info_level) {
6300 case SMB_INFO_QUERY_EAS_FROM_LIST:
6302 /* Pull any EA list from the data portion. */
6305 if (total_data < 4) {
6307 req, NT_STATUS_INVALID_PARAMETER);
6310 ea_size = IVAL(pdata,0);
6312 if (total_data > 0 && ea_size != total_data) {
6313 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6314 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6316 req, NT_STATUS_INVALID_PARAMETER);
6320 if (!lp_ea_support(SNUM(conn))) {
6321 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6325 /* Pull out the list of names. */
6326 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6329 req, NT_STATUS_INVALID_PARAMETER);
6335 case SMB_QUERY_POSIX_LOCK:
6337 if (fsp == NULL || fsp->fh->fd == -1) {
6338 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6342 if (total_data != POSIX_LOCK_DATA_SIZE) {
6344 req, NT_STATUS_INVALID_PARAMETER);
6348 /* Copy the lock range data. */
6349 lock_data = (char *)talloc_memdup(
6350 req, pdata, total_data);
6352 reply_nterror(req, NT_STATUS_NO_MEMORY);
6355 lock_data_count = total_data;
6361 *pparams = (char *)SMB_REALLOC(*pparams,2);
6362 if (*pparams == NULL) {
6363 reply_nterror(req, NT_STATUS_NO_MEMORY);
6370 * draft-leach-cifs-v1-spec-02.txt
6371 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6374 * The requested information is placed in the Data portion of the
6375 * transaction response. For the information levels greater than 0x100,
6376 * the transaction response has 1 parameter word which should be
6377 * ignored by the client.
6379 * However Windows only follows this rule for the IS_NAME_VALID call.
6381 switch (info_level) {
6382 case SMB_INFO_IS_NAME_VALID:
6387 if ((info_level & 0xFF00) == 0xFF00) {
6389 * We use levels that start with 0xFF00
6390 * internally to represent SMB2 specific levels
6392 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6396 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6398 delete_pending, write_time_ts,
6400 lock_data_count, lock_data,
6401 req->flags2, max_data_bytes,
6403 ppdata, &data_size);
6404 if (!NT_STATUS_IS_OK(status)) {
6405 if (open_was_deferred(req->xconn, req->mid)) {
6406 /* We have re-scheduled this call. */
6409 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6410 bool ok = defer_smb1_sharing_violation(req);
6415 reply_nterror(req, status);
6418 if (fixed_portion > max_data_bytes) {
6419 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6423 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6429 /****************************************************************************
6430 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6432 ****************************************************************************/
6434 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6435 connection_struct *conn,
6436 struct smb_request *req,
6437 bool overwrite_if_exists,
6438 const struct smb_filename *smb_fname_old,
6439 struct smb_filename *smb_fname_new)
6441 NTSTATUS status = NT_STATUS_OK;
6445 /* source must already exist. */
6446 if (!VALID_STAT(smb_fname_old->st)) {
6447 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6450 if (VALID_STAT(smb_fname_new->st)) {
6451 if (overwrite_if_exists) {
6452 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6453 return NT_STATUS_FILE_IS_A_DIRECTORY;
6455 status = unlink_internals(conn,
6457 FILE_ATTRIBUTE_NORMAL,
6460 if (!NT_STATUS_IS_OK(status)) {
6464 /* Disallow if newname already exists. */
6465 return NT_STATUS_OBJECT_NAME_COLLISION;
6469 /* No links from a directory. */
6470 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6471 return NT_STATUS_FILE_IS_A_DIRECTORY;
6474 /* Setting a hardlink to/from a stream isn't currently supported. */
6475 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6477 DBG_DEBUG("Old name has streams\n");
6478 return NT_STATUS_INVALID_PARAMETER;
6480 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6482 DBG_DEBUG("New name has streams\n");
6483 return NT_STATUS_INVALID_PARAMETER;
6486 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6487 smb_fname_old->base_name, smb_fname_new->base_name));
6489 ret = SMB_VFS_LINKAT(conn,
6497 status = map_nt_error_from_unix(errno);
6498 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6499 nt_errstr(status), smb_fname_old->base_name,
6500 smb_fname_new->base_name));
6505 /****************************************************************************
6506 Deal with setting the time from any of the setfilepathinfo functions.
6507 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6508 calling this function.
6509 ****************************************************************************/
6511 NTSTATUS smb_set_file_time(connection_struct *conn,
6513 const struct smb_filename *smb_fname,
6514 struct smb_file_time *ft,
6515 bool setting_write_time)
6517 struct smb_filename smb_fname_base;
6518 struct timeval_buf tbuf[4];
6520 FILE_NOTIFY_CHANGE_LAST_ACCESS
6521 |FILE_NOTIFY_CHANGE_LAST_WRITE
6522 |FILE_NOTIFY_CHANGE_CREATION;
6524 if (!VALID_STAT(smb_fname->st)) {
6525 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6528 /* get some defaults (no modifications) if any info is zero or -1. */
6529 if (is_omit_timespec(&ft->create_time)) {
6530 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6533 if (is_omit_timespec(&ft->atime)) {
6534 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6537 if (is_omit_timespec(&ft->mtime)) {
6538 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6541 if (!setting_write_time) {
6542 /* ft->mtime comes from change time, not write time. */
6543 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6546 /* Ensure the resolution is the correct for
6547 * what we can store on this filesystem. */
6549 round_timespec(conn->ts_res, &ft->create_time);
6550 round_timespec(conn->ts_res, &ft->ctime);
6551 round_timespec(conn->ts_res, &ft->atime);
6552 round_timespec(conn->ts_res, &ft->mtime);
6554 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6555 timespec_string_buf(&ft->atime, true, &tbuf[0]));
6556 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6557 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
6558 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6559 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
6560 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6561 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
6563 if (setting_write_time) {
6565 * This was a Windows setfileinfo on an open file.
6566 * NT does this a lot. We also need to
6567 * set the time here, as it can be read by
6568 * FindFirst/FindNext and with the patch for bug #2045
6569 * in smbd/fileio.c it ensures that this timestamp is
6570 * kept sticky even after a write. We save the request
6571 * away and will set it on file close and after a write. JRA.
6574 DBG_DEBUG("setting pending modtime to %s\n",
6575 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
6578 if (fsp->base_fsp) {
6579 set_sticky_write_time_fsp(fsp->base_fsp,
6582 set_sticky_write_time_fsp(fsp, ft->mtime);
6585 set_sticky_write_time_path(
6586 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6591 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6593 /* Always call ntimes on the base, even if a stream was passed in. */
6594 smb_fname_base = *smb_fname;
6595 smb_fname_base.stream_name = NULL;
6597 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6598 return map_nt_error_from_unix(errno);
6601 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6602 smb_fname->base_name);
6603 return NT_STATUS_OK;
6606 /****************************************************************************
6607 Deal with setting the dosmode from any of the setfilepathinfo functions.
6608 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6609 done before calling this function.
6610 ****************************************************************************/
6612 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6613 const struct smb_filename *smb_fname,
6616 struct smb_filename *smb_fname_base;
6619 if (!VALID_STAT(smb_fname->st)) {
6620 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6623 /* Always operate on the base_name, even if a stream was passed in. */
6624 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6625 smb_fname->base_name,
6629 if (smb_fname_base == NULL) {
6630 return NT_STATUS_NO_MEMORY;
6634 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6635 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6637 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6641 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6643 /* check the mode isn't different, before changing it */
6644 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6645 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6646 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6647 (unsigned int)dosmode));
6649 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6651 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6653 smb_fname_str_dbg(smb_fname_base),
6655 status = map_nt_error_from_unix(errno);
6659 status = NT_STATUS_OK;
6661 TALLOC_FREE(smb_fname_base);
6665 /****************************************************************************
6666 Deal with setting the size from any of the setfilepathinfo functions.
6667 ****************************************************************************/
6669 static NTSTATUS smb_set_file_size(connection_struct *conn,
6670 struct smb_request *req,
6672 const struct smb_filename *smb_fname,
6673 const SMB_STRUCT_STAT *psbuf,
6675 bool fail_after_createfile)
6677 NTSTATUS status = NT_STATUS_OK;
6678 struct smb_filename *smb_fname_tmp = NULL;
6679 files_struct *new_fsp = NULL;
6681 if (!VALID_STAT(*psbuf)) {
6682 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6685 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6687 get_file_size_stat(psbuf));
6689 if (size == get_file_size_stat(psbuf)) {
6691 return NT_STATUS_OK;
6693 if (!fsp->modified) {
6694 return NT_STATUS_OK;
6696 trigger_write_time_update_immediate(fsp);
6697 return NT_STATUS_OK;
6700 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6701 smb_fname_str_dbg(smb_fname), (double)size));
6703 if (fsp && fsp->fh->fd != -1) {
6704 /* Handle based call. */
6705 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6706 return NT_STATUS_ACCESS_DENIED;
6709 if (vfs_set_filelen(fsp, size) == -1) {
6710 return map_nt_error_from_unix(errno);
6712 trigger_write_time_update_immediate(fsp);
6713 return NT_STATUS_OK;
6716 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6717 if (smb_fname_tmp == NULL) {
6718 return NT_STATUS_NO_MEMORY;
6721 smb_fname_tmp->st = *psbuf;
6723 status = SMB_VFS_CREATE_FILE(
6726 0, /* root_dir_fid */
6727 smb_fname_tmp, /* fname */
6728 FILE_WRITE_DATA, /* access_mask */
6729 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6731 FILE_OPEN, /* create_disposition*/
6732 0, /* create_options */
6733 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6734 0, /* oplock_request */
6736 0, /* allocation_size */
6737 0, /* private_flags */
6740 &new_fsp, /* result */
6742 NULL, NULL); /* create context */
6744 TALLOC_FREE(smb_fname_tmp);
6746 if (!NT_STATUS_IS_OK(status)) {
6747 /* NB. We check for open_was_deferred in the caller. */
6751 /* See RAW-SFILEINFO-END-OF-FILE */
6752 if (fail_after_createfile) {
6753 close_file(req, new_fsp,NORMAL_CLOSE);
6754 return NT_STATUS_INVALID_LEVEL;
6757 if (vfs_set_filelen(new_fsp, size) == -1) {
6758 status = map_nt_error_from_unix(errno);
6759 close_file(req, new_fsp,NORMAL_CLOSE);
6763 trigger_write_time_update_immediate(new_fsp);
6764 close_file(req, new_fsp,NORMAL_CLOSE);
6765 return NT_STATUS_OK;
6768 /****************************************************************************
6769 Deal with SMB_INFO_SET_EA.
6770 ****************************************************************************/
6772 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6776 const struct smb_filename *smb_fname)
6778 struct ea_list *ea_list = NULL;
6779 TALLOC_CTX *ctx = NULL;
6780 NTSTATUS status = NT_STATUS_OK;
6782 if (total_data < 10) {
6784 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6785 length. They seem to have no effect. Bug #3212. JRA */
6787 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6788 /* We're done. We only get EA info in this call. */
6789 return NT_STATUS_OK;
6792 return NT_STATUS_INVALID_PARAMETER;
6795 if (IVAL(pdata,0) > total_data) {
6796 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6797 IVAL(pdata,0), (unsigned int)total_data));
6798 return NT_STATUS_INVALID_PARAMETER;
6802 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6804 return NT_STATUS_INVALID_PARAMETER;
6807 status = set_ea(conn, fsp, smb_fname, ea_list);
6812 /****************************************************************************
6813 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6814 ****************************************************************************/
6816 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6821 struct ea_list *ea_list = NULL;
6825 return NT_STATUS_INVALID_HANDLE;
6828 if (!lp_ea_support(SNUM(conn))) {
6829 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6830 "EA's not supported.\n",
6831 (unsigned int)total_data));
6832 return NT_STATUS_EAS_NOT_SUPPORTED;
6835 if (total_data < 10) {
6836 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6838 (unsigned int)total_data));
6839 return NT_STATUS_INVALID_PARAMETER;
6842 ea_list = read_nttrans_ea_list(talloc_tos(),
6847 return NT_STATUS_INVALID_PARAMETER;
6850 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6852 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6853 smb_fname_str_dbg(fsp->fsp_name),
6854 nt_errstr(status) ));
6860 /****************************************************************************
6861 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6862 ****************************************************************************/
6864 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6868 struct smb_filename *smb_fname)
6870 NTSTATUS status = NT_STATUS_OK;
6871 bool delete_on_close;
6872 uint32_t dosmode = 0;
6874 if (total_data < 1) {
6875 return NT_STATUS_INVALID_PARAMETER;
6879 return NT_STATUS_INVALID_HANDLE;
6882 delete_on_close = (CVAL(pdata,0) ? True : False);
6883 dosmode = dos_mode(conn, smb_fname);
6885 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6886 "delete_on_close = %u\n",
6887 smb_fname_str_dbg(smb_fname),
6888 (unsigned int)dosmode,
6889 (unsigned int)delete_on_close ));
6891 if (delete_on_close) {
6892 status = can_set_delete_on_close(fsp, dosmode);
6893 if (!NT_STATUS_IS_OK(status)) {
6898 /* The set is across all open files on this dev/inode pair. */
6899 if (!set_delete_on_close(fsp, delete_on_close,
6900 conn->session_info->security_token,
6901 conn->session_info->unix_token)) {
6902 return NT_STATUS_ACCESS_DENIED;
6904 return NT_STATUS_OK;
6907 /****************************************************************************
6908 Deal with SMB_FILE_POSITION_INFORMATION.
6909 ****************************************************************************/
6911 static NTSTATUS smb_file_position_information(connection_struct *conn,
6916 uint64_t position_information;
6918 if (total_data < 8) {
6919 return NT_STATUS_INVALID_PARAMETER;
6923 /* Ignore on pathname based set. */
6924 return NT_STATUS_OK;
6927 position_information = (uint64_t)IVAL(pdata,0);
6928 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6930 DEBUG(10,("smb_file_position_information: Set file position "
6931 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6932 (double)position_information));
6933 fsp->fh->position_information = position_information;
6934 return NT_STATUS_OK;
6937 /****************************************************************************
6938 Deal with SMB_FILE_MODE_INFORMATION.
6939 ****************************************************************************/
6941 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6947 if (total_data < 4) {
6948 return NT_STATUS_INVALID_PARAMETER;
6950 mode = IVAL(pdata,0);
6951 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6952 return NT_STATUS_INVALID_PARAMETER;
6954 return NT_STATUS_OK;
6957 /****************************************************************************
6958 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6959 ****************************************************************************/
6961 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6962 struct smb_request *req,
6965 const struct smb_filename *new_smb_fname)
6967 char *link_target = NULL;
6968 TALLOC_CTX *ctx = talloc_tos();
6971 /* Set a symbolic link. */
6972 /* Don't allow this if follow links is false. */
6974 if (total_data == 0) {
6975 return NT_STATUS_INVALID_PARAMETER;
6978 if (!lp_follow_symlinks(SNUM(conn))) {
6979 return NT_STATUS_ACCESS_DENIED;
6982 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6983 total_data, STR_TERMINATE);
6986 return NT_STATUS_INVALID_PARAMETER;
6989 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6990 new_smb_fname->base_name, link_target ));
6992 ret = SMB_VFS_SYMLINKAT(conn,
6997 return map_nt_error_from_unix(errno);
7000 return NT_STATUS_OK;
7003 /****************************************************************************
7004 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
7005 ****************************************************************************/
7007 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
7008 struct smb_request *req,
7009 const char *pdata, int total_data,
7010 struct smb_filename *smb_fname_new)
7012 char *oldname = NULL;
7013 struct smb_filename *smb_fname_old = NULL;
7014 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7015 TALLOC_CTX *ctx = talloc_tos();
7016 NTSTATUS status = NT_STATUS_OK;
7018 /* Set a hard link. */
7019 if (total_data == 0) {
7020 return NT_STATUS_INVALID_PARAMETER;
7023 if (req->posix_pathnames) {
7024 srvstr_get_path_posix(ctx,
7033 srvstr_get_path(ctx,
7042 if (!NT_STATUS_IS_OK(status)) {
7046 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7047 smb_fname_str_dbg(smb_fname_new), oldname));
7049 status = filename_convert(ctx,
7056 if (!NT_STATUS_IS_OK(status)) {
7060 return hardlink_internals(ctx, conn, req, false,
7061 smb_fname_old, smb_fname_new);
7064 /****************************************************************************
7065 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7066 ****************************************************************************/
7068 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7069 struct smb_request *req,
7073 struct smb_filename *smb_fname_src)
7077 char *newname = NULL;
7078 struct smb_filename *smb_fname_dst = NULL;
7079 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7080 ucf_flags_from_smb_request(req);
7081 NTSTATUS status = NT_STATUS_OK;
7082 TALLOC_CTX *ctx = talloc_tos();
7085 return NT_STATUS_INVALID_HANDLE;
7088 if (total_data < 20) {
7089 return NT_STATUS_INVALID_PARAMETER;
7092 overwrite = (CVAL(pdata,0) ? True : False);
7093 len = IVAL(pdata,16);
7095 if (len > (total_data - 20) || (len == 0)) {
7096 return NT_STATUS_INVALID_PARAMETER;
7099 if (req->posix_pathnames) {
7100 srvstr_get_path_posix(ctx,
7109 srvstr_get_path(ctx,
7118 if (!NT_STATUS_IS_OK(status)) {
7122 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7125 status = filename_convert(ctx,
7132 if (!NT_STATUS_IS_OK(status)) {
7136 if (fsp->base_fsp) {
7137 /* newname must be a stream name. */
7138 if (newname[0] != ':') {
7139 return NT_STATUS_NOT_SUPPORTED;
7142 /* Create an smb_fname to call rename_internals_fsp() with. */
7143 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7144 fsp->base_fsp->fsp_name->base_name,
7147 fsp->base_fsp->fsp_name->flags);
7148 if (smb_fname_dst == NULL) {
7149 status = NT_STATUS_NO_MEMORY;
7154 * Set the original last component, since
7155 * rename_internals_fsp() requires it.
7157 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7159 if (smb_fname_dst->original_lcomp == NULL) {
7160 status = NT_STATUS_NO_MEMORY;
7166 DEBUG(10,("smb2_file_rename_information: "
7167 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7168 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7169 smb_fname_str_dbg(smb_fname_dst)));
7170 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7171 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7175 TALLOC_FREE(smb_fname_dst);
7179 static NTSTATUS smb_file_link_information(connection_struct *conn,
7180 struct smb_request *req,
7184 struct smb_filename *smb_fname_src)
7188 char *newname = NULL;
7189 struct smb_filename *smb_fname_dst = NULL;
7190 NTSTATUS status = NT_STATUS_OK;
7191 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7192 ucf_flags_from_smb_request(req);
7193 TALLOC_CTX *ctx = talloc_tos();
7196 return NT_STATUS_INVALID_HANDLE;
7199 if (total_data < 20) {
7200 return NT_STATUS_INVALID_PARAMETER;
7203 overwrite = (CVAL(pdata,0) ? true : false);
7204 len = IVAL(pdata,16);
7206 if (len > (total_data - 20) || (len == 0)) {
7207 return NT_STATUS_INVALID_PARAMETER;
7210 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7211 srvstr_get_path_posix(ctx,
7219 ucf_flags |= UCF_POSIX_PATHNAMES;
7221 srvstr_get_path(ctx,
7230 if (!NT_STATUS_IS_OK(status)) {
7234 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7237 status = filename_convert(ctx,
7244 if (!NT_STATUS_IS_OK(status)) {
7248 if (fsp->base_fsp) {
7249 /* No stream names. */
7250 return NT_STATUS_NOT_SUPPORTED;
7253 DEBUG(10,("smb_file_link_information: "
7254 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7255 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7256 smb_fname_str_dbg(smb_fname_dst)));
7257 status = hardlink_internals(ctx,
7264 TALLOC_FREE(smb_fname_dst);
7268 /****************************************************************************
7269 Deal with SMB_FILE_RENAME_INFORMATION.
7270 ****************************************************************************/
7272 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7273 struct smb_request *req,
7277 struct smb_filename *smb_fname_src)
7282 char *newname = NULL;
7283 struct smb_filename *smb_fname_dst = NULL;
7284 bool dest_has_wcard = False;
7285 NTSTATUS status = NT_STATUS_OK;
7287 TALLOC_CTX *ctx = talloc_tos();
7289 if (total_data < 13) {
7290 return NT_STATUS_INVALID_PARAMETER;
7293 overwrite = (CVAL(pdata,0) ? True : False);
7294 root_fid = IVAL(pdata,4);
7295 len = IVAL(pdata,8);
7297 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7298 return NT_STATUS_INVALID_PARAMETER;
7301 if (req->posix_pathnames) {
7302 srvstr_get_path_wcard_posix(ctx,
7312 srvstr_get_path_wcard(ctx,
7322 if (!NT_STATUS_IS_OK(status)) {
7326 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7329 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7330 status = resolve_dfspath_wcard(ctx, conn,
7332 UCF_COND_ALLOW_WCARD_LCOMP,
7333 !conn->sconn->using_smb2,
7336 if (!NT_STATUS_IS_OK(status)) {
7341 /* Check the new name has no '/' characters. */
7342 if (strchr_m(newname, '/')) {
7343 return NT_STATUS_NOT_SUPPORTED;
7346 if (fsp && fsp->base_fsp) {
7347 /* newname must be a stream name. */
7348 if (newname[0] != ':') {
7349 return NT_STATUS_NOT_SUPPORTED;
7352 /* Create an smb_fname to call rename_internals_fsp() with. */
7353 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7354 fsp->base_fsp->fsp_name->base_name,
7357 fsp->base_fsp->fsp_name->flags);
7358 if (smb_fname_dst == NULL) {
7359 status = NT_STATUS_NO_MEMORY;
7364 * Set the original last component, since
7365 * rename_internals_fsp() requires it.
7367 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7369 if (smb_fname_dst->original_lcomp == NULL) {
7370 status = NT_STATUS_NO_MEMORY;
7376 * Build up an smb_fname_dst based on the filename passed in.
7377 * We basically just strip off the last component, and put on
7378 * the newname instead.
7380 char *base_name = NULL;
7381 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7382 ucf_flags_from_smb_request(req);
7384 if (dest_has_wcard) {
7385 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7388 /* newname must *not* be a stream name. */
7389 if (newname[0] == ':') {
7390 return NT_STATUS_NOT_SUPPORTED;
7394 * Strip off the last component (filename) of the path passed
7397 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7399 return NT_STATUS_NO_MEMORY;
7401 p = strrchr_m(base_name, '/');
7405 base_name = talloc_strdup(ctx, "");
7407 return NT_STATUS_NO_MEMORY;
7410 /* Append the new name. */
7411 base_name = talloc_asprintf_append(base_name,
7415 return NT_STATUS_NO_MEMORY;
7418 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7421 /* If an error we expect this to be
7422 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7424 if (!NT_STATUS_IS_OK(status)) {
7425 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7429 /* Create an smb_fname to call rename_internals_fsp() */
7430 smb_fname_dst = synthetic_smb_fname(ctx,
7434 smb_fname_src->flags);
7435 if (smb_fname_dst == NULL) {
7436 status = NT_STATUS_NO_MEMORY;
7443 DEBUG(10,("smb_file_rename_information: "
7444 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7445 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7446 smb_fname_str_dbg(smb_fname_dst)));
7447 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7450 DEBUG(10,("smb_file_rename_information: "
7451 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7452 smb_fname_str_dbg(smb_fname_src),
7453 smb_fname_str_dbg(smb_fname_dst)));
7454 status = rename_internals(ctx, conn, req, smb_fname_src,
7455 smb_fname_dst, 0, overwrite, false,
7457 FILE_WRITE_ATTRIBUTES);
7460 TALLOC_FREE(smb_fname_dst);
7464 /****************************************************************************
7465 Deal with SMB_SET_POSIX_ACL.
7466 ****************************************************************************/
7468 #if defined(HAVE_POSIX_ACLS)
7469 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7470 struct smb_request *req,
7474 const struct smb_filename *smb_fname)
7476 uint16_t posix_acl_version;
7477 uint16_t num_file_acls;
7478 uint16_t num_def_acls;
7479 bool valid_file_acls = true;
7480 bool valid_def_acls = true;
7482 unsigned int size_needed;
7483 unsigned int total_data;
7484 bool close_fsp = false;
7486 if (total_data_in < 0) {
7487 status = NT_STATUS_INVALID_PARAMETER;
7491 total_data = total_data_in;
7493 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7494 status = NT_STATUS_INVALID_PARAMETER;
7497 posix_acl_version = SVAL(pdata,0);
7498 num_file_acls = SVAL(pdata,2);
7499 num_def_acls = SVAL(pdata,4);
7501 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7502 valid_file_acls = false;
7506 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7507 valid_def_acls = false;
7511 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7512 status = NT_STATUS_INVALID_PARAMETER;
7517 if (num_file_acls + num_def_acls < num_file_acls) {
7518 status = NT_STATUS_INVALID_PARAMETER;
7522 size_needed = num_file_acls + num_def_acls;
7525 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7526 * than UINT_MAX, so check by division.
7528 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7529 status = NT_STATUS_INVALID_PARAMETER;
7533 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7534 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7535 status = NT_STATUS_INVALID_PARAMETER;
7538 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7540 if (total_data < size_needed) {
7541 status = NT_STATUS_INVALID_PARAMETER;
7546 * Ensure we always operate on a file descriptor, not just
7550 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7552 SEC_STD_READ_CONTROL|
7553 FILE_READ_ATTRIBUTES|
7554 FILE_WRITE_ATTRIBUTES;
7556 status = get_posix_fsp(conn,
7562 if (!NT_STATUS_IS_OK(status)) {
7568 /* Here we know fsp != NULL */
7569 SMB_ASSERT(fsp != NULL);
7571 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7572 if (!NT_STATUS_IS_OK(status)) {
7576 /* If we have a default acl, this *must* be a directory. */
7577 if (valid_def_acls && !fsp->is_directory) {
7578 DBG_INFO("Can't set default acls on "
7579 "non-directory %s\n",
7581 return NT_STATUS_INVALID_HANDLE;
7584 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7585 "num_def_acls = %"PRIu16"\n",
7590 /* Move pdata to the start of the file ACL entries. */
7591 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7593 if (valid_file_acls) {
7594 status = set_unix_posix_acl(conn,
7598 if (!NT_STATUS_IS_OK(status)) {
7603 /* Move pdata to the start of the default ACL entries. */
7604 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7606 if (valid_def_acls) {
7607 status = set_unix_posix_default_acl(conn,
7611 if (!NT_STATUS_IS_OK(status)) {
7616 status = NT_STATUS_OK;
7621 (void)close_file(req, fsp, NORMAL_CLOSE);
7628 /****************************************************************************
7629 Deal with SMB_SET_POSIX_LOCK.
7630 ****************************************************************************/
7632 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7634 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7635 struct smb_request *req,
7640 struct tevent_req *subreq = NULL;
7641 struct smbd_lock_element *lck = NULL;
7645 bool blocking_lock = False;
7646 enum brl_type lock_type;
7648 NTSTATUS status = NT_STATUS_OK;
7650 if (fsp == NULL || fsp->fh->fd == -1) {
7651 return NT_STATUS_INVALID_HANDLE;
7654 if (total_data != POSIX_LOCK_DATA_SIZE) {
7655 return NT_STATUS_INVALID_PARAMETER;
7658 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7659 case POSIX_LOCK_TYPE_READ:
7660 lock_type = READ_LOCK;
7662 case POSIX_LOCK_TYPE_WRITE:
7663 /* Return the right POSIX-mappable error code for files opened read-only. */
7664 if (!fsp->can_write) {
7665 return NT_STATUS_INVALID_HANDLE;
7667 lock_type = WRITE_LOCK;
7669 case POSIX_LOCK_TYPE_UNLOCK:
7670 lock_type = UNLOCK_LOCK;
7673 return NT_STATUS_INVALID_PARAMETER;
7676 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7677 case POSIX_LOCK_FLAG_NOWAIT:
7678 blocking_lock = false;
7680 case POSIX_LOCK_FLAG_WAIT:
7681 blocking_lock = true;
7684 return NT_STATUS_INVALID_PARAMETER;
7687 if (!lp_blocking_locks(SNUM(conn))) {
7688 blocking_lock = False;
7691 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7692 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7693 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7694 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7695 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7697 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7698 "count = %"PRIu64", offset = %"PRIu64"\n",
7700 (unsigned int)lock_type,
7705 if (lock_type == UNLOCK_LOCK) {
7706 struct smbd_lock_element l = {
7707 .req_guid = smbd_request_guid(req, 0),
7709 .brltype = UNLOCK_LOCK,
7713 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7717 lck = talloc(req, struct smbd_lock_element);
7719 return NT_STATUS_NO_MEMORY;
7722 *lck = (struct smbd_lock_element) {
7723 .req_guid = smbd_request_guid(req, 0),
7725 .brltype = lock_type,
7730 subreq = smbd_smb1_do_locks_send(
7735 blocking_lock ? UINT32_MAX : 0,
7736 true, /* large_offset */
7740 if (subreq == NULL) {
7742 return NT_STATUS_NO_MEMORY;
7744 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7745 return NT_STATUS_EVENT_PENDING;
7748 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7750 struct smb_request *req = NULL;
7754 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7757 status = smbd_smb1_do_locks_recv(subreq);
7758 TALLOC_FREE(subreq);
7760 if (NT_STATUS_IS_OK(status)) {
7761 char params[2] = {0};
7762 /* Fake up max_data_bytes here - we know it fits. */
7763 send_trans2_replies(
7773 reply_nterror(req, status);
7776 (char *)req->outbuf,
7779 IS_CONN_ENCRYPTED(req->conn),
7782 exit_server_cleanly("smb_set_posix_lock_done: "
7783 "srv_send_smb failed.");
7791 /****************************************************************************
7792 Deal with SMB_SET_FILE_BASIC_INFO.
7793 ****************************************************************************/
7795 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7799 const struct smb_filename *smb_fname)
7801 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7802 struct smb_file_time ft;
7803 uint32_t dosmode = 0;
7804 NTSTATUS status = NT_STATUS_OK;
7806 init_smb_file_time(&ft);
7808 if (total_data < 36) {
7809 return NT_STATUS_INVALID_PARAMETER;
7812 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7813 if (!NT_STATUS_IS_OK(status)) {
7817 /* Set the attributes */
7818 dosmode = IVAL(pdata,32);
7819 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7820 if (!NT_STATUS_IS_OK(status)) {
7825 ft.create_time = pull_long_date_full_timespec(pdata);
7828 ft.atime = pull_long_date_full_timespec(pdata+8);
7831 ft.mtime = pull_long_date_full_timespec(pdata+16);
7834 ft.ctime = pull_long_date_full_timespec(pdata+24);
7836 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7837 smb_fname_str_dbg(smb_fname)));
7839 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7840 if (!NT_STATUS_IS_OK(status)) {
7844 if (fsp != NULL && fsp->modified) {
7845 trigger_write_time_update_immediate(fsp);
7847 return NT_STATUS_OK;
7850 /****************************************************************************
7851 Deal with SMB_INFO_STANDARD.
7852 ****************************************************************************/
7854 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7858 const struct smb_filename *smb_fname)
7861 struct smb_file_time ft;
7863 init_smb_file_time(&ft);
7865 if (total_data < 12) {
7866 return NT_STATUS_INVALID_PARAMETER;
7870 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
7872 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
7874 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
7876 DEBUG(10,("smb_set_info_standard: file %s\n",
7877 smb_fname_str_dbg(smb_fname)));
7879 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7880 if (!NT_STATUS_IS_OK(status)) {
7884 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7885 if (!NT_STATUS_IS_OK(status)) {
7889 if (fsp != NULL && fsp->modified) {
7890 trigger_write_time_update_immediate(fsp);
7892 return NT_STATUS_OK;
7895 /****************************************************************************
7896 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7897 ****************************************************************************/
7899 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7900 struct smb_request *req,
7904 struct smb_filename *smb_fname)
7906 uint64_t allocation_size = 0;
7907 NTSTATUS status = NT_STATUS_OK;
7908 files_struct *new_fsp = NULL;
7910 if (!VALID_STAT(smb_fname->st)) {
7911 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7914 if (total_data < 8) {
7915 return NT_STATUS_INVALID_PARAMETER;
7918 allocation_size = (uint64_t)IVAL(pdata,0);
7919 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7920 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7921 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7922 (double)allocation_size));
7924 if (allocation_size) {
7925 allocation_size = smb_roundup(conn, allocation_size);
7928 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7929 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7930 (double)allocation_size));
7932 if (fsp && fsp->fh->fd != -1) {
7933 /* Open file handle. */
7934 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7935 return NT_STATUS_ACCESS_DENIED;
7938 /* Only change if needed. */
7939 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7940 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7941 return map_nt_error_from_unix(errno);
7944 /* But always update the time. */
7946 * This is equivalent to a write. Ensure it's seen immediately
7947 * if there are no pending writes.
7949 trigger_write_time_update_immediate(fsp);
7950 return NT_STATUS_OK;
7953 /* Pathname or stat or directory file. */
7954 status = SMB_VFS_CREATE_FILE(
7957 0, /* root_dir_fid */
7958 smb_fname, /* fname */
7959 FILE_WRITE_DATA, /* access_mask */
7960 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7962 FILE_OPEN, /* create_disposition*/
7963 0, /* create_options */
7964 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7965 0, /* oplock_request */
7967 0, /* allocation_size */
7968 0, /* private_flags */
7971 &new_fsp, /* result */
7973 NULL, NULL); /* create context */
7975 if (!NT_STATUS_IS_OK(status)) {
7976 /* NB. We check for open_was_deferred in the caller. */
7980 /* Only change if needed. */
7981 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7982 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7983 status = map_nt_error_from_unix(errno);
7984 close_file(req, new_fsp, NORMAL_CLOSE);
7989 /* Changing the allocation size should set the last mod time. */
7991 * This is equivalent to a write. Ensure it's seen immediately
7992 * if there are no pending writes.
7994 trigger_write_time_update_immediate(new_fsp);
7995 close_file(req, new_fsp, NORMAL_CLOSE);
7996 return NT_STATUS_OK;
7999 /****************************************************************************
8000 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
8001 ****************************************************************************/
8003 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
8004 struct smb_request *req,
8008 const struct smb_filename *smb_fname,
8009 bool fail_after_createfile)
8013 if (total_data < 8) {
8014 return NT_STATUS_INVALID_PARAMETER;
8017 size = IVAL(pdata,0);
8018 size |= (((off_t)IVAL(pdata,4)) << 32);
8019 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
8020 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
8023 return smb_set_file_size(conn, req,
8028 fail_after_createfile);
8031 /****************************************************************************
8032 Allow a UNIX info mknod.
8033 ****************************************************************************/
8035 static NTSTATUS smb_unix_mknod(connection_struct *conn,
8038 const struct smb_filename *smb_fname)
8040 uint32_t file_type = IVAL(pdata,56);
8041 #if defined(HAVE_MAKEDEV)
8042 uint32_t dev_major = IVAL(pdata,60);
8043 uint32_t dev_minor = IVAL(pdata,68);
8045 SMB_DEV_T dev = (SMB_DEV_T)0;
8046 uint32_t raw_unixmode = IVAL(pdata,84);
8051 if (total_data < 100) {
8052 return NT_STATUS_INVALID_PARAMETER;
8055 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8056 PERM_NEW_FILE, &unixmode);
8057 if (!NT_STATUS_IS_OK(status)) {
8061 #if defined(HAVE_MAKEDEV)
8062 dev = makedev(dev_major, dev_minor);
8065 switch (file_type) {
8066 /* We can't create other objects here. */
8067 case UNIX_TYPE_FILE:
8069 case UNIX_TYPE_SYMLINK:
8070 return NT_STATUS_ACCESS_DENIED;
8071 #if defined(S_IFIFO)
8072 case UNIX_TYPE_FIFO:
8073 unixmode |= S_IFIFO;
8076 #if defined(S_IFSOCK)
8077 case UNIX_TYPE_SOCKET:
8078 unixmode |= S_IFSOCK;
8081 #if defined(S_IFCHR)
8082 case UNIX_TYPE_CHARDEV:
8083 /* This is only allowed for root. */
8084 if (get_current_uid(conn) != sec_initial_uid()) {
8085 return NT_STATUS_ACCESS_DENIED;
8087 unixmode |= S_IFCHR;
8090 #if defined(S_IFBLK)
8091 case UNIX_TYPE_BLKDEV:
8092 if (get_current_uid(conn) != sec_initial_uid()) {
8093 return NT_STATUS_ACCESS_DENIED;
8095 unixmode |= S_IFBLK;
8099 return NT_STATUS_INVALID_PARAMETER;
8102 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8103 "%.0f mode 0%o for file %s\n", (double)dev,
8104 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8106 /* Ok - do the mknod. */
8107 ret = SMB_VFS_MKNODAT(conn,
8114 return map_nt_error_from_unix(errno);
8117 /* If any of the other "set" calls fail we
8118 * don't want to end up with a half-constructed mknod.
8121 if (lp_inherit_permissions(SNUM(conn))) {
8123 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
8125 return NT_STATUS_NO_MEMORY;
8127 inherit_access_posix_acl(conn, parent, smb_fname,
8129 TALLOC_FREE(parent);
8132 return NT_STATUS_OK;
8135 /****************************************************************************
8136 Deal with SMB_SET_FILE_UNIX_BASIC.
8137 ****************************************************************************/
8139 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8140 struct smb_request *req,
8144 const struct smb_filename *smb_fname)
8146 struct smb_file_time ft;
8147 uint32_t raw_unixmode;
8150 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8151 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8152 NTSTATUS status = NT_STATUS_OK;
8153 enum perm_type ptype;
8154 files_struct *all_fsps = NULL;
8155 bool modify_mtime = true;
8157 SMB_STRUCT_STAT sbuf;
8159 init_smb_file_time(&ft);
8161 if (total_data < 100) {
8162 return NT_STATUS_INVALID_PARAMETER;
8165 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8166 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8167 size=IVAL(pdata,0); /* first 8 Bytes are size */
8168 size |= (((off_t)IVAL(pdata,4)) << 32);
8171 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
8172 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
8173 set_owner = (uid_t)IVAL(pdata,40);
8174 set_grp = (gid_t)IVAL(pdata,48);
8175 raw_unixmode = IVAL(pdata,84);
8177 if (VALID_STAT(smb_fname->st)) {
8178 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8179 ptype = PERM_EXISTING_DIR;
8181 ptype = PERM_EXISTING_FILE;
8184 ptype = PERM_NEW_FILE;
8187 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8189 if (!NT_STATUS_IS_OK(status)) {
8193 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8194 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8195 smb_fname_str_dbg(smb_fname), (double)size,
8196 (unsigned int)set_owner, (unsigned int)set_grp,
8197 (int)raw_unixmode));
8199 sbuf = smb_fname->st;
8201 if (!VALID_STAT(sbuf)) {
8203 * The only valid use of this is to create character and block
8204 * devices, and named pipes. This is deprecated (IMHO) and
8205 * a new info level should be used for mknod. JRA.
8208 return smb_unix_mknod(conn,
8215 /* Horrible backwards compatibility hack as an old server bug
8216 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8220 size = get_file_size_stat(&sbuf);
8225 * Deal with the UNIX specific mode set.
8228 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8231 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8232 "setting mode 0%o for file %s\n",
8233 (unsigned int)unixmode,
8234 smb_fname_str_dbg(smb_fname)));
8235 if (fsp && fsp->fh->fd != -1) {
8236 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8238 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8241 return map_nt_error_from_unix(errno);
8246 * Deal with the UNIX specific uid set.
8249 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8250 (sbuf.st_ex_uid != set_owner)) {
8253 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8254 "changing owner %u for path %s\n",
8255 (unsigned int)set_owner,
8256 smb_fname_str_dbg(smb_fname)));
8258 if (fsp && fsp->fh->fd != -1) {
8259 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8262 * UNIX extensions calls must always operate
8265 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8266 set_owner, (gid_t)-1);
8270 status = map_nt_error_from_unix(errno);
8276 * Deal with the UNIX specific gid set.
8279 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8280 (sbuf.st_ex_gid != set_grp)) {
8283 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8284 "changing group %u for file %s\n",
8285 (unsigned int)set_grp,
8286 smb_fname_str_dbg(smb_fname)));
8287 if (fsp && fsp->fh->fd != -1) {
8288 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8291 * UNIX extensions calls must always operate
8294 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8298 status = map_nt_error_from_unix(errno);
8303 /* Deal with any size changes. */
8305 if (S_ISREG(sbuf.st_ex_mode)) {
8306 status = smb_set_file_size(conn, req,
8312 if (!NT_STATUS_IS_OK(status)) {
8317 /* Deal with any time changes. */
8318 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
8319 /* No change, don't cancel anything. */
8323 id = vfs_file_id_from_sbuf(conn, &sbuf);
8324 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8325 all_fsps = file_find_di_next(all_fsps)) {
8327 * We're setting the time explicitly for UNIX.
8328 * Cancel any pending changes over all handles.
8330 all_fsps->update_write_time_on_close = false;
8331 TALLOC_FREE(all_fsps->update_write_time_event);
8335 * Override the "setting_write_time"
8336 * parameter here as it almost does what
8337 * we need. Just remember if we modified
8338 * mtime and send the notify ourselves.
8340 if (is_omit_timespec(&ft.mtime)) {
8341 modify_mtime = false;
8344 status = smb_set_file_time(conn,
8350 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8351 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8356 /****************************************************************************
8357 Deal with SMB_SET_FILE_UNIX_INFO2.
8358 ****************************************************************************/
8360 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8361 struct smb_request *req,
8365 const struct smb_filename *smb_fname)
8368 uint32_t smb_fflags;
8371 if (total_data < 116) {
8372 return NT_STATUS_INVALID_PARAMETER;
8375 /* Start by setting all the fields that are common between UNIX_BASIC
8378 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8380 if (!NT_STATUS_IS_OK(status)) {
8384 smb_fflags = IVAL(pdata, 108);
8385 smb_fmask = IVAL(pdata, 112);
8387 /* NB: We should only attempt to alter the file flags if the client
8388 * sends a non-zero mask.
8390 if (smb_fmask != 0) {
8391 int stat_fflags = 0;
8393 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8394 smb_fmask, &stat_fflags)) {
8395 /* Client asked to alter a flag we don't understand. */
8396 return NT_STATUS_INVALID_PARAMETER;
8399 if (fsp && fsp->fh->fd != -1) {
8400 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8401 return NT_STATUS_NOT_SUPPORTED;
8403 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8404 stat_fflags) != 0) {
8405 return map_nt_error_from_unix(errno);
8410 /* XXX: need to add support for changing the create_time here. You
8411 * can do this for paths on Darwin with setattrlist(2). The right way
8412 * to hook this up is probably by extending the VFS utimes interface.
8415 return NT_STATUS_OK;
8418 /****************************************************************************
8419 Create a directory with POSIX semantics.
8420 ****************************************************************************/
8422 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8423 struct smb_request *req,
8426 struct smb_filename *smb_fname,
8427 int *pdata_return_size)
8429 NTSTATUS status = NT_STATUS_OK;
8430 uint32_t raw_unixmode = 0;
8431 mode_t unixmode = (mode_t)0;
8432 files_struct *fsp = NULL;
8433 uint16_t info_level_return = 0;
8435 char *pdata = *ppdata;
8436 struct smb2_create_blobs *posx = NULL;
8438 if (total_data < 18) {
8439 return NT_STATUS_INVALID_PARAMETER;
8442 raw_unixmode = IVAL(pdata,8);
8443 /* Next 4 bytes are not yet defined. */
8445 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8446 PERM_NEW_DIR, &unixmode);
8447 if (!NT_STATUS_IS_OK(status)) {
8451 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8452 if (!NT_STATUS_IS_OK(status)) {
8453 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8458 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8459 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8461 status = SMB_VFS_CREATE_FILE(
8464 0, /* root_dir_fid */
8465 smb_fname, /* fname */
8466 FILE_READ_ATTRIBUTES, /* access_mask */
8467 FILE_SHARE_NONE, /* share_access */
8468 FILE_CREATE, /* create_disposition*/
8469 FILE_DIRECTORY_FILE, /* create_options */
8470 0, /* file_attributes */
8471 0, /* oplock_request */
8473 0, /* allocation_size */
8474 0, /* private_flags */
8479 posx, /* in_context_blobs */
8480 NULL); /* out_context_blobs */
8484 if (NT_STATUS_IS_OK(status)) {
8485 close_file(req, fsp, NORMAL_CLOSE);
8488 info_level_return = SVAL(pdata,16);
8490 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8491 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8492 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8493 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8495 *pdata_return_size = 12;
8498 /* Realloc the data size */
8499 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8500 if (*ppdata == NULL) {
8501 *pdata_return_size = 0;
8502 return NT_STATUS_NO_MEMORY;
8506 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8507 SSVAL(pdata,2,0); /* No fnum. */
8508 SIVAL(pdata,4,info); /* Was directory created. */
8510 switch (info_level_return) {
8511 case SMB_QUERY_FILE_UNIX_BASIC:
8512 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8513 SSVAL(pdata,10,0); /* Padding. */
8514 store_file_unix_basic(conn, pdata + 12, fsp,
8517 case SMB_QUERY_FILE_UNIX_INFO2:
8518 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8519 SSVAL(pdata,10,0); /* Padding. */
8520 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8524 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8525 SSVAL(pdata,10,0); /* Padding. */
8532 /****************************************************************************
8533 Open/Create a file with POSIX semantics.
8534 ****************************************************************************/
8536 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8537 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8539 static NTSTATUS smb_posix_open(connection_struct *conn,
8540 struct smb_request *req,
8543 struct smb_filename *smb_fname,
8544 int *pdata_return_size)
8546 bool extended_oplock_granted = False;
8547 char *pdata = *ppdata;
8549 uint32_t wire_open_mode = 0;
8550 uint32_t raw_unixmode = 0;
8551 uint32_t attributes = 0;
8552 uint32_t create_disp = 0;
8553 uint32_t access_mask = 0;
8554 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8555 NTSTATUS status = NT_STATUS_OK;
8556 mode_t unixmode = (mode_t)0;
8557 files_struct *fsp = NULL;
8558 int oplock_request = 0;
8560 uint16_t info_level_return = 0;
8561 struct smb2_create_blobs *posx = NULL;
8563 if (total_data < 18) {
8564 return NT_STATUS_INVALID_PARAMETER;
8567 flags = IVAL(pdata,0);
8568 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8569 if (oplock_request) {
8570 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8573 wire_open_mode = IVAL(pdata,4);
8575 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8576 return smb_posix_mkdir(conn, req,
8583 switch (wire_open_mode & SMB_ACCMODE) {
8585 access_mask = SMB_O_RDONLY_MAPPING;
8588 access_mask = SMB_O_WRONLY_MAPPING;
8591 access_mask = (SMB_O_RDONLY_MAPPING|
8592 SMB_O_WRONLY_MAPPING);
8595 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8596 (unsigned int)wire_open_mode ));
8597 return NT_STATUS_INVALID_PARAMETER;
8600 wire_open_mode &= ~SMB_ACCMODE;
8602 /* First take care of O_CREAT|O_EXCL interactions. */
8603 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8604 case (SMB_O_CREAT | SMB_O_EXCL):
8605 /* File exists fail. File not exist create. */
8606 create_disp = FILE_CREATE;
8609 /* File exists open. File not exist create. */
8610 create_disp = FILE_OPEN_IF;
8613 /* O_EXCL on its own without O_CREAT is undefined.
8614 We deliberately ignore it as some versions of
8615 Linux CIFSFS can send a bare O_EXCL on the
8616 wire which other filesystems in the kernel
8617 ignore. See bug 9519 for details. */
8622 /* File exists open. File not exist fail. */
8623 create_disp = FILE_OPEN;
8626 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8627 (unsigned int)wire_open_mode ));
8628 return NT_STATUS_INVALID_PARAMETER;
8631 /* Next factor in the effects of O_TRUNC. */
8632 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8634 if (wire_open_mode & SMB_O_TRUNC) {
8635 switch (create_disp) {
8637 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8638 /* Leave create_disp alone as
8639 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8641 /* File exists fail. File not exist create. */
8644 /* SMB_O_CREAT | SMB_O_TRUNC */
8645 /* File exists overwrite. File not exist create. */
8646 create_disp = FILE_OVERWRITE_IF;
8650 /* File exists overwrite. File not exist fail. */
8651 create_disp = FILE_OVERWRITE;
8654 /* Cannot get here. */
8655 smb_panic("smb_posix_open: logic error");
8656 return NT_STATUS_INVALID_PARAMETER;
8660 raw_unixmode = IVAL(pdata,8);
8661 /* Next 4 bytes are not yet defined. */
8663 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8664 (VALID_STAT(smb_fname->st) ?
8665 PERM_EXISTING_FILE : PERM_NEW_FILE),
8668 if (!NT_STATUS_IS_OK(status)) {
8672 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8673 if (!NT_STATUS_IS_OK(status)) {
8674 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8679 if (wire_open_mode & SMB_O_SYNC) {
8680 create_options |= FILE_WRITE_THROUGH;
8682 if (wire_open_mode & SMB_O_APPEND) {
8683 access_mask |= FILE_APPEND_DATA;
8685 if (wire_open_mode & SMB_O_DIRECT) {
8686 attributes |= FILE_FLAG_NO_BUFFERING;
8689 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8690 VALID_STAT_OF_DIR(smb_fname->st)) {
8691 if (access_mask != SMB_O_RDONLY_MAPPING) {
8692 return NT_STATUS_FILE_IS_A_DIRECTORY;
8694 create_options &= ~FILE_NON_DIRECTORY_FILE;
8695 create_options |= FILE_DIRECTORY_FILE;
8698 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8699 smb_fname_str_dbg(smb_fname),
8700 (unsigned int)wire_open_mode,
8701 (unsigned int)unixmode ));
8703 status = SMB_VFS_CREATE_FILE(
8706 0, /* root_dir_fid */
8707 smb_fname, /* fname */
8708 access_mask, /* access_mask */
8709 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8711 create_disp, /* create_disposition*/
8712 create_options, /* create_options */
8713 attributes, /* file_attributes */
8714 oplock_request, /* oplock_request */
8716 0, /* allocation_size */
8717 0, /* private_flags */
8722 posx, /* in_context_blobs */
8723 NULL); /* out_context_blobs */
8727 if (!NT_STATUS_IS_OK(status)) {
8731 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8732 extended_oplock_granted = True;
8735 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8736 extended_oplock_granted = True;
8739 info_level_return = SVAL(pdata,16);
8741 /* Allocate the correct return size. */
8743 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8744 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8745 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8746 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8748 *pdata_return_size = 12;
8751 /* Realloc the data size */
8752 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8753 if (*ppdata == NULL) {
8754 close_file(req, fsp, ERROR_CLOSE);
8755 *pdata_return_size = 0;
8756 return NT_STATUS_NO_MEMORY;
8760 if (extended_oplock_granted) {
8761 if (flags & REQUEST_BATCH_OPLOCK) {
8762 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8764 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8766 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8767 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8769 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8772 SSVAL(pdata,2,fsp->fnum);
8773 SIVAL(pdata,4,info); /* Was file created etc. */
8775 switch (info_level_return) {
8776 case SMB_QUERY_FILE_UNIX_BASIC:
8777 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8778 SSVAL(pdata,10,0); /* padding. */
8779 store_file_unix_basic(conn, pdata + 12, fsp,
8782 case SMB_QUERY_FILE_UNIX_INFO2:
8783 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8784 SSVAL(pdata,10,0); /* padding. */
8785 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8789 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8790 SSVAL(pdata,10,0); /* padding. */
8793 return NT_STATUS_OK;
8796 /****************************************************************************
8797 Delete a file with POSIX semantics.
8798 ****************************************************************************/
8800 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8801 struct smb_request *req,
8804 struct smb_filename *smb_fname)
8806 NTSTATUS status = NT_STATUS_OK;
8807 files_struct *fsp = NULL;
8811 int create_options = 0;
8812 struct share_mode_lock *lck = NULL;
8813 bool other_nonposix_opens;
8814 struct smb2_create_blobs *posx = NULL;
8816 if (total_data < 2) {
8817 return NT_STATUS_INVALID_PARAMETER;
8820 flags = SVAL(pdata,0);
8822 if (!VALID_STAT(smb_fname->st)) {
8823 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8826 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8827 !VALID_STAT_OF_DIR(smb_fname->st)) {
8828 return NT_STATUS_NOT_A_DIRECTORY;
8831 DEBUG(10,("smb_posix_unlink: %s %s\n",
8832 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8833 smb_fname_str_dbg(smb_fname)));
8835 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8836 create_options |= FILE_DIRECTORY_FILE;
8839 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8840 if (!NT_STATUS_IS_OK(status)) {
8841 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8846 status = SMB_VFS_CREATE_FILE(
8849 0, /* root_dir_fid */
8850 smb_fname, /* fname */
8851 DELETE_ACCESS, /* access_mask */
8852 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8854 FILE_OPEN, /* create_disposition*/
8855 create_options, /* create_options */
8856 0, /* file_attributes */
8857 0, /* oplock_request */
8859 0, /* allocation_size */
8860 0, /* private_flags */
8865 posx, /* in_context_blobs */
8866 NULL); /* out_context_blobs */
8870 if (!NT_STATUS_IS_OK(status)) {
8875 * Don't lie to client. If we can't really delete due to
8876 * non-POSIX opens return SHARING_VIOLATION.
8879 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8881 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8882 "lock for file %s\n", fsp_str_dbg(fsp)));
8883 close_file(req, fsp, NORMAL_CLOSE);
8884 return NT_STATUS_INVALID_PARAMETER;
8887 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8888 if (other_nonposix_opens) {
8889 /* Fail with sharing violation. */
8891 close_file(req, fsp, NORMAL_CLOSE);
8892 return NT_STATUS_SHARING_VIOLATION;
8896 * Set the delete on close.
8898 status = smb_set_file_disposition_info(conn,
8906 if (!NT_STATUS_IS_OK(status)) {
8907 close_file(req, fsp, NORMAL_CLOSE);
8910 return close_file(req, fsp, NORMAL_CLOSE);
8913 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8914 struct smb_request *req,
8915 TALLOC_CTX *mem_ctx,
8916 uint16_t info_level,
8918 struct smb_filename *smb_fname,
8919 char **ppdata, int total_data,
8922 char *pdata = *ppdata;
8923 NTSTATUS status = NT_STATUS_OK;
8924 int data_return_size = 0;
8928 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8929 return NT_STATUS_INVALID_LEVEL;
8932 if (!CAN_WRITE(conn)) {
8933 /* Allow POSIX opens. The open path will deny
8934 * any non-readonly opens. */
8935 if (info_level != SMB_POSIX_PATH_OPEN) {
8936 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8940 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8941 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8943 info_level, total_data));
8945 switch (info_level) {
8947 case SMB_INFO_STANDARD:
8949 status = smb_set_info_standard(conn,
8957 case SMB_INFO_SET_EA:
8959 status = smb_info_set_ea(conn,
8967 case SMB_SET_FILE_BASIC_INFO:
8968 case SMB_FILE_BASIC_INFORMATION:
8970 status = smb_set_file_basic_info(conn,
8978 case SMB_FILE_ALLOCATION_INFORMATION:
8979 case SMB_SET_FILE_ALLOCATION_INFO:
8981 status = smb_set_file_allocation_info(conn, req,
8989 case SMB_FILE_END_OF_FILE_INFORMATION:
8990 case SMB_SET_FILE_END_OF_FILE_INFO:
8993 * XP/Win7 both fail after the createfile with
8994 * SMB_SET_FILE_END_OF_FILE_INFO but not
8995 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8996 * The level is known here, so pass it down
9000 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
9002 status = smb_set_file_end_of_file_info(conn, req,
9011 case SMB_FILE_DISPOSITION_INFORMATION:
9012 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
9015 /* JRA - We used to just ignore this on a path ?
9016 * Shouldn't this be invalid level on a pathname
9019 if (tran_call != TRANSACT2_SETFILEINFO) {
9020 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
9023 status = smb_set_file_disposition_info(conn,
9031 case SMB_FILE_POSITION_INFORMATION:
9033 status = smb_file_position_information(conn,
9040 case SMB_FILE_FULL_EA_INFORMATION:
9042 status = smb_set_file_full_ea_info(conn,
9049 /* From tridge Samba4 :
9050 * MODE_INFORMATION in setfileinfo (I have no
9051 * idea what "mode information" on a file is - it takes a value of 0,
9052 * 2, 4 or 6. What could it be?).
9055 case SMB_FILE_MODE_INFORMATION:
9057 status = smb_file_mode_information(conn,
9063 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9064 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9065 case SMB_FILE_SHORT_NAME_INFORMATION:
9066 return NT_STATUS_NOT_SUPPORTED;
9069 * CIFS UNIX extensions.
9072 case SMB_SET_FILE_UNIX_BASIC:
9074 status = smb_set_file_unix_basic(conn, req,
9082 case SMB_SET_FILE_UNIX_INFO2:
9084 status = smb_set_file_unix_info2(conn, req,
9092 case SMB_SET_FILE_UNIX_LINK:
9095 /* We must have a pathname for this. */
9096 return NT_STATUS_INVALID_LEVEL;
9098 status = smb_set_file_unix_link(conn, req, pdata,
9099 total_data, smb_fname);
9103 case SMB_SET_FILE_UNIX_HLINK:
9106 /* We must have a pathname for this. */
9107 return NT_STATUS_INVALID_LEVEL;
9109 status = smb_set_file_unix_hlink(conn, req,
9115 case SMB_FILE_RENAME_INFORMATION:
9117 status = smb_file_rename_information(conn, req,
9123 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9125 /* SMB2 rename information. */
9126 status = smb2_file_rename_information(conn, req,
9132 case SMB_FILE_LINK_INFORMATION:
9134 status = smb_file_link_information(conn, req,
9140 #if defined(HAVE_POSIX_ACLS)
9141 case SMB_SET_POSIX_ACL:
9143 status = smb_set_posix_acl(conn,
9153 case SMB_SET_POSIX_LOCK:
9156 return NT_STATUS_INVALID_LEVEL;
9158 status = smb_set_posix_lock(conn, req,
9159 pdata, total_data, fsp);
9163 case SMB_POSIX_PATH_OPEN:
9166 /* We must have a pathname for this. */
9167 return NT_STATUS_INVALID_LEVEL;
9170 status = smb_posix_open(conn, req,
9178 case SMB_POSIX_PATH_UNLINK:
9181 /* We must have a pathname for this. */
9182 return NT_STATUS_INVALID_LEVEL;
9185 status = smb_posix_unlink(conn, req,
9193 return NT_STATUS_INVALID_LEVEL;
9196 if (!NT_STATUS_IS_OK(status)) {
9200 *ret_data_size = data_return_size;
9201 return NT_STATUS_OK;
9204 /****************************************************************************
9205 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9206 ****************************************************************************/
9208 static void call_trans2setfilepathinfo(connection_struct *conn,
9209 struct smb_request *req,
9210 unsigned int tran_call,
9211 char **pparams, int total_params,
9212 char **ppdata, int total_data,
9213 unsigned int max_data_bytes)
9215 char *params = *pparams;
9216 char *pdata = *ppdata;
9217 uint16_t info_level;
9218 struct smb_filename *smb_fname = NULL;
9219 files_struct *fsp = NULL;
9220 NTSTATUS status = NT_STATUS_OK;
9221 int data_return_size = 0;
9224 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9228 if (tran_call == TRANSACT2_SETFILEINFO) {
9229 if (total_params < 4) {
9230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9234 fsp = file_fsp(req, SVAL(params,0));
9235 /* Basic check for non-null fsp. */
9236 if (!check_fsp_open(conn, req, fsp)) {
9239 info_level = SVAL(params,2);
9241 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9242 if (smb_fname == NULL) {
9243 reply_nterror(req, NT_STATUS_NO_MEMORY);
9247 if(fsp->fh->fd == -1) {
9249 * This is actually a SETFILEINFO on a directory
9250 * handle (returned from an NT SMB). NT5.0 seems
9251 * to do this call. JRA.
9253 if (INFO_LEVEL_IS_UNIX(info_level)) {
9254 /* Always do lstat for UNIX calls. */
9255 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9256 DEBUG(3,("call_trans2setfilepathinfo: "
9257 "SMB_VFS_LSTAT of %s failed "
9259 smb_fname_str_dbg(smb_fname),
9261 reply_nterror(req, map_nt_error_from_unix(errno));
9265 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9266 DEBUG(3,("call_trans2setfilepathinfo: "
9267 "fileinfo of %s failed (%s)\n",
9268 smb_fname_str_dbg(smb_fname),
9270 reply_nterror(req, map_nt_error_from_unix(errno));
9274 } else if (fsp->print_file) {
9276 * Doing a DELETE_ON_CLOSE should cancel a print job.
9278 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9279 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9281 DEBUG(3,("call_trans2setfilepathinfo: "
9282 "Cancelling print job (%s)\n",
9286 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9292 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9297 * Original code - this is an open file.
9299 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9300 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9301 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9303 reply_nterror(req, map_nt_error_from_unix(errno));
9309 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9312 if (total_params < 7) {
9313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9317 info_level = SVAL(params,0);
9318 if (req->posix_pathnames) {
9319 srvstr_get_path_posix(req,
9328 srvstr_get_path(req,
9337 if (!NT_STATUS_IS_OK(status)) {
9338 reply_nterror(req, status);
9342 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9343 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9344 info_level == SMB_FILE_RENAME_INFORMATION ||
9345 info_level == SMB_POSIX_PATH_OPEN ||
9346 info_level == SMB_POSIX_PATH_UNLINK) {
9347 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9350 status = filename_convert(req, conn,
9356 if (!NT_STATUS_IS_OK(status)) {
9357 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9358 reply_botherror(req,
9359 NT_STATUS_PATH_NOT_COVERED,
9360 ERRSRV, ERRbadpath);
9363 reply_nterror(req, status);
9367 if (INFO_LEVEL_IS_UNIX(info_level)) {
9369 * For CIFS UNIX extensions the target name may not exist.
9372 /* Always do lstat for UNIX calls. */
9373 SMB_VFS_LSTAT(conn, smb_fname);
9375 } else if (!VALID_STAT(smb_fname->st) &&
9376 SMB_VFS_STAT(conn, smb_fname)) {
9377 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9379 smb_fname_str_dbg(smb_fname),
9381 reply_nterror(req, map_nt_error_from_unix(errno));
9386 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9387 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9389 info_level,total_data));
9391 /* Realloc the parameter size */
9392 *pparams = (char *)SMB_REALLOC(*pparams,2);
9393 if (*pparams == NULL) {
9394 reply_nterror(req, NT_STATUS_NO_MEMORY);
9401 status = smbd_do_setfilepathinfo(conn, req, req,
9407 if (!NT_STATUS_IS_OK(status)) {
9408 if (open_was_deferred(req->xconn, req->mid)) {
9409 /* We have re-scheduled this call. */
9412 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9413 bool ok = defer_smb1_sharing_violation(req);
9418 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9419 /* We have re-scheduled this call. */
9422 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9423 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9424 ERRSRV, ERRbadpath);
9427 if (info_level == SMB_POSIX_PATH_OPEN) {
9428 reply_openerror(req, status);
9433 * Invalid EA name needs to return 2 param bytes,
9434 * not a zero-length error packet.
9436 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9437 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9440 reply_nterror(req, status);
9445 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9451 /****************************************************************************
9452 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9453 ****************************************************************************/
9455 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9456 char **pparams, int total_params,
9457 char **ppdata, int total_data,
9458 unsigned int max_data_bytes)
9460 struct smb_filename *smb_dname = NULL;
9461 char *params = *pparams;
9462 char *pdata = *ppdata;
9463 char *directory = NULL;
9464 NTSTATUS status = NT_STATUS_OK;
9465 struct ea_list *ea_list = NULL;
9466 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9467 TALLOC_CTX *ctx = talloc_tos();
9469 if (!CAN_WRITE(conn)) {
9470 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9474 if (total_params < 5) {
9475 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9479 if (req->posix_pathnames) {
9480 srvstr_get_path_posix(ctx,
9489 srvstr_get_path(ctx,
9498 if (!NT_STATUS_IS_OK(status)) {
9499 reply_nterror(req, status);
9503 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9505 status = filename_convert(ctx,
9513 if (!NT_STATUS_IS_OK(status)) {
9514 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9515 reply_botherror(req,
9516 NT_STATUS_PATH_NOT_COVERED,
9517 ERRSRV, ERRbadpath);
9520 reply_nterror(req, status);
9525 * OS/2 workplace shell seems to send SET_EA requests of "null"
9526 * length (4 bytes containing IVAL 4).
9527 * They seem to have no effect. Bug #3212. JRA.
9530 if (total_data && (total_data != 4)) {
9531 /* Any data in this call is an EA list. */
9532 if (total_data < 10) {
9533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9537 if (IVAL(pdata,0) > total_data) {
9538 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9539 IVAL(pdata,0), (unsigned int)total_data));
9540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9544 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9547 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9551 if (!lp_ea_support(SNUM(conn))) {
9552 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9556 /* If total_data == 4 Windows doesn't care what values
9557 * are placed in that field, it just ignores them.
9558 * The System i QNTC IBM SMB client puts bad values here,
9559 * so ignore them. */
9561 status = create_directory(conn, req, smb_dname);
9563 if (!NT_STATUS_IS_OK(status)) {
9564 reply_nterror(req, status);
9568 /* Try and set any given EA. */
9570 status = set_ea(conn, NULL, smb_dname, ea_list);
9571 if (!NT_STATUS_IS_OK(status)) {
9572 reply_nterror(req, status);
9577 /* Realloc the parameter and data sizes */
9578 *pparams = (char *)SMB_REALLOC(*pparams,2);
9579 if(*pparams == NULL) {
9580 reply_nterror(req, NT_STATUS_NO_MEMORY);
9587 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9590 TALLOC_FREE(smb_dname);
9594 /****************************************************************************
9595 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9596 We don't actually do this - we just send a null response.
9597 ****************************************************************************/
9599 static void call_trans2findnotifyfirst(connection_struct *conn,
9600 struct smb_request *req,
9601 char **pparams, int total_params,
9602 char **ppdata, int total_data,
9603 unsigned int max_data_bytes)
9605 char *params = *pparams;
9606 uint16_t info_level;
9608 if (total_params < 6) {
9609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9613 info_level = SVAL(params,4);
9614 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9616 switch (info_level) {
9621 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9625 /* Realloc the parameter and data sizes */
9626 *pparams = (char *)SMB_REALLOC(*pparams,6);
9627 if (*pparams == NULL) {
9628 reply_nterror(req, NT_STATUS_NO_MEMORY);
9633 SSVAL(params,0,fnf_handle);
9634 SSVAL(params,2,0); /* No changes */
9635 SSVAL(params,4,0); /* No EA errors */
9642 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9647 /****************************************************************************
9648 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9649 changes). Currently this does nothing.
9650 ****************************************************************************/
9652 static void call_trans2findnotifynext(connection_struct *conn,
9653 struct smb_request *req,
9654 char **pparams, int total_params,
9655 char **ppdata, int total_data,
9656 unsigned int max_data_bytes)
9658 char *params = *pparams;
9660 DEBUG(3,("call_trans2findnotifynext\n"));
9662 /* Realloc the parameter and data sizes */
9663 *pparams = (char *)SMB_REALLOC(*pparams,4);
9664 if (*pparams == NULL) {
9665 reply_nterror(req, NT_STATUS_NO_MEMORY);
9670 SSVAL(params,0,0); /* No changes */
9671 SSVAL(params,2,0); /* No EA errors */
9673 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9678 /****************************************************************************
9679 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9680 ****************************************************************************/
9682 static void call_trans2getdfsreferral(connection_struct *conn,
9683 struct smb_request *req,
9684 char **pparams, int total_params,
9685 char **ppdata, int total_data,
9686 unsigned int max_data_bytes)
9688 char *params = *pparams;
9689 char *pathname = NULL;
9691 int max_referral_level;
9692 NTSTATUS status = NT_STATUS_OK;
9693 TALLOC_CTX *ctx = talloc_tos();
9695 DEBUG(10,("call_trans2getdfsreferral\n"));
9697 if (total_params < 3) {
9698 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9702 max_referral_level = SVAL(params,0);
9704 if(!lp_host_msdfs()) {
9705 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9709 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9710 total_params - 2, STR_TERMINATE);
9712 reply_nterror(req, NT_STATUS_NOT_FOUND);
9715 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9716 ppdata,&status)) < 0) {
9717 reply_nterror(req, status);
9721 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9722 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9723 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9728 #define LMCAT_SPL 0x53
9729 #define LMFUNC_GETJOBID 0x60
9731 /****************************************************************************
9732 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9733 ****************************************************************************/
9735 static void call_trans2ioctl(connection_struct *conn,
9736 struct smb_request *req,
9737 char **pparams, int total_params,
9738 char **ppdata, int total_data,
9739 unsigned int max_data_bytes)
9741 const struct loadparm_substitution *lp_sub =
9742 loadparm_s3_global_substitution();
9743 char *pdata = *ppdata;
9744 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9748 /* check for an invalid fid before proceeding */
9751 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9755 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9756 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9757 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9758 if (*ppdata == NULL) {
9759 reply_nterror(req, NT_STATUS_NO_MEMORY);
9764 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9765 CAN ACCEPT THIS IN UNICODE. JRA. */
9768 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9770 status = srvstr_push(pdata, req->flags2, pdata + 2,
9771 lp_netbios_name(), 15,
9772 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9773 if (!NT_STATUS_IS_OK(status)) {
9774 reply_nterror(req, status);
9777 status = srvstr_push(pdata, req->flags2, pdata+18,
9778 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
9779 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9780 if (!NT_STATUS_IS_OK(status)) {
9781 reply_nterror(req, status);
9784 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9789 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9790 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9793 /****************************************************************************
9794 Reply to a SMBfindclose (stop trans2 directory search).
9795 ****************************************************************************/
9797 void reply_findclose(struct smb_request *req)
9800 struct smbd_server_connection *sconn = req->sconn;
9801 files_struct *fsp = NULL;
9803 START_PROFILE(SMBfindclose);
9806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9807 END_PROFILE(SMBfindclose);
9811 dptr_num = SVALS(req->vwv+0, 0);
9813 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9816 * OS/2 seems to use -1 to indicate "close all directories"
9817 * This has to mean on this specific connection struct.
9819 if (dptr_num == -1) {
9820 dptr_closecnum(req->conn);
9822 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9825 close_file(NULL, fsp, NORMAL_CLOSE);
9830 reply_outbuf(req, 0, 0);
9832 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9834 END_PROFILE(SMBfindclose);
9838 /****************************************************************************
9839 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9840 ****************************************************************************/
9842 void reply_findnclose(struct smb_request *req)
9846 START_PROFILE(SMBfindnclose);
9849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9850 END_PROFILE(SMBfindnclose);
9854 dptr_num = SVAL(req->vwv+0, 0);
9856 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9858 /* We never give out valid handles for a
9859 findnotifyfirst - so any dptr_num is ok here.
9862 reply_outbuf(req, 0, 0);
9864 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9866 END_PROFILE(SMBfindnclose);
9870 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9871 struct trans_state *state)
9873 if (get_Protocol() >= PROTOCOL_NT1) {
9874 req->flags2 |= 0x40; /* IS_LONG_NAME */
9875 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9878 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9879 if (state->call != TRANSACT2_QFSINFO &&
9880 state->call != TRANSACT2_SETFSINFO) {
9881 DEBUG(0,("handle_trans2: encryption required "
9883 (unsigned int)state->call));
9884 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9889 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9891 /* Now we must call the relevant TRANS2 function */
9892 switch(state->call) {
9893 case TRANSACT2_OPEN:
9895 START_PROFILE(Trans2_open);
9896 call_trans2open(conn, req,
9897 &state->param, state->total_param,
9898 &state->data, state->total_data,
9899 state->max_data_return);
9900 END_PROFILE(Trans2_open);
9904 case TRANSACT2_FINDFIRST:
9906 START_PROFILE(Trans2_findfirst);
9907 call_trans2findfirst(conn, req,
9908 &state->param, state->total_param,
9909 &state->data, state->total_data,
9910 state->max_data_return);
9911 END_PROFILE(Trans2_findfirst);
9915 case TRANSACT2_FINDNEXT:
9917 START_PROFILE(Trans2_findnext);
9918 call_trans2findnext(conn, req,
9919 &state->param, state->total_param,
9920 &state->data, state->total_data,
9921 state->max_data_return);
9922 END_PROFILE(Trans2_findnext);
9926 case TRANSACT2_QFSINFO:
9928 START_PROFILE(Trans2_qfsinfo);
9929 call_trans2qfsinfo(conn, req,
9930 &state->param, state->total_param,
9931 &state->data, state->total_data,
9932 state->max_data_return);
9933 END_PROFILE(Trans2_qfsinfo);
9937 case TRANSACT2_SETFSINFO:
9939 START_PROFILE(Trans2_setfsinfo);
9940 call_trans2setfsinfo(conn, req,
9941 &state->param, state->total_param,
9942 &state->data, state->total_data,
9943 state->max_data_return);
9944 END_PROFILE(Trans2_setfsinfo);
9948 case TRANSACT2_QPATHINFO:
9949 case TRANSACT2_QFILEINFO:
9951 START_PROFILE(Trans2_qpathinfo);
9952 call_trans2qfilepathinfo(conn, req, state->call,
9953 &state->param, state->total_param,
9954 &state->data, state->total_data,
9955 state->max_data_return);
9956 END_PROFILE(Trans2_qpathinfo);
9960 case TRANSACT2_SETPATHINFO:
9961 case TRANSACT2_SETFILEINFO:
9963 START_PROFILE(Trans2_setpathinfo);
9964 call_trans2setfilepathinfo(conn, req, state->call,
9965 &state->param, state->total_param,
9966 &state->data, state->total_data,
9967 state->max_data_return);
9968 END_PROFILE(Trans2_setpathinfo);
9972 case TRANSACT2_FINDNOTIFYFIRST:
9974 START_PROFILE(Trans2_findnotifyfirst);
9975 call_trans2findnotifyfirst(conn, req,
9976 &state->param, state->total_param,
9977 &state->data, state->total_data,
9978 state->max_data_return);
9979 END_PROFILE(Trans2_findnotifyfirst);
9983 case TRANSACT2_FINDNOTIFYNEXT:
9985 START_PROFILE(Trans2_findnotifynext);
9986 call_trans2findnotifynext(conn, req,
9987 &state->param, state->total_param,
9988 &state->data, state->total_data,
9989 state->max_data_return);
9990 END_PROFILE(Trans2_findnotifynext);
9994 case TRANSACT2_MKDIR:
9996 START_PROFILE(Trans2_mkdir);
9997 call_trans2mkdir(conn, req,
9998 &state->param, state->total_param,
9999 &state->data, state->total_data,
10000 state->max_data_return);
10001 END_PROFILE(Trans2_mkdir);
10005 case TRANSACT2_GET_DFS_REFERRAL:
10007 START_PROFILE(Trans2_get_dfs_referral);
10008 call_trans2getdfsreferral(conn, req,
10009 &state->param, state->total_param,
10010 &state->data, state->total_data,
10011 state->max_data_return);
10012 END_PROFILE(Trans2_get_dfs_referral);
10016 case TRANSACT2_IOCTL:
10018 START_PROFILE(Trans2_ioctl);
10019 call_trans2ioctl(conn, req,
10020 &state->param, state->total_param,
10021 &state->data, state->total_data,
10022 state->max_data_return);
10023 END_PROFILE(Trans2_ioctl);
10028 /* Error in request */
10029 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
10030 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
10034 /****************************************************************************
10035 Reply to a SMBtrans2.
10036 ****************************************************************************/
10038 void reply_trans2(struct smb_request *req)
10040 connection_struct *conn = req->conn;
10041 unsigned int dsoff;
10042 unsigned int dscnt;
10043 unsigned int psoff;
10044 unsigned int pscnt;
10045 unsigned int tran_call;
10046 struct trans_state *state;
10049 START_PROFILE(SMBtrans2);
10051 if (req->wct < 14) {
10052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10053 END_PROFILE(SMBtrans2);
10057 dsoff = SVAL(req->vwv+12, 0);
10058 dscnt = SVAL(req->vwv+11, 0);
10059 psoff = SVAL(req->vwv+10, 0);
10060 pscnt = SVAL(req->vwv+9, 0);
10061 tran_call = SVAL(req->vwv+14, 0);
10063 result = allow_new_trans(conn->pending_trans, req->mid);
10064 if (!NT_STATUS_IS_OK(result)) {
10065 DEBUG(2, ("Got invalid trans2 request: %s\n",
10066 nt_errstr(result)));
10067 reply_nterror(req, result);
10068 END_PROFILE(SMBtrans2);
10072 if (IS_IPC(conn)) {
10073 switch (tran_call) {
10074 /* List the allowed trans2 calls on IPC$ */
10075 case TRANSACT2_OPEN:
10076 case TRANSACT2_GET_DFS_REFERRAL:
10077 case TRANSACT2_QFILEINFO:
10078 case TRANSACT2_QFSINFO:
10079 case TRANSACT2_SETFSINFO:
10082 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10083 END_PROFILE(SMBtrans2);
10088 if ((state = talloc(conn, struct trans_state)) == NULL) {
10089 DEBUG(0, ("talloc failed\n"));
10090 reply_nterror(req, NT_STATUS_NO_MEMORY);
10091 END_PROFILE(SMBtrans2);
10095 state->cmd = SMBtrans2;
10097 state->mid = req->mid;
10098 state->vuid = req->vuid;
10099 state->setup_count = SVAL(req->vwv+13, 0);
10100 state->setup = NULL;
10101 state->total_param = SVAL(req->vwv+0, 0);
10102 state->param = NULL;
10103 state->total_data = SVAL(req->vwv+1, 0);
10104 state->data = NULL;
10105 state->max_param_return = SVAL(req->vwv+2, 0);
10106 state->max_data_return = SVAL(req->vwv+3, 0);
10107 state->max_setup_return = SVAL(req->vwv+4, 0);
10108 state->close_on_completion = BITSETW(req->vwv+5, 0);
10109 state->one_way = BITSETW(req->vwv+5, 1);
10111 state->call = tran_call;
10113 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10114 is so as a sanity check */
10115 if (state->setup_count != 1) {
10117 * Need to have rc=0 for ioctl to get job id for OS/2.
10118 * Network printing will fail if function is not successful.
10119 * Similar function in reply.c will be used if protocol
10120 * is LANMAN1.0 instead of LM1.2X002.
10121 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10122 * outbuf doesn't have to be set(only job id is used).
10124 if ( (state->setup_count == 4)
10125 && (tran_call == TRANSACT2_IOCTL)
10126 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10127 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10128 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10130 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10131 DEBUG(2,("Transaction is %d\n",tran_call));
10132 TALLOC_FREE(state);
10133 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10134 END_PROFILE(SMBtrans2);
10139 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10142 if (state->total_data) {
10144 if (trans_oob(state->total_data, 0, dscnt)
10145 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10149 /* Can't use talloc here, the core routines do realloc on the
10150 * params and data. */
10151 state->data = (char *)SMB_MALLOC(state->total_data);
10152 if (state->data == NULL) {
10153 DEBUG(0,("reply_trans2: data malloc fail for %u "
10154 "bytes !\n", (unsigned int)state->total_data));
10155 TALLOC_FREE(state);
10156 reply_nterror(req, NT_STATUS_NO_MEMORY);
10157 END_PROFILE(SMBtrans2);
10161 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10164 if (state->total_param) {
10166 if (trans_oob(state->total_param, 0, pscnt)
10167 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10171 /* Can't use talloc here, the core routines do realloc on the
10172 * params and data. */
10173 state->param = (char *)SMB_MALLOC(state->total_param);
10174 if (state->param == NULL) {
10175 DEBUG(0,("reply_trans: param malloc fail for %u "
10176 "bytes !\n", (unsigned int)state->total_param));
10177 SAFE_FREE(state->data);
10178 TALLOC_FREE(state);
10179 reply_nterror(req, NT_STATUS_NO_MEMORY);
10180 END_PROFILE(SMBtrans2);
10184 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10187 state->received_data = dscnt;
10188 state->received_param = pscnt;
10190 if ((state->received_param == state->total_param) &&
10191 (state->received_data == state->total_data)) {
10193 handle_trans2(conn, req, state);
10195 SAFE_FREE(state->data);
10196 SAFE_FREE(state->param);
10197 TALLOC_FREE(state);
10198 END_PROFILE(SMBtrans2);
10202 DLIST_ADD(conn->pending_trans, state);
10204 /* We need to send an interim response then receive the rest
10205 of the parameter/data bytes */
10206 reply_outbuf(req, 0, 0);
10207 show_msg((char *)req->outbuf);
10208 END_PROFILE(SMBtrans2);
10213 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10214 SAFE_FREE(state->data);
10215 SAFE_FREE(state->param);
10216 TALLOC_FREE(state);
10217 END_PROFILE(SMBtrans2);
10218 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10222 /****************************************************************************
10223 Reply to a SMBtranss2
10224 ****************************************************************************/
10226 void reply_transs2(struct smb_request *req)
10228 connection_struct *conn = req->conn;
10229 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10230 struct trans_state *state;
10232 START_PROFILE(SMBtranss2);
10234 show_msg((const char *)req->inbuf);
10236 /* Windows clients expect all replies to
10237 a transact secondary (SMBtranss2 0x33)
10238 to have a command code of transact
10239 (SMBtrans2 0x32). See bug #8989
10240 and also [MS-CIFS] section 2.2.4.47.2
10243 req->cmd = SMBtrans2;
10245 if (req->wct < 8) {
10246 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10247 END_PROFILE(SMBtranss2);
10251 for (state = conn->pending_trans; state != NULL;
10252 state = state->next) {
10253 if (state->mid == req->mid) {
10258 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10259 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10260 END_PROFILE(SMBtranss2);
10264 /* Revise state->total_param and state->total_data in case they have
10265 changed downwards */
10267 if (SVAL(req->vwv+0, 0) < state->total_param)
10268 state->total_param = SVAL(req->vwv+0, 0);
10269 if (SVAL(req->vwv+1, 0) < state->total_data)
10270 state->total_data = SVAL(req->vwv+1, 0);
10272 pcnt = SVAL(req->vwv+2, 0);
10273 poff = SVAL(req->vwv+3, 0);
10274 pdisp = SVAL(req->vwv+4, 0);
10276 dcnt = SVAL(req->vwv+5, 0);
10277 doff = SVAL(req->vwv+6, 0);
10278 ddisp = SVAL(req->vwv+7, 0);
10280 state->received_param += pcnt;
10281 state->received_data += dcnt;
10283 if ((state->received_data > state->total_data) ||
10284 (state->received_param > state->total_param))
10288 if (trans_oob(state->total_param, pdisp, pcnt)
10289 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10292 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10296 if (trans_oob(state->total_data, ddisp, dcnt)
10297 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10300 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10303 if ((state->received_param < state->total_param) ||
10304 (state->received_data < state->total_data)) {
10305 END_PROFILE(SMBtranss2);
10309 handle_trans2(conn, req, state);
10311 DLIST_REMOVE(conn->pending_trans, state);
10312 SAFE_FREE(state->data);
10313 SAFE_FREE(state->param);
10314 TALLOC_FREE(state);
10316 END_PROFILE(SMBtranss2);
10321 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10322 DLIST_REMOVE(conn->pending_trans, state);
10323 SAFE_FREE(state->data);
10324 SAFE_FREE(state->param);
10325 TALLOC_FREE(state);
10326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10327 END_PROFILE(SMBtranss2);