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"
47 #define DIR_ENTRY_SAFETY_MARGIN 4096
49 static char *store_file_unix_basic(connection_struct *conn,
52 const SMB_STRUCT_STAT *psbuf);
54 static char *store_file_unix_basic_info2(connection_struct *conn,
57 const SMB_STRUCT_STAT *psbuf);
59 /****************************************************************************
60 Check if an open file handle or smb_fname is a symlink.
61 ****************************************************************************/
63 static NTSTATUS refuse_symlink(connection_struct *conn,
64 const files_struct *fsp,
65 const struct smb_filename *smb_fname)
68 const SMB_STRUCT_STAT *pst = NULL;
71 pst = &fsp->fsp_name->st;
76 if (!VALID_STAT(*pst)) {
77 int ret = vfs_stat_smb_basename(conn,
80 if (ret == -1 && errno != ENOENT) {
81 return map_nt_error_from_unix(errno);
82 } else if (ret == -1) {
83 /* it's not a symlink.. */
89 if (S_ISLNK(pst->st_ex_mode)) {
90 return NT_STATUS_ACCESS_DENIED;
95 NTSTATUS check_access_fsp(const struct files_struct *fsp,
98 if (!(fsp->access_mask & access_mask)) {
99 return NT_STATUS_ACCESS_DENIED;
104 #if defined(HAVE_POSIX_ACLS)
105 /****************************************************************************
106 Utility function to open a fsp for a POSIX handle operation.
107 ****************************************************************************/
109 static NTSTATUS get_posix_fsp(connection_struct *conn,
110 struct smb_request *req,
111 const struct smb_filename *smb_fname,
112 uint32_t access_mask,
113 files_struct **ret_fsp)
116 struct smb_filename *smb_fname_tmp = NULL;
117 uint32_t create_disposition = FILE_OPEN;
118 uint32_t share_access = FILE_SHARE_READ|
122 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
123 * but set reasonable defaults.
125 uint32_t file_attributes = 0664|FILE_FLAG_POSIX_SEMANTICS;
126 uint32_t oplock = NO_OPLOCK;
127 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
129 /* File or directory must exist. */
130 if (!VALID_STAT(smb_fname->st)) {
131 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
133 /* Cannot be a symlink. */
134 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
135 return NT_STATUS_ACCESS_DENIED;
137 /* Set options correctly for directory open. */
138 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
140 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
141 * directories, but set reasonable defaults.
143 file_attributes = 0775|FILE_FLAG_POSIX_SEMANTICS;
144 create_options = FILE_DIRECTORY_FILE;
147 /* Createfile uses a non-const smb_fname. */
148 smb_fname_tmp = cp_smb_filename(talloc_tos(),
150 if (smb_fname_tmp == NULL) {
151 return NT_STATUS_NO_MEMORY;
154 status = SMB_VFS_CREATE_FILE(
157 0, /* root_dir_fid */
158 smb_fname_tmp, /* fname */
159 access_mask, /* access_mask */
160 share_access, /* share_access */
161 create_disposition,/* create_disposition*/
162 create_options, /* create_options */
163 file_attributes,/* file_attributes */
164 oplock, /* oplock_request */
166 0, /* allocation_size */
167 0, /* private_flags */
170 ret_fsp, /* result */
172 NULL, /* in_context */
173 NULL); /* out_context */
175 TALLOC_FREE(smb_fname_tmp);
180 /********************************************************************
181 The canonical "check access" based on object handle or path function.
182 ********************************************************************/
184 static NTSTATUS check_access(connection_struct *conn,
186 const struct smb_filename *smb_fname,
187 uint32_t access_mask)
192 status = check_access_fsp(fsp, access_mask);
194 status = smbd_check_access_rights(conn, smb_fname,
201 /********************************************************************
202 Roundup a value to the nearest allocation roundup size boundary.
203 Only do this for Windows clients.
204 ********************************************************************/
206 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
208 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
210 /* Only roundup for Windows clients. */
211 enum remote_arch_types ra_type = get_remote_arch();
212 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
213 val = SMB_ROUNDUP(val,rval);
218 /****************************************************************************
219 Utility functions for dealing with extended attributes.
220 ****************************************************************************/
222 /****************************************************************************
223 Refuse to allow clients to overwrite our private xattrs.
224 ****************************************************************************/
226 bool samba_private_attr_name(const char *unix_ea_name)
228 static const char * const prohibited_ea_names[] = {
229 SAMBA_POSIX_INHERITANCE_EA_NAME,
230 SAMBA_XATTR_DOS_ATTRIB,
238 for (i = 0; prohibited_ea_names[i]; i++) {
239 if (strequal( prohibited_ea_names[i], unix_ea_name))
242 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
243 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
249 /****************************************************************************
250 Get one EA value. Fill in a struct ea_struct.
251 ****************************************************************************/
253 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
254 connection_struct *conn,
256 const struct smb_filename *smb_fname,
258 struct ea_struct *pea)
260 /* Get the value of this xattr. Max size is 64k. */
261 size_t attr_size = 256;
267 val = talloc_realloc(mem_ctx, val, char, attr_size);
269 return NT_STATUS_NO_MEMORY;
272 if (fsp && fsp->fh->fd != -1) {
273 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
275 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
276 ea_name, val, attr_size);
279 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
285 return map_nt_error_from_unix(errno);
288 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
289 dump_data(10, (uint8_t *)val, sizeret);
292 if (strnequal(ea_name, "user.", 5)) {
293 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
295 pea->name = talloc_strdup(mem_ctx, ea_name);
297 if (pea->name == NULL) {
299 return NT_STATUS_NO_MEMORY;
301 pea->value.data = (unsigned char *)val;
302 pea->value.length = (size_t)sizeret;
306 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
307 connection_struct *conn,
309 const struct smb_filename *smb_fname,
314 /* Get a list of all xattrs. Max namesize is 64k. */
315 size_t ea_namelist_size = 1024;
316 char *ea_namelist = smallbuf;
317 char *to_free = NULL;
322 ssize_t sizeret = -1;
330 status = refuse_symlink(conn, fsp, smb_fname);
331 if (!NT_STATUS_IS_OK(status)) {
333 * Just return no EA's on a symlink.
338 if (fsp && fsp->fh->fd != -1) {
339 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
342 sizeret = SMB_VFS_LISTXATTR(conn,
348 if ((sizeret == -1) && (errno == ERANGE)) {
349 ea_namelist_size = 65536;
350 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
351 if (ea_namelist == NULL) {
352 return NT_STATUS_NO_MEMORY;
354 to_free = ea_namelist;
356 if (fsp && fsp->fh->fd != -1) {
357 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
360 sizeret = SMB_VFS_LISTXATTR(conn,
368 status = map_nt_error_from_unix(errno);
369 TALLOC_FREE(to_free);
373 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
376 TALLOC_FREE(to_free);
381 * Ensure the result is 0-terminated
384 if (ea_namelist[sizeret-1] != '\0') {
385 TALLOC_FREE(to_free);
386 return NT_STATUS_INTERNAL_ERROR;
394 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
398 *pnum_names = num_names;
400 if (pnames == NULL) {
401 TALLOC_FREE(to_free);
405 names = talloc_array(mem_ctx, char *, num_names);
407 DEBUG(0, ("talloc failed\n"));
408 TALLOC_FREE(to_free);
409 return NT_STATUS_NO_MEMORY;
412 if (ea_namelist == smallbuf) {
413 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
414 if (ea_namelist == NULL) {
416 return NT_STATUS_NO_MEMORY;
419 talloc_steal(names, ea_namelist);
421 ea_namelist = talloc_realloc(names, ea_namelist, char,
423 if (ea_namelist == NULL) {
425 return NT_STATUS_NO_MEMORY;
431 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
432 names[num_names++] = p;
440 /****************************************************************************
441 Return a linked list of the total EA's. Plus the total size
442 ****************************************************************************/
444 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
445 connection_struct *conn,
447 const struct smb_filename *smb_fname,
448 size_t *pea_total_len,
449 struct ea_list **ea_list)
451 /* Get a list of all xattrs. Max namesize is 64k. */
454 struct ea_list *ea_list_head = NULL;
455 bool posix_pathnames = false;
461 if (!lp_ea_support(SNUM(conn))) {
467 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
469 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
472 status = get_ea_names_from_file(talloc_tos(),
479 if (!NT_STATUS_IS_OK(status)) {
483 if (num_names == 0) {
487 for (i=0; i<num_names; i++) {
488 struct ea_list *listp;
491 if (strnequal(names[i], "system.", 7)
492 || samba_private_attr_name(names[i]))
496 * Filter out any underlying POSIX EA names
497 * that a Windows client can't handle.
499 if (!posix_pathnames &&
500 is_invalid_windows_ea_name(names[i])) {
504 listp = talloc(mem_ctx, struct ea_list);
506 return NT_STATUS_NO_MEMORY;
509 status = get_ea_value(listp,
516 if (!NT_STATUS_IS_OK(status)) {
521 if (listp->ea.value.length == 0) {
523 * We can never return a zero length EA.
524 * Windows reports the EA's as corrupted.
530 push_ascii_fstring(dos_ea_name, listp->ea.name);
533 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
535 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
536 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
537 (unsigned int)listp->ea.value.length));
539 DLIST_ADD_END(ea_list_head, listp);
543 /* Add on 4 for total length. */
544 if (*pea_total_len) {
548 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
549 (unsigned int)*pea_total_len));
551 *ea_list = ea_list_head;
555 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
556 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
561 if (!lp_ea_support(SNUM(conn))) {
565 if (is_ntfs_stream_smb_fname(smb_fname)) {
566 return NT_STATUS_INVALID_PARAMETER;
569 return get_ea_list_from_file_path(mem_ctx,
577 /****************************************************************************
578 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
580 ****************************************************************************/
582 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
583 connection_struct *conn, struct ea_list *ea_list)
585 unsigned int ret_data_size = 4;
588 SMB_ASSERT(total_data_size >= 4);
590 if (!lp_ea_support(SNUM(conn))) {
595 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
598 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
599 dos_namelen = strlen(dos_ea_name);
600 if (dos_namelen > 255 || dos_namelen == 0) {
603 if (ea_list->ea.value.length > 65535) {
606 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
610 /* We know we have room. */
611 SCVAL(p,0,ea_list->ea.flags);
612 SCVAL(p,1,dos_namelen);
613 SSVAL(p,2,ea_list->ea.value.length);
614 strlcpy(p+4, dos_ea_name, dos_namelen+1);
615 if (ea_list->ea.value.length > 0) {
616 memcpy(p + 4 + dos_namelen + 1,
617 ea_list->ea.value.data,
618 ea_list->ea.value.length);
621 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
622 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
625 ret_data_size = PTR_DIFF(p, pdata);
626 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
627 SIVAL(pdata,0,ret_data_size);
628 return ret_data_size;
631 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
633 unsigned int total_data_size,
634 unsigned int *ret_data_size,
635 connection_struct *conn,
636 struct ea_list *ea_list)
638 uint8_t *p = (uint8_t *)pdata;
639 uint8_t *last_start = NULL;
640 bool do_store_data = (pdata != NULL);
644 if (!lp_ea_support(SNUM(conn))) {
645 return NT_STATUS_NO_EAS_ON_FILE;
648 for (; ea_list; ea_list = ea_list->next) {
654 if (last_start != NULL && do_store_data) {
655 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
659 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
660 dos_namelen = strlen(dos_ea_name);
661 if (dos_namelen > 255 || dos_namelen == 0) {
662 return NT_STATUS_INTERNAL_ERROR;
664 if (ea_list->ea.value.length > 65535) {
665 return NT_STATUS_INTERNAL_ERROR;
668 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
671 pad = (4 - (this_size % 4)) % 4;
676 if (this_size > total_data_size) {
677 return NT_STATUS_INFO_LENGTH_MISMATCH;
680 /* We know we have room. */
681 SIVAL(p, 0x00, 0); /* next offset */
682 SCVAL(p, 0x04, ea_list->ea.flags);
683 SCVAL(p, 0x05, dos_namelen);
684 SSVAL(p, 0x06, ea_list->ea.value.length);
685 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
686 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
688 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
692 total_data_size -= this_size;
698 *ret_data_size = PTR_DIFF(p, pdata);
699 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
703 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
705 size_t total_ea_len = 0;
707 struct ea_list *ea_list = NULL;
709 if (!lp_ea_support(SNUM(conn))) {
712 mem_ctx = talloc_stackframe();
714 /* If this is a stream fsp, then we need to instead find the
715 * estimated ea len from the main file, not the stream
716 * (streams cannot have EAs), but the estimate isn't just 0 in
718 if (is_ntfs_stream_smb_fname(smb_fname)) {
721 (void)get_ea_list_from_file_path(mem_ctx,
727 if(conn->sconn->using_smb2) {
729 unsigned int ret_data_size;
731 * We're going to be using fill_ea_chained_buffer() to
732 * marshall EA's - this size is significantly larger
733 * than the SMB1 buffer. Re-calculate the size without
736 status = fill_ea_chained_buffer(mem_ctx,
742 if (!NT_STATUS_IS_OK(status)) {
745 total_ea_len = ret_data_size;
747 TALLOC_FREE(mem_ctx);
751 /****************************************************************************
752 Ensure the EA name is case insensitive by matching any existing EA name.
753 ****************************************************************************/
755 static void canonicalize_ea_name(connection_struct *conn,
757 const struct smb_filename *smb_fname,
758 fstring unix_ea_name)
761 TALLOC_CTX *mem_ctx = talloc_tos();
762 struct ea_list *ea_list;
763 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
769 if (!NT_STATUS_IS_OK(status)) {
773 for (; ea_list; ea_list = ea_list->next) {
774 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
775 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
776 &unix_ea_name[5], ea_list->ea.name));
777 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
783 /****************************************************************************
784 Set or delete an extended attribute.
785 ****************************************************************************/
787 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
788 const struct smb_filename *smb_fname, struct ea_list *ea_list)
791 bool posix_pathnames = false;
793 if (!lp_ea_support(SNUM(conn))) {
794 return NT_STATUS_EAS_NOT_SUPPORTED;
799 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
801 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
804 status = refuse_symlink(conn, fsp, smb_fname);
805 if (!NT_STATUS_IS_OK(status)) {
809 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
810 if (!NT_STATUS_IS_OK(status)) {
814 /* Setting EAs on streams isn't supported. */
815 if (is_ntfs_stream_smb_fname(smb_fname)) {
816 return NT_STATUS_INVALID_PARAMETER;
820 * Filter out invalid Windows EA names - before
821 * we set *any* of them.
824 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
825 return STATUS_INVALID_EA_NAME;
828 for (;ea_list; ea_list = ea_list->next) {
830 fstring unix_ea_name;
832 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
833 fstrcat(unix_ea_name, ea_list->ea.name);
835 canonicalize_ea_name(conn,
840 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
842 if (samba_private_attr_name(unix_ea_name)) {
843 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
844 return NT_STATUS_ACCESS_DENIED;
847 if (ea_list->ea.value.length == 0) {
848 /* Remove the attribute. */
849 if (fsp && (fsp->fh->fd != -1)) {
850 DEBUG(10,("set_ea: deleting ea name %s on "
851 "file %s by file descriptor.\n",
852 unix_ea_name, fsp_str_dbg(fsp)));
853 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
855 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
856 unix_ea_name, smb_fname->base_name));
857 ret = SMB_VFS_REMOVEXATTR(conn,
862 /* Removing a non existent attribute always succeeds. */
863 if (ret == -1 && errno == ENOATTR) {
864 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
870 if (fsp && (fsp->fh->fd != -1)) {
871 DEBUG(10,("set_ea: setting ea name %s on file "
872 "%s by file descriptor.\n",
873 unix_ea_name, fsp_str_dbg(fsp)));
874 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
875 ea_list->ea.value.data, ea_list->ea.value.length, 0);
877 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
878 unix_ea_name, smb_fname->base_name));
879 ret = SMB_VFS_SETXATTR(conn,
882 ea_list->ea.value.data,
883 ea_list->ea.value.length,
890 if (errno == ENOTSUP) {
891 return NT_STATUS_EAS_NOT_SUPPORTED;
894 return map_nt_error_from_unix(errno);
900 /****************************************************************************
901 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
902 ****************************************************************************/
904 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
906 struct ea_list *ea_list_head = NULL;
907 size_t converted_size, offset = 0;
909 while (offset + 2 < data_size) {
910 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
911 unsigned int namelen = CVAL(pdata,offset);
913 offset++; /* Go past the namelen byte. */
915 /* integer wrap paranioa. */
916 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
917 (offset > data_size) || (namelen > data_size) ||
918 (offset + namelen >= data_size)) {
921 /* Ensure the name is null terminated. */
922 if (pdata[offset + namelen] != '\0') {
925 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
927 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
928 "failed: %s", strerror(errno)));
934 offset += (namelen + 1); /* Go past the name + terminating zero. */
935 DLIST_ADD_END(ea_list_head, eal);
936 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
942 /****************************************************************************
943 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
944 ****************************************************************************/
946 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
948 struct ea_list *ea_list_head = NULL;
950 size_t bytes_used = 0;
952 while (offset < data_size) {
953 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
959 DLIST_ADD_END(ea_list_head, eal);
960 offset += bytes_used;
966 /****************************************************************************
967 Count the total EA size needed.
968 ****************************************************************************/
970 static size_t ea_list_size(struct ea_list *ealist)
973 struct ea_list *listp;
976 for (listp = ealist; listp; listp = listp->next) {
977 push_ascii_fstring(dos_ea_name, listp->ea.name);
978 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
980 /* Add on 4 for total length. */
988 /****************************************************************************
989 Return a union of EA's from a file list and a list of names.
990 The TALLOC context for the two lists *MUST* be identical as we steal
991 memory from one list to add to another. JRA.
992 ****************************************************************************/
994 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
996 struct ea_list *nlistp, *flistp;
998 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
999 for (flistp = file_list; flistp; flistp = flistp->next) {
1000 if (strequal(nlistp->ea.name, flistp->ea.name)) {
1006 /* Copy the data from this entry. */
1007 nlistp->ea.flags = flistp->ea.flags;
1008 nlistp->ea.value = flistp->ea.value;
1011 nlistp->ea.flags = 0;
1012 ZERO_STRUCT(nlistp->ea.value);
1016 *total_ea_len = ea_list_size(name_list);
1020 /****************************************************************************
1021 Send the required number of replies back.
1022 We assume all fields other than the data fields are
1023 set correctly for the type of call.
1024 HACK ! Always assumes smb_setup field is zero.
1025 ****************************************************************************/
1027 void send_trans2_replies(connection_struct *conn,
1028 struct smb_request *req,
1036 /* As we are using a protocol > LANMAN1 then the max_send
1037 variable must have been set in the sessetupX call.
1038 This takes precedence over the max_xmit field in the
1039 global struct. These different max_xmit variables should
1040 be merged as this is now too confusing */
1042 int data_to_send = datasize;
1043 int params_to_send = paramsize;
1045 const char *pp = params;
1046 const char *pd = pdata;
1047 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1048 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1049 int data_alignment_offset = 0;
1050 bool overflow = False;
1051 struct smbXsrv_connection *xconn = req->xconn;
1052 int max_send = xconn->smb1.sessions.max_send;
1054 /* Modify the data_to_send and datasize and set the error if
1055 we're trying to send more than max_data_bytes. We still send
1056 the part of the packet(s) that fit. Strange, but needed
1059 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1060 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1061 max_data_bytes, datasize ));
1062 datasize = data_to_send = max_data_bytes;
1066 /* If there genuinely are no parameters or data to send just send the empty packet */
1068 if(params_to_send == 0 && data_to_send == 0) {
1069 reply_outbuf(req, 10, 0);
1070 if (NT_STATUS_V(status)) {
1073 ntstatus_to_dos(status, &eclass, &ecode);
1074 error_packet_set((char *)req->outbuf,
1075 eclass, ecode, status,
1078 show_msg((char *)req->outbuf);
1079 if (!srv_send_smb(xconn,
1080 (char *)req->outbuf,
1081 true, req->seqnum+1,
1082 IS_CONN_ENCRYPTED(conn),
1084 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1086 TALLOC_FREE(req->outbuf);
1090 /* When sending params and data ensure that both are nicely aligned */
1091 /* Only do this alignment when there is also data to send - else
1092 can cause NT redirector problems. */
1094 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1095 data_alignment_offset = 4 - (params_to_send % 4);
1097 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1098 /* The alignment_offset is to align the param bytes on an even byte
1099 boundary. NT 4.0 Beta needs this to work correctly. */
1101 useable_space = max_send - (smb_size
1104 + data_alignment_offset);
1106 if (useable_space < 0) {
1107 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1108 "= %d!!!", useable_space));
1109 exit_server_cleanly("send_trans2_replies: Not enough space");
1112 while (params_to_send || data_to_send) {
1113 /* Calculate whether we will totally or partially fill this packet */
1115 total_sent_thistime = params_to_send + data_to_send;
1117 /* We can never send more than useable_space */
1119 * Note that 'useable_space' does not include the alignment offsets,
1120 * but we must include the alignment offsets in the calculation of
1121 * the length of the data we send over the wire, as the alignment offsets
1122 * are sent here. Fix from Marc_Jacobsen@hp.com.
1125 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1127 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1128 + data_alignment_offset);
1130 /* Set total params and data to be sent */
1131 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1132 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1134 /* Calculate how many parameters and data we can fit into
1135 * this packet. Parameters get precedence
1138 params_sent_thistime = MIN(params_to_send,useable_space);
1139 data_sent_thistime = useable_space - params_sent_thistime;
1140 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1142 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1144 /* smb_proff is the offset from the start of the SMB header to the
1145 parameter bytes, however the first 4 bytes of outbuf are
1146 the Netbios over TCP header. Thus use smb_base() to subtract
1147 them from the calculation */
1149 SSVAL(req->outbuf,smb_proff,
1150 ((smb_buf(req->outbuf)+alignment_offset)
1151 - smb_base(req->outbuf)));
1153 if(params_sent_thistime == 0)
1154 SSVAL(req->outbuf,smb_prdisp,0);
1156 /* Absolute displacement of param bytes sent in this packet */
1157 SSVAL(req->outbuf,smb_prdisp,pp - params);
1159 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1160 if(data_sent_thistime == 0) {
1161 SSVAL(req->outbuf,smb_droff,0);
1162 SSVAL(req->outbuf,smb_drdisp, 0);
1164 /* The offset of the data bytes is the offset of the
1165 parameter bytes plus the number of parameters being sent this time */
1166 SSVAL(req->outbuf, smb_droff,
1167 ((smb_buf(req->outbuf)+alignment_offset)
1168 - smb_base(req->outbuf))
1169 + params_sent_thistime + data_alignment_offset);
1170 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1173 /* Initialize the padding for alignment */
1175 if (alignment_offset != 0) {
1176 memset(smb_buf(req->outbuf), 0, alignment_offset);
1179 /* Copy the param bytes into the packet */
1181 if(params_sent_thistime) {
1182 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1183 params_sent_thistime);
1186 /* Copy in the data bytes */
1187 if(data_sent_thistime) {
1188 if (data_alignment_offset != 0) {
1189 memset((smb_buf(req->outbuf)+alignment_offset+
1190 params_sent_thistime), 0,
1191 data_alignment_offset);
1193 memcpy(smb_buf(req->outbuf)+alignment_offset
1194 +params_sent_thistime+data_alignment_offset,
1195 pd,data_sent_thistime);
1198 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1199 params_sent_thistime, data_sent_thistime, useable_space));
1200 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1201 params_to_send, data_to_send, paramsize, datasize));
1204 error_packet_set((char *)req->outbuf,
1205 ERRDOS,ERRbufferoverflow,
1206 STATUS_BUFFER_OVERFLOW,
1208 } else if (NT_STATUS_V(status)) {
1211 ntstatus_to_dos(status, &eclass, &ecode);
1212 error_packet_set((char *)req->outbuf,
1213 eclass, ecode, status,
1217 /* Send the packet */
1218 show_msg((char *)req->outbuf);
1219 if (!srv_send_smb(xconn,
1220 (char *)req->outbuf,
1221 true, req->seqnum+1,
1222 IS_CONN_ENCRYPTED(conn),
1224 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1226 TALLOC_FREE(req->outbuf);
1228 pp += params_sent_thistime;
1229 pd += data_sent_thistime;
1231 params_to_send -= params_sent_thistime;
1232 data_to_send -= data_sent_thistime;
1235 if(params_to_send < 0 || data_to_send < 0) {
1236 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1237 params_to_send, data_to_send));
1245 /****************************************************************************
1246 Reply to a TRANSACT2_OPEN.
1247 ****************************************************************************/
1249 static void call_trans2open(connection_struct *conn,
1250 struct smb_request *req,
1251 char **pparams, int total_params,
1252 char **ppdata, int total_data,
1253 unsigned int max_data_bytes)
1255 struct smb_filename *smb_fname = NULL;
1256 char *params = *pparams;
1257 char *pdata = *ppdata;
1260 bool oplock_request;
1262 bool return_additional_info;
1271 int fattr=0,mtime=0;
1272 SMB_INO_T inode = 0;
1275 struct ea_list *ea_list = NULL;
1278 uint32_t access_mask;
1279 uint32_t share_mode;
1280 uint32_t create_disposition;
1281 uint32_t create_options = 0;
1282 uint32_t private_flags = 0;
1283 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1284 TALLOC_CTX *ctx = talloc_tos();
1287 * Ensure we have enough parameters to perform the operation.
1290 if (total_params < 29) {
1291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1295 flags = SVAL(params, 0);
1296 deny_mode = SVAL(params, 2);
1297 open_attr = SVAL(params,6);
1298 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1299 if (oplock_request) {
1300 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1304 return_additional_info = BITSETW(params,0);
1305 open_sattr = SVAL(params, 4);
1306 open_time = make_unix_date3(params+8);
1308 open_ofun = SVAL(params,12);
1309 open_size = IVAL(params,14);
1310 pname = ¶ms[28];
1313 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1317 if (req->posix_pathnames) {
1318 srvstr_get_path_posix(ctx,
1327 srvstr_get_path(ctx,
1336 if (!NT_STATUS_IS_OK(status)) {
1337 reply_nterror(req, status);
1341 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1342 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1343 (unsigned int)open_ofun, open_size));
1345 status = filename_convert(ctx,
1352 if (!NT_STATUS_IS_OK(status)) {
1353 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1354 reply_botherror(req,
1355 NT_STATUS_PATH_NOT_COVERED,
1356 ERRSRV, ERRbadpath);
1359 reply_nterror(req, status);
1363 if (open_ofun == 0) {
1364 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1368 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1370 &access_mask, &share_mode,
1371 &create_disposition,
1374 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1378 /* Any data in this call is an EA list. */
1379 if (total_data && (total_data != 4)) {
1380 if (total_data < 10) {
1381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1385 if (IVAL(pdata,0) > total_data) {
1386 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1387 IVAL(pdata,0), (unsigned int)total_data));
1388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1392 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1399 if (!lp_ea_support(SNUM(conn))) {
1400 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1404 if (!req->posix_pathnames &&
1405 ea_list_has_invalid_name(ea_list)) {
1407 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1408 if(*pparams == NULL ) {
1409 reply_nterror(req, NT_STATUS_NO_MEMORY);
1413 memset(params, '\0', param_len);
1414 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1415 params, param_len, NULL, 0, max_data_bytes);
1420 status = SMB_VFS_CREATE_FILE(
1423 0, /* root_dir_fid */
1424 smb_fname, /* fname */
1425 access_mask, /* access_mask */
1426 share_mode, /* share_access */
1427 create_disposition, /* create_disposition*/
1428 create_options, /* create_options */
1429 open_attr, /* file_attributes */
1430 oplock_request, /* oplock_request */
1432 open_size, /* allocation_size */
1435 ea_list, /* ea_list */
1437 &smb_action, /* psbuf */
1438 NULL, NULL); /* create context */
1440 if (!NT_STATUS_IS_OK(status)) {
1441 if (open_was_deferred(req->xconn, req->mid)) {
1442 /* We have re-scheduled this call. */
1446 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1447 reply_openerror(req, status);
1451 fsp = fcb_or_dos_open(
1458 bool ok = defer_smb1_sharing_violation(req);
1462 reply_openerror(req, status);
1466 smb_action = FILE_WAS_OPENED;
1469 size = get_file_size_stat(&smb_fname->st);
1470 fattr = dos_mode(conn, smb_fname);
1471 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1472 inode = smb_fname->st.st_ex_ino;
1473 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1474 close_file(req, fsp, ERROR_CLOSE);
1475 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1479 /* Realloc the size of parameters and data we will return */
1480 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1481 if(*pparams == NULL ) {
1482 reply_nterror(req, NT_STATUS_NO_MEMORY);
1487 SSVAL(params,0,fsp->fnum);
1488 SSVAL(params,2,fattr);
1489 srv_put_dos_date2(params,4, mtime);
1490 SIVAL(params,8, (uint32_t)size);
1491 SSVAL(params,12,deny_mode);
1492 SSVAL(params,14,0); /* open_type - file or directory. */
1493 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1495 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1496 smb_action |= EXTENDED_OPLOCK_GRANTED;
1499 SSVAL(params,18,smb_action);
1502 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1504 SIVAL(params,20,inode);
1505 SSVAL(params,24,0); /* Padding. */
1507 uint32_t ea_size = estimate_ea_size(conn, fsp,
1509 SIVAL(params, 26, ea_size);
1511 SIVAL(params, 26, 0);
1514 /* Send the required number of replies */
1515 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1517 TALLOC_FREE(smb_fname);
1520 /*********************************************************
1521 Routine to check if a given string matches exactly.
1522 as a special case a mask of "." does NOT match. That
1523 is required for correct wildcard semantics
1524 Case can be significant or not.
1525 **********************************************************/
1527 static bool exact_match(bool has_wild,
1528 bool case_sensitive,
1532 if (mask[0] == '.' && mask[1] == 0) {
1540 if (case_sensitive) {
1541 return strcmp(str,mask)==0;
1543 return strcasecmp_m(str,mask) == 0;
1547 /****************************************************************************
1548 Return the filetype for UNIX extensions.
1549 ****************************************************************************/
1551 static uint32_t unix_filetype(mode_t mode)
1554 return UNIX_TYPE_FILE;
1555 else if(S_ISDIR(mode))
1556 return UNIX_TYPE_DIR;
1558 else if(S_ISLNK(mode))
1559 return UNIX_TYPE_SYMLINK;
1562 else if(S_ISCHR(mode))
1563 return UNIX_TYPE_CHARDEV;
1566 else if(S_ISBLK(mode))
1567 return UNIX_TYPE_BLKDEV;
1570 else if(S_ISFIFO(mode))
1571 return UNIX_TYPE_FIFO;
1574 else if(S_ISSOCK(mode))
1575 return UNIX_TYPE_SOCKET;
1578 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1579 return UNIX_TYPE_UNKNOWN;
1582 /****************************************************************************
1583 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1584 ****************************************************************************/
1586 NTSTATUS unix_perms_from_wire(connection_struct *conn,
1587 const SMB_STRUCT_STAT *psbuf,
1589 enum perm_type ptype,
1594 if (perms == SMB_MODE_NO_CHANGE) {
1595 if (!VALID_STAT(*psbuf)) {
1596 return NT_STATUS_INVALID_PARAMETER;
1598 *ret_perms = psbuf->st_ex_mode;
1599 return NT_STATUS_OK;
1603 ret = wire_perms_to_unix(perms);
1605 if (ptype == PERM_NEW_FILE) {
1607 * "create mask"/"force create mode" are
1608 * only applied to new files, not existing ones.
1610 ret &= lp_create_mask(SNUM(conn));
1611 /* Add in force bits */
1612 ret |= lp_force_create_mode(SNUM(conn));
1613 } else if (ptype == PERM_NEW_DIR) {
1615 * "directory mask"/"force directory mode" are
1616 * only applied to new directories, not existing ones.
1618 ret &= lp_directory_mask(SNUM(conn));
1619 /* Add in force bits */
1620 ret |= lp_force_directory_mode(SNUM(conn));
1624 return NT_STATUS_OK;
1627 /****************************************************************************
1628 Needed to show the msdfs symlinks as directories. Modifies psbuf
1629 to be a directory if it's a msdfs link.
1630 ****************************************************************************/
1632 static bool check_msdfs_link(connection_struct *conn,
1633 struct smb_filename *smb_fname)
1635 int saved_errno = errno;
1636 if(lp_host_msdfs() &&
1637 lp_msdfs_root(SNUM(conn)) &&
1638 is_msdfs_link(conn, smb_fname)) {
1640 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1642 smb_fname->base_name));
1643 smb_fname->st.st_ex_mode =
1644 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1645 errno = saved_errno;
1648 errno = saved_errno;
1653 /****************************************************************************
1654 Get a level dependent lanman2 dir entry.
1655 ****************************************************************************/
1657 struct smbd_dirptr_lanman2_state {
1658 connection_struct *conn;
1659 uint32_t info_level;
1660 bool check_mangled_names;
1662 bool got_exact_match;
1665 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1671 struct smbd_dirptr_lanman2_state *state =
1672 (struct smbd_dirptr_lanman2_state *)private_data;
1674 char mangled_name[13]; /* mangled 8.3 name. */
1678 /* Mangle fname if it's an illegal name. */
1679 if (mangle_must_mangle(dname, state->conn->params)) {
1681 * Slow path - ensure we can push the original name as UCS2. If
1682 * not, then just don't return this name.
1686 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1687 uint8_t *tmp = talloc_array(talloc_tos(),
1691 status = srvstr_push(NULL,
1692 FLAGS2_UNICODE_STRINGS,
1701 if (!NT_STATUS_IS_OK(status)) {
1705 ok = name_to_8_3(dname, mangled_name,
1706 true, state->conn->params);
1710 fname = mangled_name;
1715 got_match = exact_match(state->has_wild,
1716 state->conn->case_sensitive,
1718 state->got_exact_match = got_match;
1720 got_match = mask_match(fname, mask,
1721 state->conn->case_sensitive);
1724 if(!got_match && state->check_mangled_names &&
1725 !mangle_is_8_3(fname, false, state->conn->params)) {
1727 * It turns out that NT matches wildcards against
1728 * both long *and* short names. This may explain some
1729 * of the wildcard wierdness from old DOS clients
1730 * that some people have been seeing.... JRA.
1732 /* Force the mangling into 8.3. */
1733 ok = name_to_8_3(fname, mangled_name,
1734 false, state->conn->params);
1739 got_match = exact_match(state->has_wild,
1740 state->conn->case_sensitive,
1741 mangled_name, mask);
1742 state->got_exact_match = got_match;
1744 got_match = mask_match(mangled_name, mask,
1745 state->conn->case_sensitive);
1753 *_fname = talloc_strdup(ctx, fname);
1754 if (*_fname == NULL) {
1761 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1763 struct smb_filename *smb_fname,
1767 struct smbd_dirptr_lanman2_state *state =
1768 (struct smbd_dirptr_lanman2_state *)private_data;
1769 bool ms_dfs_link = false;
1772 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1773 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1774 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1775 "Couldn't lstat [%s] (%s)\n",
1776 smb_fname_str_dbg(smb_fname),
1780 } else if (!VALID_STAT(smb_fname->st) &&
1781 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1782 /* Needed to show the msdfs symlinks as
1785 ms_dfs_link = check_msdfs_link(state->conn,
1788 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1789 "Couldn't stat [%s] (%s)\n",
1790 smb_fname_str_dbg(smb_fname),
1797 mode = dos_mode_msdfs(state->conn, smb_fname);
1798 } else if (get_dosmode) {
1799 mode = dos_mode(state->conn, smb_fname);
1806 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1807 connection_struct *conn,
1809 uint32_t info_level,
1810 struct ea_list *name_list,
1811 bool check_mangled_names,
1812 bool requires_resume_key,
1815 const struct smb_filename *smb_fname,
1816 int space_remaining,
1822 uint64_t *last_entry_off)
1824 char *p, *q, *pdata = *ppdata;
1826 uint64_t file_size = 0;
1827 uint64_t allocation_size = 0;
1828 uint64_t file_id = 0;
1830 struct timespec mdate_ts = {0};
1831 struct timespec adate_ts = {0};
1832 struct timespec cdate_ts = {0};
1833 struct timespec create_date_ts = {0};
1834 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1836 char *last_entry_ptr;
1841 struct readdir_attr_data *readdir_attr_data = NULL;
1843 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1844 file_size = get_file_size_stat(&smb_fname->st);
1846 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1848 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1849 if (!NT_STATUS_IS_OK(status)) {
1850 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1855 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1857 mdate_ts = smb_fname->st.st_ex_mtime;
1858 adate_ts = smb_fname->st.st_ex_atime;
1859 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1860 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1862 if (lp_dos_filetime_resolution(SNUM(conn))) {
1863 dos_filetime_timespec(&create_date_ts);
1864 dos_filetime_timespec(&mdate_ts);
1865 dos_filetime_timespec(&adate_ts);
1866 dos_filetime_timespec(&cdate_ts);
1869 create_date = convert_timespec_to_time_t(create_date_ts);
1870 mdate = convert_timespec_to_time_t(mdate_ts);
1871 adate = convert_timespec_to_time_t(adate_ts);
1873 /* align the record */
1874 SMB_ASSERT(align >= 1);
1876 off = (int)PTR_DIFF(pdata, base_data);
1877 pad = (off + (align-1)) & ~(align-1);
1880 if (pad && pad > space_remaining) {
1881 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1882 "for padding (wanted %u, had %d)\n",
1885 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1889 /* initialize padding to 0 */
1891 memset(pdata, 0, pad);
1893 space_remaining -= pad;
1895 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1905 switch (info_level) {
1906 case SMB_FIND_INFO_STANDARD:
1907 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1908 if(requires_resume_key) {
1912 srv_put_dos_date2(p,0,create_date);
1913 srv_put_dos_date2(p,4,adate);
1914 srv_put_dos_date2(p,8,mdate);
1915 SIVAL(p,12,(uint32_t)file_size);
1916 SIVAL(p,16,(uint32_t)allocation_size);
1920 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1921 p += ucs2_align(base_data, p, 0);
1923 status = srvstr_push(base_data, flags2, p,
1924 fname, PTR_DIFF(end_data, p),
1925 STR_TERMINATE, &len);
1926 if (!NT_STATUS_IS_OK(status)) {
1929 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1931 SCVAL(nameptr, -1, len - 2);
1933 SCVAL(nameptr, -1, 0);
1937 SCVAL(nameptr, -1, len - 1);
1939 SCVAL(nameptr, -1, 0);
1945 case SMB_FIND_EA_SIZE:
1946 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1947 if (requires_resume_key) {
1951 srv_put_dos_date2(p,0,create_date);
1952 srv_put_dos_date2(p,4,adate);
1953 srv_put_dos_date2(p,8,mdate);
1954 SIVAL(p,12,(uint32_t)file_size);
1955 SIVAL(p,16,(uint32_t)allocation_size);
1958 unsigned int ea_size = estimate_ea_size(conn, NULL,
1960 SIVAL(p,22,ea_size); /* Extended attributes */
1964 status = srvstr_push(base_data, flags2,
1965 p, fname, PTR_DIFF(end_data, p),
1966 STR_TERMINATE | STR_NOALIGN, &len);
1967 if (!NT_STATUS_IS_OK(status)) {
1970 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1983 SCVAL(nameptr,0,len);
1985 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1988 case SMB_FIND_EA_LIST:
1990 struct ea_list *file_list = NULL;
1993 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1995 return NT_STATUS_INVALID_PARAMETER;
1997 if (requires_resume_key) {
2001 srv_put_dos_date2(p,0,create_date);
2002 srv_put_dos_date2(p,4,adate);
2003 srv_put_dos_date2(p,8,mdate);
2004 SIVAL(p,12,(uint32_t)file_size);
2005 SIVAL(p,16,(uint32_t)allocation_size);
2007 p += 22; /* p now points to the EA area. */
2009 status = get_ea_list_from_file(ctx, conn, NULL,
2011 &ea_len, &file_list);
2012 if (!NT_STATUS_IS_OK(status)) {
2015 name_list = ea_list_union(name_list, file_list, &ea_len);
2017 /* We need to determine if this entry will fit in the space available. */
2018 /* Max string size is 255 bytes. */
2019 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2020 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2021 "(wanted %u, had %d)\n",
2022 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2024 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2027 /* Push the ea_data followed by the name. */
2028 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2030 status = srvstr_push(base_data, flags2,
2031 p + 1, fname, PTR_DIFF(end_data, p+1),
2032 STR_TERMINATE | STR_NOALIGN, &len);
2033 if (!NT_STATUS_IS_OK(status)) {
2036 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2049 SCVAL(nameptr,0,len);
2051 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2055 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2056 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2057 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2059 SIVAL(p,0,reskey); p += 4;
2060 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2061 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2062 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2063 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2064 SOFF_T(p,0,file_size); p += 8;
2065 SOFF_T(p,0,allocation_size); p += 8;
2066 SIVAL(p,0,mode); p += 4;
2067 q = p; p += 4; /* q is placeholder for name length. */
2068 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2069 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2071 unsigned int ea_size = estimate_ea_size(conn, NULL,
2073 SIVAL(p,0,ea_size); /* Extended attributes */
2076 /* Clear the short name buffer. This is
2077 * IMPORTANT as not doing so will trigger
2078 * a Win2k client bug. JRA.
2080 if (!was_8_3 && check_mangled_names) {
2081 char mangled_name[13]; /* mangled 8.3 name. */
2082 if (!name_to_8_3(fname,mangled_name,True,
2084 /* Error - mangle failed ! */
2085 memset(mangled_name,'\0',12);
2087 mangled_name[12] = 0;
2088 status = srvstr_push(base_data, flags2,
2089 p+2, mangled_name, 24,
2090 STR_UPPER|STR_UNICODE, &len);
2091 if (!NT_STATUS_IS_OK(status)) {
2095 memset(p + 2 + len,'\0',24 - len);
2102 status = srvstr_push(base_data, flags2, p,
2103 fname, PTR_DIFF(end_data, p),
2104 STR_TERMINATE_ASCII, &len);
2105 if (!NT_STATUS_IS_OK(status)) {
2111 len = PTR_DIFF(p, pdata);
2112 pad = (len + (align-1)) & ~(align-1);
2114 * offset to the next entry, the caller
2115 * will overwrite it for the last entry
2116 * that's why we always include the padding
2120 * set padding to zero
2123 memset(p, 0, pad - len);
2130 case SMB_FIND_FILE_DIRECTORY_INFO:
2131 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2133 SIVAL(p,0,reskey); p += 4;
2134 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2135 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2136 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2137 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2138 SOFF_T(p,0,file_size); p += 8;
2139 SOFF_T(p,0,allocation_size); p += 8;
2140 SIVAL(p,0,mode); p += 4;
2141 status = srvstr_push(base_data, flags2,
2142 p + 4, fname, PTR_DIFF(end_data, p+4),
2143 STR_TERMINATE_ASCII, &len);
2144 if (!NT_STATUS_IS_OK(status)) {
2150 len = PTR_DIFF(p, pdata);
2151 pad = (len + (align-1)) & ~(align-1);
2153 * offset to the next entry, the caller
2154 * will overwrite it for the last entry
2155 * that's why we always include the padding
2159 * set padding to zero
2162 memset(p, 0, pad - len);
2169 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2170 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2172 SIVAL(p,0,reskey); p += 4;
2173 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2174 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2175 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2176 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2177 SOFF_T(p,0,file_size); p += 8;
2178 SOFF_T(p,0,allocation_size); p += 8;
2179 SIVAL(p,0,mode); p += 4;
2180 q = p; p += 4; /* q is placeholder for name length. */
2181 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2182 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2184 unsigned int ea_size = estimate_ea_size(conn, NULL,
2186 SIVAL(p,0,ea_size); /* Extended attributes */
2189 status = srvstr_push(base_data, flags2, p,
2190 fname, PTR_DIFF(end_data, p),
2191 STR_TERMINATE_ASCII, &len);
2192 if (!NT_STATUS_IS_OK(status)) {
2198 len = PTR_DIFF(p, pdata);
2199 pad = (len + (align-1)) & ~(align-1);
2201 * offset to the next entry, the caller
2202 * will overwrite it for the last entry
2203 * that's why we always include the padding
2207 * set padding to zero
2210 memset(p, 0, pad - len);
2217 case SMB_FIND_FILE_NAMES_INFO:
2218 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2220 SIVAL(p,0,reskey); p += 4;
2222 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2223 acl on a dir (tridge) */
2224 status = srvstr_push(base_data, flags2, p,
2225 fname, PTR_DIFF(end_data, p),
2226 STR_TERMINATE_ASCII, &len);
2227 if (!NT_STATUS_IS_OK(status)) {
2233 len = PTR_DIFF(p, pdata);
2234 pad = (len + (align-1)) & ~(align-1);
2236 * offset to the next entry, the caller
2237 * will overwrite it for the last entry
2238 * that's why we always include the padding
2242 * set padding to zero
2245 memset(p, 0, pad - len);
2252 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2253 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2255 SIVAL(p,0,reskey); p += 4;
2256 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2257 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2258 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2259 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2260 SOFF_T(p,0,file_size); p += 8;
2261 SOFF_T(p,0,allocation_size); p += 8;
2262 SIVAL(p,0,mode); p += 4;
2263 q = p; p += 4; /* q is placeholder for name length. */
2264 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2265 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2267 unsigned int ea_size = estimate_ea_size(conn, NULL,
2269 SIVAL(p,0,ea_size); /* Extended attributes */
2272 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2273 SBVAL(p,0,file_id); p += 8;
2274 status = srvstr_push(base_data, flags2, p,
2275 fname, PTR_DIFF(end_data, p),
2276 STR_TERMINATE_ASCII, &len);
2277 if (!NT_STATUS_IS_OK(status)) {
2283 len = PTR_DIFF(p, pdata);
2284 pad = (len + (align-1)) & ~(align-1);
2286 * offset to the next entry, the caller
2287 * will overwrite it for the last entry
2288 * that's why we always include the padding
2292 * set padding to zero
2295 memset(p, 0, pad - len);
2302 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2303 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2304 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2306 SIVAL(p,0,reskey); p += 4;
2307 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2308 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2309 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2310 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2311 SOFF_T(p,0,file_size); p += 8;
2312 SOFF_T(p,0,allocation_size); p += 8;
2313 SIVAL(p,0,mode); p += 4;
2314 q = p; p += 4; /* q is placeholder for name length */
2315 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2316 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2317 } else if (readdir_attr_data &&
2318 readdir_attr_data->type == RDATTR_AAPL) {
2320 * OS X specific SMB2 extension negotiated via
2321 * AAPL create context: return max_access in
2324 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2326 unsigned int ea_size = estimate_ea_size(conn, NULL,
2328 SIVAL(p,0,ea_size); /* Extended attributes */
2332 if (readdir_attr_data &&
2333 readdir_attr_data->type == RDATTR_AAPL) {
2335 * OS X specific SMB2 extension negotiated via
2336 * AAPL create context: return resource fork
2337 * length and compressed FinderInfo in
2340 * According to documentation short_name_len
2341 * should be 0, but on the wire behaviour
2342 * shows its set to 24 by clients.
2346 /* Resourefork length */
2347 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2349 /* Compressed FinderInfo */
2350 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2351 } else if (!was_8_3 && check_mangled_names) {
2352 char mangled_name[13]; /* mangled 8.3 name. */
2353 if (!name_to_8_3(fname,mangled_name,True,
2355 /* Error - mangle failed ! */
2356 memset(mangled_name,'\0',12);
2358 mangled_name[12] = 0;
2359 status = srvstr_push(base_data, flags2,
2360 p+2, mangled_name, 24,
2361 STR_UPPER|STR_UNICODE, &len);
2362 if (!NT_STATUS_IS_OK(status)) {
2367 memset(p + 2 + len,'\0',24 - len);
2371 /* Clear the short name buffer. This is
2372 * IMPORTANT as not doing so will trigger
2373 * a Win2k client bug. JRA.
2380 if (readdir_attr_data &&
2381 readdir_attr_data->type == RDATTR_AAPL) {
2383 * OS X specific SMB2 extension negotiated via
2384 * AAPL create context: return UNIX mode in
2387 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2388 SSVAL(p, 0, aapl_mode);
2394 SBVAL(p,0,file_id); p += 8;
2395 status = srvstr_push(base_data, flags2, p,
2396 fname, PTR_DIFF(end_data, p),
2397 STR_TERMINATE_ASCII, &len);
2398 if (!NT_STATUS_IS_OK(status)) {
2404 len = PTR_DIFF(p, pdata);
2405 pad = (len + (align-1)) & ~(align-1);
2407 * offset to the next entry, the caller
2408 * will overwrite it for the last entry
2409 * that's why we always include the padding
2413 * set padding to zero
2416 memset(p, 0, pad - len);
2423 /* CIFS UNIX Extension. */
2425 case SMB_FIND_FILE_UNIX:
2426 case SMB_FIND_FILE_UNIX_INFO2:
2428 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2430 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2432 if (info_level == SMB_FIND_FILE_UNIX) {
2433 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2434 p = store_file_unix_basic(conn, p,
2435 NULL, &smb_fname->st);
2436 status = srvstr_push(base_data, flags2, p,
2437 fname, PTR_DIFF(end_data, p),
2438 STR_TERMINATE, &len);
2439 if (!NT_STATUS_IS_OK(status)) {
2443 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2444 p = store_file_unix_basic_info2(conn, p,
2445 NULL, &smb_fname->st);
2448 status = srvstr_push(base_data, flags2, p, fname,
2449 PTR_DIFF(end_data, p), 0, &len);
2450 if (!NT_STATUS_IS_OK(status)) {
2453 SIVAL(nameptr, 0, len);
2458 len = PTR_DIFF(p, pdata);
2459 pad = (len + (align-1)) & ~(align-1);
2461 * offset to the next entry, the caller
2462 * will overwrite it for the last entry
2463 * that's why we always include the padding
2467 * set padding to zero
2470 memset(p, 0, pad - len);
2475 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2480 return NT_STATUS_INVALID_LEVEL;
2483 if (PTR_DIFF(p,pdata) > space_remaining) {
2484 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2485 "(wanted %u, had %d)\n",
2486 (unsigned int)PTR_DIFF(p,pdata),
2488 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2491 /* Setup the last entry pointer, as an offset from base_data */
2492 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2493 /* Advance the data pointer to the next slot */
2496 return NT_STATUS_OK;
2499 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2500 connection_struct *conn,
2501 struct dptr_struct *dirptr,
2503 const char *path_mask,
2506 int requires_resume_key,
2515 int space_remaining,
2516 struct smb_filename **_smb_fname,
2517 bool *got_exact_match,
2518 int *_last_entry_off,
2519 struct ea_list *name_list,
2520 struct file_id *file_id)
2523 const char *mask = NULL;
2524 long prev_dirpos = 0;
2527 struct smb_filename *smb_fname = NULL;
2528 struct smbd_dirptr_lanman2_state state;
2530 uint64_t last_entry_off = 0;
2532 enum mangled_names_options mangled_names;
2533 bool marshall_with_83_names;
2535 mangled_names = lp_mangled_names(conn->params);
2539 state.info_level = info_level;
2540 if (mangled_names != MANGLED_NAMES_NO) {
2541 state.check_mangled_names = true;
2543 state.has_wild = dptr_has_wild(dirptr);
2544 state.got_exact_match = false;
2546 *got_exact_match = false;
2548 p = strrchr_m(path_mask,'/');
2559 ok = smbd_dirptr_get_entry(ctx,
2566 smbd_dirptr_lanman2_match_fn,
2567 smbd_dirptr_lanman2_mode_fn,
2574 return NT_STATUS_END_OF_FILE;
2577 *got_exact_match = state.got_exact_match;
2579 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2581 status = smbd_marshall_dir_entry(ctx,
2586 marshall_with_83_names,
2587 requires_resume_key,
2598 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2599 DEBUG(1,("Conversion error: illegal character: %s\n",
2600 smb_fname_str_dbg(smb_fname)));
2603 if (file_id != NULL) {
2604 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2607 if (!NT_STATUS_IS_OK(status) &&
2608 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2610 TALLOC_FREE(smb_fname);
2615 if (_smb_fname != NULL) {
2616 struct smb_filename *name = NULL;
2618 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2620 TALLOC_FREE(smb_fname);
2622 return NT_STATUS_NO_MEMORY;
2627 TALLOC_FREE(smb_fname);
2630 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2631 dptr_SeekDir(dirptr, prev_dirpos);
2635 *_last_entry_off = last_entry_off;
2636 return NT_STATUS_OK;
2639 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2640 connection_struct *conn,
2641 struct dptr_struct *dirptr,
2643 const char *path_mask,
2646 bool requires_resume_key,
2652 int space_remaining,
2653 bool *got_exact_match,
2654 int *last_entry_off,
2655 struct ea_list *name_list)
2658 const bool do_pad = true;
2660 if (info_level >= 1 && info_level <= 3) {
2661 /* No alignment on earlier info levels. */
2665 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2666 path_mask, dirtype, info_level,
2667 requires_resume_key, dont_descend, ask_sharemode,
2668 true, align, do_pad,
2669 ppdata, base_data, end_data,
2673 last_entry_off, name_list, NULL);
2676 /****************************************************************************
2677 Reply to a TRANS2_FINDFIRST.
2678 ****************************************************************************/
2680 static void call_trans2findfirst(connection_struct *conn,
2681 struct smb_request *req,
2682 char **pparams, int total_params,
2683 char **ppdata, int total_data,
2684 unsigned int max_data_bytes)
2686 /* We must be careful here that we don't return more than the
2687 allowed number of data bytes. If this means returning fewer than
2688 maxentries then so be it. We assume that the redirector has
2689 enough room for the fixed number of parameter bytes it has
2691 struct smb_filename *smb_dname = NULL;
2692 char *params = *pparams;
2693 char *pdata = *ppdata;
2697 uint16_t findfirst_flags;
2698 bool close_after_first;
2700 bool requires_resume_key;
2702 char *directory = NULL;
2705 int last_entry_off=0;
2709 bool finished = False;
2710 bool dont_descend = False;
2711 bool out_of_space = False;
2712 int space_remaining;
2713 bool mask_contains_wcard = False;
2714 struct ea_list *ea_list = NULL;
2715 NTSTATUS ntstatus = NT_STATUS_OK;
2716 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
2717 struct smbd_server_connection *sconn = req->sconn;
2718 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2719 ucf_flags_from_smb_request(req);
2720 bool backup_priv = false;
2721 bool as_root = false;
2722 files_struct *fsp = NULL;
2723 const struct loadparm_substitution *lp_sub =
2724 loadparm_s3_global_substitution();
2727 if (total_params < 13) {
2728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2732 dirtype = SVAL(params,0);
2733 maxentries = SVAL(params,2);
2734 findfirst_flags = SVAL(params,4);
2735 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2736 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2737 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2738 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2739 security_token_has_privilege(get_current_nttok(conn),
2742 info_level = SVAL(params,6);
2744 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2745 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2746 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2748 info_level, max_data_bytes));
2751 /* W2K3 seems to treat zero as 1. */
2755 switch (info_level) {
2756 case SMB_FIND_INFO_STANDARD:
2757 case SMB_FIND_EA_SIZE:
2758 case SMB_FIND_EA_LIST:
2759 case SMB_FIND_FILE_DIRECTORY_INFO:
2760 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2761 case SMB_FIND_FILE_NAMES_INFO:
2762 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2763 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2764 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2766 case SMB_FIND_FILE_UNIX:
2767 case SMB_FIND_FILE_UNIX_INFO2:
2768 /* Always use filesystem for UNIX mtime query. */
2769 ask_sharemode = false;
2770 if (!lp_unix_extensions()) {
2771 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2774 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2777 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2781 if (req->posix_pathnames) {
2782 srvstr_get_path_wcard_posix(talloc_tos(),
2790 &mask_contains_wcard);
2792 srvstr_get_path_wcard(talloc_tos(),
2800 &mask_contains_wcard);
2802 if (!NT_STATUS_IS_OK(ntstatus)) {
2803 reply_nterror(req, ntstatus);
2810 ntstatus = filename_convert_with_privilege(talloc_tos(),
2815 &mask_contains_wcard,
2818 ntstatus = filename_convert(talloc_tos(), conn,
2822 &mask_contains_wcard,
2826 if (!NT_STATUS_IS_OK(ntstatus)) {
2827 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2828 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2829 ERRSRV, ERRbadpath);
2832 reply_nterror(req, ntstatus);
2836 mask = smb_dname->original_lcomp;
2838 directory = smb_dname->base_name;
2840 p = strrchr_m(directory,'/');
2842 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2843 if((directory[0] == '.') && (directory[1] == '\0')) {
2844 mask = talloc_strdup(talloc_tos(),"*");
2846 reply_nterror(req, NT_STATUS_NO_MEMORY);
2849 mask_contains_wcard = True;
2855 if (p == NULL || p == directory) {
2856 /* Ensure we don't have a directory name of "". */
2857 directory = talloc_strdup(talloc_tos(), ".");
2859 reply_nterror(req, NT_STATUS_NO_MEMORY);
2862 /* Ensure smb_dname->base_name matches. */
2863 smb_dname->base_name = directory;
2866 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2868 if (info_level == SMB_FIND_EA_LIST) {
2871 if (total_data < 4) {
2872 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2876 ea_size = IVAL(pdata,0);
2877 if (ea_size != total_data) {
2878 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2879 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2884 if (!lp_ea_support(SNUM(conn))) {
2885 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2889 /* Pull out the list of names. */
2890 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2897 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2902 *ppdata = (char *)SMB_REALLOC(
2903 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2904 if(*ppdata == NULL ) {
2905 reply_nterror(req, NT_STATUS_NO_MEMORY);
2909 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2911 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2914 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2915 /* Realloc the params space */
2916 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2917 if (*pparams == NULL) {
2918 reply_nterror(req, NT_STATUS_NO_MEMORY);
2924 * As we've cut off the last component from
2925 * smb_fname we need to re-stat smb_dname
2926 * so FILE_OPEN disposition knows the directory
2929 if (req->posix_pathnames) {
2930 ret = SMB_VFS_LSTAT(conn, smb_dname);
2932 ret = SMB_VFS_STAT(conn, smb_dname);
2936 ntstatus = map_nt_error_from_unix(errno);
2937 reply_nterror(req, ntstatus);
2942 * Open an fsp on this directory for the dptr.
2944 ntstatus = SMB_VFS_CREATE_FILE(
2947 0, /* root_dir_fid */
2948 smb_dname, /* dname */
2949 FILE_LIST_DIRECTORY, /* access_mask */
2951 FILE_SHARE_WRITE, /* share_access */
2952 FILE_OPEN, /* create_disposition*/
2953 FILE_DIRECTORY_FILE, /* create_options */
2954 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2955 NO_OPLOCK, /* oplock_request */
2957 0, /* allocation_size */
2958 0, /* private_flags */
2963 NULL, /* in_context */
2964 NULL);/* out_context */
2966 if (!NT_STATUS_IS_OK(ntstatus)) {
2967 DBG_ERR("failed to open directory %s\n",
2968 smb_fname_str_dbg(smb_dname));
2969 reply_nterror(req, ntstatus);
2973 /* Save the wildcard match and attribs we are using on this directory -
2974 needed as lanman2 assumes these are being saved between calls */
2976 ntstatus = dptr_create(conn,
2983 mask_contains_wcard,
2987 if (!NT_STATUS_IS_OK(ntstatus)) {
2989 * Use NULL here for the first parameter (req)
2990 * as this is not a client visible handle so
2991 * can'tbe part of an SMB1 chain.
2993 close_file(NULL, fsp, NORMAL_CLOSE);
2995 reply_nterror(req, ntstatus);
3000 /* Remember this in case we have
3001 to do a findnext. */
3002 dptr_set_priv(fsp->dptr);
3005 dptr_num = dptr_dnum(fsp->dptr);
3006 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
3008 /* We don't need to check for VOL here as this is returned by
3009 a different TRANS2 call. */
3011 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3012 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
3013 if (in_list(directory,
3014 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
3015 conn->case_sensitive)) {
3016 dont_descend = True;
3020 space_remaining = max_data_bytes;
3021 out_of_space = False;
3023 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
3024 bool got_exact_match = False;
3026 /* this is a heuristic to avoid seeking the dirptr except when
3027 absolutely necessary. It allows for a filename of about 40 chars */
3028 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3029 out_of_space = True;
3032 ntstatus = get_lanman2_dir_entry(talloc_tos(),
3036 mask,dirtype,info_level,
3037 requires_resume_key,dont_descend,
3042 &last_entry_off, ea_list);
3043 if (NT_STATUS_EQUAL(ntstatus,
3044 NT_STATUS_ILLEGAL_CHARACTER)) {
3046 * Bad character conversion on name. Ignore this
3051 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3052 out_of_space = true;
3054 finished = !NT_STATUS_IS_OK(ntstatus);
3058 if (!finished && !out_of_space)
3062 * As an optimisation if we know we aren't looking
3063 * for a wildcard name (ie. the name matches the wildcard exactly)
3064 * then we can finish on any (first) match.
3065 * This speeds up large directory searches. JRA.
3071 /* Ensure space_remaining never goes -ve. */
3072 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3073 space_remaining = 0;
3074 out_of_space = true;
3076 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3080 /* Check if we can close the dirptr */
3081 if(close_after_first || (finished && close_if_end)) {
3082 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3084 close_file(NULL, fsp, NORMAL_CLOSE);
3089 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3090 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3091 * the protocol level is less than NT1. Tested with smbclient. JRA.
3092 * This should fix the OS/2 client bug #2335.
3095 if(numentries == 0) {
3098 * We may have already closed the file in the
3099 * close_after_first or finished case above.
3102 close_file(NULL, fsp, NORMAL_CLOSE);
3105 if (get_Protocol() < PROTOCOL_NT1) {
3106 reply_force_doserror(req, ERRDOS, ERRnofiles);
3109 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3110 ERRDOS, ERRbadfile);
3115 /* At this point pdata points to numentries directory entries. */
3117 /* Set up the return parameter block */
3118 SSVAL(params,0,dptr_num);
3119 SSVAL(params,2,numentries);
3120 SSVAL(params,4,finished);
3121 SSVAL(params,6,0); /* Never an EA error */
3122 SSVAL(params,8,last_entry_off);
3124 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3127 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3128 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3130 reply_nterror(req, NT_STATUS_NO_MEMORY);
3134 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3135 smb_fn_name(req->cmd),
3136 mask, directory, dirtype, numentries ) );
3139 * Force a name mangle here to ensure that the
3140 * mask as an 8.3 name is top of the mangled cache.
3141 * The reasons for this are subtle. Don't remove
3142 * this code unless you know what you are doing
3143 * (see PR#13758). JRA.
3146 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3147 char mangled_name[13];
3148 name_to_8_3(mask, mangled_name, True, conn->params);
3156 TALLOC_FREE(smb_dname);
3160 /****************************************************************************
3161 Reply to a TRANS2_FINDNEXT.
3162 ****************************************************************************/
3164 static void call_trans2findnext(connection_struct *conn,
3165 struct smb_request *req,
3166 char **pparams, int total_params,
3167 char **ppdata, int total_data,
3168 unsigned int max_data_bytes)
3170 /* We must be careful here that we don't return more than the
3171 allowed number of data bytes. If this means returning fewer than
3172 maxentries then so be it. We assume that the redirector has
3173 enough room for the fixed number of parameter bytes it has
3175 char *params = *pparams;
3176 char *pdata = *ppdata;
3180 uint16_t info_level;
3181 uint32_t resume_key;
3182 uint16_t findnext_flags;
3183 bool close_after_request;
3185 bool requires_resume_key;
3187 bool mask_contains_wcard = False;
3188 char *resume_name = NULL;
3189 const char *mask = NULL;
3190 const char *directory = NULL;
3194 int i, last_entry_off=0;
3195 bool finished = False;
3196 bool dont_descend = False;
3197 bool out_of_space = False;
3198 int space_remaining;
3199 struct ea_list *ea_list = NULL;
3200 NTSTATUS ntstatus = NT_STATUS_OK;
3201 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3202 TALLOC_CTX *ctx = talloc_tos();
3203 struct smbd_server_connection *sconn = req->sconn;
3204 bool backup_priv = false;
3205 bool as_root = false;
3206 files_struct *fsp = NULL;
3207 const struct loadparm_substitution *lp_sub =
3208 loadparm_s3_global_substitution();
3210 if (total_params < 13) {
3211 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3215 dptr_num = SVAL(params,0);
3216 maxentries = SVAL(params,2);
3217 info_level = SVAL(params,4);
3218 resume_key = IVAL(params,6);
3219 findnext_flags = SVAL(params,10);
3220 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3221 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3222 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3223 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3225 if (!continue_bit) {
3226 /* We only need resume_name if continue_bit is zero. */
3227 if (req->posix_pathnames) {
3228 srvstr_get_path_wcard_posix(ctx,
3236 &mask_contains_wcard);
3238 srvstr_get_path_wcard(ctx,
3246 &mask_contains_wcard);
3248 if (!NT_STATUS_IS_OK(ntstatus)) {
3249 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3250 complain (it thinks we're asking for the directory above the shared
3251 path or an invalid name). Catch this as the resume name is only compared, never used in
3252 a file access. JRA. */
3253 srvstr_pull_talloc(ctx, params, req->flags2,
3254 &resume_name, params+12,
3258 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3259 reply_nterror(req, ntstatus);
3265 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3266 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3267 resume_key = %d resume name = %s continue=%d level = %d\n",
3268 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3269 requires_resume_key, resume_key,
3270 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3273 /* W2K3 seems to treat zero as 1. */
3277 switch (info_level) {
3278 case SMB_FIND_INFO_STANDARD:
3279 case SMB_FIND_EA_SIZE:
3280 case SMB_FIND_EA_LIST:
3281 case SMB_FIND_FILE_DIRECTORY_INFO:
3282 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3283 case SMB_FIND_FILE_NAMES_INFO:
3284 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3285 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3286 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3288 case SMB_FIND_FILE_UNIX:
3289 case SMB_FIND_FILE_UNIX_INFO2:
3290 /* Always use filesystem for UNIX mtime query. */
3291 ask_sharemode = false;
3292 if (!lp_unix_extensions()) {
3293 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3298 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3302 if (info_level == SMB_FIND_EA_LIST) {
3305 if (total_data < 4) {
3306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3310 ea_size = IVAL(pdata,0);
3311 if (ea_size != total_data) {
3312 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3313 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3318 if (!lp_ea_support(SNUM(conn))) {
3319 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3323 /* Pull out the list of names. */
3324 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3331 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3336 *ppdata = (char *)SMB_REALLOC(
3337 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3338 if(*ppdata == NULL) {
3339 reply_nterror(req, NT_STATUS_NO_MEMORY);
3344 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3347 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3350 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3351 /* Realloc the params space */
3352 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3353 if(*pparams == NULL ) {
3354 reply_nterror(req, NT_STATUS_NO_MEMORY);
3360 /* Check that the dptr is valid */
3361 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3363 reply_nterror(req, STATUS_NO_MORE_FILES);
3367 directory = dptr_path(sconn, dptr_num);
3369 /* Get the wildcard mask from the dptr */
3370 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3371 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3372 reply_nterror(req, STATUS_NO_MORE_FILES);
3376 /* Get the attr mask from the dptr */
3377 dirtype = dptr_attr(sconn, dptr_num);
3379 backup_priv = dptr_get_priv(fsp->dptr);
3381 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3382 "backup_priv = %d\n",
3383 dptr_num, mask, dirtype,
3385 dptr_TellDir(fsp->dptr),
3388 /* We don't need to check for VOL here as this is returned by
3389 a different TRANS2 call. */
3391 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3392 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
3393 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
3394 dont_descend = True;
3397 space_remaining = max_data_bytes;
3398 out_of_space = False;
3406 * Seek to the correct position. We no longer use the resume key but
3407 * depend on the last file name instead.
3410 if(!continue_bit && resume_name && *resume_name) {
3413 long current_pos = 0;
3415 * Remember, name_to_8_3 is called by
3416 * get_lanman2_dir_entry(), so the resume name
3417 * could be mangled. Ensure we check the unmangled name.
3420 if (mangle_is_mangled(resume_name, conn->params)) {
3421 char *new_resume_name = NULL;
3422 mangle_lookup_name_from_8_3(ctx,
3426 if (new_resume_name) {
3427 resume_name = new_resume_name;
3432 * Fix for NT redirector problem triggered by resume key indexes
3433 * changing between directory scans. We now return a resume key of 0
3434 * and instead look for the filename to continue from (also given
3435 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3436 * findfirst/findnext (as is usual) then the directory pointer
3437 * should already be at the correct place.
3440 finished = !dptr_SearchDir(fsp->dptr, resume_name, ¤t_pos, &st);
3441 } /* end if resume_name && !continue_bit */
3443 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3444 bool got_exact_match = False;
3446 /* this is a heuristic to avoid seeking the fsp->dptr except when
3447 absolutely necessary. It allows for a filename of about 40 chars */
3448 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3449 out_of_space = True;
3452 ntstatus = get_lanman2_dir_entry(ctx,
3456 mask,dirtype,info_level,
3457 requires_resume_key,dont_descend,
3462 &last_entry_off, ea_list);
3463 if (NT_STATUS_EQUAL(ntstatus,
3464 NT_STATUS_ILLEGAL_CHARACTER)) {
3466 * Bad character conversion on name. Ignore this
3471 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3472 out_of_space = true;
3474 finished = !NT_STATUS_IS_OK(ntstatus);
3478 if (!finished && !out_of_space)
3482 * As an optimisation if we know we aren't looking
3483 * for a wildcard name (ie. the name matches the wildcard exactly)
3484 * then we can finish on any (first) match.
3485 * This speeds up large directory searches. JRA.
3491 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3494 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3495 smb_fn_name(req->cmd),
3496 mask, directory, dirtype, numentries ) );
3498 /* Check if we can close the fsp->dptr */
3499 if(close_after_request || (finished && close_if_end)) {
3500 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3502 close_file(NULL, fsp, NORMAL_CLOSE);
3510 /* Set up the return parameter block */
3511 SSVAL(params,0,numentries);
3512 SSVAL(params,2,finished);
3513 SSVAL(params,4,0); /* Never an EA error */
3514 SSVAL(params,6,last_entry_off);
3516 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3522 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3524 const struct loadparm_substitution *lp_sub =
3525 loadparm_s3_global_substitution();
3527 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
3531 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3533 SMB_ASSERT(extended_info != NULL);
3535 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3536 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3537 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3538 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3539 #ifdef SAMBA_VERSION_REVISION
3540 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3542 extended_info->samba_subversion = 0;
3543 #ifdef SAMBA_VERSION_RC_RELEASE
3544 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3546 #ifdef SAMBA_VERSION_PRE_RELEASE
3547 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3550 #ifdef SAMBA_VERSION_VENDOR_PATCH
3551 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3553 extended_info->samba_gitcommitdate = 0;
3554 #ifdef SAMBA_VERSION_COMMIT_TIME
3555 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3558 memset(extended_info->samba_version_string, 0,
3559 sizeof(extended_info->samba_version_string));
3561 snprintf (extended_info->samba_version_string,
3562 sizeof(extended_info->samba_version_string),
3563 "%s", samba_version_string());
3566 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3567 connection_struct *conn,
3568 TALLOC_CTX *mem_ctx,
3569 uint16_t info_level,
3571 unsigned int max_data_bytes,
3572 size_t *fixed_portion,
3573 struct smb_filename *fname,
3577 const struct loadparm_substitution *lp_sub =
3578 loadparm_s3_global_substitution();
3579 char *pdata, *end_data;
3582 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3583 int snum = SNUM(conn);
3584 const char *fstype = lp_fstype(SNUM(conn));
3585 const char *filename = NULL;
3586 const uint64_t bytes_per_sector = 512;
3587 uint32_t additional_flags = 0;
3588 struct smb_filename smb_fname;
3590 NTSTATUS status = NT_STATUS_OK;
3593 if (fname == NULL || fname->base_name == NULL) {
3596 filename = fname->base_name;
3600 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3601 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3602 "info level (0x%x) on IPC$.\n",
3603 (unsigned int)info_level));
3604 return NT_STATUS_ACCESS_DENIED;
3608 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3610 ZERO_STRUCT(smb_fname);
3611 smb_fname.base_name = discard_const_p(char, filename);
3613 if(info_level != SMB_FS_QUOTA_INFORMATION
3614 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3615 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3616 return map_nt_error_from_unix(errno);
3621 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3622 return NT_STATUS_INVALID_PARAMETER;
3625 *ppdata = (char *)SMB_REALLOC(
3626 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3627 if (*ppdata == NULL) {
3628 return NT_STATUS_NO_MEMORY;
3632 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3633 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3637 switch (info_level) {
3638 case SMB_INFO_ALLOCATION:
3640 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3642 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3644 if (df_ret == (uint64_t)-1) {
3645 return map_nt_error_from_unix(errno);
3648 block_size = lp_block_size(snum);
3649 if (bsize < block_size) {
3650 uint64_t factor = block_size/bsize;
3655 if (bsize > block_size) {
3656 uint64_t factor = bsize/block_size;
3661 sectors_per_unit = bsize/bytes_per_sector;
3663 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3664 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3665 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3668 * For large drives, return max values and not modulo.
3670 dsize = MIN(dsize, UINT32_MAX);
3671 dfree = MIN(dfree, UINT32_MAX);
3673 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3674 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3675 SIVAL(pdata,l1_cUnit,dsize);
3676 SIVAL(pdata,l1_cUnitAvail,dfree);
3677 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3681 case SMB_INFO_VOLUME:
3682 /* Return volume name */
3684 * Add volume serial number - hash of a combination of
3685 * the called hostname and the service name.
3687 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3689 * Win2k3 and previous mess this up by sending a name length
3690 * one byte short. I believe only older clients (OS/2 Win9x) use
3691 * this call so try fixing this by adding a terminating null to
3692 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3694 status = srvstr_push(
3696 pdata+l2_vol_szVolLabel, vname,
3697 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3698 STR_NOALIGN|STR_TERMINATE, &len);
3699 if (!NT_STATUS_IS_OK(status)) {
3702 SCVAL(pdata,l2_vol_cch,len);
3703 data_len = l2_vol_szVolLabel + len;
3704 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3705 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3706 (unsigned)len, vname));
3709 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3710 case SMB_FS_ATTRIBUTE_INFORMATION:
3712 additional_flags = 0;
3713 #if defined(HAVE_SYS_QUOTAS)
3714 additional_flags |= FILE_VOLUME_QUOTAS;
3717 if(lp_nt_acl_support(SNUM(conn))) {
3718 additional_flags |= FILE_PERSISTENT_ACLS;
3721 /* Capabilities are filled in at connection time through STATVFS call */
3722 additional_flags |= conn->fs_capabilities;
3723 additional_flags |= lp_parm_int(conn->params->service,
3724 "share", "fake_fscaps",
3727 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3728 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3729 additional_flags); /* FS ATTRIBUTES */
3731 SIVAL(pdata,4,255); /* Max filename component length */
3732 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3733 and will think we can't do long filenames */
3734 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3735 PTR_DIFF(end_data, pdata+12),
3737 if (!NT_STATUS_IS_OK(status)) {
3741 data_len = 12 + len;
3742 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3743 /* the client only requested a portion of the
3745 data_len = max_data_bytes;
3746 status = STATUS_BUFFER_OVERFLOW;
3748 *fixed_portion = 16;
3751 case SMB_QUERY_FS_LABEL_INFO:
3752 case SMB_FS_LABEL_INFORMATION:
3753 status = srvstr_push(pdata, flags2, pdata+4, vname,
3754 PTR_DIFF(end_data, pdata+4), 0, &len);
3755 if (!NT_STATUS_IS_OK(status)) {
3762 case SMB_QUERY_FS_VOLUME_INFO:
3763 case SMB_FS_VOLUME_INFORMATION:
3766 * Add volume serial number - hash of a combination of
3767 * the called hostname and the service name.
3769 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
3770 (str_checksum(get_local_machine_name())<<16));
3772 /* Max label len is 32 characters. */
3773 status = srvstr_push(pdata, flags2, pdata+18, vname,
3774 PTR_DIFF(end_data, pdata+18),
3776 if (!NT_STATUS_IS_OK(status)) {
3779 SIVAL(pdata,12,len);
3782 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3783 (int)strlen(vname),vname,
3784 lp_servicename(talloc_tos(), lp_sub, snum)));
3785 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3786 /* the client only requested a portion of the
3788 data_len = max_data_bytes;
3789 status = STATUS_BUFFER_OVERFLOW;
3791 *fixed_portion = 24;
3794 case SMB_QUERY_FS_SIZE_INFO:
3795 case SMB_FS_SIZE_INFORMATION:
3797 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3799 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3801 if (df_ret == (uint64_t)-1) {
3802 return map_nt_error_from_unix(errno);
3804 block_size = lp_block_size(snum);
3805 if (bsize < block_size) {
3806 uint64_t factor = block_size/bsize;
3811 if (bsize > block_size) {
3812 uint64_t factor = bsize/block_size;
3817 sectors_per_unit = bsize/bytes_per_sector;
3818 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3819 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3820 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3821 SBIG_UINT(pdata,0,dsize);
3822 SBIG_UINT(pdata,8,dfree);
3823 SIVAL(pdata,16,sectors_per_unit);
3824 SIVAL(pdata,20,bytes_per_sector);
3825 *fixed_portion = 24;
3829 case SMB_FS_FULL_SIZE_INFORMATION:
3831 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3833 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3835 if (df_ret == (uint64_t)-1) {
3836 return map_nt_error_from_unix(errno);
3838 block_size = lp_block_size(snum);
3839 if (bsize < block_size) {
3840 uint64_t factor = block_size/bsize;
3845 if (bsize > block_size) {
3846 uint64_t factor = bsize/block_size;
3851 sectors_per_unit = bsize/bytes_per_sector;
3852 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3853 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3854 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3855 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3856 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3857 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3858 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3859 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3860 *fixed_portion = 32;
3864 case SMB_QUERY_FS_DEVICE_INFO:
3865 case SMB_FS_DEVICE_INFORMATION:
3867 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3869 if (!CAN_WRITE(conn)) {
3870 characteristics |= FILE_READ_ONLY_DEVICE;
3873 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3874 SIVAL(pdata,4,characteristics);
3879 #ifdef HAVE_SYS_QUOTAS
3880 case SMB_FS_QUOTA_INFORMATION:
3882 * what we have to send --metze:
3884 * Unknown1: 24 NULL bytes
3885 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3886 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3887 * Quota Flags: 2 byte :
3888 * Unknown3: 6 NULL bytes
3892 * details for Quota Flags:
3894 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3895 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3896 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3897 * 0x0001 Enable Quotas: enable quota for this fs
3901 /* we need to fake up a fsp here,
3902 * because its not send in this call
3905 SMB_NTQUOTA_STRUCT quotas;
3908 ZERO_STRUCT(quotas);
3911 fsp.fnum = FNUM_FIELD_INVALID;
3914 if (get_current_uid(conn) != 0) {
3915 DEBUG(0,("get_user_quota: access_denied "
3916 "service [%s] user [%s]\n",
3917 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
3918 conn->session_info->unix_info->unix_name));
3919 return NT_STATUS_ACCESS_DENIED;
3922 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3924 if (!NT_STATUS_IS_OK(status)) {
3925 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3931 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3932 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3934 /* Unknown1 24 NULL bytes*/
3935 SBIG_UINT(pdata,0,(uint64_t)0);
3936 SBIG_UINT(pdata,8,(uint64_t)0);
3937 SBIG_UINT(pdata,16,(uint64_t)0);
3939 /* Default Soft Quota 8 bytes */
3940 SBIG_UINT(pdata,24,quotas.softlim);
3942 /* Default Hard Quota 8 bytes */
3943 SBIG_UINT(pdata,32,quotas.hardlim);
3945 /* Quota flag 2 bytes */
3946 SSVAL(pdata,40,quotas.qflags);
3948 /* Unknown3 6 NULL bytes */
3954 #endif /* HAVE_SYS_QUOTAS */
3955 case SMB_FS_OBJECTID_INFORMATION:
3957 unsigned char objid[16];
3958 struct smb_extended_info extended_info;
3959 memcpy(pdata,create_volume_objectid(conn, objid),16);
3960 samba_extended_info_version (&extended_info);
3961 SIVAL(pdata,16,extended_info.samba_magic);
3962 SIVAL(pdata,20,extended_info.samba_version);
3963 SIVAL(pdata,24,extended_info.samba_subversion);
3964 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3965 memcpy(pdata+36,extended_info.samba_version_string,28);
3970 case SMB_FS_SECTOR_SIZE_INFORMATION:
3974 * These values match a physical Windows Server 2012
3975 * share backed by NTFS atop spinning rust.
3977 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3978 /* logical_bytes_per_sector */
3979 SIVAL(pdata, 0, bytes_per_sector);
3980 /* phys_bytes_per_sector_atomic */
3981 SIVAL(pdata, 4, bytes_per_sector);
3982 /* phys_bytes_per_sector_perf */
3983 SIVAL(pdata, 8, bytes_per_sector);
3984 /* fs_effective_phys_bytes_per_sector_atomic */
3985 SIVAL(pdata, 12, bytes_per_sector);
3987 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3988 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3989 /* byte_off_sector_align */
3990 SIVAL(pdata, 20, 0);
3991 /* byte_off_partition_align */
3992 SIVAL(pdata, 24, 0);
3993 *fixed_portion = 28;
3999 * Query the version and capabilities of the CIFS UNIX extensions
4003 case SMB_QUERY_CIFS_UNIX_INFO:
4005 bool large_write = lp_min_receive_file_size() &&
4006 !srv_is_signing_active(xconn);
4007 bool large_read = !srv_is_signing_active(xconn);
4008 int encrypt_caps = 0;
4010 if (!lp_unix_extensions()) {
4011 return NT_STATUS_INVALID_LEVEL;
4014 switch (conn->encrypt_level) {
4015 case SMB_SIGNING_OFF:
4018 case SMB_SIGNING_DESIRED:
4019 case SMB_SIGNING_IF_REQUIRED:
4020 case SMB_SIGNING_DEFAULT:
4021 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
4023 case SMB_SIGNING_REQUIRED:
4024 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
4025 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
4026 large_write = false;
4032 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
4033 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
4035 /* We have POSIX ACLs, pathname, encryption,
4036 * large read/write, and locking capability. */
4038 SBIG_UINT(pdata,4,((uint64_t)(
4039 CIFS_UNIX_POSIX_ACLS_CAP|
4040 CIFS_UNIX_POSIX_PATHNAMES_CAP|
4041 CIFS_UNIX_FCNTL_LOCKS_CAP|
4042 CIFS_UNIX_EXTATTR_CAP|
4043 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
4045 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
4047 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
4051 case SMB_QUERY_POSIX_FS_INFO:
4054 vfs_statvfs_struct svfs;
4056 if (!lp_unix_extensions()) {
4057 return NT_STATUS_INVALID_LEVEL;
4060 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
4064 SIVAL(pdata,0,svfs.OptimalTransferSize);
4065 SIVAL(pdata,4,svfs.BlockSize);
4066 SBIG_UINT(pdata,8,svfs.TotalBlocks);
4067 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4068 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4069 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4070 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4071 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4072 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4074 } else if (rc == EOPNOTSUPP) {
4075 return NT_STATUS_INVALID_LEVEL;
4076 #endif /* EOPNOTSUPP */
4078 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4079 return NT_STATUS_DOS(ERRSRV, ERRerror);
4084 case SMB_QUERY_POSIX_WHOAMI:
4090 if (!lp_unix_extensions()) {
4091 return NT_STATUS_INVALID_LEVEL;
4094 if (max_data_bytes < 40) {
4095 return NT_STATUS_BUFFER_TOO_SMALL;
4098 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4099 flags |= SMB_WHOAMI_GUEST;
4102 /* NOTE: 8 bytes for UID/GID, irrespective of native
4103 * platform size. This matches
4104 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4106 data_len = 4 /* flags */
4113 + 4 /* pad/reserved */
4114 + (conn->session_info->unix_token->ngroups * 8)
4116 + (conn->session_info->security_token->num_sids *
4120 SIVAL(pdata, 0, flags);
4121 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4123 (uint64_t)conn->session_info->unix_token->uid);
4124 SBIG_UINT(pdata, 16,
4125 (uint64_t)conn->session_info->unix_token->gid);
4128 if (data_len >= max_data_bytes) {
4129 /* Potential overflow, skip the GIDs and SIDs. */
4131 SIVAL(pdata, 24, 0); /* num_groups */
4132 SIVAL(pdata, 28, 0); /* num_sids */
4133 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4134 SIVAL(pdata, 36, 0); /* reserved */
4140 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4141 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4143 /* We walk the SID list twice, but this call is fairly
4144 * infrequent, and I don't expect that it's performance
4145 * sensitive -- jpeach
4147 for (i = 0, sid_bytes = 0;
4148 i < conn->session_info->security_token->num_sids; ++i) {
4149 sid_bytes += ndr_size_dom_sid(
4150 &conn->session_info->security_token->sids[i],
4154 /* SID list byte count */
4155 SIVAL(pdata, 32, sid_bytes);
4157 /* 4 bytes pad/reserved - must be zero */
4158 SIVAL(pdata, 36, 0);
4162 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4163 SBIG_UINT(pdata, data_len,
4164 (uint64_t)conn->session_info->unix_token->groups[i]);
4170 i < conn->session_info->security_token->num_sids; ++i) {
4171 int sid_len = ndr_size_dom_sid(
4172 &conn->session_info->security_token->sids[i],
4175 sid_linearize((uint8_t *)(pdata + data_len),
4177 &conn->session_info->security_token->sids[i]);
4178 data_len += sid_len;
4184 case SMB_MAC_QUERY_FS_INFO:
4186 * Thursby MAC extension... ONLY on NTFS filesystems
4187 * once we do streams then we don't need this
4189 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4191 SIVAL(pdata,84,0x100); /* Don't support mac... */
4197 return NT_STATUS_INVALID_LEVEL;
4200 *ret_data_len = data_len;
4204 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4205 struct smb_request *req,
4207 const DATA_BLOB *qdata)
4209 const struct loadparm_substitution *lp_sub =
4210 loadparm_s3_global_substitution();
4212 SMB_NTQUOTA_STRUCT quotas;
4214 ZERO_STRUCT(quotas);
4217 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4218 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4219 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
4220 conn->session_info->unix_info->unix_name));
4221 return NT_STATUS_ACCESS_DENIED;
4224 if (!check_fsp_ntquota_handle(conn, req,
4226 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4227 return NT_STATUS_INVALID_HANDLE;
4230 /* note: normally there're 48 bytes,
4231 * but we didn't use the last 6 bytes for now
4234 if (qdata->length < 42) {
4235 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4236 (unsigned int)qdata->length));
4237 return NT_STATUS_INVALID_PARAMETER;
4240 /* unknown_1 24 NULL bytes in pdata*/
4242 /* the soft quotas 8 bytes (uint64_t)*/
4243 quotas.softlim = BVAL(qdata->data,24);
4245 /* the hard quotas 8 bytes (uint64_t)*/
4246 quotas.hardlim = BVAL(qdata->data,32);
4248 /* quota_flags 2 bytes **/
4249 quotas.qflags = SVAL(qdata->data,40);
4251 /* unknown_2 6 NULL bytes follow*/
4253 /* now set the quotas */
4254 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4255 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4256 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4257 status = map_nt_error_from_unix(errno);
4259 status = NT_STATUS_OK;
4264 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4265 struct smb_request *req,
4266 TALLOC_CTX *mem_ctx,
4267 uint16_t info_level,
4269 const DATA_BLOB *pdata)
4271 switch (info_level) {
4272 case SMB_FS_QUOTA_INFORMATION:
4274 return smb_set_fsquota(conn,
4283 return NT_STATUS_INVALID_LEVEL;
4286 /****************************************************************************
4287 Reply to a TRANS2_QFSINFO (query filesystem info).
4288 ****************************************************************************/
4290 static void call_trans2qfsinfo(connection_struct *conn,
4291 struct smb_request *req,
4292 char **pparams, int total_params,
4293 char **ppdata, int total_data,
4294 unsigned int max_data_bytes)
4296 char *params = *pparams;
4297 uint16_t info_level;
4299 size_t fixed_portion;
4302 if (total_params < 2) {
4303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4307 info_level = SVAL(params,0);
4309 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4310 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4311 DEBUG(0,("call_trans2qfsinfo: encryption required "
4312 "and info level 0x%x sent.\n",
4313 (unsigned int)info_level));
4314 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4319 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4321 status = smbd_do_qfsinfo(req->xconn, conn, req,
4328 if (!NT_STATUS_IS_OK(status)) {
4329 reply_nterror(req, status);
4333 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4336 DEBUG( 4, ( "%s info_level = %d\n",
4337 smb_fn_name(req->cmd), info_level) );
4342 /****************************************************************************
4343 Reply to a TRANS2_SETFSINFO (set filesystem info).
4344 ****************************************************************************/
4346 static void call_trans2setfsinfo(connection_struct *conn,
4347 struct smb_request *req,
4348 char **pparams, int total_params,
4349 char **ppdata, int total_data,
4350 unsigned int max_data_bytes)
4352 const struct loadparm_substitution *lp_sub =
4353 loadparm_s3_global_substitution();
4354 struct smbXsrv_connection *xconn = req->xconn;
4355 char *pdata = *ppdata;
4356 char *params = *pparams;
4357 uint16_t info_level;
4359 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4360 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4363 if (total_params < 4) {
4364 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4366 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4370 info_level = SVAL(params,2);
4373 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4374 info_level != SMB_SET_CIFS_UNIX_INFO) {
4375 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4376 "info level (0x%x) on IPC$.\n",
4377 (unsigned int)info_level));
4378 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4383 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4384 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4385 DEBUG(0,("call_trans2setfsinfo: encryption required "
4386 "and info level 0x%x sent.\n",
4387 (unsigned int)info_level));
4388 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4393 switch(info_level) {
4394 case SMB_SET_CIFS_UNIX_INFO:
4395 if (!lp_unix_extensions()) {
4396 DEBUG(2,("call_trans2setfsinfo: "
4397 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4398 "unix extensions off\n"));
4400 NT_STATUS_INVALID_LEVEL);
4404 /* There should be 12 bytes of capabilities set. */
4405 if (total_data < 12) {
4408 NT_STATUS_INVALID_PARAMETER);
4411 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4412 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4413 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4414 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4415 /* Just print these values for now. */
4416 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4417 "major = %u, minor = %u cap_low = 0x%x, "
4419 (unsigned int)xconn->
4420 smb1.unix_info.client_major,
4421 (unsigned int)xconn->
4422 smb1.unix_info.client_minor,
4423 (unsigned int)xconn->
4424 smb1.unix_info.client_cap_low,
4425 (unsigned int)xconn->
4426 smb1.unix_info.client_cap_high));
4428 /* Here is where we must switch to posix pathname processing... */
4429 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4430 lp_set_posix_pathnames();
4431 mangle_change_to_posix();
4434 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4435 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4436 /* Client that knows how to do posix locks,
4437 * but not posix open/mkdir operations. Set a
4438 * default type for read/write checks. */
4440 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4445 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4448 size_t param_len = 0;
4449 size_t data_len = total_data;
4451 if (!lp_unix_extensions()) {
4454 NT_STATUS_INVALID_LEVEL);
4458 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4461 NT_STATUS_NOT_SUPPORTED);
4465 if (xconn->smb1.echo_handler.trusted_fde) {
4466 DEBUG( 2,("call_trans2setfsinfo: "
4467 "request transport encryption disabled"
4468 "with 'fork echo handler = yes'\n"));
4471 NT_STATUS_NOT_SUPPORTED);
4475 DEBUG( 4,("call_trans2setfsinfo: "
4476 "request transport encryption.\n"));
4478 status = srv_request_encryption_setup(conn,
4479 (unsigned char **)ppdata,
4481 (unsigned char **)pparams,
4484 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4485 !NT_STATUS_IS_OK(status)) {
4486 reply_nterror(req, status);
4490 send_trans2_replies(conn, req,
4498 if (NT_STATUS_IS_OK(status)) {
4499 /* Server-side transport
4500 * encryption is now *on*. */
4501 status = srv_encryption_start(conn);
4502 if (!NT_STATUS_IS_OK(status)) {
4503 char *reason = talloc_asprintf(talloc_tos(),
4504 "Failure in setting "
4505 "up encrypted transport: %s",
4507 exit_server_cleanly(reason);
4513 case SMB_FS_QUOTA_INFORMATION:
4517 .data = (uint8_t *)pdata,
4518 .length = total_data
4520 files_struct *fsp = NULL;
4521 fsp = file_fsp(req, SVAL(params,0));
4523 status = smb_set_fsquota(conn,
4527 if (!NT_STATUS_IS_OK(status)) {
4528 reply_nterror(req, status);
4534 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4536 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4542 * sending this reply works fine,
4543 * but I'm not sure it's the same
4544 * like windows do...
4547 reply_outbuf(req, 10, 0);
4550 #if defined(HAVE_POSIX_ACLS)
4551 /****************************************************************************
4552 Utility function to count the number of entries in a POSIX acl.
4553 ****************************************************************************/
4555 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4557 unsigned int ace_count = 0;
4558 int entry_id = SMB_ACL_FIRST_ENTRY;
4559 SMB_ACL_ENTRY_T entry;
4561 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4563 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4564 entry_id = SMB_ACL_NEXT_ENTRY;
4571 /****************************************************************************
4572 Utility function to marshall a POSIX acl into wire format.
4573 ****************************************************************************/
4575 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4577 int entry_id = SMB_ACL_FIRST_ENTRY;
4578 SMB_ACL_ENTRY_T entry;
4580 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4581 SMB_ACL_TAG_T tagtype;
4582 SMB_ACL_PERMSET_T permset;
4583 unsigned char perms = 0;
4584 unsigned int own_grp;
4587 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4588 entry_id = SMB_ACL_NEXT_ENTRY;
4591 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4592 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4596 if (sys_acl_get_permset(entry, &permset) == -1) {
4597 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4601 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4602 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4603 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4605 SCVAL(pdata,1,perms);
4608 case SMB_ACL_USER_OBJ:
4609 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4610 own_grp = (unsigned int)pst->st_ex_uid;
4611 SIVAL(pdata,2,own_grp);
4616 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4618 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4621 own_grp = (unsigned int)*puid;
4622 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4623 SIVAL(pdata,2,own_grp);
4627 case SMB_ACL_GROUP_OBJ:
4628 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4629 own_grp = (unsigned int)pst->st_ex_gid;
4630 SIVAL(pdata,2,own_grp);
4635 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4637 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4640 own_grp = (unsigned int)*pgid;
4641 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4642 SIVAL(pdata,2,own_grp);
4647 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4648 SIVAL(pdata,2,0xFFFFFFFF);
4649 SIVAL(pdata,6,0xFFFFFFFF);
4652 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4653 SIVAL(pdata,2,0xFFFFFFFF);
4654 SIVAL(pdata,6,0xFFFFFFFF);
4657 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4660 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4667 /****************************************************************************
4668 Store the FILE_UNIX_BASIC info.
4669 ****************************************************************************/
4671 static char *store_file_unix_basic(connection_struct *conn,
4674 const SMB_STRUCT_STAT *psbuf)
4678 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4679 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4681 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4684 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4687 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
4688 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
4689 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4692 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4696 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4700 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4703 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4704 devno = psbuf->st_ex_rdev;
4706 devno = psbuf->st_ex_dev;
4709 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4713 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4717 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4720 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4724 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4731 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4732 * the chflags(2) (or equivalent) flags.
4734 * XXX: this really should be behind the VFS interface. To do this, we would
4735 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4736 * Each VFS module could then implement its own mapping as appropriate for the
4737 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4739 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4743 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4747 { UF_IMMUTABLE, EXT_IMMUTABLE },
4751 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4755 { UF_HIDDEN, EXT_HIDDEN },
4758 /* Do not remove. We need to guarantee that this array has at least one
4759 * entry to build on HP-UX.
4765 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4766 uint32_t *smb_fflags, uint32_t *smb_fmask)
4770 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4771 *smb_fmask |= info2_flags_map[i].smb_fflag;
4772 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4773 *smb_fflags |= info2_flags_map[i].smb_fflag;
4778 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4779 const uint32_t smb_fflags,
4780 const uint32_t smb_fmask,
4783 uint32_t max_fmask = 0;
4786 *stat_fflags = psbuf->st_ex_flags;
4788 /* For each flags requested in smb_fmask, check the state of the
4789 * corresponding flag in smb_fflags and set or clear the matching
4793 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4794 max_fmask |= info2_flags_map[i].smb_fflag;
4795 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4796 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4797 *stat_fflags |= info2_flags_map[i].stat_fflag;
4799 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4804 /* If smb_fmask is asking to set any bits that are not supported by
4805 * our flag mappings, we should fail.
4807 if ((smb_fmask & max_fmask) != smb_fmask) {
4815 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4816 * of file flags and birth (create) time.
4818 static char *store_file_unix_basic_info2(connection_struct *conn,
4821 const SMB_STRUCT_STAT *psbuf)
4823 uint32_t file_flags = 0;
4824 uint32_t flags_mask = 0;
4826 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4828 /* Create (birth) time 64 bit */
4829 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
4832 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4833 SIVAL(pdata, 0, file_flags); /* flags */
4834 SIVAL(pdata, 4, flags_mask); /* mask */
4840 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4841 const struct stream_struct *streams,
4843 unsigned int max_data_bytes,
4844 unsigned int *data_size)
4847 unsigned int ofs = 0;
4849 if (max_data_bytes < 32) {
4850 return NT_STATUS_INFO_LENGTH_MISMATCH;
4853 for (i = 0; i < num_streams; i++) {
4854 unsigned int next_offset;
4856 smb_ucs2_t *namebuf;
4858 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4859 streams[i].name, &namelen) ||
4862 return NT_STATUS_INVALID_PARAMETER;
4866 * name_buf is now null-terminated, we need to marshall as not
4873 * We cannot overflow ...
4875 if ((ofs + 24 + namelen) > max_data_bytes) {
4876 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4878 TALLOC_FREE(namebuf);
4879 return STATUS_BUFFER_OVERFLOW;
4882 SIVAL(data, ofs+4, namelen);
4883 SOFF_T(data, ofs+8, streams[i].size);
4884 SOFF_T(data, ofs+16, streams[i].alloc_size);
4885 memcpy(data+ofs+24, namebuf, namelen);
4886 TALLOC_FREE(namebuf);
4888 next_offset = ofs + 24 + namelen;
4890 if (i == num_streams-1) {
4891 SIVAL(data, ofs, 0);
4894 unsigned int align = ndr_align_size(next_offset, 8);
4896 if ((next_offset + align) > max_data_bytes) {
4897 DEBUG(10, ("refusing to overflow align "
4898 "reply at stream %u\n",
4900 TALLOC_FREE(namebuf);
4901 return STATUS_BUFFER_OVERFLOW;
4904 memset(data+next_offset, 0, align);
4905 next_offset += align;
4907 SIVAL(data, ofs, next_offset - ofs);
4914 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4918 return NT_STATUS_OK;
4921 #if defined(HAVE_POSIX_ACLS)
4922 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4923 struct smb_request *req,
4925 struct smb_filename *smb_fname,
4927 unsigned int data_size_in,
4928 unsigned int *pdata_size_out)
4930 SMB_ACL_T file_acl = NULL;
4931 SMB_ACL_T def_acl = NULL;
4932 uint16_t num_file_acls = 0;
4933 uint16_t num_def_acls = 0;
4934 unsigned int size_needed = 0;
4937 bool close_fsp = false;
4940 * Ensure we always operate on a file descriptor, not just
4944 uint32_t access_mask = SEC_STD_READ_CONTROL|
4945 FILE_READ_ATTRIBUTES|
4946 FILE_WRITE_ATTRIBUTES;
4948 status = get_posix_fsp(conn,
4954 if (!NT_STATUS_IS_OK(status)) {
4960 SMB_ASSERT(fsp != NULL);
4962 status = refuse_symlink(conn,
4965 if (!NT_STATUS_IS_OK(status)) {
4969 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4972 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4973 DBG_INFO("ACLs not implemented on "
4974 "filesystem containing %s\n",
4976 status = NT_STATUS_NOT_IMPLEMENTED;
4980 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4982 * We can only have default POSIX ACLs on
4985 if (!fsp->is_directory) {
4986 DBG_INFO("Non-directory open %s\n",
4988 status = NT_STATUS_INVALID_HANDLE;
4991 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
4993 SMB_ACL_TYPE_DEFAULT,
4995 def_acl = free_empty_sys_acl(conn, def_acl);
4998 num_file_acls = count_acl_entries(conn, file_acl);
4999 num_def_acls = count_acl_entries(conn, def_acl);
5002 if (num_file_acls + num_def_acls < num_file_acls) {
5003 status = NT_STATUS_INVALID_PARAMETER;
5007 size_needed = num_file_acls + num_def_acls;
5010 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5011 * than UINT_MAX, so check by division.
5013 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5014 status = NT_STATUS_INVALID_PARAMETER;
5018 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5019 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5020 status = NT_STATUS_INVALID_PARAMETER;
5023 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5025 if ( data_size_in < size_needed) {
5026 DBG_INFO("data_size too small (%u) need %u\n",
5029 status = NT_STATUS_BUFFER_TOO_SMALL;
5033 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5034 SSVAL(pdata,2,num_file_acls);
5035 SSVAL(pdata,4,num_def_acls);
5036 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5038 ok = marshall_posix_acl(conn,
5043 status = NT_STATUS_INTERNAL_ERROR;
5046 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5048 ok = marshall_posix_acl(conn,
5053 status = NT_STATUS_INTERNAL_ERROR;
5057 *pdata_size_out = size_needed;
5058 status = NT_STATUS_OK;
5064 * Ensure the stat struct in smb_fname is up to
5065 * date. Structure copy.
5067 smb_fname->st = fsp->fsp_name->st;
5068 (void)close_file(req, fsp, NORMAL_CLOSE);
5072 TALLOC_FREE(file_acl);
5073 TALLOC_FREE(def_acl);
5078 /****************************************************************************
5079 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5080 ****************************************************************************/
5082 static void call_trans2qpipeinfo(connection_struct *conn,
5083 struct smb_request *req,
5084 unsigned int tran_call,
5085 char **pparams, int total_params,
5086 char **ppdata, int total_data,
5087 unsigned int max_data_bytes)
5089 char *params = *pparams;
5090 char *pdata = *ppdata;
5091 unsigned int data_size = 0;
5092 unsigned int param_size = 2;
5093 uint16_t info_level;
5097 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5101 if (total_params < 4) {
5102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5106 fsp = file_fsp(req, SVAL(params,0));
5107 if (!fsp_is_np(fsp)) {
5108 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5112 info_level = SVAL(params,2);
5114 *pparams = (char *)SMB_REALLOC(*pparams,2);
5115 if (*pparams == NULL) {
5116 reply_nterror(req, NT_STATUS_NO_MEMORY);
5121 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5122 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5125 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5126 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5127 if (*ppdata == NULL ) {
5128 reply_nterror(req, NT_STATUS_NO_MEMORY);
5133 switch (info_level) {
5134 case SMB_FILE_STANDARD_INFORMATION:
5136 SOFF_T(pdata,0,4096LL);
5143 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5147 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5153 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5154 TALLOC_CTX *mem_ctx,
5155 struct smb_request *req,
5156 uint16_t info_level,
5158 struct smb_filename *smb_fname,
5159 bool delete_pending,
5160 struct timespec write_time_ts,
5161 struct ea_list *ea_list,
5162 int lock_data_count,
5165 unsigned int max_data_bytes,
5166 size_t *fixed_portion,
5168 unsigned int *pdata_size)
5170 char *pdata = *ppdata;
5171 char *dstart, *dend;
5172 unsigned int data_size;
5173 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5174 time_t create_time, mtime, atime, c_time;
5175 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5182 uint64_t file_size = 0;
5184 uint64_t allocation_size = 0;
5185 uint64_t file_id = 0;
5186 uint32_t access_mask = 0;
5189 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5190 return NT_STATUS_INVALID_LEVEL;
5193 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5194 smb_fname_str_dbg(smb_fname),
5196 info_level, max_data_bytes));
5198 mode = dos_mode(conn, smb_fname);
5199 nlink = psbuf->st_ex_nlink;
5201 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5205 if ((nlink > 0) && delete_pending) {
5209 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5210 return NT_STATUS_INVALID_PARAMETER;
5213 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5214 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5215 if (*ppdata == NULL) {
5216 return NT_STATUS_NO_MEMORY;
5220 dend = dstart + data_size - 1;
5222 if (!is_omit_timespec(&write_time_ts) &&
5223 !INFO_LEVEL_IS_UNIX(info_level))
5225 update_stat_ex_mtime(psbuf, write_time_ts);
5228 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5229 mtime_ts = psbuf->st_ex_mtime;
5230 atime_ts = psbuf->st_ex_atime;
5231 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5233 if (lp_dos_filetime_resolution(SNUM(conn))) {
5234 dos_filetime_timespec(&create_time_ts);
5235 dos_filetime_timespec(&mtime_ts);
5236 dos_filetime_timespec(&atime_ts);
5237 dos_filetime_timespec(&ctime_ts);
5240 create_time = convert_timespec_to_time_t(create_time_ts);
5241 mtime = convert_timespec_to_time_t(mtime_ts);
5242 atime = convert_timespec_to_time_t(atime_ts);
5243 c_time = convert_timespec_to_time_t(ctime_ts);
5245 p = strrchr_m(smb_fname->base_name,'/');
5247 base_name = smb_fname->base_name;
5251 /* NT expects the name to be in an exact form of the *full*
5252 filename. See the trans2 torture test */
5253 if (ISDOT(base_name)) {
5254 dos_fname = talloc_strdup(mem_ctx, "\\");
5256 return NT_STATUS_NO_MEMORY;
5259 dos_fname = talloc_asprintf(mem_ctx,
5261 smb_fname->base_name);
5263 return NT_STATUS_NO_MEMORY;
5265 if (is_ntfs_stream_smb_fname(smb_fname)) {
5266 dos_fname = talloc_asprintf(dos_fname, "%s",
5267 smb_fname->stream_name);
5269 return NT_STATUS_NO_MEMORY;
5273 string_replace(dos_fname, '/', '\\');
5276 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5279 /* Do we have this path open ? */
5281 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5282 fsp1 = file_find_di_first(conn->sconn, fileid);
5283 if (fsp1 && fsp1->initial_allocation_size) {
5284 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5288 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5289 file_size = get_file_size_stat(psbuf);
5293 pos = fsp->fh->position_information;
5297 access_mask = fsp->access_mask;
5299 /* GENERIC_EXECUTE mapping from Windows */
5300 access_mask = 0x12019F;
5303 /* This should be an index number - looks like
5306 I think this causes us to fail the IFSKIT
5307 BasicFileInformationTest. -tpot */
5308 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5312 switch (info_level) {
5313 case SMB_INFO_STANDARD:
5314 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5316 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5317 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5318 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5319 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5320 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5321 SSVAL(pdata,l1_attrFile,mode);
5324 case SMB_INFO_QUERY_EA_SIZE:
5326 unsigned int ea_size =
5327 estimate_ea_size(conn, fsp,
5329 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5331 srv_put_dos_date2(pdata,0,create_time);
5332 srv_put_dos_date2(pdata,4,atime);
5333 srv_put_dos_date2(pdata,8,mtime); /* write time */
5334 SIVAL(pdata,12,(uint32_t)file_size);
5335 SIVAL(pdata,16,(uint32_t)allocation_size);
5336 SSVAL(pdata,20,mode);
5337 SIVAL(pdata,22,ea_size);
5341 case SMB_INFO_IS_NAME_VALID:
5342 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5344 /* os/2 needs this ? really ?*/
5345 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5347 /* This is only reached for qpathinfo */
5351 case SMB_INFO_QUERY_EAS_FROM_LIST:
5353 size_t total_ea_len = 0;
5354 struct ea_list *ea_file_list = NULL;
5355 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5358 get_ea_list_from_file(mem_ctx, conn, fsp,
5360 &total_ea_len, &ea_file_list);
5361 if (!NT_STATUS_IS_OK(status)) {
5365 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5367 if (!ea_list || (total_ea_len > data_size)) {
5369 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5373 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5377 case SMB_INFO_QUERY_ALL_EAS:
5379 /* We have data_size bytes to put EA's into. */
5380 size_t total_ea_len = 0;
5381 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5383 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5385 &total_ea_len, &ea_list);
5386 if (!NT_STATUS_IS_OK(status)) {
5390 if (!ea_list || (total_ea_len > data_size)) {
5392 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5396 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5400 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5402 /* This is FileFullEaInformation - 0xF which maps to
5403 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5405 /* We have data_size bytes to put EA's into. */
5406 size_t total_ea_len = 0;
5407 struct ea_list *ea_file_list = NULL;
5409 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5411 /*TODO: add filtering and index handling */
5414 get_ea_list_from_file(mem_ctx, conn, fsp,
5416 &total_ea_len, &ea_file_list);
5417 if (!NT_STATUS_IS_OK(status)) {
5420 if (!ea_file_list) {
5421 return NT_STATUS_NO_EAS_ON_FILE;
5424 status = fill_ea_chained_buffer(mem_ctx,
5428 conn, ea_file_list);
5429 if (!NT_STATUS_IS_OK(status)) {
5435 case SMB_FILE_BASIC_INFORMATION:
5436 case SMB_QUERY_FILE_BASIC_INFO:
5438 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5439 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5440 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5442 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5446 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5447 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5448 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5449 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5450 SIVAL(pdata,32,mode);
5452 DEBUG(5,("SMB_QFBI - "));
5453 DEBUG(5,("create: %s ", ctime(&create_time)));
5454 DEBUG(5,("access: %s ", ctime(&atime)));
5455 DEBUG(5,("write: %s ", ctime(&mtime)));
5456 DEBUG(5,("change: %s ", ctime(&c_time)));
5457 DEBUG(5,("mode: %x\n", mode));
5458 *fixed_portion = data_size;
5461 case SMB_FILE_STANDARD_INFORMATION:
5462 case SMB_QUERY_FILE_STANDARD_INFO:
5464 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5466 SOFF_T(pdata,0,allocation_size);
5467 SOFF_T(pdata,8,file_size);
5468 SIVAL(pdata,16,nlink);
5469 SCVAL(pdata,20,delete_pending?1:0);
5470 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5471 SSVAL(pdata,22,0); /* Padding. */
5472 *fixed_portion = 24;
5475 case SMB_FILE_EA_INFORMATION:
5476 case SMB_QUERY_FILE_EA_INFO:
5478 unsigned int ea_size =
5479 estimate_ea_size(conn, fsp, smb_fname);
5480 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5483 SIVAL(pdata,0,ea_size);
5487 /* Get the 8.3 name - used if NT SMB was negotiated. */
5488 case SMB_QUERY_FILE_ALT_NAME_INFO:
5489 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5491 char mangled_name[13];
5492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5493 if (!name_to_8_3(base_name,mangled_name,
5494 True,conn->params)) {
5495 return NT_STATUS_NO_MEMORY;
5497 status = srvstr_push(dstart, flags2,
5498 pdata+4, mangled_name,
5499 PTR_DIFF(dend, pdata+4),
5501 if (!NT_STATUS_IS_OK(status)) {
5504 data_size = 4 + len;
5510 case SMB_QUERY_FILE_NAME_INFO:
5513 this must be *exactly* right for ACLs on mapped drives to work
5515 status = srvstr_push(dstart, flags2,
5517 PTR_DIFF(dend, pdata+4),
5519 if (!NT_STATUS_IS_OK(status)) {
5522 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5523 data_size = 4 + len;
5528 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5530 char *nfname = NULL;
5532 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
5533 return NT_STATUS_INVALID_LEVEL;
5536 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5537 if (nfname == NULL) {
5538 return NT_STATUS_NO_MEMORY;
5541 if (ISDOT(nfname)) {
5544 string_replace(nfname, '/', '\\');
5546 if (smb_fname->stream_name != NULL) {
5547 const char *s = smb_fname->stream_name;
5548 const char *e = NULL;
5551 SMB_ASSERT(s[0] != '\0');
5554 * smb_fname->stream_name is in form
5555 * of ':StrEam:$DATA', but we should only
5556 * append ':StrEam' here.
5559 e = strchr(&s[1], ':');
5565 nfname = talloc_strndup_append(nfname, s, n);
5566 if (nfname == NULL) {
5567 return NT_STATUS_NO_MEMORY;
5571 status = srvstr_push(dstart, flags2,
5573 PTR_DIFF(dend, pdata+4),
5575 if (!NT_STATUS_IS_OK(status)) {
5578 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5579 data_size = 4 + len;
5585 case SMB_FILE_ALLOCATION_INFORMATION:
5586 case SMB_QUERY_FILE_ALLOCATION_INFO:
5587 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5589 SOFF_T(pdata,0,allocation_size);
5592 case SMB_FILE_END_OF_FILE_INFORMATION:
5593 case SMB_QUERY_FILE_END_OF_FILEINFO:
5594 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5596 SOFF_T(pdata,0,file_size);
5599 case SMB_QUERY_FILE_ALL_INFO:
5600 case SMB_FILE_ALL_INFORMATION:
5602 unsigned int ea_size =
5603 estimate_ea_size(conn, fsp, smb_fname);
5604 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5605 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5606 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5607 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5608 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5609 SIVAL(pdata,32,mode);
5610 SIVAL(pdata,36,0); /* padding. */
5612 SOFF_T(pdata,0,allocation_size);
5613 SOFF_T(pdata,8,file_size);
5614 SIVAL(pdata,16,nlink);
5615 SCVAL(pdata,20,delete_pending);
5616 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5619 SIVAL(pdata,0,ea_size);
5620 pdata += 4; /* EA info */
5621 status = srvstr_push(dstart, flags2,
5623 PTR_DIFF(dend, pdata+4),
5625 if (!NT_STATUS_IS_OK(status)) {
5630 data_size = PTR_DIFF(pdata,(*ppdata));
5631 *fixed_portion = 10;
5635 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5637 unsigned int ea_size =
5638 estimate_ea_size(conn, fsp, smb_fname);
5639 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5640 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
5641 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
5642 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
5643 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
5644 SIVAL(pdata, 0x20, mode);
5645 SIVAL(pdata, 0x24, 0); /* padding. */
5646 SBVAL(pdata, 0x28, allocation_size);
5647 SBVAL(pdata, 0x30, file_size);
5648 SIVAL(pdata, 0x38, nlink);
5649 SCVAL(pdata, 0x3C, delete_pending);
5650 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5651 SSVAL(pdata, 0x3E, 0); /* padding */
5652 SBVAL(pdata, 0x40, file_id);
5653 SIVAL(pdata, 0x48, ea_size);
5654 SIVAL(pdata, 0x4C, access_mask);
5655 SBVAL(pdata, 0x50, pos);
5656 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5657 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5661 status = srvstr_push(dstart, flags2,
5663 PTR_DIFF(dend, pdata+4),
5665 if (!NT_STATUS_IS_OK(status)) {
5670 data_size = PTR_DIFF(pdata,(*ppdata));
5671 *fixed_portion = 104;
5674 case SMB_FILE_INTERNAL_INFORMATION:
5676 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5677 SBVAL(pdata, 0, file_id);
5682 case SMB_FILE_ACCESS_INFORMATION:
5683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5684 SIVAL(pdata, 0, access_mask);
5689 case SMB_FILE_NAME_INFORMATION:
5690 /* Pathname with leading '\'. */
5693 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5694 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5695 SIVAL(pdata,0,byte_len);
5696 data_size = 4 + byte_len;
5700 case SMB_FILE_DISPOSITION_INFORMATION:
5701 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5703 SCVAL(pdata,0,delete_pending);
5707 case SMB_FILE_POSITION_INFORMATION:
5708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5710 SOFF_T(pdata,0,pos);
5714 case SMB_FILE_MODE_INFORMATION:
5715 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5716 SIVAL(pdata,0,mode);
5721 case SMB_FILE_ALIGNMENT_INFORMATION:
5722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5723 SIVAL(pdata,0,0); /* No alignment needed. */
5729 * NT4 server just returns "invalid query" to this - if we try
5730 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5733 /* The first statement above is false - verified using Thursby
5734 * client against NT4 -- gcolley.
5736 case SMB_QUERY_FILE_STREAM_INFO:
5737 case SMB_FILE_STREAM_INFORMATION: {
5738 unsigned int num_streams = 0;
5739 struct stream_struct *streams = NULL;
5741 DEBUG(10,("smbd_do_qfilepathinfo: "
5742 "SMB_FILE_STREAM_INFORMATION\n"));
5744 if (is_ntfs_stream_smb_fname(smb_fname)) {
5745 return NT_STATUS_INVALID_PARAMETER;
5748 status = vfs_streaminfo(conn,
5755 if (!NT_STATUS_IS_OK(status)) {
5756 DEBUG(10, ("could not get stream info: %s\n",
5757 nt_errstr(status)));
5761 status = marshall_stream_info(num_streams, streams,
5762 pdata, max_data_bytes,
5765 if (!NT_STATUS_IS_OK(status)) {
5766 DEBUG(10, ("marshall_stream_info failed: %s\n",
5767 nt_errstr(status)));
5768 TALLOC_FREE(streams);
5772 TALLOC_FREE(streams);
5774 *fixed_portion = 32;
5778 case SMB_QUERY_COMPRESSION_INFO:
5779 case SMB_FILE_COMPRESSION_INFORMATION:
5780 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5781 SOFF_T(pdata,0,file_size);
5782 SIVAL(pdata,8,0); /* ??? */
5783 SIVAL(pdata,12,0); /* ??? */
5785 *fixed_portion = 16;
5788 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5789 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5790 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5791 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5792 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5793 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5794 SOFF_T(pdata,32,allocation_size);
5795 SOFF_T(pdata,40,file_size);
5796 SIVAL(pdata,48,mode);
5797 SIVAL(pdata,52,0); /* ??? */
5799 *fixed_portion = 56;
5802 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5803 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5804 SIVAL(pdata,0,mode);
5811 * CIFS UNIX Extensions.
5814 case SMB_QUERY_FILE_UNIX_BASIC:
5816 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5817 data_size = PTR_DIFF(pdata,(*ppdata));
5819 DEBUG(4,("smbd_do_qfilepathinfo: "
5820 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5821 dump_data(4, (uint8_t *)(*ppdata), data_size);
5825 case SMB_QUERY_FILE_UNIX_INFO2:
5827 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5828 data_size = PTR_DIFF(pdata,(*ppdata));
5832 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5834 for (i=0; i<100; i++)
5835 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5841 case SMB_QUERY_FILE_UNIX_LINK:
5844 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5847 return NT_STATUS_NO_MEMORY;
5850 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5852 if(!S_ISLNK(psbuf->st_ex_mode)) {
5853 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5856 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5858 link_len = SMB_VFS_READLINKAT(conn,
5864 if (link_len == -1) {
5865 return map_nt_error_from_unix(errno);
5867 buffer[link_len] = 0;
5868 status = srvstr_push(dstart, flags2,
5870 PTR_DIFF(dend, pdata),
5871 STR_TERMINATE, &len);
5872 if (!NT_STATUS_IS_OK(status)) {
5876 data_size = PTR_DIFF(pdata,(*ppdata));
5881 #if defined(HAVE_POSIX_ACLS)
5882 case SMB_QUERY_POSIX_ACL:
5884 status = smb_query_posix_acl(conn,
5891 if (!NT_STATUS_IS_OK(status)) {
5899 case SMB_QUERY_POSIX_LOCK:
5904 enum brl_type lock_type;
5906 /* We need an open file with a real fd for this. */
5907 if (!fsp || fsp->fh->fd == -1) {
5908 return NT_STATUS_INVALID_LEVEL;
5911 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5912 return NT_STATUS_INVALID_PARAMETER;
5915 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5916 case POSIX_LOCK_TYPE_READ:
5917 lock_type = READ_LOCK;
5919 case POSIX_LOCK_TYPE_WRITE:
5920 lock_type = WRITE_LOCK;
5922 case POSIX_LOCK_TYPE_UNLOCK:
5924 /* There's no point in asking for an unlock... */
5925 return NT_STATUS_INVALID_PARAMETER;
5928 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5929 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5930 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5932 status = query_lock(fsp,
5939 if (ERROR_WAS_LOCK_DENIED(status)) {
5940 /* Here we need to report who has it locked... */
5941 data_size = POSIX_LOCK_DATA_SIZE;
5943 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5944 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5945 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5946 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5947 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5949 } else if (NT_STATUS_IS_OK(status)) {
5950 /* For success we just return a copy of what we sent
5951 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5952 data_size = POSIX_LOCK_DATA_SIZE;
5953 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5954 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5962 return NT_STATUS_INVALID_LEVEL;
5965 *pdata_size = data_size;
5966 return NT_STATUS_OK;
5969 /****************************************************************************
5970 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5971 file name or file id).
5972 ****************************************************************************/
5974 static void call_trans2qfilepathinfo(connection_struct *conn,
5975 struct smb_request *req,
5976 unsigned int tran_call,
5977 char **pparams, int total_params,
5978 char **ppdata, int total_data,
5979 unsigned int max_data_bytes)
5981 char *params = *pparams;
5982 char *pdata = *ppdata;
5983 uint16_t info_level;
5984 unsigned int data_size = 0;
5985 unsigned int param_size = 2;
5986 struct smb_filename *smb_fname = NULL;
5987 bool delete_pending = False;
5988 struct timespec write_time_ts;
5989 files_struct *fsp = NULL;
5990 struct file_id fileid;
5991 struct ea_list *ea_list = NULL;
5992 int lock_data_count = 0;
5993 char *lock_data = NULL;
5994 size_t fixed_portion;
5995 NTSTATUS status = NT_STATUS_OK;
5998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6002 ZERO_STRUCT(write_time_ts);
6004 if (tran_call == TRANSACT2_QFILEINFO) {
6005 if (total_params < 4) {
6006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6011 call_trans2qpipeinfo(conn, req, tran_call,
6012 pparams, total_params,
6018 fsp = file_fsp(req, SVAL(params,0));
6019 info_level = SVAL(params,2);
6021 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6023 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6024 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6028 /* Initial check for valid fsp ptr. */
6029 if (!check_fsp_open(conn, req, fsp)) {
6033 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
6034 if (smb_fname == NULL) {
6035 reply_nterror(req, NT_STATUS_NO_MEMORY);
6039 if(fsp->fake_file_handle) {
6041 * This is actually for the QUOTA_FAKE_FILE --metze
6044 /* We know this name is ok, it's already passed the checks. */
6046 } else if(fsp->fh->fd == -1) {
6048 * This is actually a QFILEINFO on a directory
6049 * handle (returned from an NT SMB). NT5.0 seems
6050 * to do this call. JRA.
6053 if (INFO_LEVEL_IS_UNIX(info_level)) {
6054 /* Always do lstat for UNIX calls. */
6055 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6056 DEBUG(3,("call_trans2qfilepathinfo: "
6057 "SMB_VFS_LSTAT of %s failed "
6059 smb_fname_str_dbg(smb_fname),
6062 map_nt_error_from_unix(errno));
6065 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6066 DEBUG(3,("call_trans2qfilepathinfo: "
6067 "SMB_VFS_STAT of %s failed (%s)\n",
6068 smb_fname_str_dbg(smb_fname),
6071 map_nt_error_from_unix(errno));
6075 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6076 fileid = vfs_file_id_from_sbuf(
6077 conn, &smb_fname->st);
6078 get_file_infos(fileid, fsp->name_hash,
6084 * Original code - this is an open file.
6086 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6087 DEBUG(3, ("fstat of %s failed (%s)\n",
6088 fsp_fnum_dbg(fsp), strerror(errno)));
6090 map_nt_error_from_unix(errno));
6093 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6094 fileid = vfs_file_id_from_sbuf(
6095 conn, &smb_fname->st);
6096 get_file_infos(fileid, fsp->name_hash,
6105 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6108 if (total_params < 7) {
6109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6113 info_level = SVAL(params,0);
6115 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6117 if (INFO_LEVEL_IS_UNIX(info_level)) {
6118 if (!lp_unix_extensions()) {
6119 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6122 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6123 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6124 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6125 req->posix_pathnames) {
6126 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6130 if (req->posix_pathnames) {
6131 srvstr_get_path_posix(req,
6140 srvstr_get_path(req,
6149 if (!NT_STATUS_IS_OK(status)) {
6150 reply_nterror(req, status);
6154 status = filename_convert(req,
6161 if (!NT_STATUS_IS_OK(status)) {
6162 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6163 reply_botherror(req,
6164 NT_STATUS_PATH_NOT_COVERED,
6165 ERRSRV, ERRbadpath);
6168 reply_nterror(req, status);
6172 /* If this is a stream, check if there is a delete_pending. */
6173 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6174 && is_ntfs_stream_smb_fname(smb_fname)) {
6175 struct smb_filename *smb_fname_base;
6177 /* Create an smb_filename with stream_name == NULL. */
6178 smb_fname_base = synthetic_smb_fname(
6180 smb_fname->base_name,
6184 if (smb_fname_base == NULL) {
6185 reply_nterror(req, NT_STATUS_NO_MEMORY);
6189 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6190 /* Always do lstat for UNIX calls. */
6191 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6192 DEBUG(3,("call_trans2qfilepathinfo: "
6193 "SMB_VFS_LSTAT of %s failed "
6195 smb_fname_str_dbg(smb_fname_base),
6197 TALLOC_FREE(smb_fname_base);
6199 map_nt_error_from_unix(errno));
6203 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6204 DEBUG(3,("call_trans2qfilepathinfo: "
6205 "fileinfo of %s failed "
6207 smb_fname_str_dbg(smb_fname_base),
6209 TALLOC_FREE(smb_fname_base);
6211 map_nt_error_from_unix(errno));
6216 status = file_name_hash(conn,
6217 smb_fname_str_dbg(smb_fname_base),
6219 if (!NT_STATUS_IS_OK(status)) {
6220 TALLOC_FREE(smb_fname_base);
6221 reply_nterror(req, status);
6225 fileid = vfs_file_id_from_sbuf(conn,
6226 &smb_fname_base->st);
6227 TALLOC_FREE(smb_fname_base);
6228 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6229 if (delete_pending) {
6230 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6235 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6236 /* Always do lstat for UNIX calls. */
6237 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6238 DEBUG(3,("call_trans2qfilepathinfo: "
6239 "SMB_VFS_LSTAT of %s failed (%s)\n",
6240 smb_fname_str_dbg(smb_fname),
6243 map_nt_error_from_unix(errno));
6248 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6249 DEBUG(3,("call_trans2qfilepathinfo: "
6250 "SMB_VFS_STAT of %s failed (%s)\n",
6251 smb_fname_str_dbg(smb_fname),
6254 map_nt_error_from_unix(errno));
6259 status = file_name_hash(conn,
6260 smb_fname_str_dbg(smb_fname),
6262 if (!NT_STATUS_IS_OK(status)) {
6263 reply_nterror(req, status);
6267 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6268 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6269 get_file_infos(fileid, name_hash, &delete_pending,
6273 if (delete_pending) {
6274 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6279 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6280 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6282 info_level,tran_call,total_data));
6284 /* Pull out any data sent here before we realloc. */
6285 switch (info_level) {
6286 case SMB_INFO_QUERY_EAS_FROM_LIST:
6288 /* Pull any EA list from the data portion. */
6291 if (total_data < 4) {
6293 req, NT_STATUS_INVALID_PARAMETER);
6296 ea_size = IVAL(pdata,0);
6298 if (total_data > 0 && ea_size != total_data) {
6299 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6300 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6302 req, NT_STATUS_INVALID_PARAMETER);
6306 if (!lp_ea_support(SNUM(conn))) {
6307 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6311 /* Pull out the list of names. */
6312 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6315 req, NT_STATUS_INVALID_PARAMETER);
6321 case SMB_QUERY_POSIX_LOCK:
6323 if (fsp == NULL || fsp->fh->fd == -1) {
6324 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6328 if (total_data != POSIX_LOCK_DATA_SIZE) {
6330 req, NT_STATUS_INVALID_PARAMETER);
6334 /* Copy the lock range data. */
6335 lock_data = (char *)talloc_memdup(
6336 req, pdata, total_data);
6338 reply_nterror(req, NT_STATUS_NO_MEMORY);
6341 lock_data_count = total_data;
6347 *pparams = (char *)SMB_REALLOC(*pparams,2);
6348 if (*pparams == NULL) {
6349 reply_nterror(req, NT_STATUS_NO_MEMORY);
6356 * draft-leach-cifs-v1-spec-02.txt
6357 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6360 * The requested information is placed in the Data portion of the
6361 * transaction response. For the information levels greater than 0x100,
6362 * the transaction response has 1 parameter word which should be
6363 * ignored by the client.
6365 * However Windows only follows this rule for the IS_NAME_VALID call.
6367 switch (info_level) {
6368 case SMB_INFO_IS_NAME_VALID:
6373 if ((info_level & 0xFF00) == 0xFF00) {
6375 * We use levels that start with 0xFF00
6376 * internally to represent SMB2 specific levels
6378 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6382 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6384 delete_pending, write_time_ts,
6386 lock_data_count, lock_data,
6387 req->flags2, max_data_bytes,
6389 ppdata, &data_size);
6390 if (!NT_STATUS_IS_OK(status)) {
6391 if (open_was_deferred(req->xconn, req->mid)) {
6392 /* We have re-scheduled this call. */
6395 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6396 bool ok = defer_smb1_sharing_violation(req);
6401 reply_nterror(req, status);
6404 if (fixed_portion > max_data_bytes) {
6405 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6409 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6415 /****************************************************************************
6416 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6418 ****************************************************************************/
6420 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6421 connection_struct *conn,
6422 struct smb_request *req,
6423 bool overwrite_if_exists,
6424 const struct smb_filename *smb_fname_old,
6425 struct smb_filename *smb_fname_new)
6427 NTSTATUS status = NT_STATUS_OK;
6431 /* source must already exist. */
6432 if (!VALID_STAT(smb_fname_old->st)) {
6433 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6436 if (VALID_STAT(smb_fname_new->st)) {
6437 if (overwrite_if_exists) {
6438 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6439 return NT_STATUS_FILE_IS_A_DIRECTORY;
6441 status = unlink_internals(conn,
6443 FILE_ATTRIBUTE_NORMAL,
6446 if (!NT_STATUS_IS_OK(status)) {
6450 /* Disallow if newname already exists. */
6451 return NT_STATUS_OBJECT_NAME_COLLISION;
6455 /* No links from a directory. */
6456 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6457 return NT_STATUS_FILE_IS_A_DIRECTORY;
6460 /* Setting a hardlink to/from a stream isn't currently supported. */
6461 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6463 DBG_DEBUG("Old name has streams\n");
6464 return NT_STATUS_INVALID_PARAMETER;
6466 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6468 DBG_DEBUG("New name has streams\n");
6469 return NT_STATUS_INVALID_PARAMETER;
6472 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6473 smb_fname_old->base_name, smb_fname_new->base_name));
6475 ret = SMB_VFS_LINKAT(conn,
6483 status = map_nt_error_from_unix(errno);
6484 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6485 nt_errstr(status), smb_fname_old->base_name,
6486 smb_fname_new->base_name));
6491 /****************************************************************************
6492 Deal with setting the time from any of the setfilepathinfo functions.
6493 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6494 calling this function.
6495 ****************************************************************************/
6497 NTSTATUS smb_set_file_time(connection_struct *conn,
6499 const struct smb_filename *smb_fname,
6500 struct smb_file_time *ft,
6501 bool setting_write_time)
6503 struct smb_filename smb_fname_base;
6504 struct timeval_buf tbuf[4];
6506 FILE_NOTIFY_CHANGE_LAST_ACCESS
6507 |FILE_NOTIFY_CHANGE_LAST_WRITE
6508 |FILE_NOTIFY_CHANGE_CREATION;
6510 if (!VALID_STAT(smb_fname->st)) {
6511 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6514 /* get some defaults (no modifications) if any info is zero or -1. */
6515 if (is_omit_timespec(&ft->create_time)) {
6516 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6519 if (is_omit_timespec(&ft->atime)) {
6520 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6523 if (is_omit_timespec(&ft->mtime)) {
6524 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6527 if (!setting_write_time) {
6528 /* ft->mtime comes from change time, not write time. */
6529 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6532 /* Ensure the resolution is the correct for
6533 * what we can store on this filesystem. */
6535 round_timespec(conn->ts_res, &ft->create_time);
6536 round_timespec(conn->ts_res, &ft->ctime);
6537 round_timespec(conn->ts_res, &ft->atime);
6538 round_timespec(conn->ts_res, &ft->mtime);
6540 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6541 timespec_string_buf(&ft->atime, true, &tbuf[0]));
6542 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6543 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
6544 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6545 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
6546 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6547 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
6549 if (setting_write_time) {
6551 * This was a Windows setfileinfo on an open file.
6552 * NT does this a lot. We also need to
6553 * set the time here, as it can be read by
6554 * FindFirst/FindNext and with the patch for bug #2045
6555 * in smbd/fileio.c it ensures that this timestamp is
6556 * kept sticky even after a write. We save the request
6557 * away and will set it on file close and after a write. JRA.
6560 DBG_DEBUG("setting pending modtime to %s\n",
6561 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
6564 if (fsp->base_fsp) {
6565 set_sticky_write_time_fsp(fsp->base_fsp,
6568 set_sticky_write_time_fsp(fsp, ft->mtime);
6571 set_sticky_write_time_path(
6572 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6577 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6579 /* Always call ntimes on the base, even if a stream was passed in. */
6580 smb_fname_base = *smb_fname;
6581 smb_fname_base.stream_name = NULL;
6583 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6584 return map_nt_error_from_unix(errno);
6587 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6588 smb_fname->base_name);
6589 return NT_STATUS_OK;
6592 /****************************************************************************
6593 Deal with setting the dosmode from any of the setfilepathinfo functions.
6594 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6595 done before calling this function.
6596 ****************************************************************************/
6598 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6599 const struct smb_filename *smb_fname,
6602 struct smb_filename *smb_fname_base;
6605 if (!VALID_STAT(smb_fname->st)) {
6606 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6609 /* Always operate on the base_name, even if a stream was passed in. */
6610 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6611 smb_fname->base_name,
6615 if (smb_fname_base == NULL) {
6616 return NT_STATUS_NO_MEMORY;
6620 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6621 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6623 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6627 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6629 /* check the mode isn't different, before changing it */
6630 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6631 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6632 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6633 (unsigned int)dosmode));
6635 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6637 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6639 smb_fname_str_dbg(smb_fname_base),
6641 status = map_nt_error_from_unix(errno);
6645 status = NT_STATUS_OK;
6647 TALLOC_FREE(smb_fname_base);
6651 /****************************************************************************
6652 Deal with setting the size from any of the setfilepathinfo functions.
6653 ****************************************************************************/
6655 static NTSTATUS smb_set_file_size(connection_struct *conn,
6656 struct smb_request *req,
6658 const struct smb_filename *smb_fname,
6659 const SMB_STRUCT_STAT *psbuf,
6661 bool fail_after_createfile)
6663 NTSTATUS status = NT_STATUS_OK;
6664 struct smb_filename *smb_fname_tmp = NULL;
6665 files_struct *new_fsp = NULL;
6667 if (!VALID_STAT(*psbuf)) {
6668 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6671 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6673 get_file_size_stat(psbuf));
6675 if (size == get_file_size_stat(psbuf)) {
6676 return NT_STATUS_OK;
6679 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6680 smb_fname_str_dbg(smb_fname), (double)size));
6682 if (fsp && fsp->fh->fd != -1) {
6683 /* Handle based call. */
6684 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6685 return NT_STATUS_ACCESS_DENIED;
6688 if (vfs_set_filelen(fsp, size) == -1) {
6689 return map_nt_error_from_unix(errno);
6691 trigger_write_time_update_immediate(fsp);
6692 return NT_STATUS_OK;
6695 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6696 if (smb_fname_tmp == NULL) {
6697 return NT_STATUS_NO_MEMORY;
6700 smb_fname_tmp->st = *psbuf;
6702 status = SMB_VFS_CREATE_FILE(
6705 0, /* root_dir_fid */
6706 smb_fname_tmp, /* fname */
6707 FILE_WRITE_DATA, /* access_mask */
6708 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6710 FILE_OPEN, /* create_disposition*/
6711 0, /* create_options */
6712 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6713 0, /* oplock_request */
6715 0, /* allocation_size */
6716 0, /* private_flags */
6719 &new_fsp, /* result */
6721 NULL, NULL); /* create context */
6723 TALLOC_FREE(smb_fname_tmp);
6725 if (!NT_STATUS_IS_OK(status)) {
6726 /* NB. We check for open_was_deferred in the caller. */
6730 /* See RAW-SFILEINFO-END-OF-FILE */
6731 if (fail_after_createfile) {
6732 close_file(req, new_fsp,NORMAL_CLOSE);
6733 return NT_STATUS_INVALID_LEVEL;
6736 if (vfs_set_filelen(new_fsp, size) == -1) {
6737 status = map_nt_error_from_unix(errno);
6738 close_file(req, new_fsp,NORMAL_CLOSE);
6742 trigger_write_time_update_immediate(new_fsp);
6743 close_file(req, new_fsp,NORMAL_CLOSE);
6744 return NT_STATUS_OK;
6747 /****************************************************************************
6748 Deal with SMB_INFO_SET_EA.
6749 ****************************************************************************/
6751 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6755 const struct smb_filename *smb_fname)
6757 struct ea_list *ea_list = NULL;
6758 TALLOC_CTX *ctx = NULL;
6759 NTSTATUS status = NT_STATUS_OK;
6761 if (total_data < 10) {
6763 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6764 length. They seem to have no effect. Bug #3212. JRA */
6766 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6767 /* We're done. We only get EA info in this call. */
6768 return NT_STATUS_OK;
6771 return NT_STATUS_INVALID_PARAMETER;
6774 if (IVAL(pdata,0) > total_data) {
6775 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6776 IVAL(pdata,0), (unsigned int)total_data));
6777 return NT_STATUS_INVALID_PARAMETER;
6781 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6783 return NT_STATUS_INVALID_PARAMETER;
6786 status = set_ea(conn, fsp, smb_fname, ea_list);
6791 /****************************************************************************
6792 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6793 ****************************************************************************/
6795 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6800 struct ea_list *ea_list = NULL;
6804 return NT_STATUS_INVALID_HANDLE;
6807 if (!lp_ea_support(SNUM(conn))) {
6808 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6809 "EA's not supported.\n",
6810 (unsigned int)total_data));
6811 return NT_STATUS_EAS_NOT_SUPPORTED;
6814 if (total_data < 10) {
6815 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6817 (unsigned int)total_data));
6818 return NT_STATUS_INVALID_PARAMETER;
6821 ea_list = read_nttrans_ea_list(talloc_tos(),
6826 return NT_STATUS_INVALID_PARAMETER;
6829 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6831 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6832 smb_fname_str_dbg(fsp->fsp_name),
6833 nt_errstr(status) ));
6839 /****************************************************************************
6840 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6841 ****************************************************************************/
6843 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6847 struct smb_filename *smb_fname)
6849 NTSTATUS status = NT_STATUS_OK;
6850 bool delete_on_close;
6851 uint32_t dosmode = 0;
6853 if (total_data < 1) {
6854 return NT_STATUS_INVALID_PARAMETER;
6858 return NT_STATUS_INVALID_HANDLE;
6861 delete_on_close = (CVAL(pdata,0) ? True : False);
6862 dosmode = dos_mode(conn, smb_fname);
6864 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6865 "delete_on_close = %u\n",
6866 smb_fname_str_dbg(smb_fname),
6867 (unsigned int)dosmode,
6868 (unsigned int)delete_on_close ));
6870 if (delete_on_close) {
6871 status = can_set_delete_on_close(fsp, dosmode);
6872 if (!NT_STATUS_IS_OK(status)) {
6877 /* The set is across all open files on this dev/inode pair. */
6878 if (!set_delete_on_close(fsp, delete_on_close,
6879 conn->session_info->security_token,
6880 conn->session_info->unix_token)) {
6881 return NT_STATUS_ACCESS_DENIED;
6883 return NT_STATUS_OK;
6886 /****************************************************************************
6887 Deal with SMB_FILE_POSITION_INFORMATION.
6888 ****************************************************************************/
6890 static NTSTATUS smb_file_position_information(connection_struct *conn,
6895 uint64_t position_information;
6897 if (total_data < 8) {
6898 return NT_STATUS_INVALID_PARAMETER;
6902 /* Ignore on pathname based set. */
6903 return NT_STATUS_OK;
6906 position_information = (uint64_t)IVAL(pdata,0);
6907 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6909 DEBUG(10,("smb_file_position_information: Set file position "
6910 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6911 (double)position_information));
6912 fsp->fh->position_information = position_information;
6913 return NT_STATUS_OK;
6916 /****************************************************************************
6917 Deal with SMB_FILE_MODE_INFORMATION.
6918 ****************************************************************************/
6920 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6926 if (total_data < 4) {
6927 return NT_STATUS_INVALID_PARAMETER;
6929 mode = IVAL(pdata,0);
6930 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6931 return NT_STATUS_INVALID_PARAMETER;
6933 return NT_STATUS_OK;
6936 /****************************************************************************
6937 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6938 ****************************************************************************/
6940 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6941 struct smb_request *req,
6944 const struct smb_filename *new_smb_fname)
6946 char *link_target = NULL;
6947 TALLOC_CTX *ctx = talloc_tos();
6950 /* Set a symbolic link. */
6951 /* Don't allow this if follow links is false. */
6953 if (total_data == 0) {
6954 return NT_STATUS_INVALID_PARAMETER;
6957 if (!lp_follow_symlinks(SNUM(conn))) {
6958 return NT_STATUS_ACCESS_DENIED;
6961 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6962 total_data, STR_TERMINATE);
6965 return NT_STATUS_INVALID_PARAMETER;
6968 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6969 new_smb_fname->base_name, link_target ));
6971 ret = SMB_VFS_SYMLINKAT(conn,
6976 return map_nt_error_from_unix(errno);
6979 return NT_STATUS_OK;
6982 /****************************************************************************
6983 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6984 ****************************************************************************/
6986 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6987 struct smb_request *req,
6988 const char *pdata, int total_data,
6989 struct smb_filename *smb_fname_new)
6991 char *oldname = NULL;
6992 struct smb_filename *smb_fname_old = NULL;
6993 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6994 TALLOC_CTX *ctx = talloc_tos();
6995 NTSTATUS status = NT_STATUS_OK;
6997 /* Set a hard link. */
6998 if (total_data == 0) {
6999 return NT_STATUS_INVALID_PARAMETER;
7002 if (req->posix_pathnames) {
7003 srvstr_get_path_posix(ctx,
7012 srvstr_get_path(ctx,
7021 if (!NT_STATUS_IS_OK(status)) {
7025 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7026 smb_fname_str_dbg(smb_fname_new), oldname));
7028 status = filename_convert(ctx,
7035 if (!NT_STATUS_IS_OK(status)) {
7039 return hardlink_internals(ctx, conn, req, false,
7040 smb_fname_old, smb_fname_new);
7043 /****************************************************************************
7044 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7045 ****************************************************************************/
7047 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7048 struct smb_request *req,
7052 struct smb_filename *smb_fname_src)
7056 char *newname = NULL;
7057 struct smb_filename *smb_fname_dst = NULL;
7058 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7059 ucf_flags_from_smb_request(req);
7060 NTSTATUS status = NT_STATUS_OK;
7061 TALLOC_CTX *ctx = talloc_tos();
7064 return NT_STATUS_INVALID_HANDLE;
7067 if (total_data < 20) {
7068 return NT_STATUS_INVALID_PARAMETER;
7071 overwrite = (CVAL(pdata,0) ? True : False);
7072 len = IVAL(pdata,16);
7074 if (len > (total_data - 20) || (len == 0)) {
7075 return NT_STATUS_INVALID_PARAMETER;
7078 if (req->posix_pathnames) {
7079 srvstr_get_path_posix(ctx,
7088 srvstr_get_path(ctx,
7097 if (!NT_STATUS_IS_OK(status)) {
7101 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7104 status = filename_convert(ctx,
7111 if (!NT_STATUS_IS_OK(status)) {
7115 if (fsp->base_fsp) {
7116 /* newname must be a stream name. */
7117 if (newname[0] != ':') {
7118 return NT_STATUS_NOT_SUPPORTED;
7121 /* Create an smb_fname to call rename_internals_fsp() with. */
7122 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7123 fsp->base_fsp->fsp_name->base_name,
7126 fsp->base_fsp->fsp_name->flags);
7127 if (smb_fname_dst == NULL) {
7128 status = NT_STATUS_NO_MEMORY;
7133 * Set the original last component, since
7134 * rename_internals_fsp() requires it.
7136 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7138 if (smb_fname_dst->original_lcomp == NULL) {
7139 status = NT_STATUS_NO_MEMORY;
7145 DEBUG(10,("smb2_file_rename_information: "
7146 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7147 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7148 smb_fname_str_dbg(smb_fname_dst)));
7149 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7150 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7154 TALLOC_FREE(smb_fname_dst);
7158 static NTSTATUS smb_file_link_information(connection_struct *conn,
7159 struct smb_request *req,
7163 struct smb_filename *smb_fname_src)
7167 char *newname = NULL;
7168 struct smb_filename *smb_fname_dst = NULL;
7169 NTSTATUS status = NT_STATUS_OK;
7170 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7171 ucf_flags_from_smb_request(req);
7172 TALLOC_CTX *ctx = talloc_tos();
7175 return NT_STATUS_INVALID_HANDLE;
7178 if (total_data < 20) {
7179 return NT_STATUS_INVALID_PARAMETER;
7182 overwrite = (CVAL(pdata,0) ? true : false);
7183 len = IVAL(pdata,16);
7185 if (len > (total_data - 20) || (len == 0)) {
7186 return NT_STATUS_INVALID_PARAMETER;
7189 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7190 srvstr_get_path_posix(ctx,
7198 ucf_flags |= UCF_POSIX_PATHNAMES;
7200 srvstr_get_path(ctx,
7209 if (!NT_STATUS_IS_OK(status)) {
7213 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7216 status = filename_convert(ctx,
7223 if (!NT_STATUS_IS_OK(status)) {
7227 if (fsp->base_fsp) {
7228 /* No stream names. */
7229 return NT_STATUS_NOT_SUPPORTED;
7232 DEBUG(10,("smb_file_link_information: "
7233 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7234 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7235 smb_fname_str_dbg(smb_fname_dst)));
7236 status = hardlink_internals(ctx,
7243 TALLOC_FREE(smb_fname_dst);
7247 /****************************************************************************
7248 Deal with SMB_FILE_RENAME_INFORMATION.
7249 ****************************************************************************/
7251 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7252 struct smb_request *req,
7256 struct smb_filename *smb_fname_src)
7261 char *newname = NULL;
7262 struct smb_filename *smb_fname_dst = NULL;
7263 bool dest_has_wcard = False;
7264 NTSTATUS status = NT_STATUS_OK;
7266 TALLOC_CTX *ctx = talloc_tos();
7268 if (total_data < 13) {
7269 return NT_STATUS_INVALID_PARAMETER;
7272 overwrite = (CVAL(pdata,0) ? True : False);
7273 root_fid = IVAL(pdata,4);
7274 len = IVAL(pdata,8);
7276 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7277 return NT_STATUS_INVALID_PARAMETER;
7280 if (req->posix_pathnames) {
7281 srvstr_get_path_wcard_posix(ctx,
7291 srvstr_get_path_wcard(ctx,
7301 if (!NT_STATUS_IS_OK(status)) {
7305 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7308 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7309 status = resolve_dfspath_wcard(ctx, conn,
7311 UCF_COND_ALLOW_WCARD_LCOMP,
7312 !conn->sconn->using_smb2,
7315 if (!NT_STATUS_IS_OK(status)) {
7320 /* Check the new name has no '/' characters. */
7321 if (strchr_m(newname, '/')) {
7322 return NT_STATUS_NOT_SUPPORTED;
7325 if (fsp && fsp->base_fsp) {
7326 /* newname must be a stream name. */
7327 if (newname[0] != ':') {
7328 return NT_STATUS_NOT_SUPPORTED;
7331 /* Create an smb_fname to call rename_internals_fsp() with. */
7332 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7333 fsp->base_fsp->fsp_name->base_name,
7336 fsp->base_fsp->fsp_name->flags);
7337 if (smb_fname_dst == NULL) {
7338 status = NT_STATUS_NO_MEMORY;
7343 * Set the original last component, since
7344 * rename_internals_fsp() requires it.
7346 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7348 if (smb_fname_dst->original_lcomp == NULL) {
7349 status = NT_STATUS_NO_MEMORY;
7355 * Build up an smb_fname_dst based on the filename passed in.
7356 * We basically just strip off the last component, and put on
7357 * the newname instead.
7359 char *base_name = NULL;
7360 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7361 ucf_flags_from_smb_request(req);
7363 if (dest_has_wcard) {
7364 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7367 /* newname must *not* be a stream name. */
7368 if (newname[0] == ':') {
7369 return NT_STATUS_NOT_SUPPORTED;
7373 * Strip off the last component (filename) of the path passed
7376 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7378 return NT_STATUS_NO_MEMORY;
7380 p = strrchr_m(base_name, '/');
7384 base_name = talloc_strdup(ctx, "");
7386 return NT_STATUS_NO_MEMORY;
7389 /* Append the new name. */
7390 base_name = talloc_asprintf_append(base_name,
7394 return NT_STATUS_NO_MEMORY;
7397 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7400 /* If an error we expect this to be
7401 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7403 if (!NT_STATUS_IS_OK(status)) {
7404 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7408 /* Create an smb_fname to call rename_internals_fsp() */
7409 smb_fname_dst = synthetic_smb_fname(ctx,
7413 smb_fname_src->flags);
7414 if (smb_fname_dst == NULL) {
7415 status = NT_STATUS_NO_MEMORY;
7422 DEBUG(10,("smb_file_rename_information: "
7423 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7424 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7425 smb_fname_str_dbg(smb_fname_dst)));
7426 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7429 DEBUG(10,("smb_file_rename_information: "
7430 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7431 smb_fname_str_dbg(smb_fname_src),
7432 smb_fname_str_dbg(smb_fname_dst)));
7433 status = rename_internals(ctx, conn, req, smb_fname_src,
7434 smb_fname_dst, 0, overwrite, false,
7436 FILE_WRITE_ATTRIBUTES);
7439 TALLOC_FREE(smb_fname_dst);
7443 /****************************************************************************
7444 Deal with SMB_SET_POSIX_ACL.
7445 ****************************************************************************/
7447 #if defined(HAVE_POSIX_ACLS)
7448 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7449 struct smb_request *req,
7453 const struct smb_filename *smb_fname)
7455 uint16_t posix_acl_version;
7456 uint16_t num_file_acls;
7457 uint16_t num_def_acls;
7458 bool valid_file_acls = true;
7459 bool valid_def_acls = true;
7461 unsigned int size_needed;
7462 unsigned int total_data;
7463 bool close_fsp = false;
7465 if (total_data_in < 0) {
7466 status = NT_STATUS_INVALID_PARAMETER;
7470 total_data = total_data_in;
7472 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7473 status = NT_STATUS_INVALID_PARAMETER;
7476 posix_acl_version = SVAL(pdata,0);
7477 num_file_acls = SVAL(pdata,2);
7478 num_def_acls = SVAL(pdata,4);
7480 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7481 valid_file_acls = false;
7485 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7486 valid_def_acls = false;
7490 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7491 status = NT_STATUS_INVALID_PARAMETER;
7496 if (num_file_acls + num_def_acls < num_file_acls) {
7497 status = NT_STATUS_INVALID_PARAMETER;
7501 size_needed = num_file_acls + num_def_acls;
7504 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7505 * than UINT_MAX, so check by division.
7507 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7508 status = NT_STATUS_INVALID_PARAMETER;
7512 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7513 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7514 status = NT_STATUS_INVALID_PARAMETER;
7517 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7519 if (total_data < size_needed) {
7520 status = NT_STATUS_INVALID_PARAMETER;
7525 * Ensure we always operate on a file descriptor, not just
7529 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7531 SEC_STD_READ_CONTROL|
7532 FILE_READ_ATTRIBUTES|
7533 FILE_WRITE_ATTRIBUTES;
7535 status = get_posix_fsp(conn,
7541 if (!NT_STATUS_IS_OK(status)) {
7547 /* Here we know fsp != NULL */
7548 SMB_ASSERT(fsp != NULL);
7550 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7551 if (!NT_STATUS_IS_OK(status)) {
7555 /* If we have a default acl, this *must* be a directory. */
7556 if (valid_def_acls && !fsp->is_directory) {
7557 DBG_INFO("Can't set default acls on "
7558 "non-directory %s\n",
7560 return NT_STATUS_INVALID_HANDLE;
7563 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7564 "num_def_acls = %"PRIu16"\n",
7569 /* Move pdata to the start of the file ACL entries. */
7570 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7572 if (valid_file_acls) {
7573 status = set_unix_posix_acl(conn,
7577 if (!NT_STATUS_IS_OK(status)) {
7582 /* Move pdata to the start of the default ACL entries. */
7583 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7585 if (valid_def_acls) {
7586 status = set_unix_posix_default_acl(conn,
7590 if (!NT_STATUS_IS_OK(status)) {
7595 status = NT_STATUS_OK;
7600 (void)close_file(req, fsp, NORMAL_CLOSE);
7607 /****************************************************************************
7608 Deal with SMB_SET_POSIX_LOCK.
7609 ****************************************************************************/
7611 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7613 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7614 struct smb_request *req,
7619 struct tevent_req *subreq = NULL;
7620 struct smbd_lock_element *lck = NULL;
7624 bool blocking_lock = False;
7625 enum brl_type lock_type;
7627 NTSTATUS status = NT_STATUS_OK;
7629 if (fsp == NULL || fsp->fh->fd == -1) {
7630 return NT_STATUS_INVALID_HANDLE;
7633 if (total_data != POSIX_LOCK_DATA_SIZE) {
7634 return NT_STATUS_INVALID_PARAMETER;
7637 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7638 case POSIX_LOCK_TYPE_READ:
7639 lock_type = READ_LOCK;
7641 case POSIX_LOCK_TYPE_WRITE:
7642 /* Return the right POSIX-mappable error code for files opened read-only. */
7643 if (!fsp->can_write) {
7644 return NT_STATUS_INVALID_HANDLE;
7646 lock_type = WRITE_LOCK;
7648 case POSIX_LOCK_TYPE_UNLOCK:
7649 lock_type = UNLOCK_LOCK;
7652 return NT_STATUS_INVALID_PARAMETER;
7655 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7656 case POSIX_LOCK_FLAG_NOWAIT:
7657 blocking_lock = false;
7659 case POSIX_LOCK_FLAG_WAIT:
7660 blocking_lock = true;
7663 return NT_STATUS_INVALID_PARAMETER;
7666 if (!lp_blocking_locks(SNUM(conn))) {
7667 blocking_lock = False;
7670 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7671 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7672 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7673 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7674 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7676 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7677 "count = %"PRIu64", offset = %"PRIu64"\n",
7679 (unsigned int)lock_type,
7684 if (lock_type == UNLOCK_LOCK) {
7685 struct smbd_lock_element l = {
7686 .req_guid = smbd_request_guid(req, 0),
7688 .brltype = UNLOCK_LOCK,
7692 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7696 lck = talloc(req, struct smbd_lock_element);
7698 return NT_STATUS_NO_MEMORY;
7701 *lck = (struct smbd_lock_element) {
7702 .req_guid = smbd_request_guid(req, 0),
7704 .brltype = lock_type,
7709 subreq = smbd_smb1_do_locks_send(
7714 blocking_lock ? UINT32_MAX : 0,
7715 true, /* large_offset */
7719 if (subreq == NULL) {
7721 return NT_STATUS_NO_MEMORY;
7723 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7724 return NT_STATUS_EVENT_PENDING;
7727 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7729 struct smb_request *req = NULL;
7733 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7736 status = smbd_smb1_do_locks_recv(subreq);
7737 TALLOC_FREE(subreq);
7739 if (NT_STATUS_IS_OK(status)) {
7740 char params[2] = {0};
7741 /* Fake up max_data_bytes here - we know it fits. */
7742 send_trans2_replies(
7752 reply_nterror(req, status);
7755 (char *)req->outbuf,
7758 IS_CONN_ENCRYPTED(req->conn),
7761 exit_server_cleanly("smb_set_posix_lock_done: "
7762 "srv_send_smb failed.");
7770 /****************************************************************************
7771 Deal with SMB_SET_FILE_BASIC_INFO.
7772 ****************************************************************************/
7774 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7778 const struct smb_filename *smb_fname)
7780 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7781 struct smb_file_time ft;
7782 uint32_t dosmode = 0;
7783 NTSTATUS status = NT_STATUS_OK;
7785 init_smb_file_time(&ft);
7787 if (total_data < 36) {
7788 return NT_STATUS_INVALID_PARAMETER;
7791 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7792 if (!NT_STATUS_IS_OK(status)) {
7796 /* Set the attributes */
7797 dosmode = IVAL(pdata,32);
7798 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7799 if (!NT_STATUS_IS_OK(status)) {
7804 ft.create_time = pull_long_date_full_timespec(pdata);
7807 ft.atime = pull_long_date_full_timespec(pdata+8);
7810 ft.mtime = pull_long_date_full_timespec(pdata+16);
7813 ft.ctime = pull_long_date_full_timespec(pdata+24);
7815 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7816 smb_fname_str_dbg(smb_fname)));
7818 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7822 /****************************************************************************
7823 Deal with SMB_INFO_STANDARD.
7824 ****************************************************************************/
7826 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7830 const struct smb_filename *smb_fname)
7833 struct smb_file_time ft;
7835 init_smb_file_time(&ft);
7837 if (total_data < 12) {
7838 return NT_STATUS_INVALID_PARAMETER;
7842 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
7844 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
7846 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
7848 DEBUG(10,("smb_set_info_standard: file %s\n",
7849 smb_fname_str_dbg(smb_fname)));
7851 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7852 if (!NT_STATUS_IS_OK(status)) {
7856 return smb_set_file_time(conn,
7863 /****************************************************************************
7864 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7865 ****************************************************************************/
7867 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7868 struct smb_request *req,
7872 struct smb_filename *smb_fname)
7874 uint64_t allocation_size = 0;
7875 NTSTATUS status = NT_STATUS_OK;
7876 files_struct *new_fsp = NULL;
7878 if (!VALID_STAT(smb_fname->st)) {
7879 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7882 if (total_data < 8) {
7883 return NT_STATUS_INVALID_PARAMETER;
7886 allocation_size = (uint64_t)IVAL(pdata,0);
7887 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7888 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7889 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7890 (double)allocation_size));
7892 if (allocation_size) {
7893 allocation_size = smb_roundup(conn, allocation_size);
7896 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7897 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7898 (double)allocation_size));
7900 if (fsp && fsp->fh->fd != -1) {
7901 /* Open file handle. */
7902 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7903 return NT_STATUS_ACCESS_DENIED;
7906 /* Only change if needed. */
7907 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7908 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7909 return map_nt_error_from_unix(errno);
7912 /* But always update the time. */
7914 * This is equivalent to a write. Ensure it's seen immediately
7915 * if there are no pending writes.
7917 trigger_write_time_update_immediate(fsp);
7918 return NT_STATUS_OK;
7921 /* Pathname or stat or directory file. */
7922 status = SMB_VFS_CREATE_FILE(
7925 0, /* root_dir_fid */
7926 smb_fname, /* fname */
7927 FILE_WRITE_DATA, /* access_mask */
7928 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7930 FILE_OPEN, /* create_disposition*/
7931 0, /* create_options */
7932 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7933 0, /* oplock_request */
7935 0, /* allocation_size */
7936 0, /* private_flags */
7939 &new_fsp, /* result */
7941 NULL, NULL); /* create context */
7943 if (!NT_STATUS_IS_OK(status)) {
7944 /* NB. We check for open_was_deferred in the caller. */
7948 /* Only change if needed. */
7949 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7950 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7951 status = map_nt_error_from_unix(errno);
7952 close_file(req, new_fsp, NORMAL_CLOSE);
7957 /* Changing the allocation size should set the last mod time. */
7959 * This is equivalent to a write. Ensure it's seen immediately
7960 * if there are no pending writes.
7962 trigger_write_time_update_immediate(new_fsp);
7963 close_file(req, new_fsp, NORMAL_CLOSE);
7964 return NT_STATUS_OK;
7967 /****************************************************************************
7968 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7969 ****************************************************************************/
7971 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7972 struct smb_request *req,
7976 const struct smb_filename *smb_fname,
7977 bool fail_after_createfile)
7981 if (total_data < 8) {
7982 return NT_STATUS_INVALID_PARAMETER;
7985 size = IVAL(pdata,0);
7986 size |= (((off_t)IVAL(pdata,4)) << 32);
7987 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7988 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7991 return smb_set_file_size(conn, req,
7996 fail_after_createfile);
7999 /****************************************************************************
8000 Allow a UNIX info mknod.
8001 ****************************************************************************/
8003 static NTSTATUS smb_unix_mknod(connection_struct *conn,
8006 const struct smb_filename *smb_fname)
8008 uint32_t file_type = IVAL(pdata,56);
8009 #if defined(HAVE_MAKEDEV)
8010 uint32_t dev_major = IVAL(pdata,60);
8011 uint32_t dev_minor = IVAL(pdata,68);
8013 SMB_DEV_T dev = (SMB_DEV_T)0;
8014 uint32_t raw_unixmode = IVAL(pdata,84);
8019 if (total_data < 100) {
8020 return NT_STATUS_INVALID_PARAMETER;
8023 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8024 PERM_NEW_FILE, &unixmode);
8025 if (!NT_STATUS_IS_OK(status)) {
8029 #if defined(HAVE_MAKEDEV)
8030 dev = makedev(dev_major, dev_minor);
8033 switch (file_type) {
8034 /* We can't create other objects here. */
8035 case UNIX_TYPE_FILE:
8037 case UNIX_TYPE_SYMLINK:
8038 return NT_STATUS_ACCESS_DENIED;
8039 #if defined(S_IFIFO)
8040 case UNIX_TYPE_FIFO:
8041 unixmode |= S_IFIFO;
8044 #if defined(S_IFSOCK)
8045 case UNIX_TYPE_SOCKET:
8046 unixmode |= S_IFSOCK;
8049 #if defined(S_IFCHR)
8050 case UNIX_TYPE_CHARDEV:
8051 /* This is only allowed for root. */
8052 if (get_current_uid(conn) != sec_initial_uid()) {
8053 return NT_STATUS_ACCESS_DENIED;
8055 unixmode |= S_IFCHR;
8058 #if defined(S_IFBLK)
8059 case UNIX_TYPE_BLKDEV:
8060 if (get_current_uid(conn) != sec_initial_uid()) {
8061 return NT_STATUS_ACCESS_DENIED;
8063 unixmode |= S_IFBLK;
8067 return NT_STATUS_INVALID_PARAMETER;
8070 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8071 "%.0f mode 0%o for file %s\n", (double)dev,
8072 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8074 /* Ok - do the mknod. */
8075 ret = SMB_VFS_MKNODAT(conn,
8082 return map_nt_error_from_unix(errno);
8085 /* If any of the other "set" calls fail we
8086 * don't want to end up with a half-constructed mknod.
8089 if (lp_inherit_permissions(SNUM(conn))) {
8091 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
8093 return NT_STATUS_NO_MEMORY;
8095 inherit_access_posix_acl(conn, parent, smb_fname,
8097 TALLOC_FREE(parent);
8100 return NT_STATUS_OK;
8103 /****************************************************************************
8104 Deal with SMB_SET_FILE_UNIX_BASIC.
8105 ****************************************************************************/
8107 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8108 struct smb_request *req,
8112 const struct smb_filename *smb_fname)
8114 struct smb_file_time ft;
8115 uint32_t raw_unixmode;
8118 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8119 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8120 NTSTATUS status = NT_STATUS_OK;
8121 enum perm_type ptype;
8122 files_struct *all_fsps = NULL;
8123 bool modify_mtime = true;
8125 SMB_STRUCT_STAT sbuf;
8127 init_smb_file_time(&ft);
8129 if (total_data < 100) {
8130 return NT_STATUS_INVALID_PARAMETER;
8133 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8134 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8135 size=IVAL(pdata,0); /* first 8 Bytes are size */
8136 size |= (((off_t)IVAL(pdata,4)) << 32);
8139 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
8140 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
8141 set_owner = (uid_t)IVAL(pdata,40);
8142 set_grp = (gid_t)IVAL(pdata,48);
8143 raw_unixmode = IVAL(pdata,84);
8145 if (VALID_STAT(smb_fname->st)) {
8146 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8147 ptype = PERM_EXISTING_DIR;
8149 ptype = PERM_EXISTING_FILE;
8152 ptype = PERM_NEW_FILE;
8155 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8157 if (!NT_STATUS_IS_OK(status)) {
8161 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8162 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8163 smb_fname_str_dbg(smb_fname), (double)size,
8164 (unsigned int)set_owner, (unsigned int)set_grp,
8165 (int)raw_unixmode));
8167 sbuf = smb_fname->st;
8169 if (!VALID_STAT(sbuf)) {
8171 * The only valid use of this is to create character and block
8172 * devices, and named pipes. This is deprecated (IMHO) and
8173 * a new info level should be used for mknod. JRA.
8176 return smb_unix_mknod(conn,
8183 /* Horrible backwards compatibility hack as an old server bug
8184 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8188 size = get_file_size_stat(&sbuf);
8193 * Deal with the UNIX specific mode set.
8196 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8199 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8200 "setting mode 0%o for file %s\n",
8201 (unsigned int)unixmode,
8202 smb_fname_str_dbg(smb_fname)));
8203 if (fsp && fsp->fh->fd != -1) {
8204 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8206 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8209 return map_nt_error_from_unix(errno);
8214 * Deal with the UNIX specific uid set.
8217 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8218 (sbuf.st_ex_uid != set_owner)) {
8221 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8222 "changing owner %u for path %s\n",
8223 (unsigned int)set_owner,
8224 smb_fname_str_dbg(smb_fname)));
8226 if (fsp && fsp->fh->fd != -1) {
8227 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8230 * UNIX extensions calls must always operate
8233 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8234 set_owner, (gid_t)-1);
8238 status = map_nt_error_from_unix(errno);
8244 * Deal with the UNIX specific gid set.
8247 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8248 (sbuf.st_ex_gid != set_grp)) {
8251 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8252 "changing group %u for file %s\n",
8253 (unsigned int)set_grp,
8254 smb_fname_str_dbg(smb_fname)));
8255 if (fsp && fsp->fh->fd != -1) {
8256 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8259 * UNIX extensions calls must always operate
8262 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8266 status = map_nt_error_from_unix(errno);
8271 /* Deal with any size changes. */
8273 if (S_ISREG(sbuf.st_ex_mode)) {
8274 status = smb_set_file_size(conn, req,
8280 if (!NT_STATUS_IS_OK(status)) {
8285 /* Deal with any time changes. */
8286 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
8287 /* No change, don't cancel anything. */
8291 id = vfs_file_id_from_sbuf(conn, &sbuf);
8292 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8293 all_fsps = file_find_di_next(all_fsps)) {
8295 * We're setting the time explicitly for UNIX.
8296 * Cancel any pending changes over all handles.
8298 all_fsps->update_write_time_on_close = false;
8299 TALLOC_FREE(all_fsps->update_write_time_event);
8303 * Override the "setting_write_time"
8304 * parameter here as it almost does what
8305 * we need. Just remember if we modified
8306 * mtime and send the notify ourselves.
8308 if (is_omit_timespec(&ft.mtime)) {
8309 modify_mtime = false;
8312 status = smb_set_file_time(conn,
8318 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8319 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8324 /****************************************************************************
8325 Deal with SMB_SET_FILE_UNIX_INFO2.
8326 ****************************************************************************/
8328 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8329 struct smb_request *req,
8333 const struct smb_filename *smb_fname)
8336 uint32_t smb_fflags;
8339 if (total_data < 116) {
8340 return NT_STATUS_INVALID_PARAMETER;
8343 /* Start by setting all the fields that are common between UNIX_BASIC
8346 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8348 if (!NT_STATUS_IS_OK(status)) {
8352 smb_fflags = IVAL(pdata, 108);
8353 smb_fmask = IVAL(pdata, 112);
8355 /* NB: We should only attempt to alter the file flags if the client
8356 * sends a non-zero mask.
8358 if (smb_fmask != 0) {
8359 int stat_fflags = 0;
8361 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8362 smb_fmask, &stat_fflags)) {
8363 /* Client asked to alter a flag we don't understand. */
8364 return NT_STATUS_INVALID_PARAMETER;
8367 if (fsp && fsp->fh->fd != -1) {
8368 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8369 return NT_STATUS_NOT_SUPPORTED;
8371 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8372 stat_fflags) != 0) {
8373 return map_nt_error_from_unix(errno);
8378 /* XXX: need to add support for changing the create_time here. You
8379 * can do this for paths on Darwin with setattrlist(2). The right way
8380 * to hook this up is probably by extending the VFS utimes interface.
8383 return NT_STATUS_OK;
8386 /****************************************************************************
8387 Create a directory with POSIX semantics.
8388 ****************************************************************************/
8390 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8391 struct smb_request *req,
8394 struct smb_filename *smb_fname,
8395 int *pdata_return_size)
8397 NTSTATUS status = NT_STATUS_OK;
8398 uint32_t raw_unixmode = 0;
8399 uint32_t mod_unixmode = 0;
8400 mode_t unixmode = (mode_t)0;
8401 files_struct *fsp = NULL;
8402 uint16_t info_level_return = 0;
8404 char *pdata = *ppdata;
8406 if (total_data < 18) {
8407 return NT_STATUS_INVALID_PARAMETER;
8410 raw_unixmode = IVAL(pdata,8);
8411 /* Next 4 bytes are not yet defined. */
8413 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8414 PERM_NEW_DIR, &unixmode);
8415 if (!NT_STATUS_IS_OK(status)) {
8419 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8421 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8422 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8424 status = SMB_VFS_CREATE_FILE(
8427 0, /* root_dir_fid */
8428 smb_fname, /* fname */
8429 FILE_READ_ATTRIBUTES, /* access_mask */
8430 FILE_SHARE_NONE, /* share_access */
8431 FILE_CREATE, /* create_disposition*/
8432 FILE_DIRECTORY_FILE, /* create_options */
8433 mod_unixmode, /* file_attributes */
8434 0, /* oplock_request */
8436 0, /* allocation_size */
8437 0, /* private_flags */
8442 NULL, NULL); /* create context */
8444 if (NT_STATUS_IS_OK(status)) {
8445 close_file(req, fsp, NORMAL_CLOSE);
8448 info_level_return = SVAL(pdata,16);
8450 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8451 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8452 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8453 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8455 *pdata_return_size = 12;
8458 /* Realloc the data size */
8459 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8460 if (*ppdata == NULL) {
8461 *pdata_return_size = 0;
8462 return NT_STATUS_NO_MEMORY;
8466 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8467 SSVAL(pdata,2,0); /* No fnum. */
8468 SIVAL(pdata,4,info); /* Was directory created. */
8470 switch (info_level_return) {
8471 case SMB_QUERY_FILE_UNIX_BASIC:
8472 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8473 SSVAL(pdata,10,0); /* Padding. */
8474 store_file_unix_basic(conn, pdata + 12, fsp,
8477 case SMB_QUERY_FILE_UNIX_INFO2:
8478 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8479 SSVAL(pdata,10,0); /* Padding. */
8480 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8484 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8485 SSVAL(pdata,10,0); /* Padding. */
8492 /****************************************************************************
8493 Open/Create a file with POSIX semantics.
8494 ****************************************************************************/
8496 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8497 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8499 static NTSTATUS smb_posix_open(connection_struct *conn,
8500 struct smb_request *req,
8503 struct smb_filename *smb_fname,
8504 int *pdata_return_size)
8506 bool extended_oplock_granted = False;
8507 char *pdata = *ppdata;
8509 uint32_t wire_open_mode = 0;
8510 uint32_t raw_unixmode = 0;
8511 uint32_t mod_unixmode = 0;
8512 uint32_t create_disp = 0;
8513 uint32_t access_mask = 0;
8514 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8515 NTSTATUS status = NT_STATUS_OK;
8516 mode_t unixmode = (mode_t)0;
8517 files_struct *fsp = NULL;
8518 int oplock_request = 0;
8520 uint16_t info_level_return = 0;
8522 if (total_data < 18) {
8523 return NT_STATUS_INVALID_PARAMETER;
8526 flags = IVAL(pdata,0);
8527 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8528 if (oplock_request) {
8529 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8532 wire_open_mode = IVAL(pdata,4);
8534 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8535 return smb_posix_mkdir(conn, req,
8542 switch (wire_open_mode & SMB_ACCMODE) {
8544 access_mask = SMB_O_RDONLY_MAPPING;
8547 access_mask = SMB_O_WRONLY_MAPPING;
8550 access_mask = (SMB_O_RDONLY_MAPPING|
8551 SMB_O_WRONLY_MAPPING);
8554 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8555 (unsigned int)wire_open_mode ));
8556 return NT_STATUS_INVALID_PARAMETER;
8559 wire_open_mode &= ~SMB_ACCMODE;
8561 /* First take care of O_CREAT|O_EXCL interactions. */
8562 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8563 case (SMB_O_CREAT | SMB_O_EXCL):
8564 /* File exists fail. File not exist create. */
8565 create_disp = FILE_CREATE;
8568 /* File exists open. File not exist create. */
8569 create_disp = FILE_OPEN_IF;
8572 /* O_EXCL on its own without O_CREAT is undefined.
8573 We deliberately ignore it as some versions of
8574 Linux CIFSFS can send a bare O_EXCL on the
8575 wire which other filesystems in the kernel
8576 ignore. See bug 9519 for details. */
8581 /* File exists open. File not exist fail. */
8582 create_disp = FILE_OPEN;
8585 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8586 (unsigned int)wire_open_mode ));
8587 return NT_STATUS_INVALID_PARAMETER;
8590 /* Next factor in the effects of O_TRUNC. */
8591 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8593 if (wire_open_mode & SMB_O_TRUNC) {
8594 switch (create_disp) {
8596 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8597 /* Leave create_disp alone as
8598 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8600 /* File exists fail. File not exist create. */
8603 /* SMB_O_CREAT | SMB_O_TRUNC */
8604 /* File exists overwrite. File not exist create. */
8605 create_disp = FILE_OVERWRITE_IF;
8609 /* File exists overwrite. File not exist fail. */
8610 create_disp = FILE_OVERWRITE;
8613 /* Cannot get here. */
8614 smb_panic("smb_posix_open: logic error");
8615 return NT_STATUS_INVALID_PARAMETER;
8619 raw_unixmode = IVAL(pdata,8);
8620 /* Next 4 bytes are not yet defined. */
8622 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8623 (VALID_STAT(smb_fname->st) ?
8624 PERM_EXISTING_FILE : PERM_NEW_FILE),
8627 if (!NT_STATUS_IS_OK(status)) {
8631 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8633 if (wire_open_mode & SMB_O_SYNC) {
8634 create_options |= FILE_WRITE_THROUGH;
8636 if (wire_open_mode & SMB_O_APPEND) {
8637 access_mask |= FILE_APPEND_DATA;
8639 if (wire_open_mode & SMB_O_DIRECT) {
8640 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8643 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8644 VALID_STAT_OF_DIR(smb_fname->st)) {
8645 if (access_mask != SMB_O_RDONLY_MAPPING) {
8646 return NT_STATUS_FILE_IS_A_DIRECTORY;
8648 create_options &= ~FILE_NON_DIRECTORY_FILE;
8649 create_options |= FILE_DIRECTORY_FILE;
8652 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8653 smb_fname_str_dbg(smb_fname),
8654 (unsigned int)wire_open_mode,
8655 (unsigned int)unixmode ));
8657 status = SMB_VFS_CREATE_FILE(
8660 0, /* root_dir_fid */
8661 smb_fname, /* fname */
8662 access_mask, /* access_mask */
8663 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8665 create_disp, /* create_disposition*/
8666 create_options, /* create_options */
8667 mod_unixmode, /* file_attributes */
8668 oplock_request, /* oplock_request */
8670 0, /* allocation_size */
8671 0, /* private_flags */
8676 NULL, NULL); /* create context */
8678 if (!NT_STATUS_IS_OK(status)) {
8682 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8683 extended_oplock_granted = True;
8686 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8687 extended_oplock_granted = True;
8690 info_level_return = SVAL(pdata,16);
8692 /* Allocate the correct return size. */
8694 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8695 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8696 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8697 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8699 *pdata_return_size = 12;
8702 /* Realloc the data size */
8703 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8704 if (*ppdata == NULL) {
8705 close_file(req, fsp, ERROR_CLOSE);
8706 *pdata_return_size = 0;
8707 return NT_STATUS_NO_MEMORY;
8711 if (extended_oplock_granted) {
8712 if (flags & REQUEST_BATCH_OPLOCK) {
8713 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8715 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8717 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8718 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8720 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8723 SSVAL(pdata,2,fsp->fnum);
8724 SIVAL(pdata,4,info); /* Was file created etc. */
8726 switch (info_level_return) {
8727 case SMB_QUERY_FILE_UNIX_BASIC:
8728 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8729 SSVAL(pdata,10,0); /* padding. */
8730 store_file_unix_basic(conn, pdata + 12, fsp,
8733 case SMB_QUERY_FILE_UNIX_INFO2:
8734 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8735 SSVAL(pdata,10,0); /* padding. */
8736 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8740 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8741 SSVAL(pdata,10,0); /* padding. */
8744 return NT_STATUS_OK;
8747 /****************************************************************************
8748 Delete a file with POSIX semantics.
8749 ****************************************************************************/
8751 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8752 struct smb_request *req,
8755 struct smb_filename *smb_fname)
8757 NTSTATUS status = NT_STATUS_OK;
8758 files_struct *fsp = NULL;
8762 int create_options = 0;
8763 struct share_mode_lock *lck = NULL;
8764 bool other_nonposix_opens;
8766 if (total_data < 2) {
8767 return NT_STATUS_INVALID_PARAMETER;
8770 flags = SVAL(pdata,0);
8772 if (!VALID_STAT(smb_fname->st)) {
8773 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8776 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8777 !VALID_STAT_OF_DIR(smb_fname->st)) {
8778 return NT_STATUS_NOT_A_DIRECTORY;
8781 DEBUG(10,("smb_posix_unlink: %s %s\n",
8782 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8783 smb_fname_str_dbg(smb_fname)));
8785 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8786 create_options |= FILE_DIRECTORY_FILE;
8789 status = SMB_VFS_CREATE_FILE(
8792 0, /* root_dir_fid */
8793 smb_fname, /* fname */
8794 DELETE_ACCESS, /* access_mask */
8795 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8797 FILE_OPEN, /* create_disposition*/
8798 create_options, /* create_options */
8799 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8800 0, /* oplock_request */
8802 0, /* allocation_size */
8803 0, /* private_flags */
8808 NULL, NULL); /* create context */
8810 if (!NT_STATUS_IS_OK(status)) {
8815 * Don't lie to client. If we can't really delete due to
8816 * non-POSIX opens return SHARING_VIOLATION.
8819 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8821 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8822 "lock for file %s\n", fsp_str_dbg(fsp)));
8823 close_file(req, fsp, NORMAL_CLOSE);
8824 return NT_STATUS_INVALID_PARAMETER;
8827 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
8828 if (other_nonposix_opens) {
8829 /* Fail with sharing violation. */
8831 close_file(req, fsp, NORMAL_CLOSE);
8832 return NT_STATUS_SHARING_VIOLATION;
8836 * Set the delete on close.
8838 status = smb_set_file_disposition_info(conn,
8846 if (!NT_STATUS_IS_OK(status)) {
8847 close_file(req, fsp, NORMAL_CLOSE);
8850 return close_file(req, fsp, NORMAL_CLOSE);
8853 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8854 struct smb_request *req,
8855 TALLOC_CTX *mem_ctx,
8856 uint16_t info_level,
8858 struct smb_filename *smb_fname,
8859 char **ppdata, int total_data,
8862 char *pdata = *ppdata;
8863 NTSTATUS status = NT_STATUS_OK;
8864 int data_return_size = 0;
8868 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8869 return NT_STATUS_INVALID_LEVEL;
8872 if (!CAN_WRITE(conn)) {
8873 /* Allow POSIX opens. The open path will deny
8874 * any non-readonly opens. */
8875 if (info_level != SMB_POSIX_PATH_OPEN) {
8876 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8880 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8881 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8883 info_level, total_data));
8885 switch (info_level) {
8887 case SMB_INFO_STANDARD:
8889 status = smb_set_info_standard(conn,
8897 case SMB_INFO_SET_EA:
8899 status = smb_info_set_ea(conn,
8907 case SMB_SET_FILE_BASIC_INFO:
8908 case SMB_FILE_BASIC_INFORMATION:
8910 status = smb_set_file_basic_info(conn,
8918 case SMB_FILE_ALLOCATION_INFORMATION:
8919 case SMB_SET_FILE_ALLOCATION_INFO:
8921 status = smb_set_file_allocation_info(conn, req,
8929 case SMB_FILE_END_OF_FILE_INFORMATION:
8930 case SMB_SET_FILE_END_OF_FILE_INFO:
8933 * XP/Win7 both fail after the createfile with
8934 * SMB_SET_FILE_END_OF_FILE_INFO but not
8935 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8936 * The level is known here, so pass it down
8940 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8942 status = smb_set_file_end_of_file_info(conn, req,
8951 case SMB_FILE_DISPOSITION_INFORMATION:
8952 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8955 /* JRA - We used to just ignore this on a path ?
8956 * Shouldn't this be invalid level on a pathname
8959 if (tran_call != TRANSACT2_SETFILEINFO) {
8960 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8963 status = smb_set_file_disposition_info(conn,
8971 case SMB_FILE_POSITION_INFORMATION:
8973 status = smb_file_position_information(conn,
8980 case SMB_FILE_FULL_EA_INFORMATION:
8982 status = smb_set_file_full_ea_info(conn,
8989 /* From tridge Samba4 :
8990 * MODE_INFORMATION in setfileinfo (I have no
8991 * idea what "mode information" on a file is - it takes a value of 0,
8992 * 2, 4 or 6. What could it be?).
8995 case SMB_FILE_MODE_INFORMATION:
8997 status = smb_file_mode_information(conn,
9003 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9004 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9005 case SMB_FILE_SHORT_NAME_INFORMATION:
9006 return NT_STATUS_NOT_SUPPORTED;
9009 * CIFS UNIX extensions.
9012 case SMB_SET_FILE_UNIX_BASIC:
9014 status = smb_set_file_unix_basic(conn, req,
9022 case SMB_SET_FILE_UNIX_INFO2:
9024 status = smb_set_file_unix_info2(conn, req,
9032 case SMB_SET_FILE_UNIX_LINK:
9035 /* We must have a pathname for this. */
9036 return NT_STATUS_INVALID_LEVEL;
9038 status = smb_set_file_unix_link(conn, req, pdata,
9039 total_data, smb_fname);
9043 case SMB_SET_FILE_UNIX_HLINK:
9046 /* We must have a pathname for this. */
9047 return NT_STATUS_INVALID_LEVEL;
9049 status = smb_set_file_unix_hlink(conn, req,
9055 case SMB_FILE_RENAME_INFORMATION:
9057 status = smb_file_rename_information(conn, req,
9063 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9065 /* SMB2 rename information. */
9066 status = smb2_file_rename_information(conn, req,
9072 case SMB_FILE_LINK_INFORMATION:
9074 status = smb_file_link_information(conn, req,
9080 #if defined(HAVE_POSIX_ACLS)
9081 case SMB_SET_POSIX_ACL:
9083 status = smb_set_posix_acl(conn,
9093 case SMB_SET_POSIX_LOCK:
9096 return NT_STATUS_INVALID_LEVEL;
9098 status = smb_set_posix_lock(conn, req,
9099 pdata, total_data, fsp);
9103 case SMB_POSIX_PATH_OPEN:
9106 /* We must have a pathname for this. */
9107 return NT_STATUS_INVALID_LEVEL;
9110 status = smb_posix_open(conn, req,
9118 case SMB_POSIX_PATH_UNLINK:
9121 /* We must have a pathname for this. */
9122 return NT_STATUS_INVALID_LEVEL;
9125 status = smb_posix_unlink(conn, req,
9133 return NT_STATUS_INVALID_LEVEL;
9136 if (!NT_STATUS_IS_OK(status)) {
9140 *ret_data_size = data_return_size;
9141 return NT_STATUS_OK;
9144 /****************************************************************************
9145 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9146 ****************************************************************************/
9148 static void call_trans2setfilepathinfo(connection_struct *conn,
9149 struct smb_request *req,
9150 unsigned int tran_call,
9151 char **pparams, int total_params,
9152 char **ppdata, int total_data,
9153 unsigned int max_data_bytes)
9155 char *params = *pparams;
9156 char *pdata = *ppdata;
9157 uint16_t info_level;
9158 struct smb_filename *smb_fname = NULL;
9159 files_struct *fsp = NULL;
9160 NTSTATUS status = NT_STATUS_OK;
9161 int data_return_size = 0;
9164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9168 if (tran_call == TRANSACT2_SETFILEINFO) {
9169 if (total_params < 4) {
9170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9174 fsp = file_fsp(req, SVAL(params,0));
9175 /* Basic check for non-null fsp. */
9176 if (!check_fsp_open(conn, req, fsp)) {
9179 info_level = SVAL(params,2);
9181 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9182 if (smb_fname == NULL) {
9183 reply_nterror(req, NT_STATUS_NO_MEMORY);
9187 if(fsp->fh->fd == -1) {
9189 * This is actually a SETFILEINFO on a directory
9190 * handle (returned from an NT SMB). NT5.0 seems
9191 * to do this call. JRA.
9193 if (INFO_LEVEL_IS_UNIX(info_level)) {
9194 /* Always do lstat for UNIX calls. */
9195 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9196 DEBUG(3,("call_trans2setfilepathinfo: "
9197 "SMB_VFS_LSTAT of %s failed "
9199 smb_fname_str_dbg(smb_fname),
9201 reply_nterror(req, map_nt_error_from_unix(errno));
9205 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9206 DEBUG(3,("call_trans2setfilepathinfo: "
9207 "fileinfo of %s failed (%s)\n",
9208 smb_fname_str_dbg(smb_fname),
9210 reply_nterror(req, map_nt_error_from_unix(errno));
9214 } else if (fsp->print_file) {
9216 * Doing a DELETE_ON_CLOSE should cancel a print job.
9218 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9219 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9221 DEBUG(3,("call_trans2setfilepathinfo: "
9222 "Cancelling print job (%s)\n",
9226 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9232 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9237 * Original code - this is an open file.
9239 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9240 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9241 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9243 reply_nterror(req, map_nt_error_from_unix(errno));
9249 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9252 if (total_params < 7) {
9253 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9257 info_level = SVAL(params,0);
9258 if (req->posix_pathnames) {
9259 srvstr_get_path_posix(req,
9268 srvstr_get_path(req,
9277 if (!NT_STATUS_IS_OK(status)) {
9278 reply_nterror(req, status);
9282 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9283 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9284 info_level == SMB_FILE_RENAME_INFORMATION ||
9285 info_level == SMB_POSIX_PATH_OPEN ||
9286 info_level == SMB_POSIX_PATH_UNLINK) {
9287 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9290 status = filename_convert(req, conn,
9296 if (!NT_STATUS_IS_OK(status)) {
9297 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9298 reply_botherror(req,
9299 NT_STATUS_PATH_NOT_COVERED,
9300 ERRSRV, ERRbadpath);
9303 reply_nterror(req, status);
9307 if (INFO_LEVEL_IS_UNIX(info_level)) {
9309 * For CIFS UNIX extensions the target name may not exist.
9312 /* Always do lstat for UNIX calls. */
9313 SMB_VFS_LSTAT(conn, smb_fname);
9315 } else if (!VALID_STAT(smb_fname->st) &&
9316 SMB_VFS_STAT(conn, smb_fname)) {
9317 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9319 smb_fname_str_dbg(smb_fname),
9321 reply_nterror(req, map_nt_error_from_unix(errno));
9326 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9327 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9329 info_level,total_data));
9331 /* Realloc the parameter size */
9332 *pparams = (char *)SMB_REALLOC(*pparams,2);
9333 if (*pparams == NULL) {
9334 reply_nterror(req, NT_STATUS_NO_MEMORY);
9341 status = smbd_do_setfilepathinfo(conn, req, req,
9347 if (!NT_STATUS_IS_OK(status)) {
9348 if (open_was_deferred(req->xconn, req->mid)) {
9349 /* We have re-scheduled this call. */
9352 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9353 bool ok = defer_smb1_sharing_violation(req);
9358 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9359 /* We have re-scheduled this call. */
9362 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9363 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9364 ERRSRV, ERRbadpath);
9367 if (info_level == SMB_POSIX_PATH_OPEN) {
9368 reply_openerror(req, status);
9373 * Invalid EA name needs to return 2 param bytes,
9374 * not a zero-length error packet.
9376 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9377 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9380 reply_nterror(req, status);
9385 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9391 /****************************************************************************
9392 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9393 ****************************************************************************/
9395 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9396 char **pparams, int total_params,
9397 char **ppdata, int total_data,
9398 unsigned int max_data_bytes)
9400 struct smb_filename *smb_dname = NULL;
9401 char *params = *pparams;
9402 char *pdata = *ppdata;
9403 char *directory = NULL;
9404 NTSTATUS status = NT_STATUS_OK;
9405 struct ea_list *ea_list = NULL;
9406 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9407 TALLOC_CTX *ctx = talloc_tos();
9409 if (!CAN_WRITE(conn)) {
9410 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9414 if (total_params < 5) {
9415 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9419 if (req->posix_pathnames) {
9420 srvstr_get_path_posix(ctx,
9429 srvstr_get_path(ctx,
9438 if (!NT_STATUS_IS_OK(status)) {
9439 reply_nterror(req, status);
9443 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9445 status = filename_convert(ctx,
9453 if (!NT_STATUS_IS_OK(status)) {
9454 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9455 reply_botherror(req,
9456 NT_STATUS_PATH_NOT_COVERED,
9457 ERRSRV, ERRbadpath);
9460 reply_nterror(req, status);
9465 * OS/2 workplace shell seems to send SET_EA requests of "null"
9466 * length (4 bytes containing IVAL 4).
9467 * They seem to have no effect. Bug #3212. JRA.
9470 if (total_data && (total_data != 4)) {
9471 /* Any data in this call is an EA list. */
9472 if (total_data < 10) {
9473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9477 if (IVAL(pdata,0) > total_data) {
9478 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9479 IVAL(pdata,0), (unsigned int)total_data));
9480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9484 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9491 if (!lp_ea_support(SNUM(conn))) {
9492 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9496 /* If total_data == 4 Windows doesn't care what values
9497 * are placed in that field, it just ignores them.
9498 * The System i QNTC IBM SMB client puts bad values here,
9499 * so ignore them. */
9501 status = create_directory(conn, req, smb_dname);
9503 if (!NT_STATUS_IS_OK(status)) {
9504 reply_nterror(req, status);
9508 /* Try and set any given EA. */
9510 status = set_ea(conn, NULL, smb_dname, ea_list);
9511 if (!NT_STATUS_IS_OK(status)) {
9512 reply_nterror(req, status);
9517 /* Realloc the parameter and data sizes */
9518 *pparams = (char *)SMB_REALLOC(*pparams,2);
9519 if(*pparams == NULL) {
9520 reply_nterror(req, NT_STATUS_NO_MEMORY);
9527 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9530 TALLOC_FREE(smb_dname);
9534 /****************************************************************************
9535 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9536 We don't actually do this - we just send a null response.
9537 ****************************************************************************/
9539 static void call_trans2findnotifyfirst(connection_struct *conn,
9540 struct smb_request *req,
9541 char **pparams, int total_params,
9542 char **ppdata, int total_data,
9543 unsigned int max_data_bytes)
9545 char *params = *pparams;
9546 uint16_t info_level;
9548 if (total_params < 6) {
9549 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9553 info_level = SVAL(params,4);
9554 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9556 switch (info_level) {
9561 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9565 /* Realloc the parameter and data sizes */
9566 *pparams = (char *)SMB_REALLOC(*pparams,6);
9567 if (*pparams == NULL) {
9568 reply_nterror(req, NT_STATUS_NO_MEMORY);
9573 SSVAL(params,0,fnf_handle);
9574 SSVAL(params,2,0); /* No changes */
9575 SSVAL(params,4,0); /* No EA errors */
9582 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9587 /****************************************************************************
9588 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9589 changes). Currently this does nothing.
9590 ****************************************************************************/
9592 static void call_trans2findnotifynext(connection_struct *conn,
9593 struct smb_request *req,
9594 char **pparams, int total_params,
9595 char **ppdata, int total_data,
9596 unsigned int max_data_bytes)
9598 char *params = *pparams;
9600 DEBUG(3,("call_trans2findnotifynext\n"));
9602 /* Realloc the parameter and data sizes */
9603 *pparams = (char *)SMB_REALLOC(*pparams,4);
9604 if (*pparams == NULL) {
9605 reply_nterror(req, NT_STATUS_NO_MEMORY);
9610 SSVAL(params,0,0); /* No changes */
9611 SSVAL(params,2,0); /* No EA errors */
9613 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9618 /****************************************************************************
9619 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9620 ****************************************************************************/
9622 static void call_trans2getdfsreferral(connection_struct *conn,
9623 struct smb_request *req,
9624 char **pparams, int total_params,
9625 char **ppdata, int total_data,
9626 unsigned int max_data_bytes)
9628 char *params = *pparams;
9629 char *pathname = NULL;
9631 int max_referral_level;
9632 NTSTATUS status = NT_STATUS_OK;
9633 TALLOC_CTX *ctx = talloc_tos();
9635 DEBUG(10,("call_trans2getdfsreferral\n"));
9637 if (total_params < 3) {
9638 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9642 max_referral_level = SVAL(params,0);
9644 if(!lp_host_msdfs()) {
9645 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9649 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9650 total_params - 2, STR_TERMINATE);
9652 reply_nterror(req, NT_STATUS_NOT_FOUND);
9655 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9656 ppdata,&status)) < 0) {
9657 reply_nterror(req, status);
9661 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9662 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9663 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9668 #define LMCAT_SPL 0x53
9669 #define LMFUNC_GETJOBID 0x60
9671 /****************************************************************************
9672 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9673 ****************************************************************************/
9675 static void call_trans2ioctl(connection_struct *conn,
9676 struct smb_request *req,
9677 char **pparams, int total_params,
9678 char **ppdata, int total_data,
9679 unsigned int max_data_bytes)
9681 const struct loadparm_substitution *lp_sub =
9682 loadparm_s3_global_substitution();
9683 char *pdata = *ppdata;
9684 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9688 /* check for an invalid fid before proceeding */
9691 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9695 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9696 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9697 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9698 if (*ppdata == NULL) {
9699 reply_nterror(req, NT_STATUS_NO_MEMORY);
9704 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9705 CAN ACCEPT THIS IN UNICODE. JRA. */
9708 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9710 status = srvstr_push(pdata, req->flags2, pdata + 2,
9711 lp_netbios_name(), 15,
9712 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9713 if (!NT_STATUS_IS_OK(status)) {
9714 reply_nterror(req, status);
9717 status = srvstr_push(pdata, req->flags2, pdata+18,
9718 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
9719 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9720 if (!NT_STATUS_IS_OK(status)) {
9721 reply_nterror(req, status);
9724 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9729 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9730 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9733 /****************************************************************************
9734 Reply to a SMBfindclose (stop trans2 directory search).
9735 ****************************************************************************/
9737 void reply_findclose(struct smb_request *req)
9740 struct smbd_server_connection *sconn = req->sconn;
9741 files_struct *fsp = NULL;
9743 START_PROFILE(SMBfindclose);
9746 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9747 END_PROFILE(SMBfindclose);
9751 dptr_num = SVALS(req->vwv+0, 0);
9753 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9756 * OS/2 seems to use -1 to indicate "close all directories"
9757 * This has to mean on this specific connection struct.
9759 if (dptr_num == -1) {
9760 dptr_closecnum(req->conn);
9762 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
9765 close_file(NULL, fsp, NORMAL_CLOSE);
9770 reply_outbuf(req, 0, 0);
9772 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9774 END_PROFILE(SMBfindclose);
9778 /****************************************************************************
9779 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9780 ****************************************************************************/
9782 void reply_findnclose(struct smb_request *req)
9786 START_PROFILE(SMBfindnclose);
9789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9790 END_PROFILE(SMBfindnclose);
9794 dptr_num = SVAL(req->vwv+0, 0);
9796 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9798 /* We never give out valid handles for a
9799 findnotifyfirst - so any dptr_num is ok here.
9802 reply_outbuf(req, 0, 0);
9804 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9806 END_PROFILE(SMBfindnclose);
9810 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9811 struct trans_state *state)
9813 if (get_Protocol() >= PROTOCOL_NT1) {
9814 req->flags2 |= 0x40; /* IS_LONG_NAME */
9815 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9818 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9819 if (state->call != TRANSACT2_QFSINFO &&
9820 state->call != TRANSACT2_SETFSINFO) {
9821 DEBUG(0,("handle_trans2: encryption required "
9823 (unsigned int)state->call));
9824 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9829 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9831 /* Now we must call the relevant TRANS2 function */
9832 switch(state->call) {
9833 case TRANSACT2_OPEN:
9835 START_PROFILE(Trans2_open);
9836 call_trans2open(conn, req,
9837 &state->param, state->total_param,
9838 &state->data, state->total_data,
9839 state->max_data_return);
9840 END_PROFILE(Trans2_open);
9844 case TRANSACT2_FINDFIRST:
9846 START_PROFILE(Trans2_findfirst);
9847 call_trans2findfirst(conn, req,
9848 &state->param, state->total_param,
9849 &state->data, state->total_data,
9850 state->max_data_return);
9851 END_PROFILE(Trans2_findfirst);
9855 case TRANSACT2_FINDNEXT:
9857 START_PROFILE(Trans2_findnext);
9858 call_trans2findnext(conn, req,
9859 &state->param, state->total_param,
9860 &state->data, state->total_data,
9861 state->max_data_return);
9862 END_PROFILE(Trans2_findnext);
9866 case TRANSACT2_QFSINFO:
9868 START_PROFILE(Trans2_qfsinfo);
9869 call_trans2qfsinfo(conn, req,
9870 &state->param, state->total_param,
9871 &state->data, state->total_data,
9872 state->max_data_return);
9873 END_PROFILE(Trans2_qfsinfo);
9877 case TRANSACT2_SETFSINFO:
9879 START_PROFILE(Trans2_setfsinfo);
9880 call_trans2setfsinfo(conn, req,
9881 &state->param, state->total_param,
9882 &state->data, state->total_data,
9883 state->max_data_return);
9884 END_PROFILE(Trans2_setfsinfo);
9888 case TRANSACT2_QPATHINFO:
9889 case TRANSACT2_QFILEINFO:
9891 START_PROFILE(Trans2_qpathinfo);
9892 call_trans2qfilepathinfo(conn, req, state->call,
9893 &state->param, state->total_param,
9894 &state->data, state->total_data,
9895 state->max_data_return);
9896 END_PROFILE(Trans2_qpathinfo);
9900 case TRANSACT2_SETPATHINFO:
9901 case TRANSACT2_SETFILEINFO:
9903 START_PROFILE(Trans2_setpathinfo);
9904 call_trans2setfilepathinfo(conn, req, state->call,
9905 &state->param, state->total_param,
9906 &state->data, state->total_data,
9907 state->max_data_return);
9908 END_PROFILE(Trans2_setpathinfo);
9912 case TRANSACT2_FINDNOTIFYFIRST:
9914 START_PROFILE(Trans2_findnotifyfirst);
9915 call_trans2findnotifyfirst(conn, req,
9916 &state->param, state->total_param,
9917 &state->data, state->total_data,
9918 state->max_data_return);
9919 END_PROFILE(Trans2_findnotifyfirst);
9923 case TRANSACT2_FINDNOTIFYNEXT:
9925 START_PROFILE(Trans2_findnotifynext);
9926 call_trans2findnotifynext(conn, req,
9927 &state->param, state->total_param,
9928 &state->data, state->total_data,
9929 state->max_data_return);
9930 END_PROFILE(Trans2_findnotifynext);
9934 case TRANSACT2_MKDIR:
9936 START_PROFILE(Trans2_mkdir);
9937 call_trans2mkdir(conn, req,
9938 &state->param, state->total_param,
9939 &state->data, state->total_data,
9940 state->max_data_return);
9941 END_PROFILE(Trans2_mkdir);
9945 case TRANSACT2_GET_DFS_REFERRAL:
9947 START_PROFILE(Trans2_get_dfs_referral);
9948 call_trans2getdfsreferral(conn, req,
9949 &state->param, state->total_param,
9950 &state->data, state->total_data,
9951 state->max_data_return);
9952 END_PROFILE(Trans2_get_dfs_referral);
9956 case TRANSACT2_IOCTL:
9958 START_PROFILE(Trans2_ioctl);
9959 call_trans2ioctl(conn, req,
9960 &state->param, state->total_param,
9961 &state->data, state->total_data,
9962 state->max_data_return);
9963 END_PROFILE(Trans2_ioctl);
9968 /* Error in request */
9969 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9970 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9974 /****************************************************************************
9975 Reply to a SMBtrans2.
9976 ****************************************************************************/
9978 void reply_trans2(struct smb_request *req)
9980 connection_struct *conn = req->conn;
9985 unsigned int tran_call;
9986 struct trans_state *state;
9989 START_PROFILE(SMBtrans2);
9991 if (req->wct < 14) {
9992 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9993 END_PROFILE(SMBtrans2);
9997 dsoff = SVAL(req->vwv+12, 0);
9998 dscnt = SVAL(req->vwv+11, 0);
9999 psoff = SVAL(req->vwv+10, 0);
10000 pscnt = SVAL(req->vwv+9, 0);
10001 tran_call = SVAL(req->vwv+14, 0);
10003 result = allow_new_trans(conn->pending_trans, req->mid);
10004 if (!NT_STATUS_IS_OK(result)) {
10005 DEBUG(2, ("Got invalid trans2 request: %s\n",
10006 nt_errstr(result)));
10007 reply_nterror(req, result);
10008 END_PROFILE(SMBtrans2);
10012 if (IS_IPC(conn)) {
10013 switch (tran_call) {
10014 /* List the allowed trans2 calls on IPC$ */
10015 case TRANSACT2_OPEN:
10016 case TRANSACT2_GET_DFS_REFERRAL:
10017 case TRANSACT2_QFILEINFO:
10018 case TRANSACT2_QFSINFO:
10019 case TRANSACT2_SETFSINFO:
10022 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10023 END_PROFILE(SMBtrans2);
10028 if ((state = talloc(conn, struct trans_state)) == NULL) {
10029 DEBUG(0, ("talloc failed\n"));
10030 reply_nterror(req, NT_STATUS_NO_MEMORY);
10031 END_PROFILE(SMBtrans2);
10035 state->cmd = SMBtrans2;
10037 state->mid = req->mid;
10038 state->vuid = req->vuid;
10039 state->setup_count = SVAL(req->vwv+13, 0);
10040 state->setup = NULL;
10041 state->total_param = SVAL(req->vwv+0, 0);
10042 state->param = NULL;
10043 state->total_data = SVAL(req->vwv+1, 0);
10044 state->data = NULL;
10045 state->max_param_return = SVAL(req->vwv+2, 0);
10046 state->max_data_return = SVAL(req->vwv+3, 0);
10047 state->max_setup_return = SVAL(req->vwv+4, 0);
10048 state->close_on_completion = BITSETW(req->vwv+5, 0);
10049 state->one_way = BITSETW(req->vwv+5, 1);
10051 state->call = tran_call;
10053 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10054 is so as a sanity check */
10055 if (state->setup_count != 1) {
10057 * Need to have rc=0 for ioctl to get job id for OS/2.
10058 * Network printing will fail if function is not successful.
10059 * Similar function in reply.c will be used if protocol
10060 * is LANMAN1.0 instead of LM1.2X002.
10061 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10062 * outbuf doesn't have to be set(only job id is used).
10064 if ( (state->setup_count == 4)
10065 && (tran_call == TRANSACT2_IOCTL)
10066 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10067 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10068 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10070 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10071 DEBUG(2,("Transaction is %d\n",tran_call));
10072 TALLOC_FREE(state);
10073 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10074 END_PROFILE(SMBtrans2);
10079 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10082 if (state->total_data) {
10084 if (trans_oob(state->total_data, 0, dscnt)
10085 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10089 /* Can't use talloc here, the core routines do realloc on the
10090 * params and data. */
10091 state->data = (char *)SMB_MALLOC(state->total_data);
10092 if (state->data == NULL) {
10093 DEBUG(0,("reply_trans2: data malloc fail for %u "
10094 "bytes !\n", (unsigned int)state->total_data));
10095 TALLOC_FREE(state);
10096 reply_nterror(req, NT_STATUS_NO_MEMORY);
10097 END_PROFILE(SMBtrans2);
10101 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10104 if (state->total_param) {
10106 if (trans_oob(state->total_param, 0, pscnt)
10107 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10111 /* Can't use talloc here, the core routines do realloc on the
10112 * params and data. */
10113 state->param = (char *)SMB_MALLOC(state->total_param);
10114 if (state->param == NULL) {
10115 DEBUG(0,("reply_trans: param malloc fail for %u "
10116 "bytes !\n", (unsigned int)state->total_param));
10117 SAFE_FREE(state->data);
10118 TALLOC_FREE(state);
10119 reply_nterror(req, NT_STATUS_NO_MEMORY);
10120 END_PROFILE(SMBtrans2);
10124 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10127 state->received_data = dscnt;
10128 state->received_param = pscnt;
10130 if ((state->received_param == state->total_param) &&
10131 (state->received_data == state->total_data)) {
10133 handle_trans2(conn, req, state);
10135 SAFE_FREE(state->data);
10136 SAFE_FREE(state->param);
10137 TALLOC_FREE(state);
10138 END_PROFILE(SMBtrans2);
10142 DLIST_ADD(conn->pending_trans, state);
10144 /* We need to send an interim response then receive the rest
10145 of the parameter/data bytes */
10146 reply_outbuf(req, 0, 0);
10147 show_msg((char *)req->outbuf);
10148 END_PROFILE(SMBtrans2);
10153 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10154 SAFE_FREE(state->data);
10155 SAFE_FREE(state->param);
10156 TALLOC_FREE(state);
10157 END_PROFILE(SMBtrans2);
10158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10162 /****************************************************************************
10163 Reply to a SMBtranss2
10164 ****************************************************************************/
10166 void reply_transs2(struct smb_request *req)
10168 connection_struct *conn = req->conn;
10169 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10170 struct trans_state *state;
10172 START_PROFILE(SMBtranss2);
10174 show_msg((const char *)req->inbuf);
10176 /* Windows clients expect all replies to
10177 a transact secondary (SMBtranss2 0x33)
10178 to have a command code of transact
10179 (SMBtrans2 0x32). See bug #8989
10180 and also [MS-CIFS] section 2.2.4.47.2
10183 req->cmd = SMBtrans2;
10185 if (req->wct < 8) {
10186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10187 END_PROFILE(SMBtranss2);
10191 for (state = conn->pending_trans; state != NULL;
10192 state = state->next) {
10193 if (state->mid == req->mid) {
10198 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10200 END_PROFILE(SMBtranss2);
10204 /* Revise state->total_param and state->total_data in case they have
10205 changed downwards */
10207 if (SVAL(req->vwv+0, 0) < state->total_param)
10208 state->total_param = SVAL(req->vwv+0, 0);
10209 if (SVAL(req->vwv+1, 0) < state->total_data)
10210 state->total_data = SVAL(req->vwv+1, 0);
10212 pcnt = SVAL(req->vwv+2, 0);
10213 poff = SVAL(req->vwv+3, 0);
10214 pdisp = SVAL(req->vwv+4, 0);
10216 dcnt = SVAL(req->vwv+5, 0);
10217 doff = SVAL(req->vwv+6, 0);
10218 ddisp = SVAL(req->vwv+7, 0);
10220 state->received_param += pcnt;
10221 state->received_data += dcnt;
10223 if ((state->received_data > state->total_data) ||
10224 (state->received_param > state->total_param))
10228 if (trans_oob(state->total_param, pdisp, pcnt)
10229 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10232 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10236 if (trans_oob(state->total_data, ddisp, dcnt)
10237 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10240 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10243 if ((state->received_param < state->total_param) ||
10244 (state->received_data < state->total_data)) {
10245 END_PROFILE(SMBtranss2);
10249 handle_trans2(conn, req, state);
10251 DLIST_REMOVE(conn->pending_trans, state);
10252 SAFE_FREE(state->data);
10253 SAFE_FREE(state->param);
10254 TALLOC_FREE(state);
10256 END_PROFILE(SMBtranss2);
10261 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10262 DLIST_REMOVE(conn->pending_trans, state);
10263 SAFE_FREE(state->data);
10264 SAFE_FREE(state->param);
10265 TALLOC_FREE(state);
10266 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10267 END_PROFILE(SMBtranss2);