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"
47 #include "lib/util/string_wrappers.h"
49 #define DIR_ENTRY_SAFETY_MARGIN 4096
51 static char *store_file_unix_basic(connection_struct *conn,
54 const SMB_STRUCT_STAT *psbuf);
56 static char *store_file_unix_basic_info2(connection_struct *conn,
59 const SMB_STRUCT_STAT *psbuf);
61 /****************************************************************************
62 Check if an open file handle or smb_fname is a symlink.
63 ****************************************************************************/
65 static NTSTATUS refuse_symlink(connection_struct *conn,
66 const files_struct *fsp,
67 const struct smb_filename *smb_fname)
70 const SMB_STRUCT_STAT *pst = NULL;
73 pst = &fsp->fsp_name->st;
78 if (!VALID_STAT(*pst)) {
79 int ret = vfs_stat_smb_basename(conn,
82 if (ret == -1 && errno != ENOENT) {
83 return map_nt_error_from_unix(errno);
84 } else if (ret == -1) {
85 /* it's not a symlink.. */
91 if (S_ISLNK(pst->st_ex_mode)) {
92 return NT_STATUS_ACCESS_DENIED;
97 NTSTATUS check_access_fsp(const struct files_struct *fsp,
100 if (!(fsp->access_mask & access_mask)) {
101 return NT_STATUS_ACCESS_DENIED;
106 #if defined(HAVE_POSIX_ACLS)
107 /****************************************************************************
108 Utility function to open a fsp for a POSIX handle operation.
109 ****************************************************************************/
111 static NTSTATUS get_posix_fsp(connection_struct *conn,
112 struct smb_request *req,
113 const struct smb_filename *smb_fname,
114 uint32_t access_mask,
115 files_struct **ret_fsp)
118 struct smb_filename *smb_fname_tmp = NULL;
119 uint32_t create_disposition = FILE_OPEN;
120 uint32_t share_access = FILE_SHARE_READ|
123 struct smb2_create_blobs *posx = NULL;
126 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
127 * but set reasonable defaults.
129 uint32_t file_attributes = 0664;
130 uint32_t oplock = NO_OPLOCK;
131 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
133 /* File or directory must exist. */
134 if (!VALID_STAT(smb_fname->st)) {
135 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
137 /* Cannot be a symlink. */
138 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
139 return NT_STATUS_ACCESS_DENIED;
141 /* Set options correctly for directory open. */
142 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
144 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
145 * directories, but set reasonable defaults.
147 file_attributes = 0775;
148 create_options = FILE_DIRECTORY_FILE;
151 /* Createfile uses a non-const smb_fname. */
152 smb_fname_tmp = cp_smb_filename(talloc_tos(),
154 if (smb_fname_tmp == NULL) {
155 status = NT_STATUS_NO_MEMORY;
159 status = make_smb2_posix_create_ctx(
160 talloc_tos(), &posx, file_attributes);
161 if (!NT_STATUS_IS_OK(status)) {
162 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
167 status = SMB_VFS_CREATE_FILE(
170 &conn->cwd_fsp, /* dirfsp */
171 smb_fname_tmp, /* fname */
172 access_mask, /* access_mask */
173 share_access, /* share_access */
174 create_disposition,/* create_disposition*/
175 create_options, /* create_options */
176 file_attributes,/* file_attributes */
177 oplock, /* oplock_request */
179 0, /* allocation_size */
180 0, /* private_flags */
183 ret_fsp, /* result */
185 posx, /* in_context */
186 NULL); /* out_context */
190 TALLOC_FREE(smb_fname_tmp);
195 /********************************************************************
196 The canonical "check access" based on path.
197 ********************************************************************/
199 static NTSTATUS check_access(connection_struct *conn,
200 struct files_struct *dirfsp,
201 const struct smb_filename *smb_fname,
202 uint32_t access_mask)
204 SMB_ASSERT(dirfsp == dirfsp->conn->cwd_fsp);
205 return smbd_check_access_rights(conn,
212 /********************************************************************
213 Roundup a value to the nearest allocation roundup size boundary.
214 Only do this for Windows clients.
215 ********************************************************************/
217 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
219 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
221 /* Only roundup for Windows clients. */
222 enum remote_arch_types ra_type = get_remote_arch();
223 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
224 val = SMB_ROUNDUP(val,rval);
229 /****************************************************************************
230 Utility functions for dealing with extended attributes.
231 ****************************************************************************/
233 /****************************************************************************
234 Refuse to allow clients to overwrite our private xattrs.
235 ****************************************************************************/
237 bool samba_private_attr_name(const char *unix_ea_name)
239 static const char * const prohibited_ea_names[] = {
240 SAMBA_POSIX_INHERITANCE_EA_NAME,
241 SAMBA_XATTR_DOS_ATTRIB,
249 for (i = 0; prohibited_ea_names[i]; i++) {
250 if (strequal( prohibited_ea_names[i], unix_ea_name))
253 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
254 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
260 /****************************************************************************
261 Get one EA value. Fill in a struct ea_struct.
262 ****************************************************************************/
264 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
265 connection_struct *conn,
267 const struct smb_filename *smb_fname,
269 struct ea_struct *pea)
271 /* Get the value of this xattr. Max size is 64k. */
272 size_t attr_size = 256;
278 val = talloc_realloc(mem_ctx, val, char, attr_size);
280 return NT_STATUS_NO_MEMORY;
283 if (fsp && fsp->fh->fd != -1) {
284 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
286 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
287 ea_name, val, attr_size);
290 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
296 return map_nt_error_from_unix(errno);
299 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
300 dump_data(10, (uint8_t *)val, sizeret);
303 if (strnequal(ea_name, "user.", 5)) {
304 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
306 pea->name = talloc_strdup(mem_ctx, ea_name);
308 if (pea->name == NULL) {
310 return NT_STATUS_NO_MEMORY;
312 pea->value.data = (unsigned char *)val;
313 pea->value.length = (size_t)sizeret;
317 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
318 connection_struct *conn,
320 const struct smb_filename *smb_fname,
325 /* Get a list of all xattrs. Max namesize is 64k. */
326 size_t ea_namelist_size = 1024;
327 char *ea_namelist = smallbuf;
328 char *to_free = NULL;
333 ssize_t sizeret = -1;
341 status = refuse_symlink(conn, fsp, smb_fname);
342 if (!NT_STATUS_IS_OK(status)) {
344 * Just return no EA's on a symlink.
349 if (fsp && fsp->fh->fd != -1) {
350 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
353 sizeret = SMB_VFS_LISTXATTR(conn,
359 if ((sizeret == -1) && (errno == ERANGE)) {
360 ea_namelist_size = 65536;
361 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
362 if (ea_namelist == NULL) {
363 return NT_STATUS_NO_MEMORY;
365 to_free = ea_namelist;
367 if (fsp && fsp->fh->fd != -1) {
368 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
371 sizeret = SMB_VFS_LISTXATTR(conn,
379 status = map_nt_error_from_unix(errno);
380 TALLOC_FREE(to_free);
384 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
387 TALLOC_FREE(to_free);
392 * Ensure the result is 0-terminated
395 if (ea_namelist[sizeret-1] != '\0') {
396 TALLOC_FREE(to_free);
397 return NT_STATUS_INTERNAL_ERROR;
405 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
409 *pnum_names = num_names;
411 if (pnames == NULL) {
412 TALLOC_FREE(to_free);
416 names = talloc_array(mem_ctx, char *, num_names);
418 DEBUG(0, ("talloc failed\n"));
419 TALLOC_FREE(to_free);
420 return NT_STATUS_NO_MEMORY;
423 if (ea_namelist == smallbuf) {
424 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
425 if (ea_namelist == NULL) {
427 return NT_STATUS_NO_MEMORY;
430 talloc_steal(names, ea_namelist);
432 ea_namelist = talloc_realloc(names, ea_namelist, char,
434 if (ea_namelist == NULL) {
436 return NT_STATUS_NO_MEMORY;
442 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
443 names[num_names++] = p;
451 /****************************************************************************
452 Return a linked list of the total EA's. Plus the total size
453 ****************************************************************************/
455 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
456 connection_struct *conn,
458 const struct smb_filename *smb_fname,
459 size_t *pea_total_len,
460 struct ea_list **ea_list)
462 /* Get a list of all xattrs. Max namesize is 64k. */
465 struct ea_list *ea_list_head = NULL;
466 bool posix_pathnames = false;
472 if (!lp_ea_support(SNUM(conn))) {
478 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
480 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
483 status = get_ea_names_from_file(talloc_tos(),
490 if (!NT_STATUS_IS_OK(status)) {
494 if (num_names == 0) {
498 for (i=0; i<num_names; i++) {
499 struct ea_list *listp;
502 if (strnequal(names[i], "system.", 7)
503 || samba_private_attr_name(names[i]))
507 * Filter out any underlying POSIX EA names
508 * that a Windows client can't handle.
510 if (!posix_pathnames &&
511 is_invalid_windows_ea_name(names[i])) {
515 listp = talloc(mem_ctx, struct ea_list);
517 return NT_STATUS_NO_MEMORY;
520 status = get_ea_value(listp,
527 if (!NT_STATUS_IS_OK(status)) {
532 if (listp->ea.value.length == 0) {
534 * We can never return a zero length EA.
535 * Windows reports the EA's as corrupted.
541 push_ascii_fstring(dos_ea_name, listp->ea.name);
544 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
546 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
547 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
548 (unsigned int)listp->ea.value.length));
550 DLIST_ADD_END(ea_list_head, listp);
554 /* Add on 4 for total length. */
555 if (*pea_total_len) {
559 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
560 (unsigned int)*pea_total_len));
562 *ea_list = ea_list_head;
566 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
567 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
572 if (!lp_ea_support(SNUM(conn))) {
576 if (is_ntfs_stream_smb_fname(smb_fname)) {
577 return NT_STATUS_INVALID_PARAMETER;
580 return get_ea_list_from_file_path(mem_ctx,
588 /****************************************************************************
589 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
591 ****************************************************************************/
593 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
594 connection_struct *conn, struct ea_list *ea_list)
596 unsigned int ret_data_size = 4;
599 SMB_ASSERT(total_data_size >= 4);
601 if (!lp_ea_support(SNUM(conn))) {
606 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
609 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
610 dos_namelen = strlen(dos_ea_name);
611 if (dos_namelen > 255 || dos_namelen == 0) {
614 if (ea_list->ea.value.length > 65535) {
617 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
621 /* We know we have room. */
622 SCVAL(p,0,ea_list->ea.flags);
623 SCVAL(p,1,dos_namelen);
624 SSVAL(p,2,ea_list->ea.value.length);
625 strlcpy(p+4, dos_ea_name, dos_namelen+1);
626 if (ea_list->ea.value.length > 0) {
627 memcpy(p + 4 + dos_namelen + 1,
628 ea_list->ea.value.data,
629 ea_list->ea.value.length);
632 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
633 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
636 ret_data_size = PTR_DIFF(p, pdata);
637 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
638 SIVAL(pdata,0,ret_data_size);
639 return ret_data_size;
642 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
644 unsigned int total_data_size,
645 unsigned int *ret_data_size,
646 connection_struct *conn,
647 struct ea_list *ea_list)
649 uint8_t *p = (uint8_t *)pdata;
650 uint8_t *last_start = NULL;
651 bool do_store_data = (pdata != NULL);
655 if (!lp_ea_support(SNUM(conn))) {
656 return NT_STATUS_NO_EAS_ON_FILE;
659 for (; ea_list; ea_list = ea_list->next) {
665 if (last_start != NULL && do_store_data) {
666 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
670 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
671 dos_namelen = strlen(dos_ea_name);
672 if (dos_namelen > 255 || dos_namelen == 0) {
673 return NT_STATUS_INTERNAL_ERROR;
675 if (ea_list->ea.value.length > 65535) {
676 return NT_STATUS_INTERNAL_ERROR;
679 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
682 pad = (4 - (this_size % 4)) % 4;
687 if (this_size > total_data_size) {
688 return NT_STATUS_INFO_LENGTH_MISMATCH;
691 /* We know we have room. */
692 SIVAL(p, 0x00, 0); /* next offset */
693 SCVAL(p, 0x04, ea_list->ea.flags);
694 SCVAL(p, 0x05, dos_namelen);
695 SSVAL(p, 0x06, ea_list->ea.value.length);
696 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
697 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
699 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
703 total_data_size -= this_size;
709 *ret_data_size = PTR_DIFF(p, pdata);
710 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
714 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
716 size_t total_ea_len = 0;
718 struct ea_list *ea_list = NULL;
720 if (!lp_ea_support(SNUM(conn))) {
723 mem_ctx = talloc_stackframe();
725 /* If this is a stream fsp, then we need to instead find the
726 * estimated ea len from the main file, not the stream
727 * (streams cannot have EAs), but the estimate isn't just 0 in
729 if (is_ntfs_stream_smb_fname(smb_fname)) {
732 (void)get_ea_list_from_file_path(mem_ctx,
738 if(conn->sconn->using_smb2) {
740 unsigned int ret_data_size;
742 * We're going to be using fill_ea_chained_buffer() to
743 * marshall EA's - this size is significantly larger
744 * than the SMB1 buffer. Re-calculate the size without
747 status = fill_ea_chained_buffer(mem_ctx,
753 if (!NT_STATUS_IS_OK(status)) {
756 total_ea_len = ret_data_size;
758 TALLOC_FREE(mem_ctx);
762 /****************************************************************************
763 Ensure the EA name is case insensitive by matching any existing EA name.
764 ****************************************************************************/
766 static void canonicalize_ea_name(connection_struct *conn,
768 const struct smb_filename *smb_fname,
769 fstring unix_ea_name)
772 TALLOC_CTX *mem_ctx = talloc_tos();
773 struct ea_list *ea_list;
774 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
780 if (!NT_STATUS_IS_OK(status)) {
784 for (; ea_list; ea_list = ea_list->next) {
785 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
786 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
787 &unix_ea_name[5], ea_list->ea.name));
788 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
794 /****************************************************************************
795 Set or delete an extended attribute.
796 ****************************************************************************/
798 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
799 const struct smb_filename *smb_fname, struct ea_list *ea_list)
802 bool posix_pathnames = false;
804 if (!lp_ea_support(SNUM(conn))) {
805 return NT_STATUS_EAS_NOT_SUPPORTED;
810 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
812 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
815 status = refuse_symlink(conn, fsp, smb_fname);
816 if (!NT_STATUS_IS_OK(status)) {
821 status = check_access_fsp(fsp, FILE_WRITE_EA);
823 status = check_access(conn,
828 if (!NT_STATUS_IS_OK(status)) {
832 /* Setting EAs on streams isn't supported. */
833 if (is_ntfs_stream_smb_fname(smb_fname)) {
834 return NT_STATUS_INVALID_PARAMETER;
838 * Filter out invalid Windows EA names - before
839 * we set *any* of them.
842 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
843 return STATUS_INVALID_EA_NAME;
846 for (;ea_list; ea_list = ea_list->next) {
848 fstring unix_ea_name;
850 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
851 fstrcat(unix_ea_name, ea_list->ea.name);
853 canonicalize_ea_name(conn,
858 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
860 if (samba_private_attr_name(unix_ea_name)) {
861 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
862 return NT_STATUS_ACCESS_DENIED;
865 if (ea_list->ea.value.length == 0) {
866 /* Remove the attribute. */
867 if (fsp && (fsp->fh->fd != -1)) {
868 DEBUG(10,("set_ea: deleting ea name %s on "
869 "file %s by file descriptor.\n",
870 unix_ea_name, fsp_str_dbg(fsp)));
871 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
873 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
874 unix_ea_name, smb_fname->base_name));
875 ret = SMB_VFS_REMOVEXATTR(conn,
880 /* Removing a non existent attribute always succeeds. */
881 if (ret == -1 && errno == ENOATTR) {
882 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
888 if (fsp && (fsp->fh->fd != -1)) {
889 DEBUG(10,("set_ea: setting ea name %s on file "
890 "%s by file descriptor.\n",
891 unix_ea_name, fsp_str_dbg(fsp)));
892 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
893 ea_list->ea.value.data, ea_list->ea.value.length, 0);
895 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
896 unix_ea_name, smb_fname->base_name));
897 ret = SMB_VFS_SETXATTR(conn,
900 ea_list->ea.value.data,
901 ea_list->ea.value.length,
908 if (errno == ENOTSUP) {
909 return NT_STATUS_EAS_NOT_SUPPORTED;
912 return map_nt_error_from_unix(errno);
918 /****************************************************************************
919 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
920 ****************************************************************************/
922 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
924 struct ea_list *ea_list_head = NULL;
925 size_t converted_size, offset = 0;
927 while (offset + 2 < data_size) {
928 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
929 unsigned int namelen = CVAL(pdata,offset);
931 offset++; /* Go past the namelen byte. */
933 /* integer wrap paranioa. */
934 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
935 (offset > data_size) || (namelen > data_size) ||
936 (offset + namelen >= data_size)) {
939 /* Ensure the name is null terminated. */
940 if (pdata[offset + namelen] != '\0') {
943 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
945 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
946 "failed: %s", strerror(errno)));
952 offset += (namelen + 1); /* Go past the name + terminating zero. */
953 DLIST_ADD_END(ea_list_head, eal);
954 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
960 /****************************************************************************
961 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
962 ****************************************************************************/
964 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
966 struct ea_list *ea_list_head = NULL;
968 size_t bytes_used = 0;
970 while (offset < data_size) {
971 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
977 DLIST_ADD_END(ea_list_head, eal);
978 offset += bytes_used;
984 /****************************************************************************
985 Count the total EA size needed.
986 ****************************************************************************/
988 static size_t ea_list_size(struct ea_list *ealist)
991 struct ea_list *listp;
994 for (listp = ealist; listp; listp = listp->next) {
995 push_ascii_fstring(dos_ea_name, listp->ea.name);
996 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
998 /* Add on 4 for total length. */
1006 /****************************************************************************
1007 Return a union of EA's from a file list and a list of names.
1008 The TALLOC context for the two lists *MUST* be identical as we steal
1009 memory from one list to add to another. JRA.
1010 ****************************************************************************/
1012 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
1014 struct ea_list *nlistp, *flistp;
1016 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
1017 for (flistp = file_list; flistp; flistp = flistp->next) {
1018 if (strequal(nlistp->ea.name, flistp->ea.name)) {
1024 /* Copy the data from this entry. */
1025 nlistp->ea.flags = flistp->ea.flags;
1026 nlistp->ea.value = flistp->ea.value;
1029 nlistp->ea.flags = 0;
1030 ZERO_STRUCT(nlistp->ea.value);
1034 *total_ea_len = ea_list_size(name_list);
1038 /****************************************************************************
1039 Send the required number of replies back.
1040 We assume all fields other than the data fields are
1041 set correctly for the type of call.
1042 HACK ! Always assumes smb_setup field is zero.
1043 ****************************************************************************/
1045 void send_trans2_replies(connection_struct *conn,
1046 struct smb_request *req,
1054 /* As we are using a protocol > LANMAN1 then the max_send
1055 variable must have been set in the sessetupX call.
1056 This takes precedence over the max_xmit field in the
1057 global struct. These different max_xmit variables should
1058 be merged as this is now too confusing */
1060 int data_to_send = datasize;
1061 int params_to_send = paramsize;
1063 const char *pp = params;
1064 const char *pd = pdata;
1065 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1066 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1067 int data_alignment_offset = 0;
1068 bool overflow = False;
1069 struct smbXsrv_connection *xconn = req->xconn;
1070 int max_send = xconn->smb1.sessions.max_send;
1072 /* Modify the data_to_send and datasize and set the error if
1073 we're trying to send more than max_data_bytes. We still send
1074 the part of the packet(s) that fit. Strange, but needed
1077 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1078 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1079 max_data_bytes, datasize ));
1080 datasize = data_to_send = max_data_bytes;
1084 /* If there genuinely are no parameters or data to send just send the empty packet */
1086 if(params_to_send == 0 && data_to_send == 0) {
1087 reply_outbuf(req, 10, 0);
1088 if (NT_STATUS_V(status)) {
1091 ntstatus_to_dos(status, &eclass, &ecode);
1092 error_packet_set((char *)req->outbuf,
1093 eclass, ecode, status,
1096 show_msg((char *)req->outbuf);
1097 if (!srv_send_smb(xconn,
1098 (char *)req->outbuf,
1099 true, req->seqnum+1,
1100 IS_CONN_ENCRYPTED(conn),
1102 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1104 TALLOC_FREE(req->outbuf);
1108 /* When sending params and data ensure that both are nicely aligned */
1109 /* Only do this alignment when there is also data to send - else
1110 can cause NT redirector problems. */
1112 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1113 data_alignment_offset = 4 - (params_to_send % 4);
1115 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1116 /* The alignment_offset is to align the param bytes on an even byte
1117 boundary. NT 4.0 Beta needs this to work correctly. */
1119 useable_space = max_send - (smb_size
1122 + data_alignment_offset);
1124 if (useable_space < 0) {
1125 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1126 "= %d!!!", useable_space));
1127 exit_server_cleanly("send_trans2_replies: Not enough space");
1130 while (params_to_send || data_to_send) {
1131 /* Calculate whether we will totally or partially fill this packet */
1133 total_sent_thistime = params_to_send + data_to_send;
1135 /* We can never send more than useable_space */
1137 * Note that 'useable_space' does not include the alignment offsets,
1138 * but we must include the alignment offsets in the calculation of
1139 * the length of the data we send over the wire, as the alignment offsets
1140 * are sent here. Fix from Marc_Jacobsen@hp.com.
1143 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1145 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1146 + data_alignment_offset);
1148 /* Set total params and data to be sent */
1149 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1150 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1152 /* Calculate how many parameters and data we can fit into
1153 * this packet. Parameters get precedence
1156 params_sent_thistime = MIN(params_to_send,useable_space);
1157 data_sent_thistime = useable_space - params_sent_thistime;
1158 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1160 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1162 /* smb_proff is the offset from the start of the SMB header to the
1163 parameter bytes, however the first 4 bytes of outbuf are
1164 the Netbios over TCP header. Thus use smb_base() to subtract
1165 them from the calculation */
1167 SSVAL(req->outbuf,smb_proff,
1168 ((smb_buf(req->outbuf)+alignment_offset)
1169 - smb_base(req->outbuf)));
1171 if(params_sent_thistime == 0)
1172 SSVAL(req->outbuf,smb_prdisp,0);
1174 /* Absolute displacement of param bytes sent in this packet */
1175 SSVAL(req->outbuf,smb_prdisp,pp - params);
1177 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1178 if(data_sent_thistime == 0) {
1179 SSVAL(req->outbuf,smb_droff,0);
1180 SSVAL(req->outbuf,smb_drdisp, 0);
1182 /* The offset of the data bytes is the offset of the
1183 parameter bytes plus the number of parameters being sent this time */
1184 SSVAL(req->outbuf, smb_droff,
1185 ((smb_buf(req->outbuf)+alignment_offset)
1186 - smb_base(req->outbuf))
1187 + params_sent_thistime + data_alignment_offset);
1188 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1191 /* Initialize the padding for alignment */
1193 if (alignment_offset != 0) {
1194 memset(smb_buf(req->outbuf), 0, alignment_offset);
1197 /* Copy the param bytes into the packet */
1199 if(params_sent_thistime) {
1200 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1201 params_sent_thistime);
1204 /* Copy in the data bytes */
1205 if(data_sent_thistime) {
1206 if (data_alignment_offset != 0) {
1207 memset((smb_buf(req->outbuf)+alignment_offset+
1208 params_sent_thistime), 0,
1209 data_alignment_offset);
1211 memcpy(smb_buf(req->outbuf)+alignment_offset
1212 +params_sent_thistime+data_alignment_offset,
1213 pd,data_sent_thistime);
1216 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1217 params_sent_thistime, data_sent_thistime, useable_space));
1218 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1219 params_to_send, data_to_send, paramsize, datasize));
1222 error_packet_set((char *)req->outbuf,
1223 ERRDOS,ERRbufferoverflow,
1224 STATUS_BUFFER_OVERFLOW,
1226 } else if (NT_STATUS_V(status)) {
1229 ntstatus_to_dos(status, &eclass, &ecode);
1230 error_packet_set((char *)req->outbuf,
1231 eclass, ecode, status,
1235 /* Send the packet */
1236 show_msg((char *)req->outbuf);
1237 if (!srv_send_smb(xconn,
1238 (char *)req->outbuf,
1239 true, req->seqnum+1,
1240 IS_CONN_ENCRYPTED(conn),
1242 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1244 TALLOC_FREE(req->outbuf);
1246 pp += params_sent_thistime;
1247 pd += data_sent_thistime;
1249 params_to_send -= params_sent_thistime;
1250 data_to_send -= data_sent_thistime;
1253 if(params_to_send < 0 || data_to_send < 0) {
1254 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1255 params_to_send, data_to_send));
1263 /****************************************************************************
1264 Reply to a TRANSACT2_OPEN.
1265 ****************************************************************************/
1267 static void call_trans2open(connection_struct *conn,
1268 struct smb_request *req,
1269 char **pparams, int total_params,
1270 char **ppdata, int total_data,
1271 unsigned int max_data_bytes)
1273 struct smb_filename *smb_fname = NULL;
1274 char *params = *pparams;
1275 char *pdata = *ppdata;
1278 bool oplock_request;
1280 bool return_additional_info;
1289 int fattr=0,mtime=0;
1290 SMB_INO_T inode = 0;
1293 struct ea_list *ea_list = NULL;
1296 uint32_t access_mask;
1297 uint32_t share_mode;
1298 uint32_t create_disposition;
1299 uint32_t create_options = 0;
1300 uint32_t private_flags = 0;
1301 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1302 TALLOC_CTX *ctx = talloc_tos();
1305 * Ensure we have enough parameters to perform the operation.
1308 if (total_params < 29) {
1309 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1313 flags = SVAL(params, 0);
1314 deny_mode = SVAL(params, 2);
1315 open_attr = SVAL(params,6);
1316 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1317 if (oplock_request) {
1318 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1322 return_additional_info = BITSETW(params,0);
1323 open_sattr = SVAL(params, 4);
1324 open_time = make_unix_date3(params+8);
1326 open_ofun = SVAL(params,12);
1327 open_size = IVAL(params,14);
1328 pname = ¶ms[28];
1331 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1335 if (req->posix_pathnames) {
1336 srvstr_get_path_posix(ctx,
1345 srvstr_get_path(ctx,
1354 if (!NT_STATUS_IS_OK(status)) {
1355 reply_nterror(req, status);
1359 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1360 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1361 (unsigned int)open_ofun, open_size));
1363 status = filename_convert(ctx,
1370 if (!NT_STATUS_IS_OK(status)) {
1371 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1372 reply_botherror(req,
1373 NT_STATUS_PATH_NOT_COVERED,
1374 ERRSRV, ERRbadpath);
1377 reply_nterror(req, status);
1381 if (open_ofun == 0) {
1382 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1386 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1388 &access_mask, &share_mode,
1389 &create_disposition,
1392 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1396 /* Any data in this call is an EA list. */
1397 if (total_data && (total_data != 4)) {
1398 if (total_data < 10) {
1399 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1403 if (IVAL(pdata,0) > total_data) {
1404 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1405 IVAL(pdata,0), (unsigned int)total_data));
1406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1410 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1413 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1417 if (!lp_ea_support(SNUM(conn))) {
1418 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1422 if (!req->posix_pathnames &&
1423 ea_list_has_invalid_name(ea_list)) {
1425 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1426 if(*pparams == NULL ) {
1427 reply_nterror(req, NT_STATUS_NO_MEMORY);
1431 memset(params, '\0', param_len);
1432 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1433 params, param_len, NULL, 0, max_data_bytes);
1438 status = SMB_VFS_CREATE_FILE(
1441 &conn->cwd_fsp, /* dirfsp */
1442 smb_fname, /* fname */
1443 access_mask, /* access_mask */
1444 share_mode, /* share_access */
1445 create_disposition, /* create_disposition*/
1446 create_options, /* create_options */
1447 open_attr, /* file_attributes */
1448 oplock_request, /* oplock_request */
1450 open_size, /* allocation_size */
1453 ea_list, /* ea_list */
1455 &smb_action, /* psbuf */
1456 NULL, NULL); /* create context */
1458 if (!NT_STATUS_IS_OK(status)) {
1459 if (open_was_deferred(req->xconn, req->mid)) {
1460 /* We have re-scheduled this call. */
1464 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1465 reply_openerror(req, status);
1469 fsp = fcb_or_dos_open(
1476 bool ok = defer_smb1_sharing_violation(req);
1480 reply_openerror(req, status);
1484 smb_action = FILE_WAS_OPENED;
1487 size = get_file_size_stat(&smb_fname->st);
1488 fattr = dos_mode(conn, smb_fname);
1489 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1490 inode = smb_fname->st.st_ex_ino;
1491 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1492 close_file(req, fsp, ERROR_CLOSE);
1493 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1497 /* Realloc the size of parameters and data we will return */
1498 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1499 if(*pparams == NULL ) {
1500 reply_nterror(req, NT_STATUS_NO_MEMORY);
1505 SSVAL(params,0,fsp->fnum);
1506 SSVAL(params,2,fattr);
1507 srv_put_dos_date2(params,4, mtime);
1508 SIVAL(params,8, (uint32_t)size);
1509 SSVAL(params,12,deny_mode);
1510 SSVAL(params,14,0); /* open_type - file or directory. */
1511 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1513 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1514 smb_action |= EXTENDED_OPLOCK_GRANTED;
1517 SSVAL(params,18,smb_action);
1520 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1522 SIVAL(params,20,inode);
1523 SSVAL(params,24,0); /* Padding. */
1525 uint32_t ea_size = estimate_ea_size(conn, fsp,
1527 SIVAL(params, 26, ea_size);
1529 SIVAL(params, 26, 0);
1532 /* Send the required number of replies */
1533 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1535 TALLOC_FREE(smb_fname);
1538 /*********************************************************
1539 Routine to check if a given string matches exactly.
1540 as a special case a mask of "." does NOT match. That
1541 is required for correct wildcard semantics
1542 Case can be significant or not.
1543 **********************************************************/
1545 static bool exact_match(bool has_wild,
1546 bool case_sensitive,
1550 if (mask[0] == '.' && mask[1] == 0) {
1558 if (case_sensitive) {
1559 return strcmp(str,mask)==0;
1561 return strcasecmp_m(str,mask) == 0;
1565 /****************************************************************************
1566 Return the filetype for UNIX extensions.
1567 ****************************************************************************/
1569 static uint32_t unix_filetype(mode_t mode)
1572 return UNIX_TYPE_FILE;
1573 else if(S_ISDIR(mode))
1574 return UNIX_TYPE_DIR;
1576 else if(S_ISLNK(mode))
1577 return UNIX_TYPE_SYMLINK;
1580 else if(S_ISCHR(mode))
1581 return UNIX_TYPE_CHARDEV;
1584 else if(S_ISBLK(mode))
1585 return UNIX_TYPE_BLKDEV;
1588 else if(S_ISFIFO(mode))
1589 return UNIX_TYPE_FIFO;
1592 else if(S_ISSOCK(mode))
1593 return UNIX_TYPE_SOCKET;
1596 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1597 return UNIX_TYPE_UNKNOWN;
1600 /****************************************************************************
1601 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1602 ****************************************************************************/
1604 NTSTATUS unix_perms_from_wire(connection_struct *conn,
1605 const SMB_STRUCT_STAT *psbuf,
1607 enum perm_type ptype,
1612 if (perms == SMB_MODE_NO_CHANGE) {
1613 if (!VALID_STAT(*psbuf)) {
1614 return NT_STATUS_INVALID_PARAMETER;
1616 *ret_perms = psbuf->st_ex_mode;
1617 return NT_STATUS_OK;
1621 ret = wire_perms_to_unix(perms);
1623 if (ptype == PERM_NEW_FILE) {
1625 * "create mask"/"force create mode" are
1626 * only applied to new files, not existing ones.
1628 ret &= lp_create_mask(SNUM(conn));
1629 /* Add in force bits */
1630 ret |= lp_force_create_mode(SNUM(conn));
1631 } else if (ptype == PERM_NEW_DIR) {
1633 * "directory mask"/"force directory mode" are
1634 * only applied to new directories, not existing ones.
1636 ret &= lp_directory_mask(SNUM(conn));
1637 /* Add in force bits */
1638 ret |= lp_force_directory_mode(SNUM(conn));
1642 return NT_STATUS_OK;
1645 /****************************************************************************
1646 Needed to show the msdfs symlinks as directories. Modifies psbuf
1647 to be a directory if it's a msdfs link.
1648 ****************************************************************************/
1650 static bool check_msdfs_link(connection_struct *conn,
1651 struct smb_filename *smb_fname)
1653 int saved_errno = errno;
1654 if(lp_host_msdfs() &&
1655 lp_msdfs_root(SNUM(conn)) &&
1656 is_msdfs_link(conn, smb_fname)) {
1658 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1660 smb_fname->base_name));
1661 smb_fname->st.st_ex_mode =
1662 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1663 errno = saved_errno;
1666 errno = saved_errno;
1671 /****************************************************************************
1672 Get a level dependent lanman2 dir entry.
1673 ****************************************************************************/
1675 struct smbd_dirptr_lanman2_state {
1676 connection_struct *conn;
1677 uint32_t info_level;
1678 bool check_mangled_names;
1680 bool got_exact_match;
1683 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1689 struct smbd_dirptr_lanman2_state *state =
1690 (struct smbd_dirptr_lanman2_state *)private_data;
1692 char mangled_name[13]; /* mangled 8.3 name. */
1696 /* Mangle fname if it's an illegal name. */
1697 if (mangle_must_mangle(dname, state->conn->params)) {
1699 * Slow path - ensure we can push the original name as UCS2. If
1700 * not, then just don't return this name.
1704 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1705 uint8_t *tmp = talloc_array(talloc_tos(),
1709 status = srvstr_push(NULL,
1710 FLAGS2_UNICODE_STRINGS,
1719 if (!NT_STATUS_IS_OK(status)) {
1723 ok = name_to_8_3(dname, mangled_name,
1724 true, state->conn->params);
1728 fname = mangled_name;
1733 got_match = exact_match(state->has_wild,
1734 state->conn->case_sensitive,
1736 state->got_exact_match = got_match;
1738 got_match = mask_match(fname, mask,
1739 state->conn->case_sensitive);
1742 if(!got_match && state->check_mangled_names &&
1743 !mangle_is_8_3(fname, false, state->conn->params)) {
1745 * It turns out that NT matches wildcards against
1746 * both long *and* short names. This may explain some
1747 * of the wildcard wierdness from old DOS clients
1748 * that some people have been seeing.... JRA.
1750 /* Force the mangling into 8.3. */
1751 ok = name_to_8_3(fname, mangled_name,
1752 false, state->conn->params);
1757 got_match = exact_match(state->has_wild,
1758 state->conn->case_sensitive,
1759 mangled_name, mask);
1760 state->got_exact_match = got_match;
1762 got_match = mask_match(mangled_name, mask,
1763 state->conn->case_sensitive);
1771 *_fname = talloc_strdup(ctx, fname);
1772 if (*_fname == NULL) {
1779 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1781 struct smb_filename *smb_fname,
1785 struct smbd_dirptr_lanman2_state *state =
1786 (struct smbd_dirptr_lanman2_state *)private_data;
1787 bool ms_dfs_link = false;
1790 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1791 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1792 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1793 "Couldn't lstat [%s] (%s)\n",
1794 smb_fname_str_dbg(smb_fname),
1798 } else if (!VALID_STAT(smb_fname->st) &&
1799 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1800 /* Needed to show the msdfs symlinks as
1803 ms_dfs_link = check_msdfs_link(state->conn,
1806 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1807 "Couldn't stat [%s] (%s)\n",
1808 smb_fname_str_dbg(smb_fname),
1815 mode = dos_mode_msdfs(state->conn, smb_fname);
1816 } else if (get_dosmode) {
1817 mode = dos_mode(state->conn, smb_fname);
1824 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1825 connection_struct *conn,
1827 uint32_t info_level,
1828 struct ea_list *name_list,
1829 bool check_mangled_names,
1830 bool requires_resume_key,
1833 const struct smb_filename *smb_fname,
1834 int space_remaining,
1840 uint64_t *last_entry_off)
1842 char *p, *q, *pdata = *ppdata;
1844 uint64_t file_size = 0;
1845 uint64_t allocation_size = 0;
1846 uint64_t file_id = 0;
1848 struct timespec mdate_ts = {0};
1849 struct timespec adate_ts = {0};
1850 struct timespec cdate_ts = {0};
1851 struct timespec create_date_ts = {0};
1852 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1854 char *last_entry_ptr;
1859 struct readdir_attr_data *readdir_attr_data = NULL;
1861 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1862 file_size = get_file_size_stat(&smb_fname->st);
1864 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1866 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1867 if (!NT_STATUS_IS_OK(status)) {
1868 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1873 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1875 mdate_ts = smb_fname->st.st_ex_mtime;
1876 adate_ts = smb_fname->st.st_ex_atime;
1877 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1878 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1880 if (lp_dos_filetime_resolution(SNUM(conn))) {
1881 dos_filetime_timespec(&create_date_ts);
1882 dos_filetime_timespec(&mdate_ts);
1883 dos_filetime_timespec(&adate_ts);
1884 dos_filetime_timespec(&cdate_ts);
1887 create_date = convert_timespec_to_time_t(create_date_ts);
1888 mdate = convert_timespec_to_time_t(mdate_ts);
1889 adate = convert_timespec_to_time_t(adate_ts);
1891 /* align the record */
1892 SMB_ASSERT(align >= 1);
1894 off = (int)PTR_DIFF(pdata, base_data);
1895 pad = (off + (align-1)) & ~(align-1);
1898 if (pad && pad > space_remaining) {
1899 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1900 "for padding (wanted %u, had %d)\n",
1903 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1907 /* initialize padding to 0 */
1909 memset(pdata, 0, pad);
1911 space_remaining -= pad;
1913 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1923 switch (info_level) {
1924 case SMB_FIND_INFO_STANDARD:
1925 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1926 if(requires_resume_key) {
1930 srv_put_dos_date2(p,0,create_date);
1931 srv_put_dos_date2(p,4,adate);
1932 srv_put_dos_date2(p,8,mdate);
1933 SIVAL(p,12,(uint32_t)file_size);
1934 SIVAL(p,16,(uint32_t)allocation_size);
1938 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1939 p += ucs2_align(base_data, p, 0);
1941 status = srvstr_push(base_data, flags2, p,
1942 fname, PTR_DIFF(end_data, p),
1943 STR_TERMINATE, &len);
1944 if (!NT_STATUS_IS_OK(status)) {
1947 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1949 SCVAL(nameptr, -1, len - 2);
1951 SCVAL(nameptr, -1, 0);
1955 SCVAL(nameptr, -1, len - 1);
1957 SCVAL(nameptr, -1, 0);
1963 case SMB_FIND_EA_SIZE:
1964 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1965 if (requires_resume_key) {
1969 srv_put_dos_date2(p,0,create_date);
1970 srv_put_dos_date2(p,4,adate);
1971 srv_put_dos_date2(p,8,mdate);
1972 SIVAL(p,12,(uint32_t)file_size);
1973 SIVAL(p,16,(uint32_t)allocation_size);
1976 unsigned int ea_size = estimate_ea_size(conn, NULL,
1978 SIVAL(p,22,ea_size); /* Extended attributes */
1982 status = srvstr_push(base_data, flags2,
1983 p, fname, PTR_DIFF(end_data, p),
1984 STR_TERMINATE | STR_NOALIGN, &len);
1985 if (!NT_STATUS_IS_OK(status)) {
1988 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2001 SCVAL(nameptr,0,len);
2003 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2006 case SMB_FIND_EA_LIST:
2008 struct ea_list *file_list = NULL;
2011 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
2013 return NT_STATUS_INVALID_PARAMETER;
2015 if (requires_resume_key) {
2019 srv_put_dos_date2(p,0,create_date);
2020 srv_put_dos_date2(p,4,adate);
2021 srv_put_dos_date2(p,8,mdate);
2022 SIVAL(p,12,(uint32_t)file_size);
2023 SIVAL(p,16,(uint32_t)allocation_size);
2025 p += 22; /* p now points to the EA area. */
2027 status = get_ea_list_from_file(ctx, conn, NULL,
2029 &ea_len, &file_list);
2030 if (!NT_STATUS_IS_OK(status)) {
2033 name_list = ea_list_union(name_list, file_list, &ea_len);
2035 /* We need to determine if this entry will fit in the space available. */
2036 /* Max string size is 255 bytes. */
2037 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2038 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2039 "(wanted %u, had %d)\n",
2040 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2042 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2045 /* Push the ea_data followed by the name. */
2046 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2048 status = srvstr_push(base_data, flags2,
2049 p + 1, fname, PTR_DIFF(end_data, p+1),
2050 STR_TERMINATE | STR_NOALIGN, &len);
2051 if (!NT_STATUS_IS_OK(status)) {
2054 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2067 SCVAL(nameptr,0,len);
2069 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2073 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2074 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2075 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2077 SIVAL(p,0,reskey); p += 4;
2078 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2079 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2080 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2081 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2082 SOFF_T(p,0,file_size); p += 8;
2083 SOFF_T(p,0,allocation_size); p += 8;
2084 SIVAL(p,0,mode); p += 4;
2085 q = p; p += 4; /* q is placeholder for name length. */
2086 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2087 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2089 unsigned int ea_size = estimate_ea_size(conn, NULL,
2091 SIVAL(p,0,ea_size); /* Extended attributes */
2094 /* Clear the short name buffer. This is
2095 * IMPORTANT as not doing so will trigger
2096 * a Win2k client bug. JRA.
2098 if (!was_8_3 && check_mangled_names) {
2099 char mangled_name[13]; /* mangled 8.3 name. */
2100 if (!name_to_8_3(fname,mangled_name,True,
2102 /* Error - mangle failed ! */
2103 memset(mangled_name,'\0',12);
2105 mangled_name[12] = 0;
2106 status = srvstr_push(base_data, flags2,
2107 p+2, mangled_name, 24,
2108 STR_UPPER|STR_UNICODE, &len);
2109 if (!NT_STATUS_IS_OK(status)) {
2113 memset(p + 2 + len,'\0',24 - len);
2120 status = srvstr_push(base_data, flags2, p,
2121 fname, PTR_DIFF(end_data, p),
2122 STR_TERMINATE_ASCII, &len);
2123 if (!NT_STATUS_IS_OK(status)) {
2129 len = PTR_DIFF(p, pdata);
2130 pad = (len + (align-1)) & ~(align-1);
2132 * offset to the next entry, the caller
2133 * will overwrite it for the last entry
2134 * that's why we always include the padding
2138 * set padding to zero
2141 memset(p, 0, pad - len);
2148 case SMB_FIND_FILE_DIRECTORY_INFO:
2149 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2151 SIVAL(p,0,reskey); p += 4;
2152 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2153 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2154 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2155 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2156 SOFF_T(p,0,file_size); p += 8;
2157 SOFF_T(p,0,allocation_size); p += 8;
2158 SIVAL(p,0,mode); p += 4;
2159 status = srvstr_push(base_data, flags2,
2160 p + 4, fname, PTR_DIFF(end_data, p+4),
2161 STR_TERMINATE_ASCII, &len);
2162 if (!NT_STATUS_IS_OK(status)) {
2168 len = PTR_DIFF(p, pdata);
2169 pad = (len + (align-1)) & ~(align-1);
2171 * offset to the next entry, the caller
2172 * will overwrite it for the last entry
2173 * that's why we always include the padding
2177 * set padding to zero
2180 memset(p, 0, pad - len);
2187 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2188 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2190 SIVAL(p,0,reskey); p += 4;
2191 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2192 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2193 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2194 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2195 SOFF_T(p,0,file_size); p += 8;
2196 SOFF_T(p,0,allocation_size); p += 8;
2197 SIVAL(p,0,mode); p += 4;
2198 q = p; p += 4; /* q is placeholder for name length. */
2199 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2200 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2202 unsigned int ea_size = estimate_ea_size(conn, NULL,
2204 SIVAL(p,0,ea_size); /* Extended attributes */
2207 status = srvstr_push(base_data, flags2, p,
2208 fname, PTR_DIFF(end_data, p),
2209 STR_TERMINATE_ASCII, &len);
2210 if (!NT_STATUS_IS_OK(status)) {
2216 len = PTR_DIFF(p, pdata);
2217 pad = (len + (align-1)) & ~(align-1);
2219 * offset to the next entry, the caller
2220 * will overwrite it for the last entry
2221 * that's why we always include the padding
2225 * set padding to zero
2228 memset(p, 0, pad - len);
2235 case SMB_FIND_FILE_NAMES_INFO:
2236 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2238 SIVAL(p,0,reskey); p += 4;
2240 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2241 acl on a dir (tridge) */
2242 status = srvstr_push(base_data, flags2, p,
2243 fname, PTR_DIFF(end_data, p),
2244 STR_TERMINATE_ASCII, &len);
2245 if (!NT_STATUS_IS_OK(status)) {
2251 len = PTR_DIFF(p, pdata);
2252 pad = (len + (align-1)) & ~(align-1);
2254 * offset to the next entry, the caller
2255 * will overwrite it for the last entry
2256 * that's why we always include the padding
2260 * set padding to zero
2263 memset(p, 0, pad - len);
2270 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2271 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2273 SIVAL(p,0,reskey); p += 4;
2274 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2275 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2276 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2277 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2278 SOFF_T(p,0,file_size); p += 8;
2279 SOFF_T(p,0,allocation_size); p += 8;
2280 SIVAL(p,0,mode); p += 4;
2281 q = p; p += 4; /* q is placeholder for name length. */
2282 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2283 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2285 unsigned int ea_size = estimate_ea_size(conn, NULL,
2287 SIVAL(p,0,ea_size); /* Extended attributes */
2290 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2291 SBVAL(p,0,file_id); p += 8;
2292 status = srvstr_push(base_data, flags2, p,
2293 fname, PTR_DIFF(end_data, p),
2294 STR_TERMINATE_ASCII, &len);
2295 if (!NT_STATUS_IS_OK(status)) {
2301 len = PTR_DIFF(p, pdata);
2302 pad = (len + (align-1)) & ~(align-1);
2304 * offset to the next entry, the caller
2305 * will overwrite it for the last entry
2306 * that's why we always include the padding
2310 * set padding to zero
2313 memset(p, 0, pad - len);
2320 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2321 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2322 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2324 SIVAL(p,0,reskey); p += 4;
2325 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2326 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2327 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2328 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2329 SOFF_T(p,0,file_size); p += 8;
2330 SOFF_T(p,0,allocation_size); p += 8;
2331 SIVAL(p,0,mode); p += 4;
2332 q = p; p += 4; /* q is placeholder for name length */
2333 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2334 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2335 } else if (readdir_attr_data &&
2336 readdir_attr_data->type == RDATTR_AAPL) {
2338 * OS X specific SMB2 extension negotiated via
2339 * AAPL create context: return max_access in
2342 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2344 unsigned int ea_size = estimate_ea_size(conn, NULL,
2346 SIVAL(p,0,ea_size); /* Extended attributes */
2350 if (readdir_attr_data &&
2351 readdir_attr_data->type == RDATTR_AAPL) {
2353 * OS X specific SMB2 extension negotiated via
2354 * AAPL create context: return resource fork
2355 * length and compressed FinderInfo in
2358 * According to documentation short_name_len
2359 * should be 0, but on the wire behaviour
2360 * shows its set to 24 by clients.
2364 /* Resourefork length */
2365 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2367 /* Compressed FinderInfo */
2368 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2369 } else if (!was_8_3 && check_mangled_names) {
2370 char mangled_name[13]; /* mangled 8.3 name. */
2371 if (!name_to_8_3(fname,mangled_name,True,
2373 /* Error - mangle failed ! */
2374 memset(mangled_name,'\0',12);
2376 mangled_name[12] = 0;
2377 status = srvstr_push(base_data, flags2,
2378 p+2, mangled_name, 24,
2379 STR_UPPER|STR_UNICODE, &len);
2380 if (!NT_STATUS_IS_OK(status)) {
2385 memset(p + 2 + len,'\0',24 - len);
2389 /* Clear the short name buffer. This is
2390 * IMPORTANT as not doing so will trigger
2391 * a Win2k client bug. JRA.
2398 if (readdir_attr_data &&
2399 readdir_attr_data->type == RDATTR_AAPL) {
2401 * OS X specific SMB2 extension negotiated via
2402 * AAPL create context: return UNIX mode in
2405 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2406 SSVAL(p, 0, aapl_mode);
2412 SBVAL(p,0,file_id); p += 8;
2413 status = srvstr_push(base_data, flags2, p,
2414 fname, PTR_DIFF(end_data, p),
2415 STR_TERMINATE_ASCII, &len);
2416 if (!NT_STATUS_IS_OK(status)) {
2422 len = PTR_DIFF(p, pdata);
2423 pad = (len + (align-1)) & ~(align-1);
2425 * offset to the next entry, the caller
2426 * will overwrite it for the last entry
2427 * that's why we always include the padding
2431 * set padding to zero
2434 memset(p, 0, pad - len);
2441 /* CIFS UNIX Extension. */
2443 case SMB_FIND_FILE_UNIX:
2444 case SMB_FIND_FILE_UNIX_INFO2:
2446 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2448 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2450 if (info_level == SMB_FIND_FILE_UNIX) {
2451 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2452 p = store_file_unix_basic(conn, p,
2453 NULL, &smb_fname->st);
2454 status = srvstr_push(base_data, flags2, p,
2455 fname, PTR_DIFF(end_data, p),
2456 STR_TERMINATE, &len);
2457 if (!NT_STATUS_IS_OK(status)) {
2461 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2462 p = store_file_unix_basic_info2(conn, p,
2463 NULL, &smb_fname->st);
2466 status = srvstr_push(base_data, flags2, p, fname,
2467 PTR_DIFF(end_data, p), 0, &len);
2468 if (!NT_STATUS_IS_OK(status)) {
2471 SIVAL(nameptr, 0, len);
2476 len = PTR_DIFF(p, pdata);
2477 pad = (len + (align-1)) & ~(align-1);
2479 * offset to the next entry, the caller
2480 * will overwrite it for the last entry
2481 * that's why we always include the padding
2485 * set padding to zero
2488 memset(p, 0, pad - len);
2493 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2498 return NT_STATUS_INVALID_LEVEL;
2501 if (PTR_DIFF(p,pdata) > space_remaining) {
2502 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2503 "(wanted %u, had %d)\n",
2504 (unsigned int)PTR_DIFF(p,pdata),
2506 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2509 /* Setup the last entry pointer, as an offset from base_data */
2510 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2511 /* Advance the data pointer to the next slot */
2514 return NT_STATUS_OK;
2517 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2518 connection_struct *conn,
2519 struct dptr_struct *dirptr,
2521 const char *path_mask,
2524 int requires_resume_key,
2533 int space_remaining,
2534 struct smb_filename **_smb_fname,
2535 bool *got_exact_match,
2536 int *_last_entry_off,
2537 struct ea_list *name_list,
2538 struct file_id *file_id)
2541 const char *mask = NULL;
2542 long prev_dirpos = 0;
2545 struct smb_filename *smb_fname = NULL;
2546 struct smbd_dirptr_lanman2_state state;
2548 uint64_t last_entry_off = 0;
2550 enum mangled_names_options mangled_names;
2551 bool marshall_with_83_names;
2553 mangled_names = lp_mangled_names(conn->params);
2557 state.info_level = info_level;
2558 if (mangled_names != MANGLED_NAMES_NO) {
2559 state.check_mangled_names = true;
2561 state.has_wild = dptr_has_wild(dirptr);
2562 state.got_exact_match = false;
2564 *got_exact_match = false;
2566 p = strrchr_m(path_mask,'/');
2577 ok = smbd_dirptr_get_entry(ctx,
2584 smbd_dirptr_lanman2_match_fn,
2585 smbd_dirptr_lanman2_mode_fn,
2592 return NT_STATUS_END_OF_FILE;
2595 *got_exact_match = state.got_exact_match;
2597 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2599 status = smbd_marshall_dir_entry(ctx,
2604 marshall_with_83_names,
2605 requires_resume_key,
2616 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2617 DEBUG(1,("Conversion error: illegal character: %s\n",
2618 smb_fname_str_dbg(smb_fname)));
2621 if (file_id != NULL) {
2622 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2625 if (!NT_STATUS_IS_OK(status) &&
2626 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2628 TALLOC_FREE(smb_fname);
2633 if (_smb_fname != NULL) {
2634 struct smb_filename *name = NULL;
2636 name = synthetic_smb_fname(ctx,
2643 TALLOC_FREE(smb_fname);
2645 return NT_STATUS_NO_MEMORY;
2650 TALLOC_FREE(smb_fname);
2653 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2654 dptr_SeekDir(dirptr, prev_dirpos);
2658 *_last_entry_off = last_entry_off;
2659 return NT_STATUS_OK;
2662 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2663 connection_struct *conn,
2664 struct dptr_struct *dirptr,
2666 const char *path_mask,
2669 bool requires_resume_key,
2675 int space_remaining,
2676 bool *got_exact_match,
2677 int *last_entry_off,
2678 struct ea_list *name_list)
2681 const bool do_pad = true;
2683 if (info_level >= 1 && info_level <= 3) {
2684 /* No alignment on earlier info levels. */
2688 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2689 path_mask, dirtype, info_level,
2690 requires_resume_key, dont_descend, ask_sharemode,
2691 true, align, do_pad,
2692 ppdata, base_data, end_data,
2696 last_entry_off, name_list, NULL);
2699 /****************************************************************************
2700 Reply to a TRANS2_FINDFIRST.
2701 ****************************************************************************/
2703 static void call_trans2findfirst(connection_struct *conn,
2704 struct smb_request *req,
2705 char **pparams, int total_params,
2706 char **ppdata, int total_data,
2707 unsigned int max_data_bytes)
2709 /* We must be careful here that we don't return more than the
2710 allowed number of data bytes. If this means returning fewer than
2711 maxentries then so be it. We assume that the redirector has
2712 enough room for the fixed number of parameter bytes it has
2714 struct smb_filename *smb_dname = NULL;
2715 char *params = *pparams;
2716 char *pdata = *ppdata;
2720 uint16_t findfirst_flags;
2721 bool close_after_first;
2723 bool requires_resume_key;
2725 char *directory = NULL;
2728 int last_entry_off=0;
2732 bool finished = False;
2733 bool dont_descend = False;
2734 bool out_of_space = False;
2735 int space_remaining;
2736 bool mask_contains_wcard = False;
2737 struct ea_list *ea_list = NULL;
2738 NTSTATUS ntstatus = NT_STATUS_OK;
2739 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
2740 struct smbd_server_connection *sconn = req->sconn;
2741 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2742 ucf_flags_from_smb_request(req);
2743 bool backup_priv = false;
2744 bool as_root = false;
2745 files_struct *fsp = NULL;
2746 const struct loadparm_substitution *lp_sub =
2747 loadparm_s3_global_substitution();
2750 if (total_params < 13) {
2751 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2755 dirtype = SVAL(params,0);
2756 maxentries = SVAL(params,2);
2757 findfirst_flags = SVAL(params,4);
2758 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2759 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2760 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2761 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2762 security_token_has_privilege(get_current_nttok(conn),
2765 info_level = SVAL(params,6);
2767 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2768 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2769 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2771 info_level, max_data_bytes));
2774 /* W2K3 seems to treat zero as 1. */
2778 switch (info_level) {
2779 case SMB_FIND_INFO_STANDARD:
2780 case SMB_FIND_EA_SIZE:
2781 case SMB_FIND_EA_LIST:
2782 case SMB_FIND_FILE_DIRECTORY_INFO:
2783 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2784 case SMB_FIND_FILE_NAMES_INFO:
2785 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2786 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2787 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2789 case SMB_FIND_FILE_UNIX:
2790 case SMB_FIND_FILE_UNIX_INFO2:
2791 /* Always use filesystem for UNIX mtime query. */
2792 ask_sharemode = false;
2793 if (!lp_unix_extensions()) {
2794 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2797 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2800 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2804 if (req->posix_pathnames) {
2805 srvstr_get_path_wcard_posix(talloc_tos(),
2813 &mask_contains_wcard);
2815 srvstr_get_path_wcard(talloc_tos(),
2823 &mask_contains_wcard);
2825 if (!NT_STATUS_IS_OK(ntstatus)) {
2826 reply_nterror(req, ntstatus);
2833 ntstatus = filename_convert_with_privilege(talloc_tos(),
2838 &mask_contains_wcard,
2841 ntstatus = filename_convert(talloc_tos(), conn,
2845 &mask_contains_wcard,
2849 if (!NT_STATUS_IS_OK(ntstatus)) {
2850 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2851 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2852 ERRSRV, ERRbadpath);
2855 reply_nterror(req, ntstatus);
2859 mask = get_original_lcomp(talloc_tos(),
2864 reply_nterror(req, NT_STATUS_NO_MEMORY);
2868 directory = smb_dname->base_name;
2870 p = strrchr_m(directory,'/');
2872 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2873 if((directory[0] == '.') && (directory[1] == '\0')) {
2874 mask = talloc_strdup(talloc_tos(),"*");
2876 reply_nterror(req, NT_STATUS_NO_MEMORY);
2879 mask_contains_wcard = True;
2885 if (p == NULL || p == directory) {
2886 struct smb_filename *old_name = smb_dname;
2888 /* Ensure we don't have a directory name of "". */
2889 smb_dname = synthetic_smb_fname(talloc_tos(),
2895 TALLOC_FREE(old_name);
2896 if (smb_dname == NULL) {
2897 reply_nterror(req, NT_STATUS_NO_MEMORY);
2900 directory = smb_dname->base_name;
2903 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2905 if (info_level == SMB_FIND_EA_LIST) {
2908 if (total_data < 4) {
2909 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2913 ea_size = IVAL(pdata,0);
2914 if (ea_size != total_data) {
2915 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2916 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2917 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2921 if (!lp_ea_support(SNUM(conn))) {
2922 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2926 /* Pull out the list of names. */
2927 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2934 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2939 *ppdata = (char *)SMB_REALLOC(
2940 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2941 if(*ppdata == NULL ) {
2942 reply_nterror(req, NT_STATUS_NO_MEMORY);
2946 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2948 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2951 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2952 /* Realloc the params space */
2953 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2954 if (*pparams == NULL) {
2955 reply_nterror(req, NT_STATUS_NO_MEMORY);
2961 * As we've cut off the last component from
2962 * smb_fname we need to re-stat smb_dname
2963 * so FILE_OPEN disposition knows the directory
2966 if (req->posix_pathnames) {
2967 ret = SMB_VFS_LSTAT(conn, smb_dname);
2969 ret = SMB_VFS_STAT(conn, smb_dname);
2973 ntstatus = map_nt_error_from_unix(errno);
2974 reply_nterror(req, ntstatus);
2979 * Open an fsp on this directory for the dptr.
2981 ntstatus = SMB_VFS_CREATE_FILE(
2984 &conn->cwd_fsp, /* dirfsp */
2985 smb_dname, /* dname */
2986 FILE_LIST_DIRECTORY, /* access_mask */
2988 FILE_SHARE_WRITE, /* share_access */
2989 FILE_OPEN, /* create_disposition*/
2990 FILE_DIRECTORY_FILE, /* create_options */
2991 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2992 NO_OPLOCK, /* oplock_request */
2994 0, /* allocation_size */
2995 0, /* private_flags */
3000 NULL, /* in_context */
3001 NULL);/* out_context */
3003 if (!NT_STATUS_IS_OK(ntstatus)) {
3004 DBG_ERR("failed to open directory %s\n",
3005 smb_fname_str_dbg(smb_dname));
3006 reply_nterror(req, ntstatus);
3010 /* Save the wildcard match and attribs we are using on this directory -
3011 needed as lanman2 assumes these are being saved between calls */
3013 ntstatus = dptr_create(conn,
3023 if (!NT_STATUS_IS_OK(ntstatus)) {
3025 * Use NULL here for the first parameter (req)
3026 * as this is not a client visible handle so
3027 * can'tbe part of an SMB1 chain.
3029 close_file(NULL, fsp, NORMAL_CLOSE);
3031 reply_nterror(req, ntstatus);
3036 /* Remember this in case we have
3037 to do a findnext. */
3038 dptr_set_priv(fsp->dptr);
3041 dptr_num = dptr_dnum(fsp->dptr);
3042 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
3044 /* We don't need to check for VOL here as this is returned by
3045 a different TRANS2 call. */
3047 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3048 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
3049 if (in_list(directory,
3050 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
3051 conn->case_sensitive)) {
3052 dont_descend = True;
3056 space_remaining = max_data_bytes;
3057 out_of_space = False;
3059 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
3060 bool got_exact_match = False;
3062 /* this is a heuristic to avoid seeking the dirptr except when
3063 absolutely necessary. It allows for a filename of about 40 chars */
3064 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3065 out_of_space = True;
3068 ntstatus = get_lanman2_dir_entry(talloc_tos(),
3072 mask,dirtype,info_level,
3073 requires_resume_key,dont_descend,
3078 &last_entry_off, ea_list);
3079 if (NT_STATUS_EQUAL(ntstatus,
3080 NT_STATUS_ILLEGAL_CHARACTER)) {
3082 * Bad character conversion on name. Ignore this
3087 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3088 out_of_space = true;
3090 finished = !NT_STATUS_IS_OK(ntstatus);
3094 if (!finished && !out_of_space)
3098 * As an optimisation if we know we aren't looking
3099 * for a wildcard name (ie. the name matches the wildcard exactly)
3100 * then we can finish on any (first) match.
3101 * This speeds up large directory searches. JRA.
3107 /* Ensure space_remaining never goes -ve. */
3108 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3109 space_remaining = 0;
3110 out_of_space = true;
3112 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3116 /* Check if we can close the dirptr */
3117 if(close_after_first || (finished && close_if_end)) {
3118 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3120 close_file(NULL, fsp, NORMAL_CLOSE);
3125 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3126 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3127 * the protocol level is less than NT1. Tested with smbclient. JRA.
3128 * This should fix the OS/2 client bug #2335.
3131 if(numentries == 0) {
3134 * We may have already closed the file in the
3135 * close_after_first or finished case above.
3138 close_file(NULL, fsp, NORMAL_CLOSE);
3141 if (get_Protocol() < PROTOCOL_NT1) {
3142 reply_force_doserror(req, ERRDOS, ERRnofiles);
3145 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3146 ERRDOS, ERRbadfile);
3151 /* At this point pdata points to numentries directory entries. */
3153 /* Set up the return parameter block */
3154 SSVAL(params,0,dptr_num);
3155 SSVAL(params,2,numentries);
3156 SSVAL(params,4,finished);
3157 SSVAL(params,6,0); /* Never an EA error */
3158 SSVAL(params,8,last_entry_off);
3160 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3163 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3164 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3166 reply_nterror(req, NT_STATUS_NO_MEMORY);
3170 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3171 smb_fn_name(req->cmd),
3172 mask, directory, dirtype, numentries ) );
3175 * Force a name mangle here to ensure that the
3176 * mask as an 8.3 name is top of the mangled cache.
3177 * The reasons for this are subtle. Don't remove
3178 * this code unless you know what you are doing
3179 * (see PR#13758). JRA.
3182 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3183 char mangled_name[13];
3184 name_to_8_3(mask, mangled_name, True, conn->params);
3192 TALLOC_FREE(smb_dname);
3196 /****************************************************************************
3197 Reply to a TRANS2_FINDNEXT.
3198 ****************************************************************************/
3200 static void call_trans2findnext(connection_struct *conn,
3201 struct smb_request *req,
3202 char **pparams, int total_params,
3203 char **ppdata, int total_data,
3204 unsigned int max_data_bytes)
3206 /* We must be careful here that we don't return more than the
3207 allowed number of data bytes. If this means returning fewer than
3208 maxentries then so be it. We assume that the redirector has
3209 enough room for the fixed number of parameter bytes it has
3211 char *params = *pparams;
3212 char *pdata = *ppdata;
3216 uint16_t info_level;
3217 uint32_t resume_key;
3218 uint16_t findnext_flags;
3219 bool close_after_request;
3221 bool requires_resume_key;
3223 bool mask_contains_wcard = False;
3224 char *resume_name = NULL;
3225 const char *mask = NULL;
3226 const char *directory = NULL;
3230 int i, last_entry_off=0;
3231 bool finished = False;
3232 bool dont_descend = False;
3233 bool out_of_space = False;
3234 int space_remaining;
3235 struct ea_list *ea_list = NULL;
3236 NTSTATUS ntstatus = NT_STATUS_OK;
3237 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3238 TALLOC_CTX *ctx = talloc_tos();
3239 struct smbd_server_connection *sconn = req->sconn;
3240 bool backup_priv = false;
3241 bool as_root = false;
3242 files_struct *fsp = NULL;
3243 const struct loadparm_substitution *lp_sub =
3244 loadparm_s3_global_substitution();
3246 if (total_params < 13) {
3247 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3251 dptr_num = SVAL(params,0);
3252 maxentries = SVAL(params,2);
3253 info_level = SVAL(params,4);
3254 resume_key = IVAL(params,6);
3255 findnext_flags = SVAL(params,10);
3256 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3257 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3258 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3259 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3261 if (!continue_bit) {
3262 /* We only need resume_name if continue_bit is zero. */
3263 if (req->posix_pathnames) {
3264 srvstr_get_path_wcard_posix(ctx,
3272 &mask_contains_wcard);
3274 srvstr_get_path_wcard(ctx,
3282 &mask_contains_wcard);
3284 if (!NT_STATUS_IS_OK(ntstatus)) {
3285 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3286 complain (it thinks we're asking for the directory above the shared
3287 path or an invalid name). Catch this as the resume name is only compared, never used in
3288 a file access. JRA. */
3289 srvstr_pull_talloc(ctx, params, req->flags2,
3290 &resume_name, params+12,
3294 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3295 reply_nterror(req, ntstatus);
3301 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3302 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3303 resume_key = %d resume name = %s continue=%d level = %d\n",
3304 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3305 requires_resume_key, resume_key,
3306 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3309 /* W2K3 seems to treat zero as 1. */
3313 switch (info_level) {
3314 case SMB_FIND_INFO_STANDARD:
3315 case SMB_FIND_EA_SIZE:
3316 case SMB_FIND_EA_LIST:
3317 case SMB_FIND_FILE_DIRECTORY_INFO:
3318 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3319 case SMB_FIND_FILE_NAMES_INFO:
3320 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3321 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3322 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3324 case SMB_FIND_FILE_UNIX:
3325 case SMB_FIND_FILE_UNIX_INFO2:
3326 /* Always use filesystem for UNIX mtime query. */
3327 ask_sharemode = false;
3328 if (!lp_unix_extensions()) {
3329 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3334 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3338 if (info_level == SMB_FIND_EA_LIST) {
3341 if (total_data < 4) {
3342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3346 ea_size = IVAL(pdata,0);
3347 if (ea_size != total_data) {
3348 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3349 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3354 if (!lp_ea_support(SNUM(conn))) {
3355 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3359 /* Pull out the list of names. */
3360 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3367 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3372 *ppdata = (char *)SMB_REALLOC(
3373 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3374 if(*ppdata == NULL) {
3375 reply_nterror(req, NT_STATUS_NO_MEMORY);
3380 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3383 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3386 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3387 /* Realloc the params space */
3388 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3389 if(*pparams == NULL ) {
3390 reply_nterror(req, NT_STATUS_NO_MEMORY);
3396 /* Check that the dptr is valid */
3397 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3399 reply_nterror(req, STATUS_NO_MORE_FILES);
3403 directory = dptr_path(sconn, dptr_num);
3405 /* Get the wildcard mask from the dptr */
3406 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3407 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3408 reply_nterror(req, STATUS_NO_MORE_FILES);
3412 /* Get the attr mask from the dptr */
3413 dirtype = dptr_attr(sconn, dptr_num);
3415 backup_priv = dptr_get_priv(fsp->dptr);
3417 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3418 "backup_priv = %d\n",
3419 dptr_num, mask, dirtype,
3421 dptr_TellDir(fsp->dptr),
3424 /* We don't need to check for VOL here as this is returned by
3425 a different TRANS2 call. */
3427 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3428 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
3429 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
3430 dont_descend = True;
3433 space_remaining = max_data_bytes;
3434 out_of_space = False;
3442 * Seek to the correct position. We no longer use the resume key but
3443 * depend on the last file name instead.
3446 if(!continue_bit && resume_name && *resume_name) {
3449 long current_pos = 0;
3451 * Remember, name_to_8_3 is called by
3452 * get_lanman2_dir_entry(), so the resume name
3453 * could be mangled. Ensure we check the unmangled name.
3456 if (mangle_is_mangled(resume_name, conn->params)) {
3457 char *new_resume_name = NULL;
3458 mangle_lookup_name_from_8_3(ctx,
3462 if (new_resume_name) {
3463 resume_name = new_resume_name;
3468 * Fix for NT redirector problem triggered by resume key indexes
3469 * changing between directory scans. We now return a resume key of 0
3470 * and instead look for the filename to continue from (also given
3471 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3472 * findfirst/findnext (as is usual) then the directory pointer
3473 * should already be at the correct place.
3476 finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
3477 } /* end if resume_name && !continue_bit */
3479 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3480 bool got_exact_match = False;
3482 /* this is a heuristic to avoid seeking the fsp->dptr except when
3483 absolutely necessary. It allows for a filename of about 40 chars */
3484 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3485 out_of_space = True;
3488 ntstatus = get_lanman2_dir_entry(ctx,
3492 mask,dirtype,info_level,
3493 requires_resume_key,dont_descend,
3498 &last_entry_off, ea_list);
3499 if (NT_STATUS_EQUAL(ntstatus,
3500 NT_STATUS_ILLEGAL_CHARACTER)) {
3502 * Bad character conversion on name. Ignore this
3507 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3508 out_of_space = true;
3510 finished = !NT_STATUS_IS_OK(ntstatus);
3514 if (!finished && !out_of_space)
3518 * As an optimisation if we know we aren't looking
3519 * for a wildcard name (ie. the name matches the wildcard exactly)
3520 * then we can finish on any (first) match.
3521 * This speeds up large directory searches. JRA.
3527 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3530 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3531 smb_fn_name(req->cmd),
3532 mask, directory, dirtype, numentries ) );
3534 /* Check if we can close the fsp->dptr */
3535 if(close_after_request || (finished && close_if_end)) {
3536 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3538 close_file(NULL, fsp, NORMAL_CLOSE);
3546 /* Set up the return parameter block */
3547 SSVAL(params,0,numentries);
3548 SSVAL(params,2,finished);
3549 SSVAL(params,4,0); /* Never an EA error */
3550 SSVAL(params,6,last_entry_off);
3552 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3558 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3560 const struct loadparm_substitution *lp_sub =
3561 loadparm_s3_global_substitution();
3563 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
3567 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3569 SMB_ASSERT(extended_info != NULL);
3571 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3572 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3573 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3574 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3575 #ifdef SAMBA_VERSION_REVISION
3576 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3578 extended_info->samba_subversion = 0;
3579 #ifdef SAMBA_VERSION_RC_RELEASE
3580 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3582 #ifdef SAMBA_VERSION_PRE_RELEASE
3583 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3586 #ifdef SAMBA_VERSION_VENDOR_PATCH
3587 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3589 extended_info->samba_gitcommitdate = 0;
3590 #ifdef SAMBA_VERSION_COMMIT_TIME
3591 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3594 memset(extended_info->samba_version_string, 0,
3595 sizeof(extended_info->samba_version_string));
3597 snprintf (extended_info->samba_version_string,
3598 sizeof(extended_info->samba_version_string),
3599 "%s", samba_version_string());
3602 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3603 connection_struct *conn,
3604 TALLOC_CTX *mem_ctx,
3605 uint16_t info_level,
3607 unsigned int max_data_bytes,
3608 size_t *fixed_portion,
3609 struct smb_filename *fname,
3613 const struct loadparm_substitution *lp_sub =
3614 loadparm_s3_global_substitution();
3615 char *pdata, *end_data;
3618 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3619 int snum = SNUM(conn);
3620 const char *fstype = lp_fstype(SNUM(conn));
3621 const char *filename = NULL;
3622 const uint64_t bytes_per_sector = 512;
3623 uint32_t additional_flags = 0;
3624 struct smb_filename smb_fname;
3626 NTSTATUS status = NT_STATUS_OK;
3629 if (fname == NULL || fname->base_name == NULL) {
3632 filename = fname->base_name;
3636 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3637 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3638 "info level (0x%x) on IPC$.\n",
3639 (unsigned int)info_level));
3640 return NT_STATUS_ACCESS_DENIED;
3644 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3646 ZERO_STRUCT(smb_fname);
3647 smb_fname.base_name = discard_const_p(char, filename);
3649 if(info_level != SMB_FS_QUOTA_INFORMATION
3650 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3651 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3652 return map_nt_error_from_unix(errno);
3657 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3658 return NT_STATUS_INVALID_PARAMETER;
3661 *ppdata = (char *)SMB_REALLOC(
3662 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3663 if (*ppdata == NULL) {
3664 return NT_STATUS_NO_MEMORY;
3668 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3669 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3673 switch (info_level) {
3674 case SMB_INFO_ALLOCATION:
3676 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3678 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3680 if (df_ret == (uint64_t)-1) {
3681 return map_nt_error_from_unix(errno);
3684 block_size = lp_block_size(snum);
3685 if (bsize < block_size) {
3686 uint64_t factor = block_size/bsize;
3691 if (bsize > block_size) {
3692 uint64_t factor = bsize/block_size;
3697 sectors_per_unit = bsize/bytes_per_sector;
3699 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3700 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3701 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3704 * For large drives, return max values and not modulo.
3706 dsize = MIN(dsize, UINT32_MAX);
3707 dfree = MIN(dfree, UINT32_MAX);
3709 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3710 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3711 SIVAL(pdata,l1_cUnit,dsize);
3712 SIVAL(pdata,l1_cUnitAvail,dfree);
3713 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3717 case SMB_INFO_VOLUME:
3718 /* Return volume name */
3720 * Add volume serial number - hash of a combination of
3721 * the called hostname and the service name.
3723 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3725 * Win2k3 and previous mess this up by sending a name length
3726 * one byte short. I believe only older clients (OS/2 Win9x) use
3727 * this call so try fixing this by adding a terminating null to
3728 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3730 status = srvstr_push(
3732 pdata+l2_vol_szVolLabel, vname,
3733 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3734 STR_NOALIGN|STR_TERMINATE, &len);
3735 if (!NT_STATUS_IS_OK(status)) {
3738 SCVAL(pdata,l2_vol_cch,len);
3739 data_len = l2_vol_szVolLabel + len;
3740 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3741 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3742 (unsigned)len, vname));
3745 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3746 case SMB_FS_ATTRIBUTE_INFORMATION:
3748 additional_flags = 0;
3749 #if defined(HAVE_SYS_QUOTAS)
3750 additional_flags |= FILE_VOLUME_QUOTAS;
3753 if(lp_nt_acl_support(SNUM(conn))) {
3754 additional_flags |= FILE_PERSISTENT_ACLS;
3757 /* Capabilities are filled in at connection time through STATVFS call */
3758 additional_flags |= conn->fs_capabilities;
3759 additional_flags |= lp_parm_int(conn->params->service,
3760 "share", "fake_fscaps",
3763 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3764 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3765 additional_flags); /* FS ATTRIBUTES */
3767 SIVAL(pdata,4,255); /* Max filename component length */
3768 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3769 and will think we can't do long filenames */
3770 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3771 PTR_DIFF(end_data, pdata+12),
3773 if (!NT_STATUS_IS_OK(status)) {
3777 data_len = 12 + len;
3778 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3779 /* the client only requested a portion of the
3781 data_len = max_data_bytes;
3782 status = STATUS_BUFFER_OVERFLOW;
3784 *fixed_portion = 16;
3787 case SMB_QUERY_FS_LABEL_INFO:
3788 case SMB_FS_LABEL_INFORMATION:
3789 status = srvstr_push(pdata, flags2, pdata+4, vname,
3790 PTR_DIFF(end_data, pdata+4), 0, &len);
3791 if (!NT_STATUS_IS_OK(status)) {
3798 case SMB_QUERY_FS_VOLUME_INFO:
3799 case SMB_FS_VOLUME_INFORMATION:
3802 * Add volume serial number - hash of a combination of
3803 * the called hostname and the service name.
3805 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
3806 (str_checksum(get_local_machine_name())<<16));
3808 /* Max label len is 32 characters. */
3809 status = srvstr_push(pdata, flags2, pdata+18, vname,
3810 PTR_DIFF(end_data, pdata+18),
3812 if (!NT_STATUS_IS_OK(status)) {
3815 SIVAL(pdata,12,len);
3818 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3819 (int)strlen(vname),vname,
3820 lp_servicename(talloc_tos(), lp_sub, snum)));
3821 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3822 /* the client only requested a portion of the
3824 data_len = max_data_bytes;
3825 status = STATUS_BUFFER_OVERFLOW;
3827 *fixed_portion = 24;
3830 case SMB_QUERY_FS_SIZE_INFO:
3831 case SMB_FS_SIZE_INFORMATION:
3833 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3835 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3837 if (df_ret == (uint64_t)-1) {
3838 return map_nt_error_from_unix(errno);
3840 block_size = lp_block_size(snum);
3841 if (bsize < block_size) {
3842 uint64_t factor = block_size/bsize;
3847 if (bsize > block_size) {
3848 uint64_t factor = bsize/block_size;
3853 sectors_per_unit = bsize/bytes_per_sector;
3854 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3855 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3856 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3857 SBIG_UINT(pdata,0,dsize);
3858 SBIG_UINT(pdata,8,dfree);
3859 SIVAL(pdata,16,sectors_per_unit);
3860 SIVAL(pdata,20,bytes_per_sector);
3861 *fixed_portion = 24;
3865 case SMB_FS_FULL_SIZE_INFORMATION:
3867 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3869 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3871 if (df_ret == (uint64_t)-1) {
3872 return map_nt_error_from_unix(errno);
3874 block_size = lp_block_size(snum);
3875 if (bsize < block_size) {
3876 uint64_t factor = block_size/bsize;
3881 if (bsize > block_size) {
3882 uint64_t factor = bsize/block_size;
3887 sectors_per_unit = bsize/bytes_per_sector;
3888 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3889 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3890 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3891 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3892 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3893 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3894 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3895 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3896 *fixed_portion = 32;
3900 case SMB_QUERY_FS_DEVICE_INFO:
3901 case SMB_FS_DEVICE_INFORMATION:
3903 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3905 if (!CAN_WRITE(conn)) {
3906 characteristics |= FILE_READ_ONLY_DEVICE;
3909 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3910 SIVAL(pdata,4,characteristics);
3915 #ifdef HAVE_SYS_QUOTAS
3916 case SMB_FS_QUOTA_INFORMATION:
3918 * what we have to send --metze:
3920 * Unknown1: 24 NULL bytes
3921 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3922 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3923 * Quota Flags: 2 byte :
3924 * Unknown3: 6 NULL bytes
3928 * details for Quota Flags:
3930 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3931 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3932 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3933 * 0x0001 Enable Quotas: enable quota for this fs
3937 /* we need to fake up a fsp here,
3938 * because its not send in this call
3941 SMB_NTQUOTA_STRUCT quotas;
3944 ZERO_STRUCT(quotas);
3947 fsp.fnum = FNUM_FIELD_INVALID;
3950 if (get_current_uid(conn) != 0) {
3951 DEBUG(0,("get_user_quota: access_denied "
3952 "service [%s] user [%s]\n",
3953 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
3954 conn->session_info->unix_info->unix_name));
3955 return NT_STATUS_ACCESS_DENIED;
3958 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3960 if (!NT_STATUS_IS_OK(status)) {
3961 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3967 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3968 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3970 /* Unknown1 24 NULL bytes*/
3971 SBIG_UINT(pdata,0,(uint64_t)0);
3972 SBIG_UINT(pdata,8,(uint64_t)0);
3973 SBIG_UINT(pdata,16,(uint64_t)0);
3975 /* Default Soft Quota 8 bytes */
3976 SBIG_UINT(pdata,24,quotas.softlim);
3978 /* Default Hard Quota 8 bytes */
3979 SBIG_UINT(pdata,32,quotas.hardlim);
3981 /* Quota flag 2 bytes */
3982 SSVAL(pdata,40,quotas.qflags);
3984 /* Unknown3 6 NULL bytes */
3990 #endif /* HAVE_SYS_QUOTAS */
3991 case SMB_FS_OBJECTID_INFORMATION:
3993 unsigned char objid[16];
3994 struct smb_extended_info extended_info;
3995 memcpy(pdata,create_volume_objectid(conn, objid),16);
3996 samba_extended_info_version (&extended_info);
3997 SIVAL(pdata,16,extended_info.samba_magic);
3998 SIVAL(pdata,20,extended_info.samba_version);
3999 SIVAL(pdata,24,extended_info.samba_subversion);
4000 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
4001 memcpy(pdata+36,extended_info.samba_version_string,28);
4006 case SMB_FS_SECTOR_SIZE_INFORMATION:
4010 * These values match a physical Windows Server 2012
4011 * share backed by NTFS atop spinning rust.
4013 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
4014 /* logical_bytes_per_sector */
4015 SIVAL(pdata, 0, bytes_per_sector);
4016 /* phys_bytes_per_sector_atomic */
4017 SIVAL(pdata, 4, bytes_per_sector);
4018 /* phys_bytes_per_sector_perf */
4019 SIVAL(pdata, 8, bytes_per_sector);
4020 /* fs_effective_phys_bytes_per_sector_atomic */
4021 SIVAL(pdata, 12, bytes_per_sector);
4023 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
4024 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
4025 /* byte_off_sector_align */
4026 SIVAL(pdata, 20, 0);
4027 /* byte_off_partition_align */
4028 SIVAL(pdata, 24, 0);
4029 *fixed_portion = 28;
4035 * Query the version and capabilities of the CIFS UNIX extensions
4039 case SMB_QUERY_CIFS_UNIX_INFO:
4041 bool large_write = lp_min_receive_file_size() &&
4042 !srv_is_signing_active(xconn);
4043 bool large_read = !srv_is_signing_active(xconn);
4044 int encrypt_caps = 0;
4046 if (!lp_unix_extensions()) {
4047 return NT_STATUS_INVALID_LEVEL;
4050 switch (conn->encrypt_level) {
4051 case SMB_SIGNING_OFF:
4054 case SMB_SIGNING_DESIRED:
4055 case SMB_SIGNING_IF_REQUIRED:
4056 case SMB_SIGNING_DEFAULT:
4057 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
4059 case SMB_SIGNING_REQUIRED:
4060 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
4061 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
4062 large_write = false;
4068 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
4069 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
4071 /* We have POSIX ACLs, pathname, encryption,
4072 * large read/write, and locking capability. */
4074 SBIG_UINT(pdata,4,((uint64_t)(
4075 CIFS_UNIX_POSIX_ACLS_CAP|
4076 CIFS_UNIX_POSIX_PATHNAMES_CAP|
4077 CIFS_UNIX_FCNTL_LOCKS_CAP|
4078 CIFS_UNIX_EXTATTR_CAP|
4079 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
4081 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
4083 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
4087 case SMB_QUERY_POSIX_FS_INFO:
4090 vfs_statvfs_struct svfs;
4092 if (!lp_unix_extensions()) {
4093 return NT_STATUS_INVALID_LEVEL;
4096 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
4100 SIVAL(pdata,0,svfs.OptimalTransferSize);
4101 SIVAL(pdata,4,svfs.BlockSize);
4102 SBIG_UINT(pdata,8,svfs.TotalBlocks);
4103 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4104 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4105 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4106 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4107 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4108 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4110 } else if (rc == EOPNOTSUPP) {
4111 return NT_STATUS_INVALID_LEVEL;
4112 #endif /* EOPNOTSUPP */
4114 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4115 return NT_STATUS_DOS(ERRSRV, ERRerror);
4120 case SMB_QUERY_POSIX_WHOAMI:
4126 if (!lp_unix_extensions()) {
4127 return NT_STATUS_INVALID_LEVEL;
4130 if (max_data_bytes < 40) {
4131 return NT_STATUS_BUFFER_TOO_SMALL;
4134 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4135 flags |= SMB_WHOAMI_GUEST;
4138 /* NOTE: 8 bytes for UID/GID, irrespective of native
4139 * platform size. This matches
4140 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4142 data_len = 4 /* flags */
4149 + 4 /* pad/reserved */
4150 + (conn->session_info->unix_token->ngroups * 8)
4152 + (conn->session_info->security_token->num_sids *
4156 SIVAL(pdata, 0, flags);
4157 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4159 (uint64_t)conn->session_info->unix_token->uid);
4160 SBIG_UINT(pdata, 16,
4161 (uint64_t)conn->session_info->unix_token->gid);
4164 if (data_len >= max_data_bytes) {
4165 /* Potential overflow, skip the GIDs and SIDs. */
4167 SIVAL(pdata, 24, 0); /* num_groups */
4168 SIVAL(pdata, 28, 0); /* num_sids */
4169 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4170 SIVAL(pdata, 36, 0); /* reserved */
4176 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4177 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4179 /* We walk the SID list twice, but this call is fairly
4180 * infrequent, and I don't expect that it's performance
4181 * sensitive -- jpeach
4183 for (i = 0, sid_bytes = 0;
4184 i < conn->session_info->security_token->num_sids; ++i) {
4185 sid_bytes += ndr_size_dom_sid(
4186 &conn->session_info->security_token->sids[i],
4190 /* SID list byte count */
4191 SIVAL(pdata, 32, sid_bytes);
4193 /* 4 bytes pad/reserved - must be zero */
4194 SIVAL(pdata, 36, 0);
4198 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4199 SBIG_UINT(pdata, data_len,
4200 (uint64_t)conn->session_info->unix_token->groups[i]);
4206 i < conn->session_info->security_token->num_sids; ++i) {
4207 int sid_len = ndr_size_dom_sid(
4208 &conn->session_info->security_token->sids[i],
4211 sid_linearize((uint8_t *)(pdata + data_len),
4213 &conn->session_info->security_token->sids[i]);
4214 data_len += sid_len;
4220 case SMB_MAC_QUERY_FS_INFO:
4222 * Thursby MAC extension... ONLY on NTFS filesystems
4223 * once we do streams then we don't need this
4225 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4227 SIVAL(pdata,84,0x100); /* Don't support mac... */
4233 return NT_STATUS_INVALID_LEVEL;
4236 *ret_data_len = data_len;
4240 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4241 struct smb_request *req,
4243 const DATA_BLOB *qdata)
4245 const struct loadparm_substitution *lp_sub =
4246 loadparm_s3_global_substitution();
4248 SMB_NTQUOTA_STRUCT quotas;
4250 ZERO_STRUCT(quotas);
4253 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4254 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4255 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
4256 conn->session_info->unix_info->unix_name));
4257 return NT_STATUS_ACCESS_DENIED;
4260 if (!check_fsp_ntquota_handle(conn, req,
4262 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4263 return NT_STATUS_INVALID_HANDLE;
4266 /* note: normally there're 48 bytes,
4267 * but we didn't use the last 6 bytes for now
4270 if (qdata->length < 42) {
4271 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4272 (unsigned int)qdata->length));
4273 return NT_STATUS_INVALID_PARAMETER;
4276 /* unknown_1 24 NULL bytes in pdata*/
4278 /* the soft quotas 8 bytes (uint64_t)*/
4279 quotas.softlim = BVAL(qdata->data,24);
4281 /* the hard quotas 8 bytes (uint64_t)*/
4282 quotas.hardlim = BVAL(qdata->data,32);
4284 /* quota_flags 2 bytes **/
4285 quotas.qflags = SVAL(qdata->data,40);
4287 /* unknown_2 6 NULL bytes follow*/
4289 /* now set the quotas */
4290 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4291 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4292 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4293 status = map_nt_error_from_unix(errno);
4295 status = NT_STATUS_OK;
4300 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4301 struct smb_request *req,
4302 TALLOC_CTX *mem_ctx,
4303 uint16_t info_level,
4305 const DATA_BLOB *pdata)
4307 switch (info_level) {
4308 case SMB_FS_QUOTA_INFORMATION:
4310 return smb_set_fsquota(conn,
4319 return NT_STATUS_INVALID_LEVEL;
4322 /****************************************************************************
4323 Reply to a TRANS2_QFSINFO (query filesystem info).
4324 ****************************************************************************/
4326 static void call_trans2qfsinfo(connection_struct *conn,
4327 struct smb_request *req,
4328 char **pparams, int total_params,
4329 char **ppdata, int total_data,
4330 unsigned int max_data_bytes)
4332 char *params = *pparams;
4333 uint16_t info_level;
4335 size_t fixed_portion;
4338 if (total_params < 2) {
4339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4343 info_level = SVAL(params,0);
4345 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4346 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4347 DEBUG(0,("call_trans2qfsinfo: encryption required "
4348 "and info level 0x%x sent.\n",
4349 (unsigned int)info_level));
4350 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4355 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4357 status = smbd_do_qfsinfo(req->xconn, conn, req,
4364 if (!NT_STATUS_IS_OK(status)) {
4365 reply_nterror(req, status);
4369 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4372 DEBUG( 4, ( "%s info_level = %d\n",
4373 smb_fn_name(req->cmd), info_level) );
4378 /****************************************************************************
4379 Reply to a TRANS2_SETFSINFO (set filesystem info).
4380 ****************************************************************************/
4382 static void call_trans2setfsinfo(connection_struct *conn,
4383 struct smb_request *req,
4384 char **pparams, int total_params,
4385 char **ppdata, int total_data,
4386 unsigned int max_data_bytes)
4388 const struct loadparm_substitution *lp_sub =
4389 loadparm_s3_global_substitution();
4390 struct smbXsrv_connection *xconn = req->xconn;
4391 char *pdata = *ppdata;
4392 char *params = *pparams;
4393 uint16_t info_level;
4395 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4396 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4399 if (total_params < 4) {
4400 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4406 info_level = SVAL(params,2);
4409 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4410 info_level != SMB_SET_CIFS_UNIX_INFO) {
4411 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4412 "info level (0x%x) on IPC$.\n",
4413 (unsigned int)info_level));
4414 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4419 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4420 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4421 DEBUG(0,("call_trans2setfsinfo: encryption required "
4422 "and info level 0x%x sent.\n",
4423 (unsigned int)info_level));
4424 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4429 switch(info_level) {
4430 case SMB_SET_CIFS_UNIX_INFO:
4431 if (!lp_unix_extensions()) {
4432 DEBUG(2,("call_trans2setfsinfo: "
4433 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4434 "unix extensions off\n"));
4436 NT_STATUS_INVALID_LEVEL);
4440 /* There should be 12 bytes of capabilities set. */
4441 if (total_data < 12) {
4444 NT_STATUS_INVALID_PARAMETER);
4447 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4448 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4449 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4450 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4451 /* Just print these values for now. */
4452 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4453 "major = %u, minor = %u cap_low = 0x%x, "
4455 (unsigned int)xconn->
4456 smb1.unix_info.client_major,
4457 (unsigned int)xconn->
4458 smb1.unix_info.client_minor,
4459 (unsigned int)xconn->
4460 smb1.unix_info.client_cap_low,
4461 (unsigned int)xconn->
4462 smb1.unix_info.client_cap_high));
4464 /* Here is where we must switch to posix pathname processing... */
4465 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4466 lp_set_posix_pathnames();
4467 mangle_change_to_posix();
4470 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4471 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4472 /* Client that knows how to do posix locks,
4473 * but not posix open/mkdir operations. Set a
4474 * default type for read/write checks. */
4476 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4481 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4484 size_t param_len = 0;
4485 size_t data_len = total_data;
4487 if (!lp_unix_extensions()) {
4490 NT_STATUS_INVALID_LEVEL);
4494 if (lp_server_smb_encrypt(SNUM(conn)) ==
4495 SMB_ENCRYPTION_OFF) {
4498 NT_STATUS_NOT_SUPPORTED);
4502 if (xconn->smb1.echo_handler.trusted_fde) {
4503 DEBUG( 2,("call_trans2setfsinfo: "
4504 "request transport encryption disabled"
4505 "with 'fork echo handler = yes'\n"));
4508 NT_STATUS_NOT_SUPPORTED);
4512 DEBUG( 4,("call_trans2setfsinfo: "
4513 "request transport encryption.\n"));
4515 status = srv_request_encryption_setup(conn,
4516 (unsigned char **)ppdata,
4518 (unsigned char **)pparams,
4521 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4522 !NT_STATUS_IS_OK(status)) {
4523 reply_nterror(req, status);
4527 send_trans2_replies(conn, req,
4535 if (NT_STATUS_IS_OK(status)) {
4536 /* Server-side transport
4537 * encryption is now *on*. */
4538 status = srv_encryption_start(conn);
4539 if (!NT_STATUS_IS_OK(status)) {
4540 char *reason = talloc_asprintf(talloc_tos(),
4541 "Failure in setting "
4542 "up encrypted transport: %s",
4544 exit_server_cleanly(reason);
4550 case SMB_FS_QUOTA_INFORMATION:
4554 .data = (uint8_t *)pdata,
4555 .length = total_data
4557 files_struct *fsp = NULL;
4558 fsp = file_fsp(req, SVAL(params,0));
4560 status = smb_set_fsquota(conn,
4564 if (!NT_STATUS_IS_OK(status)) {
4565 reply_nterror(req, status);
4571 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4573 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4579 * sending this reply works fine,
4580 * but I'm not sure it's the same
4581 * like windows do...
4584 reply_outbuf(req, 10, 0);
4587 #if defined(HAVE_POSIX_ACLS)
4588 /****************************************************************************
4589 Utility function to count the number of entries in a POSIX acl.
4590 ****************************************************************************/
4592 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4594 unsigned int ace_count = 0;
4595 int entry_id = SMB_ACL_FIRST_ENTRY;
4596 SMB_ACL_ENTRY_T entry;
4598 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4600 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4601 entry_id = SMB_ACL_NEXT_ENTRY;
4608 /****************************************************************************
4609 Utility function to marshall a POSIX acl into wire format.
4610 ****************************************************************************/
4612 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4614 int entry_id = SMB_ACL_FIRST_ENTRY;
4615 SMB_ACL_ENTRY_T entry;
4617 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4618 SMB_ACL_TAG_T tagtype;
4619 SMB_ACL_PERMSET_T permset;
4620 unsigned char perms = 0;
4621 unsigned int own_grp;
4624 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4625 entry_id = SMB_ACL_NEXT_ENTRY;
4628 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4629 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4633 if (sys_acl_get_permset(entry, &permset) == -1) {
4634 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4638 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4639 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4640 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4642 SCVAL(pdata,1,perms);
4645 case SMB_ACL_USER_OBJ:
4646 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4647 own_grp = (unsigned int)pst->st_ex_uid;
4648 SIVAL(pdata,2,own_grp);
4653 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4655 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4658 own_grp = (unsigned int)*puid;
4659 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4660 SIVAL(pdata,2,own_grp);
4664 case SMB_ACL_GROUP_OBJ:
4665 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4666 own_grp = (unsigned int)pst->st_ex_gid;
4667 SIVAL(pdata,2,own_grp);
4672 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4674 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4677 own_grp = (unsigned int)*pgid;
4678 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4679 SIVAL(pdata,2,own_grp);
4684 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4685 SIVAL(pdata,2,0xFFFFFFFF);
4686 SIVAL(pdata,6,0xFFFFFFFF);
4689 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4690 SIVAL(pdata,2,0xFFFFFFFF);
4691 SIVAL(pdata,6,0xFFFFFFFF);
4694 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4697 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4704 /****************************************************************************
4705 Store the FILE_UNIX_BASIC info.
4706 ****************************************************************************/
4708 static char *store_file_unix_basic(connection_struct *conn,
4711 const SMB_STRUCT_STAT *psbuf)
4715 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4716 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4718 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4721 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4724 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
4725 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
4726 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4729 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4733 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4737 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4740 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4741 devno = psbuf->st_ex_rdev;
4743 devno = psbuf->st_ex_dev;
4746 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4750 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4754 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4757 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4761 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4768 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4769 * the chflags(2) (or equivalent) flags.
4771 * XXX: this really should be behind the VFS interface. To do this, we would
4772 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4773 * Each VFS module could then implement its own mapping as appropriate for the
4774 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4776 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4780 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4784 { UF_IMMUTABLE, EXT_IMMUTABLE },
4788 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4792 { UF_HIDDEN, EXT_HIDDEN },
4795 /* Do not remove. We need to guarantee that this array has at least one
4796 * entry to build on HP-UX.
4802 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4803 uint32_t *smb_fflags, uint32_t *smb_fmask)
4807 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4808 *smb_fmask |= info2_flags_map[i].smb_fflag;
4809 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4810 *smb_fflags |= info2_flags_map[i].smb_fflag;
4815 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4816 const uint32_t smb_fflags,
4817 const uint32_t smb_fmask,
4820 uint32_t max_fmask = 0;
4823 *stat_fflags = psbuf->st_ex_flags;
4825 /* For each flags requested in smb_fmask, check the state of the
4826 * corresponding flag in smb_fflags and set or clear the matching
4830 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4831 max_fmask |= info2_flags_map[i].smb_fflag;
4832 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4833 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4834 *stat_fflags |= info2_flags_map[i].stat_fflag;
4836 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4841 /* If smb_fmask is asking to set any bits that are not supported by
4842 * our flag mappings, we should fail.
4844 if ((smb_fmask & max_fmask) != smb_fmask) {
4852 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4853 * of file flags and birth (create) time.
4855 static char *store_file_unix_basic_info2(connection_struct *conn,
4858 const SMB_STRUCT_STAT *psbuf)
4860 uint32_t file_flags = 0;
4861 uint32_t flags_mask = 0;
4863 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4865 /* Create (birth) time 64 bit */
4866 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
4869 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4870 SIVAL(pdata, 0, file_flags); /* flags */
4871 SIVAL(pdata, 4, flags_mask); /* mask */
4877 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4878 const struct stream_struct *streams,
4880 unsigned int max_data_bytes,
4881 unsigned int *data_size)
4884 unsigned int ofs = 0;
4886 if (max_data_bytes < 32) {
4887 return NT_STATUS_INFO_LENGTH_MISMATCH;
4890 for (i = 0; i < num_streams; i++) {
4891 unsigned int next_offset;
4893 smb_ucs2_t *namebuf;
4895 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4896 streams[i].name, &namelen) ||
4899 return NT_STATUS_INVALID_PARAMETER;
4903 * name_buf is now null-terminated, we need to marshall as not
4910 * We cannot overflow ...
4912 if ((ofs + 24 + namelen) > max_data_bytes) {
4913 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4915 TALLOC_FREE(namebuf);
4916 return STATUS_BUFFER_OVERFLOW;
4919 SIVAL(data, ofs+4, namelen);
4920 SOFF_T(data, ofs+8, streams[i].size);
4921 SOFF_T(data, ofs+16, streams[i].alloc_size);
4922 memcpy(data+ofs+24, namebuf, namelen);
4923 TALLOC_FREE(namebuf);
4925 next_offset = ofs + 24 + namelen;
4927 if (i == num_streams-1) {
4928 SIVAL(data, ofs, 0);
4931 unsigned int align = ndr_align_size(next_offset, 8);
4933 if ((next_offset + align) > max_data_bytes) {
4934 DEBUG(10, ("refusing to overflow align "
4935 "reply at stream %u\n",
4937 TALLOC_FREE(namebuf);
4938 return STATUS_BUFFER_OVERFLOW;
4941 memset(data+next_offset, 0, align);
4942 next_offset += align;
4944 SIVAL(data, ofs, next_offset - ofs);
4951 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4955 return NT_STATUS_OK;
4958 #if defined(HAVE_POSIX_ACLS)
4959 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4960 struct smb_request *req,
4962 struct smb_filename *smb_fname,
4964 unsigned int data_size_in,
4965 unsigned int *pdata_size_out)
4967 SMB_ACL_T file_acl = NULL;
4968 SMB_ACL_T def_acl = NULL;
4969 uint16_t num_file_acls = 0;
4970 uint16_t num_def_acls = 0;
4971 unsigned int size_needed = 0;
4974 bool close_fsp = false;
4977 * Ensure we always operate on a file descriptor, not just
4981 uint32_t access_mask = SEC_STD_READ_CONTROL|
4982 FILE_READ_ATTRIBUTES|
4983 FILE_WRITE_ATTRIBUTES;
4985 status = get_posix_fsp(conn,
4991 if (!NT_STATUS_IS_OK(status)) {
4997 SMB_ASSERT(fsp != NULL);
4999 status = refuse_symlink(conn,
5002 if (!NT_STATUS_IS_OK(status)) {
5006 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5009 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5010 DBG_INFO("ACLs not implemented on "
5011 "filesystem containing %s\n",
5013 status = NT_STATUS_NOT_IMPLEMENTED;
5017 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
5019 * We can only have default POSIX ACLs on
5022 if (!fsp->fsp_flags.is_directory) {
5023 DBG_INFO("Non-directory open %s\n",
5025 status = NT_STATUS_INVALID_HANDLE;
5028 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
5030 SMB_ACL_TYPE_DEFAULT,
5032 def_acl = free_empty_sys_acl(conn, def_acl);
5035 num_file_acls = count_acl_entries(conn, file_acl);
5036 num_def_acls = count_acl_entries(conn, def_acl);
5039 if (num_file_acls + num_def_acls < num_file_acls) {
5040 status = NT_STATUS_INVALID_PARAMETER;
5044 size_needed = num_file_acls + num_def_acls;
5047 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5048 * than UINT_MAX, so check by division.
5050 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5051 status = NT_STATUS_INVALID_PARAMETER;
5055 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5056 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5057 status = NT_STATUS_INVALID_PARAMETER;
5060 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5062 if ( data_size_in < size_needed) {
5063 DBG_INFO("data_size too small (%u) need %u\n",
5066 status = NT_STATUS_BUFFER_TOO_SMALL;
5070 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5071 SSVAL(pdata,2,num_file_acls);
5072 SSVAL(pdata,4,num_def_acls);
5073 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5075 ok = marshall_posix_acl(conn,
5080 status = NT_STATUS_INTERNAL_ERROR;
5083 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5085 ok = marshall_posix_acl(conn,
5090 status = NT_STATUS_INTERNAL_ERROR;
5094 *pdata_size_out = size_needed;
5095 status = NT_STATUS_OK;
5101 * Ensure the stat struct in smb_fname is up to
5102 * date. Structure copy.
5104 smb_fname->st = fsp->fsp_name->st;
5105 (void)close_file(req, fsp, NORMAL_CLOSE);
5109 TALLOC_FREE(file_acl);
5110 TALLOC_FREE(def_acl);
5115 /****************************************************************************
5116 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5117 ****************************************************************************/
5119 static void call_trans2qpipeinfo(connection_struct *conn,
5120 struct smb_request *req,
5121 unsigned int tran_call,
5122 char **pparams, int total_params,
5123 char **ppdata, int total_data,
5124 unsigned int max_data_bytes)
5126 char *params = *pparams;
5127 char *pdata = *ppdata;
5128 unsigned int data_size = 0;
5129 unsigned int param_size = 2;
5130 uint16_t info_level;
5134 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5138 if (total_params < 4) {
5139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5143 fsp = file_fsp(req, SVAL(params,0));
5144 if (!fsp_is_np(fsp)) {
5145 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5149 info_level = SVAL(params,2);
5151 *pparams = (char *)SMB_REALLOC(*pparams,2);
5152 if (*pparams == NULL) {
5153 reply_nterror(req, NT_STATUS_NO_MEMORY);
5158 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5162 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5163 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5164 if (*ppdata == NULL ) {
5165 reply_nterror(req, NT_STATUS_NO_MEMORY);
5170 switch (info_level) {
5171 case SMB_FILE_STANDARD_INFORMATION:
5173 SOFF_T(pdata,0,4096LL);
5180 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5184 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5190 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5191 TALLOC_CTX *mem_ctx,
5192 struct smb_request *req,
5193 uint16_t info_level,
5195 struct smb_filename *smb_fname,
5196 bool delete_pending,
5197 struct timespec write_time_ts,
5198 struct ea_list *ea_list,
5199 int lock_data_count,
5202 unsigned int max_data_bytes,
5203 size_t *fixed_portion,
5205 unsigned int *pdata_size)
5207 char *pdata = *ppdata;
5208 char *dstart, *dend;
5209 unsigned int data_size;
5210 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5211 time_t create_time, mtime, atime, c_time;
5212 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5219 uint64_t file_size = 0;
5221 uint64_t allocation_size = 0;
5222 uint64_t file_id = 0;
5223 uint32_t access_mask = 0;
5226 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5227 return NT_STATUS_INVALID_LEVEL;
5230 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5231 smb_fname_str_dbg(smb_fname),
5233 info_level, max_data_bytes));
5235 mode = dos_mode(conn, smb_fname);
5236 nlink = psbuf->st_ex_nlink;
5238 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5242 if ((nlink > 0) && delete_pending) {
5246 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5247 return NT_STATUS_INVALID_PARAMETER;
5250 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5251 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5252 if (*ppdata == NULL) {
5253 return NT_STATUS_NO_MEMORY;
5257 dend = dstart + data_size - 1;
5259 if (!is_omit_timespec(&write_time_ts) &&
5260 !INFO_LEVEL_IS_UNIX(info_level))
5262 update_stat_ex_mtime(psbuf, write_time_ts);
5265 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5266 mtime_ts = psbuf->st_ex_mtime;
5267 atime_ts = psbuf->st_ex_atime;
5268 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5270 if (lp_dos_filetime_resolution(SNUM(conn))) {
5271 dos_filetime_timespec(&create_time_ts);
5272 dos_filetime_timespec(&mtime_ts);
5273 dos_filetime_timespec(&atime_ts);
5274 dos_filetime_timespec(&ctime_ts);
5277 create_time = convert_timespec_to_time_t(create_time_ts);
5278 mtime = convert_timespec_to_time_t(mtime_ts);
5279 atime = convert_timespec_to_time_t(atime_ts);
5280 c_time = convert_timespec_to_time_t(ctime_ts);
5282 p = strrchr_m(smb_fname->base_name,'/');
5284 base_name = smb_fname->base_name;
5288 /* NT expects the name to be in an exact form of the *full*
5289 filename. See the trans2 torture test */
5290 if (ISDOT(base_name)) {
5291 dos_fname = talloc_strdup(mem_ctx, "\\");
5293 return NT_STATUS_NO_MEMORY;
5296 dos_fname = talloc_asprintf(mem_ctx,
5298 smb_fname->base_name);
5300 return NT_STATUS_NO_MEMORY;
5302 if (is_ntfs_stream_smb_fname(smb_fname)) {
5303 dos_fname = talloc_asprintf(dos_fname, "%s",
5304 smb_fname->stream_name);
5306 return NT_STATUS_NO_MEMORY;
5310 string_replace(dos_fname, '/', '\\');
5313 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5316 /* Do we have this path open ? */
5318 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5319 fsp1 = file_find_di_first(conn->sconn, fileid);
5320 if (fsp1 && fsp1->initial_allocation_size) {
5321 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5325 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5326 file_size = get_file_size_stat(psbuf);
5330 pos = fsp->fh->position_information;
5334 access_mask = fsp->access_mask;
5336 /* GENERIC_EXECUTE mapping from Windows */
5337 access_mask = 0x12019F;
5340 /* This should be an index number - looks like
5343 I think this causes us to fail the IFSKIT
5344 BasicFileInformationTest. -tpot */
5345 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5349 switch (info_level) {
5350 case SMB_INFO_STANDARD:
5351 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5353 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5354 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5355 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5356 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5357 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5358 SSVAL(pdata,l1_attrFile,mode);
5361 case SMB_INFO_QUERY_EA_SIZE:
5363 unsigned int ea_size =
5364 estimate_ea_size(conn, fsp,
5366 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5368 srv_put_dos_date2(pdata,0,create_time);
5369 srv_put_dos_date2(pdata,4,atime);
5370 srv_put_dos_date2(pdata,8,mtime); /* write time */
5371 SIVAL(pdata,12,(uint32_t)file_size);
5372 SIVAL(pdata,16,(uint32_t)allocation_size);
5373 SSVAL(pdata,20,mode);
5374 SIVAL(pdata,22,ea_size);
5378 case SMB_INFO_IS_NAME_VALID:
5379 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5381 /* os/2 needs this ? really ?*/
5382 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5384 /* This is only reached for qpathinfo */
5388 case SMB_INFO_QUERY_EAS_FROM_LIST:
5390 size_t total_ea_len = 0;
5391 struct ea_list *ea_file_list = NULL;
5392 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5395 get_ea_list_from_file(mem_ctx, conn, fsp,
5397 &total_ea_len, &ea_file_list);
5398 if (!NT_STATUS_IS_OK(status)) {
5402 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
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 SMB_INFO_QUERY_ALL_EAS:
5416 /* We have data_size bytes to put EA's into. */
5417 size_t total_ea_len = 0;
5418 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5420 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5422 &total_ea_len, &ea_list);
5423 if (!NT_STATUS_IS_OK(status)) {
5427 if (!ea_list || (total_ea_len > data_size)) {
5429 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5433 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5437 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5439 /* This is FileFullEaInformation - 0xF which maps to
5440 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5442 /* We have data_size bytes to put EA's into. */
5443 size_t total_ea_len = 0;
5444 struct ea_list *ea_file_list = NULL;
5446 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5448 /*TODO: add filtering and index handling */
5451 get_ea_list_from_file(mem_ctx, conn, fsp,
5453 &total_ea_len, &ea_file_list);
5454 if (!NT_STATUS_IS_OK(status)) {
5457 if (!ea_file_list) {
5458 return NT_STATUS_NO_EAS_ON_FILE;
5461 status = fill_ea_chained_buffer(mem_ctx,
5465 conn, ea_file_list);
5466 if (!NT_STATUS_IS_OK(status)) {
5472 case SMB_FILE_BASIC_INFORMATION:
5473 case SMB_QUERY_FILE_BASIC_INFO:
5475 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5477 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5479 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5483 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5484 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5485 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5486 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5487 SIVAL(pdata,32,mode);
5489 DEBUG(5,("SMB_QFBI - "));
5490 DEBUG(5,("create: %s ", ctime(&create_time)));
5491 DEBUG(5,("access: %s ", ctime(&atime)));
5492 DEBUG(5,("write: %s ", ctime(&mtime)));
5493 DEBUG(5,("change: %s ", ctime(&c_time)));
5494 DEBUG(5,("mode: %x\n", mode));
5495 *fixed_portion = data_size;
5498 case SMB_FILE_STANDARD_INFORMATION:
5499 case SMB_QUERY_FILE_STANDARD_INFO:
5501 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5503 SOFF_T(pdata,0,allocation_size);
5504 SOFF_T(pdata,8,file_size);
5505 SIVAL(pdata,16,nlink);
5506 SCVAL(pdata,20,delete_pending?1:0);
5507 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5508 SSVAL(pdata,22,0); /* Padding. */
5509 *fixed_portion = 24;
5512 case SMB_FILE_EA_INFORMATION:
5513 case SMB_QUERY_FILE_EA_INFO:
5515 unsigned int ea_size =
5516 estimate_ea_size(conn, fsp, smb_fname);
5517 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5520 SIVAL(pdata,0,ea_size);
5524 /* Get the 8.3 name - used if NT SMB was negotiated. */
5525 case SMB_QUERY_FILE_ALT_NAME_INFO:
5526 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5528 char mangled_name[13];
5529 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5530 if (!name_to_8_3(base_name,mangled_name,
5531 True,conn->params)) {
5532 return NT_STATUS_NO_MEMORY;
5534 status = srvstr_push(dstart, flags2,
5535 pdata+4, mangled_name,
5536 PTR_DIFF(dend, pdata+4),
5538 if (!NT_STATUS_IS_OK(status)) {
5541 data_size = 4 + len;
5547 case SMB_QUERY_FILE_NAME_INFO:
5550 this must be *exactly* right for ACLs on mapped drives to work
5552 status = srvstr_push(dstart, flags2,
5554 PTR_DIFF(dend, pdata+4),
5556 if (!NT_STATUS_IS_OK(status)) {
5559 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5560 data_size = 4 + len;
5565 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5567 char *nfname = NULL;
5569 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
5570 return NT_STATUS_INVALID_LEVEL;
5573 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5574 if (nfname == NULL) {
5575 return NT_STATUS_NO_MEMORY;
5578 if (ISDOT(nfname)) {
5581 string_replace(nfname, '/', '\\');
5583 if (smb_fname->stream_name != NULL) {
5584 const char *s = smb_fname->stream_name;
5585 const char *e = NULL;
5588 SMB_ASSERT(s[0] != '\0');
5591 * smb_fname->stream_name is in form
5592 * of ':StrEam:$DATA', but we should only
5593 * append ':StrEam' here.
5596 e = strchr(&s[1], ':');
5602 nfname = talloc_strndup_append(nfname, s, n);
5603 if (nfname == NULL) {
5604 return NT_STATUS_NO_MEMORY;
5608 status = srvstr_push(dstart, flags2,
5610 PTR_DIFF(dend, pdata+4),
5612 if (!NT_STATUS_IS_OK(status)) {
5615 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5616 data_size = 4 + len;
5622 case SMB_FILE_ALLOCATION_INFORMATION:
5623 case SMB_QUERY_FILE_ALLOCATION_INFO:
5624 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5626 SOFF_T(pdata,0,allocation_size);
5629 case SMB_FILE_END_OF_FILE_INFORMATION:
5630 case SMB_QUERY_FILE_END_OF_FILEINFO:
5631 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5633 SOFF_T(pdata,0,file_size);
5636 case SMB_QUERY_FILE_ALL_INFO:
5637 case SMB_FILE_ALL_INFORMATION:
5639 unsigned int ea_size =
5640 estimate_ea_size(conn, fsp, smb_fname);
5641 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5642 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5643 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5644 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5645 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5646 SIVAL(pdata,32,mode);
5647 SIVAL(pdata,36,0); /* padding. */
5649 SOFF_T(pdata,0,allocation_size);
5650 SOFF_T(pdata,8,file_size);
5651 SIVAL(pdata,16,nlink);
5652 SCVAL(pdata,20,delete_pending);
5653 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5656 SIVAL(pdata,0,ea_size);
5657 pdata += 4; /* EA info */
5658 status = srvstr_push(dstart, flags2,
5660 PTR_DIFF(dend, pdata+4),
5662 if (!NT_STATUS_IS_OK(status)) {
5667 data_size = PTR_DIFF(pdata,(*ppdata));
5668 *fixed_portion = 10;
5672 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5674 unsigned int ea_size =
5675 estimate_ea_size(conn, fsp, smb_fname);
5676 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5677 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
5678 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
5679 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
5680 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
5681 SIVAL(pdata, 0x20, mode);
5682 SIVAL(pdata, 0x24, 0); /* padding. */
5683 SBVAL(pdata, 0x28, allocation_size);
5684 SBVAL(pdata, 0x30, file_size);
5685 SIVAL(pdata, 0x38, nlink);
5686 SCVAL(pdata, 0x3C, delete_pending);
5687 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5688 SSVAL(pdata, 0x3E, 0); /* padding */
5689 SBVAL(pdata, 0x40, file_id);
5690 SIVAL(pdata, 0x48, ea_size);
5691 SIVAL(pdata, 0x4C, access_mask);
5692 SBVAL(pdata, 0x50, pos);
5693 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5694 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5698 status = srvstr_push(dstart, flags2,
5700 PTR_DIFF(dend, pdata+4),
5702 if (!NT_STATUS_IS_OK(status)) {
5707 data_size = PTR_DIFF(pdata,(*ppdata));
5708 *fixed_portion = 104;
5711 case SMB_FILE_INTERNAL_INFORMATION:
5713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5714 SBVAL(pdata, 0, file_id);
5719 case SMB_FILE_ACCESS_INFORMATION:
5720 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5721 SIVAL(pdata, 0, access_mask);
5726 case SMB_FILE_NAME_INFORMATION:
5727 /* Pathname with leading '\'. */
5730 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5732 SIVAL(pdata,0,byte_len);
5733 data_size = 4 + byte_len;
5737 case SMB_FILE_DISPOSITION_INFORMATION:
5738 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5740 SCVAL(pdata,0,delete_pending);
5744 case SMB_FILE_POSITION_INFORMATION:
5745 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5747 SOFF_T(pdata,0,pos);
5751 case SMB_FILE_MODE_INFORMATION:
5752 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5753 SIVAL(pdata,0,mode);
5758 case SMB_FILE_ALIGNMENT_INFORMATION:
5759 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5760 SIVAL(pdata,0,0); /* No alignment needed. */
5766 * NT4 server just returns "invalid query" to this - if we try
5767 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5770 /* The first statement above is false - verified using Thursby
5771 * client against NT4 -- gcolley.
5773 case SMB_QUERY_FILE_STREAM_INFO:
5774 case SMB_FILE_STREAM_INFORMATION: {
5775 unsigned int num_streams = 0;
5776 struct stream_struct *streams = NULL;
5778 DEBUG(10,("smbd_do_qfilepathinfo: "
5779 "SMB_FILE_STREAM_INFORMATION\n"));
5781 if (is_ntfs_stream_smb_fname(smb_fname)) {
5782 return NT_STATUS_INVALID_PARAMETER;
5785 status = vfs_streaminfo(conn,
5792 if (!NT_STATUS_IS_OK(status)) {
5793 DEBUG(10, ("could not get stream info: %s\n",
5794 nt_errstr(status)));
5798 status = marshall_stream_info(num_streams, streams,
5799 pdata, max_data_bytes,
5802 if (!NT_STATUS_IS_OK(status)) {
5803 DEBUG(10, ("marshall_stream_info failed: %s\n",
5804 nt_errstr(status)));
5805 TALLOC_FREE(streams);
5809 TALLOC_FREE(streams);
5811 *fixed_portion = 32;
5815 case SMB_QUERY_COMPRESSION_INFO:
5816 case SMB_FILE_COMPRESSION_INFORMATION:
5817 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5818 SOFF_T(pdata,0,file_size);
5819 SIVAL(pdata,8,0); /* ??? */
5820 SIVAL(pdata,12,0); /* ??? */
5822 *fixed_portion = 16;
5825 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5826 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5827 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5828 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5829 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5830 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5831 SOFF_T(pdata,32,allocation_size);
5832 SOFF_T(pdata,40,file_size);
5833 SIVAL(pdata,48,mode);
5834 SIVAL(pdata,52,0); /* ??? */
5836 *fixed_portion = 56;
5839 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5840 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5841 SIVAL(pdata,0,mode);
5848 * CIFS UNIX Extensions.
5851 case SMB_QUERY_FILE_UNIX_BASIC:
5853 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5854 data_size = PTR_DIFF(pdata,(*ppdata));
5856 DEBUG(4,("smbd_do_qfilepathinfo: "
5857 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5858 dump_data(4, (uint8_t *)(*ppdata), data_size);
5862 case SMB_QUERY_FILE_UNIX_INFO2:
5864 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5865 data_size = PTR_DIFF(pdata,(*ppdata));
5869 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5871 for (i=0; i<100; i++)
5872 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5878 case SMB_QUERY_FILE_UNIX_LINK:
5881 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5884 return NT_STATUS_NO_MEMORY;
5887 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5889 if(!S_ISLNK(psbuf->st_ex_mode)) {
5890 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5893 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5895 link_len = SMB_VFS_READLINKAT(conn,
5901 if (link_len == -1) {
5902 return map_nt_error_from_unix(errno);
5904 buffer[link_len] = 0;
5905 status = srvstr_push(dstart, flags2,
5907 PTR_DIFF(dend, pdata),
5908 STR_TERMINATE, &len);
5909 if (!NT_STATUS_IS_OK(status)) {
5913 data_size = PTR_DIFF(pdata,(*ppdata));
5918 #if defined(HAVE_POSIX_ACLS)
5919 case SMB_QUERY_POSIX_ACL:
5921 status = smb_query_posix_acl(conn,
5928 if (!NT_STATUS_IS_OK(status)) {
5936 case SMB_QUERY_POSIX_LOCK:
5941 enum brl_type lock_type;
5943 /* We need an open file with a real fd for this. */
5944 if (!fsp || fsp->fh->fd == -1) {
5945 return NT_STATUS_INVALID_LEVEL;
5948 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5949 return NT_STATUS_INVALID_PARAMETER;
5952 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5953 case POSIX_LOCK_TYPE_READ:
5954 lock_type = READ_LOCK;
5956 case POSIX_LOCK_TYPE_WRITE:
5957 lock_type = WRITE_LOCK;
5959 case POSIX_LOCK_TYPE_UNLOCK:
5961 /* There's no point in asking for an unlock... */
5962 return NT_STATUS_INVALID_PARAMETER;
5965 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5966 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5967 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5969 status = query_lock(fsp,
5976 if (ERROR_WAS_LOCK_DENIED(status)) {
5977 /* Here we need to report who has it locked... */
5978 data_size = POSIX_LOCK_DATA_SIZE;
5980 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5981 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5982 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5983 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5984 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5986 } else if (NT_STATUS_IS_OK(status)) {
5987 /* For success we just return a copy of what we sent
5988 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5989 data_size = POSIX_LOCK_DATA_SIZE;
5990 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5991 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5999 return NT_STATUS_INVALID_LEVEL;
6002 *pdata_size = data_size;
6003 return NT_STATUS_OK;
6006 /****************************************************************************
6007 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
6008 file name or file id).
6009 ****************************************************************************/
6011 static void call_trans2qfilepathinfo(connection_struct *conn,
6012 struct smb_request *req,
6013 unsigned int tran_call,
6014 char **pparams, int total_params,
6015 char **ppdata, int total_data,
6016 unsigned int max_data_bytes)
6018 char *params = *pparams;
6019 char *pdata = *ppdata;
6020 uint16_t info_level;
6021 unsigned int data_size = 0;
6022 unsigned int param_size = 2;
6023 struct smb_filename *smb_fname = NULL;
6024 bool delete_pending = False;
6025 struct timespec write_time_ts;
6026 files_struct *fsp = NULL;
6027 struct file_id fileid;
6028 struct ea_list *ea_list = NULL;
6029 int lock_data_count = 0;
6030 char *lock_data = NULL;
6031 size_t fixed_portion;
6032 NTSTATUS status = NT_STATUS_OK;
6035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6039 ZERO_STRUCT(write_time_ts);
6041 if (tran_call == TRANSACT2_QFILEINFO) {
6042 if (total_params < 4) {
6043 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6048 call_trans2qpipeinfo(conn, req, tran_call,
6049 pparams, total_params,
6055 fsp = file_fsp(req, SVAL(params,0));
6056 info_level = SVAL(params,2);
6058 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6060 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6061 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6065 /* Initial check for valid fsp ptr. */
6066 if (!check_fsp_open(conn, req, fsp)) {
6070 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
6071 if (smb_fname == NULL) {
6072 reply_nterror(req, NT_STATUS_NO_MEMORY);
6076 if(fsp->fake_file_handle) {
6078 * This is actually for the QUOTA_FAKE_FILE --metze
6081 /* We know this name is ok, it's already passed the checks. */
6083 } else if(fsp->fh->fd == -1) {
6085 * This is actually a QFILEINFO on a directory
6086 * handle (returned from an NT SMB). NT5.0 seems
6087 * to do this call. JRA.
6090 if (INFO_LEVEL_IS_UNIX(info_level)) {
6091 /* Always do lstat for UNIX calls. */
6092 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6093 DEBUG(3,("call_trans2qfilepathinfo: "
6094 "SMB_VFS_LSTAT of %s failed "
6096 smb_fname_str_dbg(smb_fname),
6099 map_nt_error_from_unix(errno));
6102 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6103 DEBUG(3,("call_trans2qfilepathinfo: "
6104 "SMB_VFS_STAT of %s failed (%s)\n",
6105 smb_fname_str_dbg(smb_fname),
6108 map_nt_error_from_unix(errno));
6112 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6113 fileid = vfs_file_id_from_sbuf(
6114 conn, &smb_fname->st);
6115 get_file_infos(fileid, fsp->name_hash,
6121 * Original code - this is an open file.
6123 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6124 DEBUG(3, ("fstat of %s failed (%s)\n",
6125 fsp_fnum_dbg(fsp), strerror(errno)));
6127 map_nt_error_from_unix(errno));
6130 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6131 fileid = vfs_file_id_from_sbuf(
6132 conn, &smb_fname->st);
6133 get_file_infos(fileid, fsp->name_hash,
6142 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6145 if (total_params < 7) {
6146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6150 info_level = SVAL(params,0);
6152 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6154 if (INFO_LEVEL_IS_UNIX(info_level)) {
6155 if (!lp_unix_extensions()) {
6156 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6159 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6160 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6161 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6162 req->posix_pathnames) {
6163 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6167 if (req->posix_pathnames) {
6168 srvstr_get_path_posix(req,
6177 srvstr_get_path(req,
6186 if (!NT_STATUS_IS_OK(status)) {
6187 reply_nterror(req, status);
6191 status = filename_convert(req,
6198 if (!NT_STATUS_IS_OK(status)) {
6199 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6200 reply_botherror(req,
6201 NT_STATUS_PATH_NOT_COVERED,
6202 ERRSRV, ERRbadpath);
6205 reply_nterror(req, status);
6209 /* If this is a stream, check if there is a delete_pending. */
6210 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6211 && is_ntfs_stream_smb_fname(smb_fname)) {
6212 struct smb_filename *smb_fname_base;
6214 /* Create an smb_filename with stream_name == NULL. */
6215 smb_fname_base = synthetic_smb_fname(
6217 smb_fname->base_name,
6222 if (smb_fname_base == NULL) {
6223 reply_nterror(req, NT_STATUS_NO_MEMORY);
6227 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6228 /* Always do lstat for UNIX calls. */
6229 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6230 DEBUG(3,("call_trans2qfilepathinfo: "
6231 "SMB_VFS_LSTAT of %s failed "
6233 smb_fname_str_dbg(smb_fname_base),
6235 TALLOC_FREE(smb_fname_base);
6237 map_nt_error_from_unix(errno));
6241 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6242 DEBUG(3,("call_trans2qfilepathinfo: "
6243 "fileinfo of %s failed "
6245 smb_fname_str_dbg(smb_fname_base),
6247 TALLOC_FREE(smb_fname_base);
6249 map_nt_error_from_unix(errno));
6254 status = file_name_hash(conn,
6255 smb_fname_str_dbg(smb_fname_base),
6257 if (!NT_STATUS_IS_OK(status)) {
6258 TALLOC_FREE(smb_fname_base);
6259 reply_nterror(req, status);
6263 fileid = vfs_file_id_from_sbuf(conn,
6264 &smb_fname_base->st);
6265 TALLOC_FREE(smb_fname_base);
6266 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6267 if (delete_pending) {
6268 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6273 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6274 /* Always do lstat for UNIX calls. */
6275 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6276 DEBUG(3,("call_trans2qfilepathinfo: "
6277 "SMB_VFS_LSTAT of %s failed (%s)\n",
6278 smb_fname_str_dbg(smb_fname),
6281 map_nt_error_from_unix(errno));
6286 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6287 DEBUG(3,("call_trans2qfilepathinfo: "
6288 "SMB_VFS_STAT of %s failed (%s)\n",
6289 smb_fname_str_dbg(smb_fname),
6292 map_nt_error_from_unix(errno));
6297 status = file_name_hash(conn,
6298 smb_fname_str_dbg(smb_fname),
6300 if (!NT_STATUS_IS_OK(status)) {
6301 reply_nterror(req, status);
6305 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6306 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6307 get_file_infos(fileid, name_hash, &delete_pending,
6311 if (delete_pending) {
6312 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6317 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6318 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6320 info_level,tran_call,total_data));
6322 /* Pull out any data sent here before we realloc. */
6323 switch (info_level) {
6324 case SMB_INFO_QUERY_EAS_FROM_LIST:
6326 /* Pull any EA list from the data portion. */
6329 if (total_data < 4) {
6331 req, NT_STATUS_INVALID_PARAMETER);
6334 ea_size = IVAL(pdata,0);
6336 if (total_data > 0 && ea_size != total_data) {
6337 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6338 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6340 req, NT_STATUS_INVALID_PARAMETER);
6344 if (!lp_ea_support(SNUM(conn))) {
6345 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6349 /* Pull out the list of names. */
6350 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6353 req, NT_STATUS_INVALID_PARAMETER);
6359 case SMB_QUERY_POSIX_LOCK:
6361 if (fsp == NULL || fsp->fh->fd == -1) {
6362 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6366 if (total_data != POSIX_LOCK_DATA_SIZE) {
6368 req, NT_STATUS_INVALID_PARAMETER);
6372 /* Copy the lock range data. */
6373 lock_data = (char *)talloc_memdup(
6374 req, pdata, total_data);
6376 reply_nterror(req, NT_STATUS_NO_MEMORY);
6379 lock_data_count = total_data;
6385 *pparams = (char *)SMB_REALLOC(*pparams,2);
6386 if (*pparams == NULL) {
6387 reply_nterror(req, NT_STATUS_NO_MEMORY);
6394 * draft-leach-cifs-v1-spec-02.txt
6395 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6398 * The requested information is placed in the Data portion of the
6399 * transaction response. For the information levels greater than 0x100,
6400 * the transaction response has 1 parameter word which should be
6401 * ignored by the client.
6403 * However Windows only follows this rule for the IS_NAME_VALID call.
6405 switch (info_level) {
6406 case SMB_INFO_IS_NAME_VALID:
6411 if ((info_level & 0xFF00) == 0xFF00) {
6413 * We use levels that start with 0xFF00
6414 * internally to represent SMB2 specific levels
6416 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6420 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6422 delete_pending, write_time_ts,
6424 lock_data_count, lock_data,
6425 req->flags2, max_data_bytes,
6427 ppdata, &data_size);
6428 if (!NT_STATUS_IS_OK(status)) {
6429 if (open_was_deferred(req->xconn, req->mid)) {
6430 /* We have re-scheduled this call. */
6433 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6434 bool ok = defer_smb1_sharing_violation(req);
6439 reply_nterror(req, status);
6442 if (fixed_portion > max_data_bytes) {
6443 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6447 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6453 /****************************************************************************
6454 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6456 ****************************************************************************/
6458 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6459 connection_struct *conn,
6460 struct smb_request *req,
6461 bool overwrite_if_exists,
6462 const struct smb_filename *smb_fname_old,
6463 struct smb_filename *smb_fname_new)
6465 NTSTATUS status = NT_STATUS_OK;
6469 /* source must already exist. */
6470 if (!VALID_STAT(smb_fname_old->st)) {
6471 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6474 if (VALID_STAT(smb_fname_new->st)) {
6475 if (overwrite_if_exists) {
6476 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6477 return NT_STATUS_FILE_IS_A_DIRECTORY;
6479 status = unlink_internals(conn,
6481 FILE_ATTRIBUTE_NORMAL,
6484 if (!NT_STATUS_IS_OK(status)) {
6488 /* Disallow if newname already exists. */
6489 return NT_STATUS_OBJECT_NAME_COLLISION;
6493 /* No links from a directory. */
6494 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6495 return NT_STATUS_FILE_IS_A_DIRECTORY;
6498 /* Setting a hardlink to/from a stream isn't currently supported. */
6499 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6501 DBG_DEBUG("Old name has streams\n");
6502 return NT_STATUS_INVALID_PARAMETER;
6504 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6506 DBG_DEBUG("New name has streams\n");
6507 return NT_STATUS_INVALID_PARAMETER;
6510 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6511 smb_fname_old->base_name, smb_fname_new->base_name));
6513 ret = SMB_VFS_LINKAT(conn,
6521 status = map_nt_error_from_unix(errno);
6522 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6523 nt_errstr(status), smb_fname_old->base_name,
6524 smb_fname_new->base_name));
6529 /****************************************************************************
6530 Deal with setting the time from any of the setfilepathinfo functions.
6531 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6532 calling this function.
6533 ****************************************************************************/
6535 NTSTATUS smb_set_file_time(connection_struct *conn,
6537 const struct smb_filename *smb_fname,
6538 struct smb_file_time *ft,
6539 bool setting_write_time)
6541 struct smb_filename smb_fname_base;
6542 struct timeval_buf tbuf[4];
6544 FILE_NOTIFY_CHANGE_LAST_ACCESS
6545 |FILE_NOTIFY_CHANGE_LAST_WRITE
6546 |FILE_NOTIFY_CHANGE_CREATION;
6548 if (!VALID_STAT(smb_fname->st)) {
6549 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6552 /* get some defaults (no modifications) if any info is zero or -1. */
6553 if (is_omit_timespec(&ft->create_time)) {
6554 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6557 if (is_omit_timespec(&ft->atime)) {
6558 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6561 if (is_omit_timespec(&ft->mtime)) {
6562 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6565 if (!setting_write_time) {
6566 /* ft->mtime comes from change time, not write time. */
6567 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6570 /* Ensure the resolution is the correct for
6571 * what we can store on this filesystem. */
6573 round_timespec(conn->ts_res, &ft->create_time);
6574 round_timespec(conn->ts_res, &ft->ctime);
6575 round_timespec(conn->ts_res, &ft->atime);
6576 round_timespec(conn->ts_res, &ft->mtime);
6578 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6579 timespec_string_buf(&ft->atime, true, &tbuf[0]));
6580 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6581 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
6582 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6583 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
6584 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6585 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
6587 if (setting_write_time) {
6589 * This was a Windows setfileinfo on an open file.
6590 * NT does this a lot. We also need to
6591 * set the time here, as it can be read by
6592 * FindFirst/FindNext and with the patch for bug #2045
6593 * in smbd/fileio.c it ensures that this timestamp is
6594 * kept sticky even after a write. We save the request
6595 * away and will set it on file close and after a write. JRA.
6598 DBG_DEBUG("setting pending modtime to %s\n",
6599 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
6602 if (fsp->base_fsp) {
6603 set_sticky_write_time_fsp(fsp->base_fsp,
6606 set_sticky_write_time_fsp(fsp, ft->mtime);
6609 set_sticky_write_time_path(
6610 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6615 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6617 /* Always call ntimes on the base, even if a stream was passed in. */
6618 smb_fname_base = *smb_fname;
6619 smb_fname_base.stream_name = NULL;
6621 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6622 return map_nt_error_from_unix(errno);
6625 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6626 smb_fname->base_name);
6627 return NT_STATUS_OK;
6630 /****************************************************************************
6631 Deal with setting the dosmode from any of the setfilepathinfo functions.
6632 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6633 done before calling this function.
6634 ****************************************************************************/
6636 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6637 const struct smb_filename *smb_fname,
6640 struct smb_filename *smb_fname_base;
6643 if (!VALID_STAT(smb_fname->st)) {
6644 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6647 /* Always operate on the base_name, even if a stream was passed in. */
6648 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6649 smb_fname->base_name,
6654 if (smb_fname_base == NULL) {
6655 return NT_STATUS_NO_MEMORY;
6659 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6660 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6662 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6666 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6668 /* check the mode isn't different, before changing it */
6669 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6670 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6671 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6672 (unsigned int)dosmode));
6674 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6676 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6678 smb_fname_str_dbg(smb_fname_base),
6680 status = map_nt_error_from_unix(errno);
6684 status = NT_STATUS_OK;
6686 TALLOC_FREE(smb_fname_base);
6690 /****************************************************************************
6691 Deal with setting the size from any of the setfilepathinfo functions.
6692 ****************************************************************************/
6694 static NTSTATUS smb_set_file_size(connection_struct *conn,
6695 struct smb_request *req,
6697 const struct smb_filename *smb_fname,
6698 const SMB_STRUCT_STAT *psbuf,
6700 bool fail_after_createfile)
6702 NTSTATUS status = NT_STATUS_OK;
6703 struct smb_filename *smb_fname_tmp = NULL;
6704 files_struct *new_fsp = NULL;
6706 if (!VALID_STAT(*psbuf)) {
6707 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6710 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6712 get_file_size_stat(psbuf));
6714 if (size == get_file_size_stat(psbuf)) {
6716 return NT_STATUS_OK;
6718 if (!fsp->fsp_flags.modified) {
6719 return NT_STATUS_OK;
6721 trigger_write_time_update_immediate(fsp);
6722 return NT_STATUS_OK;
6725 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6726 smb_fname_str_dbg(smb_fname), (double)size));
6728 if (fsp && fsp->fh->fd != -1) {
6729 /* Handle based call. */
6730 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6731 return NT_STATUS_ACCESS_DENIED;
6734 if (vfs_set_filelen(fsp, size) == -1) {
6735 return map_nt_error_from_unix(errno);
6737 trigger_write_time_update_immediate(fsp);
6738 return NT_STATUS_OK;
6741 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6742 if (smb_fname_tmp == NULL) {
6743 return NT_STATUS_NO_MEMORY;
6746 smb_fname_tmp->st = *psbuf;
6748 status = SMB_VFS_CREATE_FILE(
6751 &conn->cwd_fsp, /* dirfsp */
6752 smb_fname_tmp, /* fname */
6753 FILE_WRITE_DATA, /* access_mask */
6754 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6756 FILE_OPEN, /* create_disposition*/
6757 0, /* create_options */
6758 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6759 0, /* oplock_request */
6761 0, /* allocation_size */
6762 0, /* private_flags */
6765 &new_fsp, /* result */
6767 NULL, NULL); /* create context */
6769 TALLOC_FREE(smb_fname_tmp);
6771 if (!NT_STATUS_IS_OK(status)) {
6772 /* NB. We check for open_was_deferred in the caller. */
6776 /* See RAW-SFILEINFO-END-OF-FILE */
6777 if (fail_after_createfile) {
6778 close_file(req, new_fsp,NORMAL_CLOSE);
6779 return NT_STATUS_INVALID_LEVEL;
6782 if (vfs_set_filelen(new_fsp, size) == -1) {
6783 status = map_nt_error_from_unix(errno);
6784 close_file(req, new_fsp,NORMAL_CLOSE);
6788 trigger_write_time_update_immediate(new_fsp);
6789 close_file(req, new_fsp,NORMAL_CLOSE);
6790 return NT_STATUS_OK;
6793 /****************************************************************************
6794 Deal with SMB_INFO_SET_EA.
6795 ****************************************************************************/
6797 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6801 const struct smb_filename *smb_fname)
6803 struct ea_list *ea_list = NULL;
6804 TALLOC_CTX *ctx = NULL;
6805 NTSTATUS status = NT_STATUS_OK;
6807 if (total_data < 10) {
6809 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6810 length. They seem to have no effect. Bug #3212. JRA */
6812 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6813 /* We're done. We only get EA info in this call. */
6814 return NT_STATUS_OK;
6817 return NT_STATUS_INVALID_PARAMETER;
6820 if (IVAL(pdata,0) > total_data) {
6821 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6822 IVAL(pdata,0), (unsigned int)total_data));
6823 return NT_STATUS_INVALID_PARAMETER;
6827 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6829 return NT_STATUS_INVALID_PARAMETER;
6832 status = set_ea(conn, fsp, smb_fname, ea_list);
6837 /****************************************************************************
6838 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6839 ****************************************************************************/
6841 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6846 struct ea_list *ea_list = NULL;
6850 return NT_STATUS_INVALID_HANDLE;
6853 if (!lp_ea_support(SNUM(conn))) {
6854 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6855 "EA's not supported.\n",
6856 (unsigned int)total_data));
6857 return NT_STATUS_EAS_NOT_SUPPORTED;
6860 if (total_data < 10) {
6861 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6863 (unsigned int)total_data));
6864 return NT_STATUS_INVALID_PARAMETER;
6867 ea_list = read_nttrans_ea_list(talloc_tos(),
6872 return NT_STATUS_INVALID_PARAMETER;
6875 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6877 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6878 smb_fname_str_dbg(fsp->fsp_name),
6879 nt_errstr(status) ));
6885 /****************************************************************************
6886 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6887 ****************************************************************************/
6889 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6893 struct smb_filename *smb_fname)
6895 NTSTATUS status = NT_STATUS_OK;
6896 bool delete_on_close;
6897 uint32_t dosmode = 0;
6899 if (total_data < 1) {
6900 return NT_STATUS_INVALID_PARAMETER;
6904 return NT_STATUS_INVALID_HANDLE;
6907 delete_on_close = (CVAL(pdata,0) ? True : False);
6908 dosmode = dos_mode(conn, smb_fname);
6910 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6911 "delete_on_close = %u\n",
6912 smb_fname_str_dbg(smb_fname),
6913 (unsigned int)dosmode,
6914 (unsigned int)delete_on_close ));
6916 if (delete_on_close) {
6917 status = can_set_delete_on_close(fsp, dosmode);
6918 if (!NT_STATUS_IS_OK(status)) {
6923 /* The set is across all open files on this dev/inode pair. */
6924 if (!set_delete_on_close(fsp, delete_on_close,
6925 conn->session_info->security_token,
6926 conn->session_info->unix_token)) {
6927 return NT_STATUS_ACCESS_DENIED;
6929 return NT_STATUS_OK;
6932 /****************************************************************************
6933 Deal with SMB_FILE_POSITION_INFORMATION.
6934 ****************************************************************************/
6936 static NTSTATUS smb_file_position_information(connection_struct *conn,
6941 uint64_t position_information;
6943 if (total_data < 8) {
6944 return NT_STATUS_INVALID_PARAMETER;
6948 /* Ignore on pathname based set. */
6949 return NT_STATUS_OK;
6952 position_information = (uint64_t)IVAL(pdata,0);
6953 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6955 DEBUG(10,("smb_file_position_information: Set file position "
6956 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6957 (double)position_information));
6958 fsp->fh->position_information = position_information;
6959 return NT_STATUS_OK;
6962 /****************************************************************************
6963 Deal with SMB_FILE_MODE_INFORMATION.
6964 ****************************************************************************/
6966 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6972 if (total_data < 4) {
6973 return NT_STATUS_INVALID_PARAMETER;
6975 mode = IVAL(pdata,0);
6976 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6977 return NT_STATUS_INVALID_PARAMETER;
6979 return NT_STATUS_OK;
6982 /****************************************************************************
6983 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6984 ****************************************************************************/
6986 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6987 struct smb_request *req,
6990 const struct smb_filename *new_smb_fname)
6992 char *link_target = NULL;
6993 struct smb_filename target_fname;
6994 TALLOC_CTX *ctx = talloc_tos();
6998 /* Set a symbolic link. */
6999 /* Don't allow this if follow links is false. */
7001 if (total_data == 0) {
7002 return NT_STATUS_INVALID_PARAMETER;
7005 if (!lp_follow_symlinks(SNUM(conn))) {
7006 return NT_STATUS_ACCESS_DENIED;
7009 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
7010 total_data, STR_TERMINATE);
7013 return NT_STATUS_INVALID_PARAMETER;
7016 target_fname = (struct smb_filename) {
7017 .base_name = link_target,
7020 /* Removes @GMT tokens if any */
7021 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
7022 if (!NT_STATUS_IS_OK(status)) {
7026 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
7027 new_smb_fname->base_name, link_target ));
7029 ret = SMB_VFS_SYMLINKAT(conn,
7034 return map_nt_error_from_unix(errno);
7037 return NT_STATUS_OK;
7040 /****************************************************************************
7041 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
7042 ****************************************************************************/
7044 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
7045 struct smb_request *req,
7046 const char *pdata, int total_data,
7047 struct smb_filename *smb_fname_new)
7049 char *oldname = NULL;
7050 struct smb_filename *smb_fname_old = NULL;
7051 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7052 TALLOC_CTX *ctx = talloc_tos();
7053 NTSTATUS status = NT_STATUS_OK;
7055 /* Set a hard link. */
7056 if (total_data == 0) {
7057 return NT_STATUS_INVALID_PARAMETER;
7060 if (req->posix_pathnames) {
7061 srvstr_get_path_posix(ctx,
7070 srvstr_get_path(ctx,
7079 if (!NT_STATUS_IS_OK(status)) {
7083 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7084 smb_fname_str_dbg(smb_fname_new), oldname));
7086 status = filename_convert(ctx,
7093 if (!NT_STATUS_IS_OK(status)) {
7097 return hardlink_internals(ctx, conn, req, false,
7098 smb_fname_old, smb_fname_new);
7101 /****************************************************************************
7102 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7103 ****************************************************************************/
7105 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7106 struct smb_request *req,
7110 struct smb_filename *smb_fname_src)
7114 char *newname = NULL;
7115 struct smb_filename *smb_fname_dst = NULL;
7116 const char *dst_original_lcomp = NULL;
7117 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7118 NTSTATUS status = NT_STATUS_OK;
7119 TALLOC_CTX *ctx = talloc_tos();
7122 return NT_STATUS_INVALID_HANDLE;
7125 if (total_data < 20) {
7126 return NT_STATUS_INVALID_PARAMETER;
7129 overwrite = (CVAL(pdata,0) ? True : False);
7130 len = IVAL(pdata,16);
7132 if (len > (total_data - 20) || (len == 0)) {
7133 return NT_STATUS_INVALID_PARAMETER;
7136 if (req->posix_pathnames) {
7137 srvstr_get_path_posix(ctx,
7146 srvstr_get_path(ctx,
7155 if (!NT_STATUS_IS_OK(status)) {
7159 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7162 status = filename_convert(ctx,
7169 if (!NT_STATUS_IS_OK(status)) {
7173 if (fsp->base_fsp) {
7174 /* newname must be a stream name. */
7175 if (newname[0] != ':') {
7176 return NT_STATUS_NOT_SUPPORTED;
7179 /* Create an smb_fname to call rename_internals_fsp() with. */
7180 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7181 fsp->base_fsp->fsp_name->base_name,
7184 fsp->base_fsp->fsp_name->twrp,
7185 fsp->base_fsp->fsp_name->flags);
7186 if (smb_fname_dst == NULL) {
7187 status = NT_STATUS_NO_MEMORY;
7193 * Set the original last component, since
7194 * rename_internals_fsp() requires it.
7196 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7200 if (dst_original_lcomp == NULL) {
7201 status = NT_STATUS_NO_MEMORY;
7205 DEBUG(10,("smb2_file_rename_information: "
7206 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7207 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7208 smb_fname_str_dbg(smb_fname_dst)));
7209 status = rename_internals_fsp(conn,
7213 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7217 TALLOC_FREE(smb_fname_dst);
7221 static NTSTATUS smb_file_link_information(connection_struct *conn,
7222 struct smb_request *req,
7226 struct smb_filename *smb_fname_src)
7230 char *newname = NULL;
7231 struct smb_filename *smb_fname_dst = NULL;
7232 NTSTATUS status = NT_STATUS_OK;
7233 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7234 TALLOC_CTX *ctx = talloc_tos();
7237 return NT_STATUS_INVALID_HANDLE;
7240 if (total_data < 20) {
7241 return NT_STATUS_INVALID_PARAMETER;
7244 overwrite = (CVAL(pdata,0) ? true : false);
7245 len = IVAL(pdata,16);
7247 if (len > (total_data - 20) || (len == 0)) {
7248 return NT_STATUS_INVALID_PARAMETER;
7251 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7252 srvstr_get_path_posix(ctx,
7260 ucf_flags |= UCF_POSIX_PATHNAMES;
7262 srvstr_get_path(ctx,
7271 if (!NT_STATUS_IS_OK(status)) {
7275 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7278 status = filename_convert(ctx,
7285 if (!NT_STATUS_IS_OK(status)) {
7289 if (fsp->base_fsp) {
7290 /* No stream names. */
7291 return NT_STATUS_NOT_SUPPORTED;
7294 DEBUG(10,("smb_file_link_information: "
7295 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7296 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7297 smb_fname_str_dbg(smb_fname_dst)));
7298 status = hardlink_internals(ctx,
7305 TALLOC_FREE(smb_fname_dst);
7309 /****************************************************************************
7310 Deal with SMB_FILE_RENAME_INFORMATION.
7311 ****************************************************************************/
7313 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7314 struct smb_request *req,
7318 struct smb_filename *smb_fname_src)
7323 char *newname = NULL;
7324 struct smb_filename *smb_fname_dst = NULL;
7325 const char *dst_original_lcomp = NULL;
7326 bool dest_has_wcard = False;
7327 NTSTATUS status = NT_STATUS_OK;
7329 TALLOC_CTX *ctx = talloc_tos();
7331 if (total_data < 13) {
7332 return NT_STATUS_INVALID_PARAMETER;
7335 overwrite = (CVAL(pdata,0) ? True : False);
7336 root_fid = IVAL(pdata,4);
7337 len = IVAL(pdata,8);
7339 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7340 return NT_STATUS_INVALID_PARAMETER;
7343 if (req->posix_pathnames) {
7344 srvstr_get_path_wcard_posix(ctx,
7354 srvstr_get_path_wcard(ctx,
7364 if (!NT_STATUS_IS_OK(status)) {
7368 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7371 /* Check the new name has no '/' characters. */
7372 if (strchr_m(newname, '/')) {
7373 return NT_STATUS_NOT_SUPPORTED;
7376 if (fsp && fsp->base_fsp) {
7377 /* newname must be a stream name. */
7378 if (newname[0] != ':') {
7379 return NT_STATUS_NOT_SUPPORTED;
7382 /* Create an smb_fname to call rename_internals_fsp() with. */
7383 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7384 fsp->base_fsp->fsp_name->base_name,
7387 fsp->base_fsp->fsp_name->twrp,
7388 fsp->base_fsp->fsp_name->flags);
7389 if (smb_fname_dst == NULL) {
7390 status = NT_STATUS_NO_MEMORY;
7395 * Get the original last component, since
7396 * rename_internals_fsp() requires it.
7398 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7402 if (dst_original_lcomp == NULL) {
7403 status = NT_STATUS_NO_MEMORY;
7409 * Build up an smb_fname_dst based on the filename passed in.
7410 * We basically just strip off the last component, and put on
7411 * the newname instead.
7413 char *base_name = NULL;
7414 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7416 if (dest_has_wcard) {
7417 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7420 /* newname must *not* be a stream name. */
7421 if (newname[0] == ':') {
7422 return NT_STATUS_NOT_SUPPORTED;
7426 * Strip off the last component (filename) of the path passed
7429 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7431 return NT_STATUS_NO_MEMORY;
7433 p = strrchr_m(base_name, '/');
7437 base_name = talloc_strdup(ctx, "");
7439 return NT_STATUS_NO_MEMORY;
7442 /* Append the new name. */
7443 base_name = talloc_asprintf_append(base_name,
7447 return NT_STATUS_NO_MEMORY;
7450 status = filename_convert(ctx,
7458 /* If an error we expect this to be
7459 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7461 if (!NT_STATUS_IS_OK(status)) {
7462 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7466 /* Create an smb_fname to call rename_internals_fsp() */
7467 smb_fname_dst = synthetic_smb_fname(ctx,
7471 smb_fname_src->twrp,
7472 smb_fname_src->flags);
7473 if (smb_fname_dst == NULL) {
7474 status = NT_STATUS_NO_MEMORY;
7478 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7482 if (dst_original_lcomp == NULL) {
7483 status = NT_STATUS_NO_MEMORY;
7489 DEBUG(10,("smb_file_rename_information: "
7490 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7491 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7492 smb_fname_str_dbg(smb_fname_dst)));
7493 status = rename_internals_fsp(conn,
7500 DEBUG(10,("smb_file_rename_information: "
7501 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7502 smb_fname_str_dbg(smb_fname_src),
7503 smb_fname_str_dbg(smb_fname_dst)));
7504 status = rename_internals(ctx,
7514 FILE_WRITE_ATTRIBUTES);
7517 TALLOC_FREE(smb_fname_dst);
7521 /****************************************************************************
7522 Deal with SMB_SET_POSIX_ACL.
7523 ****************************************************************************/
7525 #if defined(HAVE_POSIX_ACLS)
7526 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7527 struct smb_request *req,
7531 const struct smb_filename *smb_fname)
7533 uint16_t posix_acl_version;
7534 uint16_t num_file_acls;
7535 uint16_t num_def_acls;
7536 bool valid_file_acls = true;
7537 bool valid_def_acls = true;
7539 unsigned int size_needed;
7540 unsigned int total_data;
7541 bool close_fsp = false;
7543 if (total_data_in < 0) {
7544 status = NT_STATUS_INVALID_PARAMETER;
7548 total_data = total_data_in;
7550 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7551 status = NT_STATUS_INVALID_PARAMETER;
7554 posix_acl_version = SVAL(pdata,0);
7555 num_file_acls = SVAL(pdata,2);
7556 num_def_acls = SVAL(pdata,4);
7558 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7559 valid_file_acls = false;
7563 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7564 valid_def_acls = false;
7568 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7569 status = NT_STATUS_INVALID_PARAMETER;
7574 if (num_file_acls + num_def_acls < num_file_acls) {
7575 status = NT_STATUS_INVALID_PARAMETER;
7579 size_needed = num_file_acls + num_def_acls;
7582 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7583 * than UINT_MAX, so check by division.
7585 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7586 status = NT_STATUS_INVALID_PARAMETER;
7590 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7591 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7592 status = NT_STATUS_INVALID_PARAMETER;
7595 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7597 if (total_data < size_needed) {
7598 status = NT_STATUS_INVALID_PARAMETER;
7603 * Ensure we always operate on a file descriptor, not just
7607 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7609 SEC_STD_READ_CONTROL|
7610 FILE_READ_ATTRIBUTES|
7611 FILE_WRITE_ATTRIBUTES;
7613 status = get_posix_fsp(conn,
7619 if (!NT_STATUS_IS_OK(status)) {
7625 /* Here we know fsp != NULL */
7626 SMB_ASSERT(fsp != NULL);
7628 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7629 if (!NT_STATUS_IS_OK(status)) {
7633 /* If we have a default acl, this *must* be a directory. */
7634 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
7635 DBG_INFO("Can't set default acls on "
7636 "non-directory %s\n",
7638 return NT_STATUS_INVALID_HANDLE;
7641 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7642 "num_def_acls = %"PRIu16"\n",
7647 /* Move pdata to the start of the file ACL entries. */
7648 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7650 if (valid_file_acls) {
7651 status = set_unix_posix_acl(conn,
7655 if (!NT_STATUS_IS_OK(status)) {
7660 /* Move pdata to the start of the default ACL entries. */
7661 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7663 if (valid_def_acls) {
7664 status = set_unix_posix_default_acl(conn,
7668 if (!NT_STATUS_IS_OK(status)) {
7673 status = NT_STATUS_OK;
7678 (void)close_file(req, fsp, NORMAL_CLOSE);
7685 /****************************************************************************
7686 Deal with SMB_SET_POSIX_LOCK.
7687 ****************************************************************************/
7689 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7691 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7692 struct smb_request *req,
7697 struct tevent_req *subreq = NULL;
7698 struct smbd_lock_element *lck = NULL;
7702 bool blocking_lock = False;
7703 enum brl_type lock_type;
7705 NTSTATUS status = NT_STATUS_OK;
7707 if (fsp == NULL || fsp->fh->fd == -1) {
7708 return NT_STATUS_INVALID_HANDLE;
7711 if (total_data != POSIX_LOCK_DATA_SIZE) {
7712 return NT_STATUS_INVALID_PARAMETER;
7715 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7716 case POSIX_LOCK_TYPE_READ:
7717 lock_type = READ_LOCK;
7719 case POSIX_LOCK_TYPE_WRITE:
7720 /* Return the right POSIX-mappable error code for files opened read-only. */
7721 if (!fsp->fsp_flags.can_write) {
7722 return NT_STATUS_INVALID_HANDLE;
7724 lock_type = WRITE_LOCK;
7726 case POSIX_LOCK_TYPE_UNLOCK:
7727 lock_type = UNLOCK_LOCK;
7730 return NT_STATUS_INVALID_PARAMETER;
7733 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7734 case POSIX_LOCK_FLAG_NOWAIT:
7735 blocking_lock = false;
7737 case POSIX_LOCK_FLAG_WAIT:
7738 blocking_lock = true;
7741 return NT_STATUS_INVALID_PARAMETER;
7744 if (!lp_blocking_locks(SNUM(conn))) {
7745 blocking_lock = False;
7748 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7749 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7750 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7751 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7752 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7754 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7755 "count = %"PRIu64", offset = %"PRIu64"\n",
7757 (unsigned int)lock_type,
7762 if (lock_type == UNLOCK_LOCK) {
7763 struct smbd_lock_element l = {
7764 .req_guid = smbd_request_guid(req, 0),
7766 .brltype = UNLOCK_LOCK,
7770 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7774 lck = talloc(req, struct smbd_lock_element);
7776 return NT_STATUS_NO_MEMORY;
7779 *lck = (struct smbd_lock_element) {
7780 .req_guid = smbd_request_guid(req, 0),
7782 .brltype = lock_type,
7787 subreq = smbd_smb1_do_locks_send(
7792 blocking_lock ? UINT32_MAX : 0,
7793 true, /* large_offset */
7797 if (subreq == NULL) {
7799 return NT_STATUS_NO_MEMORY;
7801 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7802 return NT_STATUS_EVENT_PENDING;
7805 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7807 struct smb_request *req = NULL;
7811 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7814 status = smbd_smb1_do_locks_recv(subreq);
7815 TALLOC_FREE(subreq);
7817 if (NT_STATUS_IS_OK(status)) {
7818 char params[2] = {0};
7819 /* Fake up max_data_bytes here - we know it fits. */
7820 send_trans2_replies(
7830 reply_nterror(req, status);
7833 (char *)req->outbuf,
7836 IS_CONN_ENCRYPTED(req->conn),
7839 exit_server_cleanly("smb_set_posix_lock_done: "
7840 "srv_send_smb failed.");
7848 /****************************************************************************
7849 Deal with SMB_SET_FILE_BASIC_INFO.
7850 ****************************************************************************/
7852 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7856 const struct smb_filename *smb_fname)
7858 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7859 struct smb_file_time ft;
7860 uint32_t dosmode = 0;
7861 NTSTATUS status = NT_STATUS_OK;
7863 init_smb_file_time(&ft);
7865 if (total_data < 36) {
7866 return NT_STATUS_INVALID_PARAMETER;
7870 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7872 status = check_access(conn,
7875 FILE_WRITE_ATTRIBUTES);
7877 if (!NT_STATUS_IS_OK(status)) {
7881 /* Set the attributes */
7882 dosmode = IVAL(pdata,32);
7883 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7884 if (!NT_STATUS_IS_OK(status)) {
7889 ft.create_time = pull_long_date_full_timespec(pdata);
7892 ft.atime = pull_long_date_full_timespec(pdata+8);
7895 ft.mtime = pull_long_date_full_timespec(pdata+16);
7898 ft.ctime = pull_long_date_full_timespec(pdata+24);
7900 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7901 smb_fname_str_dbg(smb_fname)));
7903 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7904 if (!NT_STATUS_IS_OK(status)) {
7908 if (fsp != NULL && fsp->fsp_flags.modified) {
7909 trigger_write_time_update_immediate(fsp);
7911 return NT_STATUS_OK;
7914 /****************************************************************************
7915 Deal with SMB_INFO_STANDARD.
7916 ****************************************************************************/
7918 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7922 const struct smb_filename *smb_fname)
7925 struct smb_file_time ft;
7927 init_smb_file_time(&ft);
7929 if (total_data < 12) {
7930 return NT_STATUS_INVALID_PARAMETER;
7934 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
7936 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
7938 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
7940 DEBUG(10,("smb_set_info_standard: file %s\n",
7941 smb_fname_str_dbg(smb_fname)));
7944 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7946 status = check_access(conn,
7949 FILE_WRITE_ATTRIBUTES);
7951 if (!NT_STATUS_IS_OK(status)) {
7955 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7956 if (!NT_STATUS_IS_OK(status)) {
7960 if (fsp != NULL && fsp->fsp_flags.modified) {
7961 trigger_write_time_update_immediate(fsp);
7963 return NT_STATUS_OK;
7966 /****************************************************************************
7967 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7968 ****************************************************************************/
7970 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7971 struct smb_request *req,
7975 struct smb_filename *smb_fname)
7977 uint64_t allocation_size = 0;
7978 NTSTATUS status = NT_STATUS_OK;
7979 files_struct *new_fsp = NULL;
7981 if (!VALID_STAT(smb_fname->st)) {
7982 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7985 if (total_data < 8) {
7986 return NT_STATUS_INVALID_PARAMETER;
7989 allocation_size = (uint64_t)IVAL(pdata,0);
7990 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7991 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7992 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7993 (double)allocation_size));
7995 if (allocation_size) {
7996 allocation_size = smb_roundup(conn, allocation_size);
7999 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
8000 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
8001 (double)allocation_size));
8003 if (fsp && fsp->fh->fd != -1) {
8004 /* Open file handle. */
8005 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
8006 return NT_STATUS_ACCESS_DENIED;
8009 /* Only change if needed. */
8010 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8011 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
8012 return map_nt_error_from_unix(errno);
8015 /* But always update the time. */
8017 * This is equivalent to a write. Ensure it's seen immediately
8018 * if there are no pending writes.
8020 trigger_write_time_update_immediate(fsp);
8021 return NT_STATUS_OK;
8024 /* Pathname or stat or directory file. */
8025 status = SMB_VFS_CREATE_FILE(
8028 &conn->cwd_fsp, /* dirfsp */
8029 smb_fname, /* fname */
8030 FILE_WRITE_DATA, /* access_mask */
8031 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8033 FILE_OPEN, /* create_disposition*/
8034 0, /* create_options */
8035 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8036 0, /* oplock_request */
8038 0, /* allocation_size */
8039 0, /* private_flags */
8042 &new_fsp, /* result */
8044 NULL, NULL); /* create context */
8046 if (!NT_STATUS_IS_OK(status)) {
8047 /* NB. We check for open_was_deferred in the caller. */
8051 /* Only change if needed. */
8052 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8053 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
8054 status = map_nt_error_from_unix(errno);
8055 close_file(req, new_fsp, NORMAL_CLOSE);
8060 /* Changing the allocation size should set the last mod time. */
8062 * This is equivalent to a write. Ensure it's seen immediately
8063 * if there are no pending writes.
8065 trigger_write_time_update_immediate(new_fsp);
8066 close_file(req, new_fsp, NORMAL_CLOSE);
8067 return NT_STATUS_OK;
8070 /****************************************************************************
8071 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
8072 ****************************************************************************/
8074 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
8075 struct smb_request *req,
8079 const struct smb_filename *smb_fname,
8080 bool fail_after_createfile)
8084 if (total_data < 8) {
8085 return NT_STATUS_INVALID_PARAMETER;
8088 size = IVAL(pdata,0);
8089 size |= (((off_t)IVAL(pdata,4)) << 32);
8090 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
8091 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
8094 return smb_set_file_size(conn, req,
8099 fail_after_createfile);
8102 /****************************************************************************
8103 Allow a UNIX info mknod.
8104 ****************************************************************************/
8106 static NTSTATUS smb_unix_mknod(connection_struct *conn,
8109 const struct smb_filename *smb_fname)
8111 uint32_t file_type = IVAL(pdata,56);
8112 #if defined(HAVE_MAKEDEV)
8113 uint32_t dev_major = IVAL(pdata,60);
8114 uint32_t dev_minor = IVAL(pdata,68);
8116 SMB_DEV_T dev = (SMB_DEV_T)0;
8117 uint32_t raw_unixmode = IVAL(pdata,84);
8122 if (total_data < 100) {
8123 return NT_STATUS_INVALID_PARAMETER;
8126 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8127 PERM_NEW_FILE, &unixmode);
8128 if (!NT_STATUS_IS_OK(status)) {
8132 #if defined(HAVE_MAKEDEV)
8133 dev = makedev(dev_major, dev_minor);
8136 switch (file_type) {
8137 /* We can't create other objects here. */
8138 case UNIX_TYPE_FILE:
8140 case UNIX_TYPE_SYMLINK:
8141 return NT_STATUS_ACCESS_DENIED;
8142 #if defined(S_IFIFO)
8143 case UNIX_TYPE_FIFO:
8144 unixmode |= S_IFIFO;
8147 #if defined(S_IFSOCK)
8148 case UNIX_TYPE_SOCKET:
8149 unixmode |= S_IFSOCK;
8152 #if defined(S_IFCHR)
8153 case UNIX_TYPE_CHARDEV:
8154 /* This is only allowed for root. */
8155 if (get_current_uid(conn) != sec_initial_uid()) {
8156 return NT_STATUS_ACCESS_DENIED;
8158 unixmode |= S_IFCHR;
8161 #if defined(S_IFBLK)
8162 case UNIX_TYPE_BLKDEV:
8163 if (get_current_uid(conn) != sec_initial_uid()) {
8164 return NT_STATUS_ACCESS_DENIED;
8166 unixmode |= S_IFBLK;
8170 return NT_STATUS_INVALID_PARAMETER;
8173 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8174 "%.0f mode 0%o for file %s\n", (double)dev,
8175 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8177 /* Ok - do the mknod. */
8178 ret = SMB_VFS_MKNODAT(conn,
8185 return map_nt_error_from_unix(errno);
8188 /* If any of the other "set" calls fail we
8189 * don't want to end up with a half-constructed mknod.
8192 if (lp_inherit_permissions(SNUM(conn))) {
8193 struct smb_filename *parent_fname = NULL;
8196 ok = parent_smb_fname(talloc_tos(),
8201 return NT_STATUS_NO_MEMORY;
8203 inherit_access_posix_acl(conn,
8207 TALLOC_FREE(parent_fname);
8210 return NT_STATUS_OK;
8213 /****************************************************************************
8214 Deal with SMB_SET_FILE_UNIX_BASIC.
8215 ****************************************************************************/
8217 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8218 struct smb_request *req,
8222 const struct smb_filename *smb_fname)
8224 struct smb_file_time ft;
8225 uint32_t raw_unixmode;
8228 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8229 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8230 NTSTATUS status = NT_STATUS_OK;
8231 enum perm_type ptype;
8232 files_struct *all_fsps = NULL;
8233 bool modify_mtime = true;
8235 SMB_STRUCT_STAT sbuf;
8237 init_smb_file_time(&ft);
8239 if (total_data < 100) {
8240 return NT_STATUS_INVALID_PARAMETER;
8243 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8244 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8245 size=IVAL(pdata,0); /* first 8 Bytes are size */
8246 size |= (((off_t)IVAL(pdata,4)) << 32);
8249 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
8250 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
8251 set_owner = (uid_t)IVAL(pdata,40);
8252 set_grp = (gid_t)IVAL(pdata,48);
8253 raw_unixmode = IVAL(pdata,84);
8255 if (VALID_STAT(smb_fname->st)) {
8256 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8257 ptype = PERM_EXISTING_DIR;
8259 ptype = PERM_EXISTING_FILE;
8262 ptype = PERM_NEW_FILE;
8265 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8267 if (!NT_STATUS_IS_OK(status)) {
8271 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8272 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8273 smb_fname_str_dbg(smb_fname), (double)size,
8274 (unsigned int)set_owner, (unsigned int)set_grp,
8275 (int)raw_unixmode));
8277 sbuf = smb_fname->st;
8279 if (!VALID_STAT(sbuf)) {
8281 * The only valid use of this is to create character and block
8282 * devices, and named pipes. This is deprecated (IMHO) and
8283 * a new info level should be used for mknod. JRA.
8286 return smb_unix_mknod(conn,
8293 /* Horrible backwards compatibility hack as an old server bug
8294 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8298 size = get_file_size_stat(&sbuf);
8303 * Deal with the UNIX specific mode set.
8306 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8309 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8310 "setting mode 0%o for file %s\n",
8311 (unsigned int)unixmode,
8312 smb_fname_str_dbg(smb_fname)));
8313 if (fsp && fsp->fh->fd != -1) {
8314 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8316 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8319 return map_nt_error_from_unix(errno);
8324 * Deal with the UNIX specific uid set.
8327 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8328 (sbuf.st_ex_uid != set_owner)) {
8331 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8332 "changing owner %u for path %s\n",
8333 (unsigned int)set_owner,
8334 smb_fname_str_dbg(smb_fname)));
8336 if (fsp && fsp->fh->fd != -1) {
8337 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8340 * UNIX extensions calls must always operate
8343 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8344 set_owner, (gid_t)-1);
8348 status = map_nt_error_from_unix(errno);
8354 * Deal with the UNIX specific gid set.
8357 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8358 (sbuf.st_ex_gid != set_grp)) {
8361 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8362 "changing group %u for file %s\n",
8363 (unsigned int)set_grp,
8364 smb_fname_str_dbg(smb_fname)));
8365 if (fsp && fsp->fh->fd != -1) {
8366 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8369 * UNIX extensions calls must always operate
8372 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8376 status = map_nt_error_from_unix(errno);
8381 /* Deal with any size changes. */
8383 if (S_ISREG(sbuf.st_ex_mode)) {
8384 status = smb_set_file_size(conn, req,
8390 if (!NT_STATUS_IS_OK(status)) {
8395 /* Deal with any time changes. */
8396 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
8397 /* No change, don't cancel anything. */
8401 id = vfs_file_id_from_sbuf(conn, &sbuf);
8402 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8403 all_fsps = file_find_di_next(all_fsps)) {
8405 * We're setting the time explicitly for UNIX.
8406 * Cancel any pending changes over all handles.
8408 all_fsps->fsp_flags.update_write_time_on_close = false;
8409 TALLOC_FREE(all_fsps->update_write_time_event);
8413 * Override the "setting_write_time"
8414 * parameter here as it almost does what
8415 * we need. Just remember if we modified
8416 * mtime and send the notify ourselves.
8418 if (is_omit_timespec(&ft.mtime)) {
8419 modify_mtime = false;
8422 status = smb_set_file_time(conn,
8428 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8429 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8434 /****************************************************************************
8435 Deal with SMB_SET_FILE_UNIX_INFO2.
8436 ****************************************************************************/
8438 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8439 struct smb_request *req,
8443 const struct smb_filename *smb_fname)
8446 uint32_t smb_fflags;
8449 if (total_data < 116) {
8450 return NT_STATUS_INVALID_PARAMETER;
8453 /* Start by setting all the fields that are common between UNIX_BASIC
8456 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8458 if (!NT_STATUS_IS_OK(status)) {
8462 smb_fflags = IVAL(pdata, 108);
8463 smb_fmask = IVAL(pdata, 112);
8465 /* NB: We should only attempt to alter the file flags if the client
8466 * sends a non-zero mask.
8468 if (smb_fmask != 0) {
8469 int stat_fflags = 0;
8471 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8472 smb_fmask, &stat_fflags)) {
8473 /* Client asked to alter a flag we don't understand. */
8474 return NT_STATUS_INVALID_PARAMETER;
8477 if (fsp && fsp->fh->fd != -1) {
8478 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8479 return NT_STATUS_NOT_SUPPORTED;
8481 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8482 stat_fflags) != 0) {
8483 return map_nt_error_from_unix(errno);
8488 /* XXX: need to add support for changing the create_time here. You
8489 * can do this for paths on Darwin with setattrlist(2). The right way
8490 * to hook this up is probably by extending the VFS utimes interface.
8493 return NT_STATUS_OK;
8496 /****************************************************************************
8497 Create a directory with POSIX semantics.
8498 ****************************************************************************/
8500 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8501 struct smb_request *req,
8504 struct smb_filename *smb_fname,
8505 int *pdata_return_size)
8507 NTSTATUS status = NT_STATUS_OK;
8508 uint32_t raw_unixmode = 0;
8509 mode_t unixmode = (mode_t)0;
8510 files_struct *fsp = NULL;
8511 uint16_t info_level_return = 0;
8513 char *pdata = *ppdata;
8514 struct smb2_create_blobs *posx = NULL;
8516 if (total_data < 18) {
8517 return NT_STATUS_INVALID_PARAMETER;
8520 raw_unixmode = IVAL(pdata,8);
8521 /* Next 4 bytes are not yet defined. */
8523 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8524 PERM_NEW_DIR, &unixmode);
8525 if (!NT_STATUS_IS_OK(status)) {
8529 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8530 if (!NT_STATUS_IS_OK(status)) {
8531 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8536 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8537 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8539 status = SMB_VFS_CREATE_FILE(
8542 &conn->cwd_fsp, /* dirfsp */
8543 smb_fname, /* fname */
8544 FILE_READ_ATTRIBUTES, /* access_mask */
8545 FILE_SHARE_NONE, /* share_access */
8546 FILE_CREATE, /* create_disposition*/
8547 FILE_DIRECTORY_FILE, /* create_options */
8548 0, /* file_attributes */
8549 0, /* oplock_request */
8551 0, /* allocation_size */
8552 0, /* private_flags */
8557 posx, /* in_context_blobs */
8558 NULL); /* out_context_blobs */
8562 if (NT_STATUS_IS_OK(status)) {
8563 close_file(req, fsp, NORMAL_CLOSE);
8566 info_level_return = SVAL(pdata,16);
8568 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8569 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8570 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8571 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8573 *pdata_return_size = 12;
8576 /* Realloc the data size */
8577 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8578 if (*ppdata == NULL) {
8579 *pdata_return_size = 0;
8580 return NT_STATUS_NO_MEMORY;
8584 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8585 SSVAL(pdata,2,0); /* No fnum. */
8586 SIVAL(pdata,4,info); /* Was directory created. */
8588 switch (info_level_return) {
8589 case SMB_QUERY_FILE_UNIX_BASIC:
8590 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8591 SSVAL(pdata,10,0); /* Padding. */
8592 store_file_unix_basic(conn, pdata + 12, fsp,
8595 case SMB_QUERY_FILE_UNIX_INFO2:
8596 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8597 SSVAL(pdata,10,0); /* Padding. */
8598 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8602 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8603 SSVAL(pdata,10,0); /* Padding. */
8610 /****************************************************************************
8611 Open/Create a file with POSIX semantics.
8612 ****************************************************************************/
8614 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8615 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8617 static NTSTATUS smb_posix_open(connection_struct *conn,
8618 struct smb_request *req,
8621 struct smb_filename *smb_fname,
8622 int *pdata_return_size)
8624 bool extended_oplock_granted = False;
8625 char *pdata = *ppdata;
8627 uint32_t wire_open_mode = 0;
8628 uint32_t raw_unixmode = 0;
8629 uint32_t attributes = 0;
8630 uint32_t create_disp = 0;
8631 uint32_t access_mask = 0;
8632 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8633 NTSTATUS status = NT_STATUS_OK;
8634 mode_t unixmode = (mode_t)0;
8635 files_struct *fsp = NULL;
8636 int oplock_request = 0;
8638 uint16_t info_level_return = 0;
8639 struct smb2_create_blobs *posx = NULL;
8641 if (total_data < 18) {
8642 return NT_STATUS_INVALID_PARAMETER;
8645 flags = IVAL(pdata,0);
8646 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8647 if (oplock_request) {
8648 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8651 wire_open_mode = IVAL(pdata,4);
8653 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8654 return smb_posix_mkdir(conn, req,
8661 switch (wire_open_mode & SMB_ACCMODE) {
8663 access_mask = SMB_O_RDONLY_MAPPING;
8666 access_mask = SMB_O_WRONLY_MAPPING;
8669 access_mask = (SMB_O_RDONLY_MAPPING|
8670 SMB_O_WRONLY_MAPPING);
8673 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8674 (unsigned int)wire_open_mode ));
8675 return NT_STATUS_INVALID_PARAMETER;
8678 wire_open_mode &= ~SMB_ACCMODE;
8680 /* First take care of O_CREAT|O_EXCL interactions. */
8681 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8682 case (SMB_O_CREAT | SMB_O_EXCL):
8683 /* File exists fail. File not exist create. */
8684 create_disp = FILE_CREATE;
8687 /* File exists open. File not exist create. */
8688 create_disp = FILE_OPEN_IF;
8691 /* O_EXCL on its own without O_CREAT is undefined.
8692 We deliberately ignore it as some versions of
8693 Linux CIFSFS can send a bare O_EXCL on the
8694 wire which other filesystems in the kernel
8695 ignore. See bug 9519 for details. */
8700 /* File exists open. File not exist fail. */
8701 create_disp = FILE_OPEN;
8704 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8705 (unsigned int)wire_open_mode ));
8706 return NT_STATUS_INVALID_PARAMETER;
8709 /* Next factor in the effects of O_TRUNC. */
8710 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8712 if (wire_open_mode & SMB_O_TRUNC) {
8713 switch (create_disp) {
8715 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8716 /* Leave create_disp alone as
8717 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8719 /* File exists fail. File not exist create. */
8722 /* SMB_O_CREAT | SMB_O_TRUNC */
8723 /* File exists overwrite. File not exist create. */
8724 create_disp = FILE_OVERWRITE_IF;
8728 /* File exists overwrite. File not exist fail. */
8729 create_disp = FILE_OVERWRITE;
8732 /* Cannot get here. */
8733 smb_panic("smb_posix_open: logic error");
8734 return NT_STATUS_INVALID_PARAMETER;
8738 raw_unixmode = IVAL(pdata,8);
8739 /* Next 4 bytes are not yet defined. */
8741 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8742 (VALID_STAT(smb_fname->st) ?
8743 PERM_EXISTING_FILE : PERM_NEW_FILE),
8746 if (!NT_STATUS_IS_OK(status)) {
8750 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8751 if (!NT_STATUS_IS_OK(status)) {
8752 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8757 if (wire_open_mode & SMB_O_SYNC) {
8758 create_options |= FILE_WRITE_THROUGH;
8760 if (wire_open_mode & SMB_O_APPEND) {
8761 access_mask |= FILE_APPEND_DATA;
8763 if (wire_open_mode & SMB_O_DIRECT) {
8764 attributes |= FILE_FLAG_NO_BUFFERING;
8767 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8768 VALID_STAT_OF_DIR(smb_fname->st)) {
8769 if (access_mask != SMB_O_RDONLY_MAPPING) {
8770 return NT_STATUS_FILE_IS_A_DIRECTORY;
8772 create_options &= ~FILE_NON_DIRECTORY_FILE;
8773 create_options |= FILE_DIRECTORY_FILE;
8776 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8777 smb_fname_str_dbg(smb_fname),
8778 (unsigned int)wire_open_mode,
8779 (unsigned int)unixmode ));
8781 status = SMB_VFS_CREATE_FILE(
8784 &conn->cwd_fsp, /* dirfsp */
8785 smb_fname, /* fname */
8786 access_mask, /* access_mask */
8787 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8789 create_disp, /* create_disposition*/
8790 create_options, /* create_options */
8791 attributes, /* file_attributes */
8792 oplock_request, /* oplock_request */
8794 0, /* allocation_size */
8795 0, /* private_flags */
8800 posx, /* in_context_blobs */
8801 NULL); /* out_context_blobs */
8805 if (!NT_STATUS_IS_OK(status)) {
8809 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8810 extended_oplock_granted = True;
8813 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8814 extended_oplock_granted = True;
8817 info_level_return = SVAL(pdata,16);
8819 /* Allocate the correct return size. */
8821 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8822 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8823 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8824 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8826 *pdata_return_size = 12;
8829 /* Realloc the data size */
8830 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8831 if (*ppdata == NULL) {
8832 close_file(req, fsp, ERROR_CLOSE);
8833 *pdata_return_size = 0;
8834 return NT_STATUS_NO_MEMORY;
8838 if (extended_oplock_granted) {
8839 if (flags & REQUEST_BATCH_OPLOCK) {
8840 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8842 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8844 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8845 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8847 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8850 SSVAL(pdata,2,fsp->fnum);
8851 SIVAL(pdata,4,info); /* Was file created etc. */
8853 switch (info_level_return) {
8854 case SMB_QUERY_FILE_UNIX_BASIC:
8855 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8856 SSVAL(pdata,10,0); /* padding. */
8857 store_file_unix_basic(conn, pdata + 12, fsp,
8860 case SMB_QUERY_FILE_UNIX_INFO2:
8861 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8862 SSVAL(pdata,10,0); /* padding. */
8863 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8867 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8868 SSVAL(pdata,10,0); /* padding. */
8871 return NT_STATUS_OK;
8874 /****************************************************************************
8875 Delete a file with POSIX semantics.
8876 ****************************************************************************/
8878 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8879 struct smb_request *req,
8882 struct smb_filename *smb_fname)
8884 NTSTATUS status = NT_STATUS_OK;
8885 files_struct *fsp = NULL;
8889 int create_options = 0;
8890 struct share_mode_lock *lck = NULL;
8891 bool other_nonposix_opens;
8892 struct smb2_create_blobs *posx = NULL;
8894 if (total_data < 2) {
8895 return NT_STATUS_INVALID_PARAMETER;
8898 flags = SVAL(pdata,0);
8900 if (!VALID_STAT(smb_fname->st)) {
8901 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8904 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8905 !VALID_STAT_OF_DIR(smb_fname->st)) {
8906 return NT_STATUS_NOT_A_DIRECTORY;
8909 DEBUG(10,("smb_posix_unlink: %s %s\n",
8910 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8911 smb_fname_str_dbg(smb_fname)));
8913 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8914 create_options |= FILE_DIRECTORY_FILE;
8917 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8918 if (!NT_STATUS_IS_OK(status)) {
8919 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8924 status = SMB_VFS_CREATE_FILE(
8927 &conn->cwd_fsp, /* dirfsp */
8928 smb_fname, /* fname */
8929 DELETE_ACCESS, /* access_mask */
8930 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8932 FILE_OPEN, /* create_disposition*/
8933 create_options, /* create_options */
8934 0, /* file_attributes */
8935 0, /* oplock_request */
8937 0, /* allocation_size */
8938 0, /* private_flags */
8943 posx, /* in_context_blobs */
8944 NULL); /* out_context_blobs */
8948 if (!NT_STATUS_IS_OK(status)) {
8953 * Don't lie to client. If we can't really delete due to
8954 * non-POSIX opens return SHARING_VIOLATION.
8957 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8959 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8960 "lock for file %s\n", fsp_str_dbg(fsp)));
8961 close_file(req, fsp, NORMAL_CLOSE);
8962 return NT_STATUS_INVALID_PARAMETER;
8965 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8966 if (other_nonposix_opens) {
8967 /* Fail with sharing violation. */
8969 close_file(req, fsp, NORMAL_CLOSE);
8970 return NT_STATUS_SHARING_VIOLATION;
8974 * Set the delete on close.
8976 status = smb_set_file_disposition_info(conn,
8984 if (!NT_STATUS_IS_OK(status)) {
8985 close_file(req, fsp, NORMAL_CLOSE);
8988 return close_file(req, fsp, NORMAL_CLOSE);
8991 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8992 struct smb_request *req,
8993 TALLOC_CTX *mem_ctx,
8994 uint16_t info_level,
8996 struct smb_filename *smb_fname,
8997 char **ppdata, int total_data,
9000 char *pdata = *ppdata;
9001 NTSTATUS status = NT_STATUS_OK;
9002 int data_return_size = 0;
9006 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
9007 return NT_STATUS_INVALID_LEVEL;
9010 if (!CAN_WRITE(conn)) {
9011 /* Allow POSIX opens. The open path will deny
9012 * any non-readonly opens. */
9013 if (info_level != SMB_POSIX_PATH_OPEN) {
9014 return NT_STATUS_DOS(ERRSRV, ERRaccess);
9018 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
9019 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
9021 info_level, total_data));
9023 switch (info_level) {
9025 case SMB_INFO_STANDARD:
9027 status = smb_set_info_standard(conn,
9035 case SMB_INFO_SET_EA:
9037 status = smb_info_set_ea(conn,
9045 case SMB_SET_FILE_BASIC_INFO:
9046 case SMB_FILE_BASIC_INFORMATION:
9048 status = smb_set_file_basic_info(conn,
9056 case SMB_FILE_ALLOCATION_INFORMATION:
9057 case SMB_SET_FILE_ALLOCATION_INFO:
9059 status = smb_set_file_allocation_info(conn, req,
9067 case SMB_FILE_END_OF_FILE_INFORMATION:
9068 case SMB_SET_FILE_END_OF_FILE_INFO:
9071 * XP/Win7 both fail after the createfile with
9072 * SMB_SET_FILE_END_OF_FILE_INFO but not
9073 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
9074 * The level is known here, so pass it down
9078 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
9080 status = smb_set_file_end_of_file_info(conn, req,
9089 case SMB_FILE_DISPOSITION_INFORMATION:
9090 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
9093 /* JRA - We used to just ignore this on a path ?
9094 * Shouldn't this be invalid level on a pathname
9097 if (tran_call != TRANSACT2_SETFILEINFO) {
9098 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
9101 status = smb_set_file_disposition_info(conn,
9109 case SMB_FILE_POSITION_INFORMATION:
9111 status = smb_file_position_information(conn,
9118 case SMB_FILE_FULL_EA_INFORMATION:
9120 status = smb_set_file_full_ea_info(conn,
9127 /* From tridge Samba4 :
9128 * MODE_INFORMATION in setfileinfo (I have no
9129 * idea what "mode information" on a file is - it takes a value of 0,
9130 * 2, 4 or 6. What could it be?).
9133 case SMB_FILE_MODE_INFORMATION:
9135 status = smb_file_mode_information(conn,
9141 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9142 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9143 case SMB_FILE_SHORT_NAME_INFORMATION:
9144 return NT_STATUS_NOT_SUPPORTED;
9147 * CIFS UNIX extensions.
9150 case SMB_SET_FILE_UNIX_BASIC:
9152 status = smb_set_file_unix_basic(conn, req,
9160 case SMB_SET_FILE_UNIX_INFO2:
9162 status = smb_set_file_unix_info2(conn, req,
9170 case SMB_SET_FILE_UNIX_LINK:
9173 /* We must have a pathname for this. */
9174 return NT_STATUS_INVALID_LEVEL;
9176 status = smb_set_file_unix_link(conn, req, pdata,
9177 total_data, smb_fname);
9181 case SMB_SET_FILE_UNIX_HLINK:
9184 /* We must have a pathname for this. */
9185 return NT_STATUS_INVALID_LEVEL;
9187 status = smb_set_file_unix_hlink(conn, req,
9193 case SMB_FILE_RENAME_INFORMATION:
9195 status = smb_file_rename_information(conn, req,
9201 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9203 /* SMB2 rename information. */
9204 status = smb2_file_rename_information(conn, req,
9210 case SMB_FILE_LINK_INFORMATION:
9212 status = smb_file_link_information(conn, req,
9218 #if defined(HAVE_POSIX_ACLS)
9219 case SMB_SET_POSIX_ACL:
9221 status = smb_set_posix_acl(conn,
9231 case SMB_SET_POSIX_LOCK:
9234 return NT_STATUS_INVALID_LEVEL;
9236 status = smb_set_posix_lock(conn, req,
9237 pdata, total_data, fsp);
9241 case SMB_POSIX_PATH_OPEN:
9244 /* We must have a pathname for this. */
9245 return NT_STATUS_INVALID_LEVEL;
9248 status = smb_posix_open(conn, req,
9256 case SMB_POSIX_PATH_UNLINK:
9259 /* We must have a pathname for this. */
9260 return NT_STATUS_INVALID_LEVEL;
9263 status = smb_posix_unlink(conn, req,
9271 return NT_STATUS_INVALID_LEVEL;
9274 if (!NT_STATUS_IS_OK(status)) {
9278 *ret_data_size = data_return_size;
9279 return NT_STATUS_OK;
9282 /****************************************************************************
9283 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9284 ****************************************************************************/
9286 static void call_trans2setfilepathinfo(connection_struct *conn,
9287 struct smb_request *req,
9288 unsigned int tran_call,
9289 char **pparams, int total_params,
9290 char **ppdata, int total_data,
9291 unsigned int max_data_bytes)
9293 char *params = *pparams;
9294 char *pdata = *ppdata;
9295 uint16_t info_level;
9296 struct smb_filename *smb_fname = NULL;
9297 files_struct *fsp = NULL;
9298 NTSTATUS status = NT_STATUS_OK;
9299 int data_return_size = 0;
9302 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9306 if (tran_call == TRANSACT2_SETFILEINFO) {
9307 if (total_params < 4) {
9308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9312 fsp = file_fsp(req, SVAL(params,0));
9313 /* Basic check for non-null fsp. */
9314 if (!check_fsp_open(conn, req, fsp)) {
9317 info_level = SVAL(params,2);
9319 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9320 if (smb_fname == NULL) {
9321 reply_nterror(req, NT_STATUS_NO_MEMORY);
9325 if(fsp->fh->fd == -1) {
9327 * This is actually a SETFILEINFO on a directory
9328 * handle (returned from an NT SMB). NT5.0 seems
9329 * to do this call. JRA.
9331 if (INFO_LEVEL_IS_UNIX(info_level)) {
9332 /* Always do lstat for UNIX calls. */
9333 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9334 DEBUG(3,("call_trans2setfilepathinfo: "
9335 "SMB_VFS_LSTAT of %s failed "
9337 smb_fname_str_dbg(smb_fname),
9339 reply_nterror(req, map_nt_error_from_unix(errno));
9343 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9344 DEBUG(3,("call_trans2setfilepathinfo: "
9345 "fileinfo of %s failed (%s)\n",
9346 smb_fname_str_dbg(smb_fname),
9348 reply_nterror(req, map_nt_error_from_unix(errno));
9352 } else if (fsp->print_file) {
9354 * Doing a DELETE_ON_CLOSE should cancel a print job.
9356 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9357 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9359 DEBUG(3,("call_trans2setfilepathinfo: "
9360 "Cancelling print job (%s)\n",
9364 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9370 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9375 * Original code - this is an open file.
9377 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9378 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9379 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9381 reply_nterror(req, map_nt_error_from_unix(errno));
9387 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9390 if (total_params < 7) {
9391 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9395 info_level = SVAL(params,0);
9396 if (req->posix_pathnames) {
9397 srvstr_get_path_posix(req,
9406 srvstr_get_path(req,
9415 if (!NT_STATUS_IS_OK(status)) {
9416 reply_nterror(req, status);
9420 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9421 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9422 info_level == SMB_FILE_RENAME_INFORMATION ||
9423 info_level == SMB_POSIX_PATH_OPEN ||
9424 info_level == SMB_POSIX_PATH_UNLINK) {
9425 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9428 status = filename_convert(req, conn,
9434 if (!NT_STATUS_IS_OK(status)) {
9435 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9436 reply_botherror(req,
9437 NT_STATUS_PATH_NOT_COVERED,
9438 ERRSRV, ERRbadpath);
9441 reply_nterror(req, status);
9445 if (INFO_LEVEL_IS_UNIX(info_level)) {
9447 * For CIFS UNIX extensions the target name may not exist.
9450 /* Always do lstat for UNIX calls. */
9451 SMB_VFS_LSTAT(conn, smb_fname);
9453 } else if (!VALID_STAT(smb_fname->st) &&
9454 SMB_VFS_STAT(conn, smb_fname)) {
9455 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9457 smb_fname_str_dbg(smb_fname),
9459 reply_nterror(req, map_nt_error_from_unix(errno));
9464 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9465 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9467 info_level,total_data));
9469 /* Realloc the parameter size */
9470 *pparams = (char *)SMB_REALLOC(*pparams,2);
9471 if (*pparams == NULL) {
9472 reply_nterror(req, NT_STATUS_NO_MEMORY);
9479 status = smbd_do_setfilepathinfo(conn, req, req,
9485 if (!NT_STATUS_IS_OK(status)) {
9486 if (open_was_deferred(req->xconn, req->mid)) {
9487 /* We have re-scheduled this call. */
9490 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9491 bool ok = defer_smb1_sharing_violation(req);
9496 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9497 /* We have re-scheduled this call. */
9500 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9501 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9502 ERRSRV, ERRbadpath);
9505 if (info_level == SMB_POSIX_PATH_OPEN) {
9506 reply_openerror(req, status);
9511 * Invalid EA name needs to return 2 param bytes,
9512 * not a zero-length error packet.
9514 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9515 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9518 reply_nterror(req, status);
9523 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9529 /****************************************************************************
9530 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9531 ****************************************************************************/
9533 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9534 char **pparams, int total_params,
9535 char **ppdata, int total_data,
9536 unsigned int max_data_bytes)
9538 struct smb_filename *smb_dname = NULL;
9539 char *params = *pparams;
9540 char *pdata = *ppdata;
9541 char *directory = NULL;
9542 NTSTATUS status = NT_STATUS_OK;
9543 struct ea_list *ea_list = NULL;
9544 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9545 TALLOC_CTX *ctx = talloc_tos();
9547 if (!CAN_WRITE(conn)) {
9548 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9552 if (total_params < 5) {
9553 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9557 if (req->posix_pathnames) {
9558 srvstr_get_path_posix(ctx,
9567 srvstr_get_path(ctx,
9576 if (!NT_STATUS_IS_OK(status)) {
9577 reply_nterror(req, status);
9581 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9583 status = filename_convert(ctx,
9591 if (!NT_STATUS_IS_OK(status)) {
9592 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9593 reply_botherror(req,
9594 NT_STATUS_PATH_NOT_COVERED,
9595 ERRSRV, ERRbadpath);
9598 reply_nterror(req, status);
9603 * OS/2 workplace shell seems to send SET_EA requests of "null"
9604 * length (4 bytes containing IVAL 4).
9605 * They seem to have no effect. Bug #3212. JRA.
9608 if (total_data && (total_data != 4)) {
9609 /* Any data in this call is an EA list. */
9610 if (total_data < 10) {
9611 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9615 if (IVAL(pdata,0) > total_data) {
9616 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9617 IVAL(pdata,0), (unsigned int)total_data));
9618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9622 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9629 if (!lp_ea_support(SNUM(conn))) {
9630 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9634 /* If total_data == 4 Windows doesn't care what values
9635 * are placed in that field, it just ignores them.
9636 * The System i QNTC IBM SMB client puts bad values here,
9637 * so ignore them. */
9639 status = create_directory(conn, req, smb_dname);
9641 if (!NT_STATUS_IS_OK(status)) {
9642 reply_nterror(req, status);
9646 /* Try and set any given EA. */
9648 status = set_ea(conn, NULL, smb_dname, ea_list);
9649 if (!NT_STATUS_IS_OK(status)) {
9650 reply_nterror(req, status);
9655 /* Realloc the parameter and data sizes */
9656 *pparams = (char *)SMB_REALLOC(*pparams,2);
9657 if(*pparams == NULL) {
9658 reply_nterror(req, NT_STATUS_NO_MEMORY);
9665 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9668 TALLOC_FREE(smb_dname);
9672 /****************************************************************************
9673 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9674 We don't actually do this - we just send a null response.
9675 ****************************************************************************/
9677 static void call_trans2findnotifyfirst(connection_struct *conn,
9678 struct smb_request *req,
9679 char **pparams, int total_params,
9680 char **ppdata, int total_data,
9681 unsigned int max_data_bytes)
9683 char *params = *pparams;
9684 uint16_t info_level;
9686 if (total_params < 6) {
9687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9691 info_level = SVAL(params,4);
9692 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9694 switch (info_level) {
9699 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9703 /* Realloc the parameter and data sizes */
9704 *pparams = (char *)SMB_REALLOC(*pparams,6);
9705 if (*pparams == NULL) {
9706 reply_nterror(req, NT_STATUS_NO_MEMORY);
9711 SSVAL(params,0,fnf_handle);
9712 SSVAL(params,2,0); /* No changes */
9713 SSVAL(params,4,0); /* No EA errors */
9720 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9725 /****************************************************************************
9726 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9727 changes). Currently this does nothing.
9728 ****************************************************************************/
9730 static void call_trans2findnotifynext(connection_struct *conn,
9731 struct smb_request *req,
9732 char **pparams, int total_params,
9733 char **ppdata, int total_data,
9734 unsigned int max_data_bytes)
9736 char *params = *pparams;
9738 DEBUG(3,("call_trans2findnotifynext\n"));
9740 /* Realloc the parameter and data sizes */
9741 *pparams = (char *)SMB_REALLOC(*pparams,4);
9742 if (*pparams == NULL) {
9743 reply_nterror(req, NT_STATUS_NO_MEMORY);
9748 SSVAL(params,0,0); /* No changes */
9749 SSVAL(params,2,0); /* No EA errors */
9751 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9756 /****************************************************************************
9757 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9758 ****************************************************************************/
9760 static void call_trans2getdfsreferral(connection_struct *conn,
9761 struct smb_request *req,
9762 char **pparams, int total_params,
9763 char **ppdata, int total_data,
9764 unsigned int max_data_bytes)
9766 char *params = *pparams;
9767 char *pathname = NULL;
9769 int max_referral_level;
9770 NTSTATUS status = NT_STATUS_OK;
9771 TALLOC_CTX *ctx = talloc_tos();
9773 DEBUG(10,("call_trans2getdfsreferral\n"));
9775 if (total_params < 3) {
9776 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9780 max_referral_level = SVAL(params,0);
9782 if(!lp_host_msdfs()) {
9783 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9787 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9788 total_params - 2, STR_TERMINATE);
9790 reply_nterror(req, NT_STATUS_NOT_FOUND);
9793 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9794 ppdata,&status)) < 0) {
9795 reply_nterror(req, status);
9799 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9800 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9801 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9806 #define LMCAT_SPL 0x53
9807 #define LMFUNC_GETJOBID 0x60
9809 /****************************************************************************
9810 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9811 ****************************************************************************/
9813 static void call_trans2ioctl(connection_struct *conn,
9814 struct smb_request *req,
9815 char **pparams, int total_params,
9816 char **ppdata, int total_data,
9817 unsigned int max_data_bytes)
9819 const struct loadparm_substitution *lp_sub =
9820 loadparm_s3_global_substitution();
9821 char *pdata = *ppdata;
9822 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9826 /* check for an invalid fid before proceeding */
9829 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9833 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9834 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9835 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9836 if (*ppdata == NULL) {
9837 reply_nterror(req, NT_STATUS_NO_MEMORY);
9842 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9843 CAN ACCEPT THIS IN UNICODE. JRA. */
9846 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9848 status = srvstr_push(pdata, req->flags2, pdata + 2,
9849 lp_netbios_name(), 15,
9850 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9851 if (!NT_STATUS_IS_OK(status)) {
9852 reply_nterror(req, status);
9855 status = srvstr_push(pdata, req->flags2, pdata+18,
9856 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
9857 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9858 if (!NT_STATUS_IS_OK(status)) {
9859 reply_nterror(req, status);
9862 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9867 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9868 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9871 /****************************************************************************
9872 Reply to a SMBfindclose (stop trans2 directory search).
9873 ****************************************************************************/
9875 void reply_findclose(struct smb_request *req)
9878 struct smbd_server_connection *sconn = req->sconn;
9879 files_struct *fsp = NULL;
9881 START_PROFILE(SMBfindclose);
9884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9885 END_PROFILE(SMBfindclose);
9889 dptr_num = SVALS(req->vwv+0, 0);
9891 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9894 * OS/2 seems to use -1 to indicate "close all directories"
9895 * This has to mean on this specific connection struct.
9897 if (dptr_num == -1) {
9898 dptr_closecnum(req->conn);
9900 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9903 close_file(NULL, fsp, NORMAL_CLOSE);
9908 reply_outbuf(req, 0, 0);
9910 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9912 END_PROFILE(SMBfindclose);
9916 /****************************************************************************
9917 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9918 ****************************************************************************/
9920 void reply_findnclose(struct smb_request *req)
9924 START_PROFILE(SMBfindnclose);
9927 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9928 END_PROFILE(SMBfindnclose);
9932 dptr_num = SVAL(req->vwv+0, 0);
9934 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9936 /* We never give out valid handles for a
9937 findnotifyfirst - so any dptr_num is ok here.
9940 reply_outbuf(req, 0, 0);
9942 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9944 END_PROFILE(SMBfindnclose);
9948 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9949 struct trans_state *state)
9951 if (get_Protocol() >= PROTOCOL_NT1) {
9952 req->flags2 |= 0x40; /* IS_LONG_NAME */
9953 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9956 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9957 if (state->call != TRANSACT2_QFSINFO &&
9958 state->call != TRANSACT2_SETFSINFO) {
9959 DEBUG(0,("handle_trans2: encryption required "
9961 (unsigned int)state->call));
9962 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9967 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9969 /* Now we must call the relevant TRANS2 function */
9970 switch(state->call) {
9971 case TRANSACT2_OPEN:
9973 START_PROFILE(Trans2_open);
9974 call_trans2open(conn, req,
9975 &state->param, state->total_param,
9976 &state->data, state->total_data,
9977 state->max_data_return);
9978 END_PROFILE(Trans2_open);
9982 case TRANSACT2_FINDFIRST:
9984 START_PROFILE(Trans2_findfirst);
9985 call_trans2findfirst(conn, req,
9986 &state->param, state->total_param,
9987 &state->data, state->total_data,
9988 state->max_data_return);
9989 END_PROFILE(Trans2_findfirst);
9993 case TRANSACT2_FINDNEXT:
9995 START_PROFILE(Trans2_findnext);
9996 call_trans2findnext(conn, req,
9997 &state->param, state->total_param,
9998 &state->data, state->total_data,
9999 state->max_data_return);
10000 END_PROFILE(Trans2_findnext);
10004 case TRANSACT2_QFSINFO:
10006 START_PROFILE(Trans2_qfsinfo);
10007 call_trans2qfsinfo(conn, req,
10008 &state->param, state->total_param,
10009 &state->data, state->total_data,
10010 state->max_data_return);
10011 END_PROFILE(Trans2_qfsinfo);
10015 case TRANSACT2_SETFSINFO:
10017 START_PROFILE(Trans2_setfsinfo);
10018 call_trans2setfsinfo(conn, req,
10019 &state->param, state->total_param,
10020 &state->data, state->total_data,
10021 state->max_data_return);
10022 END_PROFILE(Trans2_setfsinfo);
10026 case TRANSACT2_QPATHINFO:
10027 case TRANSACT2_QFILEINFO:
10029 START_PROFILE(Trans2_qpathinfo);
10030 call_trans2qfilepathinfo(conn, req, state->call,
10031 &state->param, state->total_param,
10032 &state->data, state->total_data,
10033 state->max_data_return);
10034 END_PROFILE(Trans2_qpathinfo);
10038 case TRANSACT2_SETPATHINFO:
10039 case TRANSACT2_SETFILEINFO:
10041 START_PROFILE(Trans2_setpathinfo);
10042 call_trans2setfilepathinfo(conn, req, state->call,
10043 &state->param, state->total_param,
10044 &state->data, state->total_data,
10045 state->max_data_return);
10046 END_PROFILE(Trans2_setpathinfo);
10050 case TRANSACT2_FINDNOTIFYFIRST:
10052 START_PROFILE(Trans2_findnotifyfirst);
10053 call_trans2findnotifyfirst(conn, req,
10054 &state->param, state->total_param,
10055 &state->data, state->total_data,
10056 state->max_data_return);
10057 END_PROFILE(Trans2_findnotifyfirst);
10061 case TRANSACT2_FINDNOTIFYNEXT:
10063 START_PROFILE(Trans2_findnotifynext);
10064 call_trans2findnotifynext(conn, req,
10065 &state->param, state->total_param,
10066 &state->data, state->total_data,
10067 state->max_data_return);
10068 END_PROFILE(Trans2_findnotifynext);
10072 case TRANSACT2_MKDIR:
10074 START_PROFILE(Trans2_mkdir);
10075 call_trans2mkdir(conn, req,
10076 &state->param, state->total_param,
10077 &state->data, state->total_data,
10078 state->max_data_return);
10079 END_PROFILE(Trans2_mkdir);
10083 case TRANSACT2_GET_DFS_REFERRAL:
10085 START_PROFILE(Trans2_get_dfs_referral);
10086 call_trans2getdfsreferral(conn, req,
10087 &state->param, state->total_param,
10088 &state->data, state->total_data,
10089 state->max_data_return);
10090 END_PROFILE(Trans2_get_dfs_referral);
10094 case TRANSACT2_IOCTL:
10096 START_PROFILE(Trans2_ioctl);
10097 call_trans2ioctl(conn, req,
10098 &state->param, state->total_param,
10099 &state->data, state->total_data,
10100 state->max_data_return);
10101 END_PROFILE(Trans2_ioctl);
10106 /* Error in request */
10107 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
10108 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
10112 /****************************************************************************
10113 Reply to a SMBtrans2.
10114 ****************************************************************************/
10116 void reply_trans2(struct smb_request *req)
10118 connection_struct *conn = req->conn;
10119 unsigned int dsoff;
10120 unsigned int dscnt;
10121 unsigned int psoff;
10122 unsigned int pscnt;
10123 unsigned int tran_call;
10124 struct trans_state *state;
10127 START_PROFILE(SMBtrans2);
10129 if (req->wct < 14) {
10130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10131 END_PROFILE(SMBtrans2);
10135 dsoff = SVAL(req->vwv+12, 0);
10136 dscnt = SVAL(req->vwv+11, 0);
10137 psoff = SVAL(req->vwv+10, 0);
10138 pscnt = SVAL(req->vwv+9, 0);
10139 tran_call = SVAL(req->vwv+14, 0);
10141 result = allow_new_trans(conn->pending_trans, req->mid);
10142 if (!NT_STATUS_IS_OK(result)) {
10143 DEBUG(2, ("Got invalid trans2 request: %s\n",
10144 nt_errstr(result)));
10145 reply_nterror(req, result);
10146 END_PROFILE(SMBtrans2);
10150 if (IS_IPC(conn)) {
10151 switch (tran_call) {
10152 /* List the allowed trans2 calls on IPC$ */
10153 case TRANSACT2_OPEN:
10154 case TRANSACT2_GET_DFS_REFERRAL:
10155 case TRANSACT2_QFILEINFO:
10156 case TRANSACT2_QFSINFO:
10157 case TRANSACT2_SETFSINFO:
10160 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10161 END_PROFILE(SMBtrans2);
10166 if ((state = talloc(conn, struct trans_state)) == NULL) {
10167 DEBUG(0, ("talloc failed\n"));
10168 reply_nterror(req, NT_STATUS_NO_MEMORY);
10169 END_PROFILE(SMBtrans2);
10173 state->cmd = SMBtrans2;
10175 state->mid = req->mid;
10176 state->vuid = req->vuid;
10177 state->setup_count = SVAL(req->vwv+13, 0);
10178 state->setup = NULL;
10179 state->total_param = SVAL(req->vwv+0, 0);
10180 state->param = NULL;
10181 state->total_data = SVAL(req->vwv+1, 0);
10182 state->data = NULL;
10183 state->max_param_return = SVAL(req->vwv+2, 0);
10184 state->max_data_return = SVAL(req->vwv+3, 0);
10185 state->max_setup_return = SVAL(req->vwv+4, 0);
10186 state->close_on_completion = BITSETW(req->vwv+5, 0);
10187 state->one_way = BITSETW(req->vwv+5, 1);
10189 state->call = tran_call;
10191 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10192 is so as a sanity check */
10193 if (state->setup_count != 1) {
10195 * Need to have rc=0 for ioctl to get job id for OS/2.
10196 * Network printing will fail if function is not successful.
10197 * Similar function in reply.c will be used if protocol
10198 * is LANMAN1.0 instead of LM1.2X002.
10199 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10200 * outbuf doesn't have to be set(only job id is used).
10202 if ( (state->setup_count == 4)
10203 && (tran_call == TRANSACT2_IOCTL)
10204 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10205 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10206 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10208 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10209 DEBUG(2,("Transaction is %d\n",tran_call));
10210 TALLOC_FREE(state);
10211 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10212 END_PROFILE(SMBtrans2);
10217 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10220 if (state->total_data) {
10222 if (trans_oob(state->total_data, 0, dscnt)
10223 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10227 /* Can't use talloc here, the core routines do realloc on the
10228 * params and data. */
10229 state->data = (char *)SMB_MALLOC(state->total_data);
10230 if (state->data == NULL) {
10231 DEBUG(0,("reply_trans2: data malloc fail for %u "
10232 "bytes !\n", (unsigned int)state->total_data));
10233 TALLOC_FREE(state);
10234 reply_nterror(req, NT_STATUS_NO_MEMORY);
10235 END_PROFILE(SMBtrans2);
10239 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10242 if (state->total_param) {
10244 if (trans_oob(state->total_param, 0, pscnt)
10245 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10249 /* Can't use talloc here, the core routines do realloc on the
10250 * params and data. */
10251 state->param = (char *)SMB_MALLOC(state->total_param);
10252 if (state->param == NULL) {
10253 DEBUG(0,("reply_trans: param malloc fail for %u "
10254 "bytes !\n", (unsigned int)state->total_param));
10255 SAFE_FREE(state->data);
10256 TALLOC_FREE(state);
10257 reply_nterror(req, NT_STATUS_NO_MEMORY);
10258 END_PROFILE(SMBtrans2);
10262 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10265 state->received_data = dscnt;
10266 state->received_param = pscnt;
10268 if ((state->received_param == state->total_param) &&
10269 (state->received_data == state->total_data)) {
10271 handle_trans2(conn, req, state);
10273 SAFE_FREE(state->data);
10274 SAFE_FREE(state->param);
10275 TALLOC_FREE(state);
10276 END_PROFILE(SMBtrans2);
10280 DLIST_ADD(conn->pending_trans, state);
10282 /* We need to send an interim response then receive the rest
10283 of the parameter/data bytes */
10284 reply_outbuf(req, 0, 0);
10285 show_msg((char *)req->outbuf);
10286 END_PROFILE(SMBtrans2);
10291 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10292 SAFE_FREE(state->data);
10293 SAFE_FREE(state->param);
10294 TALLOC_FREE(state);
10295 END_PROFILE(SMBtrans2);
10296 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10300 /****************************************************************************
10301 Reply to a SMBtranss2
10302 ****************************************************************************/
10304 void reply_transs2(struct smb_request *req)
10306 connection_struct *conn = req->conn;
10307 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10308 struct trans_state *state;
10310 START_PROFILE(SMBtranss2);
10312 show_msg((const char *)req->inbuf);
10314 /* Windows clients expect all replies to
10315 a transact secondary (SMBtranss2 0x33)
10316 to have a command code of transact
10317 (SMBtrans2 0x32). See bug #8989
10318 and also [MS-CIFS] section 2.2.4.47.2
10321 req->cmd = SMBtrans2;
10323 if (req->wct < 8) {
10324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10325 END_PROFILE(SMBtranss2);
10329 for (state = conn->pending_trans; state != NULL;
10330 state = state->next) {
10331 if (state->mid == req->mid) {
10336 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10338 END_PROFILE(SMBtranss2);
10342 /* Revise state->total_param and state->total_data in case they have
10343 changed downwards */
10345 if (SVAL(req->vwv+0, 0) < state->total_param)
10346 state->total_param = SVAL(req->vwv+0, 0);
10347 if (SVAL(req->vwv+1, 0) < state->total_data)
10348 state->total_data = SVAL(req->vwv+1, 0);
10350 pcnt = SVAL(req->vwv+2, 0);
10351 poff = SVAL(req->vwv+3, 0);
10352 pdisp = SVAL(req->vwv+4, 0);
10354 dcnt = SVAL(req->vwv+5, 0);
10355 doff = SVAL(req->vwv+6, 0);
10356 ddisp = SVAL(req->vwv+7, 0);
10358 state->received_param += pcnt;
10359 state->received_data += dcnt;
10361 if ((state->received_data > state->total_data) ||
10362 (state->received_param > state->total_param))
10366 if (trans_oob(state->total_param, pdisp, pcnt)
10367 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10370 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10374 if (trans_oob(state->total_data, ddisp, dcnt)
10375 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10378 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10381 if ((state->received_param < state->total_param) ||
10382 (state->received_data < state->total_data)) {
10383 END_PROFILE(SMBtranss2);
10387 handle_trans2(conn, req, state);
10389 DLIST_REMOVE(conn->pending_trans, state);
10390 SAFE_FREE(state->data);
10391 SAFE_FREE(state->param);
10392 TALLOC_FREE(state);
10394 END_PROFILE(SMBtranss2);
10399 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10400 DLIST_REMOVE(conn->pending_trans, state);
10401 SAFE_FREE(state->data);
10402 SAFE_FREE(state->param);
10403 TALLOC_FREE(state);
10404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10405 END_PROFILE(SMBtranss2);