2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
41 #include "lib/util_ea.h"
42 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
55 const SMB_STRUCT_STAT *psbuf);
57 /****************************************************************************
58 Check if an open file handle or smb_fname is a symlink.
59 ****************************************************************************/
61 static NTSTATUS refuse_symlink(connection_struct *conn,
62 const files_struct *fsp,
63 const struct smb_filename *smb_fname)
66 const SMB_STRUCT_STAT *pst = NULL;
69 pst = &fsp->fsp_name->st;
74 if (!VALID_STAT(*pst)) {
75 int ret = vfs_stat_smb_basename(conn,
78 if (ret == -1 && errno != ENOENT) {
79 return map_nt_error_from_unix(errno);
80 } else if (ret == -1) {
81 /* it's not a symlink.. */
87 if (S_ISLNK(pst->st_ex_mode)) {
88 return NT_STATUS_ACCESS_DENIED;
93 NTSTATUS check_access_fsp(const struct files_struct *fsp,
96 if (!(fsp->access_mask & access_mask)) {
97 return NT_STATUS_ACCESS_DENIED;
102 #if defined(HAVE_POSIX_ACLS)
103 /****************************************************************************
104 Utility function to open a fsp for a POSIX handle operation.
105 ****************************************************************************/
107 static NTSTATUS get_posix_fsp(connection_struct *conn,
108 struct smb_request *req,
109 const struct smb_filename *smb_fname,
110 uint32_t access_mask,
111 files_struct **ret_fsp)
114 struct smb_filename *smb_fname_tmp = NULL;
115 uint32_t create_disposition = FILE_OPEN;
116 uint32_t share_access = FILE_SHARE_READ|
120 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
121 * but set reasonable defaults.
123 uint32_t file_attributes = 0664|FILE_FLAG_POSIX_SEMANTICS;
124 uint32_t oplock = NO_OPLOCK;
125 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
127 /* File or directory must exist. */
128 if (!VALID_STAT(smb_fname->st)) {
129 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
131 /* Cannot be a symlink. */
132 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
133 return NT_STATUS_ACCESS_DENIED;
135 /* Set options correctly for directory open. */
136 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
138 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
139 * directories, but set reasonable defaults.
141 file_attributes = 0775|FILE_FLAG_POSIX_SEMANTICS;
142 create_options = FILE_DIRECTORY_FILE;
145 /* Createfile uses a non-const smb_fname. */
146 smb_fname_tmp = cp_smb_filename(talloc_tos(),
148 if (smb_fname_tmp == NULL) {
149 return NT_STATUS_NO_MEMORY;
152 status = SMB_VFS_CREATE_FILE(
155 0, /* root_dir_fid */
156 smb_fname_tmp, /* fname */
157 access_mask, /* access_mask */
158 share_access, /* share_access */
159 create_disposition,/* create_disposition*/
160 create_options, /* create_options */
161 file_attributes,/* file_attributes */
162 oplock, /* oplock_request */
164 0, /* allocation_size */
165 0, /* private_flags */
168 ret_fsp, /* result */
170 NULL, /* in_context */
171 NULL); /* out_context */
173 TALLOC_FREE(smb_fname_tmp);
178 /********************************************************************
179 The canonical "check access" based on object handle or path function.
180 ********************************************************************/
182 static NTSTATUS check_access(connection_struct *conn,
184 const struct smb_filename *smb_fname,
185 uint32_t access_mask)
190 status = check_access_fsp(fsp, access_mask);
192 status = smbd_check_access_rights(conn, smb_fname,
199 /********************************************************************
200 Roundup a value to the nearest allocation roundup size boundary.
201 Only do this for Windows clients.
202 ********************************************************************/
204 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
206 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
208 /* Only roundup for Windows clients. */
209 enum remote_arch_types ra_type = get_remote_arch();
210 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
211 val = SMB_ROUNDUP(val,rval);
216 /****************************************************************************
217 Utility functions for dealing with extended attributes.
218 ****************************************************************************/
220 /****************************************************************************
221 Refuse to allow clients to overwrite our private xattrs.
222 ****************************************************************************/
224 bool samba_private_attr_name(const char *unix_ea_name)
226 static const char * const prohibited_ea_names[] = {
227 SAMBA_POSIX_INHERITANCE_EA_NAME,
228 SAMBA_XATTR_DOS_ATTRIB,
236 for (i = 0; prohibited_ea_names[i]; i++) {
237 if (strequal( prohibited_ea_names[i], unix_ea_name))
240 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
241 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
247 /****************************************************************************
248 Get one EA value. Fill in a struct ea_struct.
249 ****************************************************************************/
251 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
252 connection_struct *conn,
254 const struct smb_filename *smb_fname,
256 struct ea_struct *pea)
258 /* Get the value of this xattr. Max size is 64k. */
259 size_t attr_size = 256;
265 val = talloc_realloc(mem_ctx, val, char, attr_size);
267 return NT_STATUS_NO_MEMORY;
270 if (fsp && fsp->fh->fd != -1) {
271 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
273 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
274 ea_name, val, attr_size);
277 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
283 return map_nt_error_from_unix(errno);
286 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
287 dump_data(10, (uint8_t *)val, sizeret);
290 if (strnequal(ea_name, "user.", 5)) {
291 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
293 pea->name = talloc_strdup(mem_ctx, ea_name);
295 if (pea->name == NULL) {
297 return NT_STATUS_NO_MEMORY;
299 pea->value.data = (unsigned char *)val;
300 pea->value.length = (size_t)sizeret;
304 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
305 connection_struct *conn,
307 const struct smb_filename *smb_fname,
312 /* Get a list of all xattrs. Max namesize is 64k. */
313 size_t ea_namelist_size = 1024;
314 char *ea_namelist = smallbuf;
315 char *to_free = NULL;
320 ssize_t sizeret = -1;
328 status = refuse_symlink(conn, fsp, smb_fname);
329 if (!NT_STATUS_IS_OK(status)) {
331 * Just return no EA's on a symlink.
336 if (fsp && fsp->fh->fd != -1) {
337 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
340 sizeret = SMB_VFS_LISTXATTR(conn,
346 if ((sizeret == -1) && (errno == ERANGE)) {
347 ea_namelist_size = 65536;
348 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
349 if (ea_namelist == NULL) {
350 return NT_STATUS_NO_MEMORY;
352 to_free = ea_namelist;
354 if (fsp && fsp->fh->fd != -1) {
355 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
358 sizeret = SMB_VFS_LISTXATTR(conn,
366 status = map_nt_error_from_unix(errno);
367 TALLOC_FREE(to_free);
371 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
374 TALLOC_FREE(to_free);
379 * Ensure the result is 0-terminated
382 if (ea_namelist[sizeret-1] != '\0') {
383 TALLOC_FREE(to_free);
384 return NT_STATUS_INTERNAL_ERROR;
392 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
396 *pnum_names = num_names;
398 if (pnames == NULL) {
399 TALLOC_FREE(to_free);
403 names = talloc_array(mem_ctx, char *, num_names);
405 DEBUG(0, ("talloc failed\n"));
406 TALLOC_FREE(to_free);
407 return NT_STATUS_NO_MEMORY;
410 if (ea_namelist == smallbuf) {
411 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
412 if (ea_namelist == NULL) {
414 return NT_STATUS_NO_MEMORY;
417 talloc_steal(names, ea_namelist);
419 ea_namelist = talloc_realloc(names, ea_namelist, char,
421 if (ea_namelist == NULL) {
423 return NT_STATUS_NO_MEMORY;
429 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
430 names[num_names++] = p;
438 /****************************************************************************
439 Return a linked list of the total EA's. Plus the total size
440 ****************************************************************************/
442 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
443 connection_struct *conn,
445 const struct smb_filename *smb_fname,
446 size_t *pea_total_len,
447 struct ea_list **ea_list)
449 /* Get a list of all xattrs. Max namesize is 64k. */
452 struct ea_list *ea_list_head = NULL;
453 bool posix_pathnames = false;
459 if (!lp_ea_support(SNUM(conn))) {
465 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
467 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
470 status = get_ea_names_from_file(talloc_tos(),
477 if (!NT_STATUS_IS_OK(status)) {
481 if (num_names == 0) {
485 for (i=0; i<num_names; i++) {
486 struct ea_list *listp;
489 if (strnequal(names[i], "system.", 7)
490 || samba_private_attr_name(names[i]))
494 * Filter out any underlying POSIX EA names
495 * that a Windows client can't handle.
497 if (!posix_pathnames &&
498 is_invalid_windows_ea_name(names[i])) {
502 listp = talloc(mem_ctx, struct ea_list);
504 return NT_STATUS_NO_MEMORY;
507 status = get_ea_value(listp,
514 if (!NT_STATUS_IS_OK(status)) {
519 if (listp->ea.value.length == 0) {
521 * We can never return a zero length EA.
522 * Windows reports the EA's as corrupted.
528 push_ascii_fstring(dos_ea_name, listp->ea.name);
531 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
533 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
534 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
535 (unsigned int)listp->ea.value.length));
537 DLIST_ADD_END(ea_list_head, listp);
541 /* Add on 4 for total length. */
542 if (*pea_total_len) {
546 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
547 (unsigned int)*pea_total_len));
549 *ea_list = ea_list_head;
553 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
554 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
559 if (!lp_ea_support(SNUM(conn))) {
563 if (is_ntfs_stream_smb_fname(smb_fname)) {
564 return NT_STATUS_INVALID_PARAMETER;
567 return get_ea_list_from_file_path(mem_ctx,
575 /****************************************************************************
576 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
578 ****************************************************************************/
580 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
581 connection_struct *conn, struct ea_list *ea_list)
583 unsigned int ret_data_size = 4;
586 SMB_ASSERT(total_data_size >= 4);
588 if (!lp_ea_support(SNUM(conn))) {
593 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
596 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
597 dos_namelen = strlen(dos_ea_name);
598 if (dos_namelen > 255 || dos_namelen == 0) {
601 if (ea_list->ea.value.length > 65535) {
604 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
608 /* We know we have room. */
609 SCVAL(p,0,ea_list->ea.flags);
610 SCVAL(p,1,dos_namelen);
611 SSVAL(p,2,ea_list->ea.value.length);
612 strlcpy(p+4, dos_ea_name, dos_namelen+1);
613 if (ea_list->ea.value.length > 0) {
614 memcpy(p + 4 + dos_namelen + 1,
615 ea_list->ea.value.data,
616 ea_list->ea.value.length);
619 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
620 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
623 ret_data_size = PTR_DIFF(p, pdata);
624 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
625 SIVAL(pdata,0,ret_data_size);
626 return ret_data_size;
629 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
631 unsigned int total_data_size,
632 unsigned int *ret_data_size,
633 connection_struct *conn,
634 struct ea_list *ea_list)
636 uint8_t *p = (uint8_t *)pdata;
637 uint8_t *last_start = NULL;
638 bool do_store_data = (pdata != NULL);
642 if (!lp_ea_support(SNUM(conn))) {
643 return NT_STATUS_NO_EAS_ON_FILE;
646 for (; ea_list; ea_list = ea_list->next) {
652 if (last_start != NULL && do_store_data) {
653 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
657 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
658 dos_namelen = strlen(dos_ea_name);
659 if (dos_namelen > 255 || dos_namelen == 0) {
660 return NT_STATUS_INTERNAL_ERROR;
662 if (ea_list->ea.value.length > 65535) {
663 return NT_STATUS_INTERNAL_ERROR;
666 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
669 pad = (4 - (this_size % 4)) % 4;
674 if (this_size > total_data_size) {
675 return NT_STATUS_INFO_LENGTH_MISMATCH;
678 /* We know we have room. */
679 SIVAL(p, 0x00, 0); /* next offset */
680 SCVAL(p, 0x04, ea_list->ea.flags);
681 SCVAL(p, 0x05, dos_namelen);
682 SSVAL(p, 0x06, ea_list->ea.value.length);
683 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
684 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
686 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
690 total_data_size -= this_size;
696 *ret_data_size = PTR_DIFF(p, pdata);
697 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
701 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
703 size_t total_ea_len = 0;
705 struct ea_list *ea_list = NULL;
707 if (!lp_ea_support(SNUM(conn))) {
710 mem_ctx = talloc_stackframe();
712 /* If this is a stream fsp, then we need to instead find the
713 * estimated ea len from the main file, not the stream
714 * (streams cannot have EAs), but the estimate isn't just 0 in
716 if (is_ntfs_stream_smb_fname(smb_fname)) {
719 (void)get_ea_list_from_file_path(mem_ctx,
725 if(conn->sconn->using_smb2) {
727 unsigned int ret_data_size;
729 * We're going to be using fill_ea_chained_buffer() to
730 * marshall EA's - this size is significantly larger
731 * than the SMB1 buffer. Re-calculate the size without
734 status = fill_ea_chained_buffer(mem_ctx,
740 if (!NT_STATUS_IS_OK(status)) {
743 total_ea_len = ret_data_size;
745 TALLOC_FREE(mem_ctx);
749 /****************************************************************************
750 Ensure the EA name is case insensitive by matching any existing EA name.
751 ****************************************************************************/
753 static void canonicalize_ea_name(connection_struct *conn,
755 const struct smb_filename *smb_fname,
756 fstring unix_ea_name)
759 TALLOC_CTX *mem_ctx = talloc_tos();
760 struct ea_list *ea_list;
761 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
767 if (!NT_STATUS_IS_OK(status)) {
771 for (; ea_list; ea_list = ea_list->next) {
772 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
773 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
774 &unix_ea_name[5], ea_list->ea.name));
775 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
781 /****************************************************************************
782 Set or delete an extended attribute.
783 ****************************************************************************/
785 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
786 const struct smb_filename *smb_fname, struct ea_list *ea_list)
789 bool posix_pathnames = false;
791 if (!lp_ea_support(SNUM(conn))) {
792 return NT_STATUS_EAS_NOT_SUPPORTED;
797 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
799 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
802 status = refuse_symlink(conn, fsp, smb_fname);
803 if (!NT_STATUS_IS_OK(status)) {
807 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
808 if (!NT_STATUS_IS_OK(status)) {
812 /* Setting EAs on streams isn't supported. */
813 if (is_ntfs_stream_smb_fname(smb_fname)) {
814 return NT_STATUS_INVALID_PARAMETER;
818 * Filter out invalid Windows EA names - before
819 * we set *any* of them.
822 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
823 return STATUS_INVALID_EA_NAME;
826 for (;ea_list; ea_list = ea_list->next) {
828 fstring unix_ea_name;
830 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
831 fstrcat(unix_ea_name, ea_list->ea.name);
833 canonicalize_ea_name(conn,
838 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
840 if (samba_private_attr_name(unix_ea_name)) {
841 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
842 return NT_STATUS_ACCESS_DENIED;
845 if (ea_list->ea.value.length == 0) {
846 /* Remove the attribute. */
847 if (fsp && (fsp->fh->fd != -1)) {
848 DEBUG(10,("set_ea: deleting ea name %s on "
849 "file %s by file descriptor.\n",
850 unix_ea_name, fsp_str_dbg(fsp)));
851 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
853 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
854 unix_ea_name, smb_fname->base_name));
855 ret = SMB_VFS_REMOVEXATTR(conn,
860 /* Removing a non existent attribute always succeeds. */
861 if (ret == -1 && errno == ENOATTR) {
862 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
868 if (fsp && (fsp->fh->fd != -1)) {
869 DEBUG(10,("set_ea: setting ea name %s on file "
870 "%s by file descriptor.\n",
871 unix_ea_name, fsp_str_dbg(fsp)));
872 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
873 ea_list->ea.value.data, ea_list->ea.value.length, 0);
875 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
876 unix_ea_name, smb_fname->base_name));
877 ret = SMB_VFS_SETXATTR(conn,
880 ea_list->ea.value.data,
881 ea_list->ea.value.length,
888 if (errno == ENOTSUP) {
889 return NT_STATUS_EAS_NOT_SUPPORTED;
892 return map_nt_error_from_unix(errno);
898 /****************************************************************************
899 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
900 ****************************************************************************/
902 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
904 struct ea_list *ea_list_head = NULL;
905 size_t converted_size, offset = 0;
907 while (offset + 2 < data_size) {
908 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
909 unsigned int namelen = CVAL(pdata,offset);
911 offset++; /* Go past the namelen byte. */
913 /* integer wrap paranioa. */
914 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
915 (offset > data_size) || (namelen > data_size) ||
916 (offset + namelen >= data_size)) {
919 /* Ensure the name is null terminated. */
920 if (pdata[offset + namelen] != '\0') {
923 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
925 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
926 "failed: %s", strerror(errno)));
932 offset += (namelen + 1); /* Go past the name + terminating zero. */
933 DLIST_ADD_END(ea_list_head, eal);
934 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
940 /****************************************************************************
941 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
942 ****************************************************************************/
944 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
946 struct ea_list *ea_list_head = NULL;
948 size_t bytes_used = 0;
950 while (offset < data_size) {
951 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
957 DLIST_ADD_END(ea_list_head, eal);
958 offset += bytes_used;
964 /****************************************************************************
965 Count the total EA size needed.
966 ****************************************************************************/
968 static size_t ea_list_size(struct ea_list *ealist)
971 struct ea_list *listp;
974 for (listp = ealist; listp; listp = listp->next) {
975 push_ascii_fstring(dos_ea_name, listp->ea.name);
976 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
978 /* Add on 4 for total length. */
986 /****************************************************************************
987 Return a union of EA's from a file list and a list of names.
988 The TALLOC context for the two lists *MUST* be identical as we steal
989 memory from one list to add to another. JRA.
990 ****************************************************************************/
992 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
994 struct ea_list *nlistp, *flistp;
996 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
997 for (flistp = file_list; flistp; flistp = flistp->next) {
998 if (strequal(nlistp->ea.name, flistp->ea.name)) {
1004 /* Copy the data from this entry. */
1005 nlistp->ea.flags = flistp->ea.flags;
1006 nlistp->ea.value = flistp->ea.value;
1009 nlistp->ea.flags = 0;
1010 ZERO_STRUCT(nlistp->ea.value);
1014 *total_ea_len = ea_list_size(name_list);
1018 /****************************************************************************
1019 Send the required number of replies back.
1020 We assume all fields other than the data fields are
1021 set correctly for the type of call.
1022 HACK ! Always assumes smb_setup field is zero.
1023 ****************************************************************************/
1025 void send_trans2_replies(connection_struct *conn,
1026 struct smb_request *req,
1034 /* As we are using a protocol > LANMAN1 then the max_send
1035 variable must have been set in the sessetupX call.
1036 This takes precedence over the max_xmit field in the
1037 global struct. These different max_xmit variables should
1038 be merged as this is now too confusing */
1040 int data_to_send = datasize;
1041 int params_to_send = paramsize;
1043 const char *pp = params;
1044 const char *pd = pdata;
1045 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1046 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1047 int data_alignment_offset = 0;
1048 bool overflow = False;
1049 struct smbXsrv_connection *xconn = req->xconn;
1050 int max_send = xconn->smb1.sessions.max_send;
1052 /* Modify the data_to_send and datasize and set the error if
1053 we're trying to send more than max_data_bytes. We still send
1054 the part of the packet(s) that fit. Strange, but needed
1057 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1058 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1059 max_data_bytes, datasize ));
1060 datasize = data_to_send = max_data_bytes;
1064 /* If there genuinely are no parameters or data to send just send the empty packet */
1066 if(params_to_send == 0 && data_to_send == 0) {
1067 reply_outbuf(req, 10, 0);
1068 if (NT_STATUS_V(status)) {
1071 ntstatus_to_dos(status, &eclass, &ecode);
1072 error_packet_set((char *)req->outbuf,
1073 eclass, ecode, status,
1076 show_msg((char *)req->outbuf);
1077 if (!srv_send_smb(xconn,
1078 (char *)req->outbuf,
1079 true, req->seqnum+1,
1080 IS_CONN_ENCRYPTED(conn),
1082 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1084 TALLOC_FREE(req->outbuf);
1088 /* When sending params and data ensure that both are nicely aligned */
1089 /* Only do this alignment when there is also data to send - else
1090 can cause NT redirector problems. */
1092 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1093 data_alignment_offset = 4 - (params_to_send % 4);
1095 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1096 /* The alignment_offset is to align the param bytes on an even byte
1097 boundary. NT 4.0 Beta needs this to work correctly. */
1099 useable_space = max_send - (smb_size
1102 + data_alignment_offset);
1104 if (useable_space < 0) {
1105 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1106 "= %d!!!", useable_space));
1107 exit_server_cleanly("send_trans2_replies: Not enough space");
1110 while (params_to_send || data_to_send) {
1111 /* Calculate whether we will totally or partially fill this packet */
1113 total_sent_thistime = params_to_send + data_to_send;
1115 /* We can never send more than useable_space */
1117 * Note that 'useable_space' does not include the alignment offsets,
1118 * but we must include the alignment offsets in the calculation of
1119 * the length of the data we send over the wire, as the alignment offsets
1120 * are sent here. Fix from Marc_Jacobsen@hp.com.
1123 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1125 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1126 + data_alignment_offset);
1128 /* Set total params and data to be sent */
1129 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1130 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1132 /* Calculate how many parameters and data we can fit into
1133 * this packet. Parameters get precedence
1136 params_sent_thistime = MIN(params_to_send,useable_space);
1137 data_sent_thistime = useable_space - params_sent_thistime;
1138 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1140 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1142 /* smb_proff is the offset from the start of the SMB header to the
1143 parameter bytes, however the first 4 bytes of outbuf are
1144 the Netbios over TCP header. Thus use smb_base() to subtract
1145 them from the calculation */
1147 SSVAL(req->outbuf,smb_proff,
1148 ((smb_buf(req->outbuf)+alignment_offset)
1149 - smb_base(req->outbuf)));
1151 if(params_sent_thistime == 0)
1152 SSVAL(req->outbuf,smb_prdisp,0);
1154 /* Absolute displacement of param bytes sent in this packet */
1155 SSVAL(req->outbuf,smb_prdisp,pp - params);
1157 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1158 if(data_sent_thistime == 0) {
1159 SSVAL(req->outbuf,smb_droff,0);
1160 SSVAL(req->outbuf,smb_drdisp, 0);
1162 /* The offset of the data bytes is the offset of the
1163 parameter bytes plus the number of parameters being sent this time */
1164 SSVAL(req->outbuf, smb_droff,
1165 ((smb_buf(req->outbuf)+alignment_offset)
1166 - smb_base(req->outbuf))
1167 + params_sent_thistime + data_alignment_offset);
1168 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1171 /* Initialize the padding for alignment */
1173 if (alignment_offset != 0) {
1174 memset(smb_buf(req->outbuf), 0, alignment_offset);
1177 /* Copy the param bytes into the packet */
1179 if(params_sent_thistime) {
1180 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1181 params_sent_thistime);
1184 /* Copy in the data bytes */
1185 if(data_sent_thistime) {
1186 if (data_alignment_offset != 0) {
1187 memset((smb_buf(req->outbuf)+alignment_offset+
1188 params_sent_thistime), 0,
1189 data_alignment_offset);
1191 memcpy(smb_buf(req->outbuf)+alignment_offset
1192 +params_sent_thistime+data_alignment_offset,
1193 pd,data_sent_thistime);
1196 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1197 params_sent_thistime, data_sent_thistime, useable_space));
1198 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1199 params_to_send, data_to_send, paramsize, datasize));
1202 error_packet_set((char *)req->outbuf,
1203 ERRDOS,ERRbufferoverflow,
1204 STATUS_BUFFER_OVERFLOW,
1206 } else if (NT_STATUS_V(status)) {
1209 ntstatus_to_dos(status, &eclass, &ecode);
1210 error_packet_set((char *)req->outbuf,
1211 eclass, ecode, status,
1215 /* Send the packet */
1216 show_msg((char *)req->outbuf);
1217 if (!srv_send_smb(xconn,
1218 (char *)req->outbuf,
1219 true, req->seqnum+1,
1220 IS_CONN_ENCRYPTED(conn),
1222 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1224 TALLOC_FREE(req->outbuf);
1226 pp += params_sent_thistime;
1227 pd += data_sent_thistime;
1229 params_to_send -= params_sent_thistime;
1230 data_to_send -= data_sent_thistime;
1233 if(params_to_send < 0 || data_to_send < 0) {
1234 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1235 params_to_send, data_to_send));
1243 /****************************************************************************
1244 Reply to a TRANSACT2_OPEN.
1245 ****************************************************************************/
1247 static void call_trans2open(connection_struct *conn,
1248 struct smb_request *req,
1249 char **pparams, int total_params,
1250 char **ppdata, int total_data,
1251 unsigned int max_data_bytes)
1253 struct smb_filename *smb_fname = NULL;
1254 char *params = *pparams;
1255 char *pdata = *ppdata;
1258 bool oplock_request;
1260 bool return_additional_info;
1269 int fattr=0,mtime=0;
1270 SMB_INO_T inode = 0;
1273 struct ea_list *ea_list = NULL;
1276 uint32_t access_mask;
1277 uint32_t share_mode;
1278 uint32_t create_disposition;
1279 uint32_t create_options = 0;
1280 uint32_t private_flags = 0;
1281 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1282 TALLOC_CTX *ctx = talloc_tos();
1285 * Ensure we have enough parameters to perform the operation.
1288 if (total_params < 29) {
1289 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1293 flags = SVAL(params, 0);
1294 deny_mode = SVAL(params, 2);
1295 open_attr = SVAL(params,6);
1296 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1297 if (oplock_request) {
1298 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1302 return_additional_info = BITSETW(params,0);
1303 open_sattr = SVAL(params, 4);
1304 open_time = make_unix_date3(params+8);
1306 open_ofun = SVAL(params,12);
1307 open_size = IVAL(params,14);
1308 pname = ¶ms[28];
1311 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1315 if (req->posix_pathnames) {
1316 srvstr_get_path_posix(ctx,
1325 srvstr_get_path(ctx,
1334 if (!NT_STATUS_IS_OK(status)) {
1335 reply_nterror(req, status);
1339 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1340 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1341 (unsigned int)open_ofun, open_size));
1343 status = filename_convert(ctx,
1350 if (!NT_STATUS_IS_OK(status)) {
1351 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1352 reply_botherror(req,
1353 NT_STATUS_PATH_NOT_COVERED,
1354 ERRSRV, ERRbadpath);
1357 reply_nterror(req, status);
1361 if (open_ofun == 0) {
1362 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1366 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1368 &access_mask, &share_mode,
1369 &create_disposition,
1372 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1376 /* Any data in this call is an EA list. */
1377 if (total_data && (total_data != 4)) {
1378 if (total_data < 10) {
1379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1383 if (IVAL(pdata,0) > total_data) {
1384 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1385 IVAL(pdata,0), (unsigned int)total_data));
1386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1390 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1393 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1397 if (!lp_ea_support(SNUM(conn))) {
1398 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1402 if (!req->posix_pathnames &&
1403 ea_list_has_invalid_name(ea_list)) {
1405 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1406 if(*pparams == NULL ) {
1407 reply_nterror(req, NT_STATUS_NO_MEMORY);
1411 memset(params, '\0', param_len);
1412 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1413 params, param_len, NULL, 0, max_data_bytes);
1418 status = SMB_VFS_CREATE_FILE(
1421 0, /* root_dir_fid */
1422 smb_fname, /* fname */
1423 access_mask, /* access_mask */
1424 share_mode, /* share_access */
1425 create_disposition, /* create_disposition*/
1426 create_options, /* create_options */
1427 open_attr, /* file_attributes */
1428 oplock_request, /* oplock_request */
1430 open_size, /* allocation_size */
1433 ea_list, /* ea_list */
1435 &smb_action, /* psbuf */
1436 NULL, NULL); /* create context */
1438 if (!NT_STATUS_IS_OK(status)) {
1439 if (open_was_deferred(req->xconn, req->mid)) {
1440 /* We have re-scheduled this call. */
1443 reply_openerror(req, status);
1447 size = get_file_size_stat(&smb_fname->st);
1448 fattr = dos_mode(conn, smb_fname);
1449 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1450 inode = smb_fname->st.st_ex_ino;
1451 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1452 close_file(req, fsp, ERROR_CLOSE);
1453 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1457 /* Realloc the size of parameters and data we will return */
1458 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1459 if(*pparams == NULL ) {
1460 reply_nterror(req, NT_STATUS_NO_MEMORY);
1465 SSVAL(params,0,fsp->fnum);
1466 SSVAL(params,2,fattr);
1467 srv_put_dos_date2(params,4, mtime);
1468 SIVAL(params,8, (uint32_t)size);
1469 SSVAL(params,12,deny_mode);
1470 SSVAL(params,14,0); /* open_type - file or directory. */
1471 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1473 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1474 smb_action |= EXTENDED_OPLOCK_GRANTED;
1477 SSVAL(params,18,smb_action);
1480 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1482 SIVAL(params,20,inode);
1483 SSVAL(params,24,0); /* Padding. */
1485 uint32_t ea_size = estimate_ea_size(conn, fsp,
1487 SIVAL(params, 26, ea_size);
1489 SIVAL(params, 26, 0);
1492 /* Send the required number of replies */
1493 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1495 TALLOC_FREE(smb_fname);
1498 /*********************************************************
1499 Routine to check if a given string matches exactly.
1500 as a special case a mask of "." does NOT match. That
1501 is required for correct wildcard semantics
1502 Case can be significant or not.
1503 **********************************************************/
1505 static bool exact_match(bool has_wild,
1506 bool case_sensitive,
1510 if (mask[0] == '.' && mask[1] == 0) {
1518 if (case_sensitive) {
1519 return strcmp(str,mask)==0;
1521 return strcasecmp_m(str,mask) == 0;
1525 /****************************************************************************
1526 Return the filetype for UNIX extensions.
1527 ****************************************************************************/
1529 static uint32_t unix_filetype(mode_t mode)
1532 return UNIX_TYPE_FILE;
1533 else if(S_ISDIR(mode))
1534 return UNIX_TYPE_DIR;
1536 else if(S_ISLNK(mode))
1537 return UNIX_TYPE_SYMLINK;
1540 else if(S_ISCHR(mode))
1541 return UNIX_TYPE_CHARDEV;
1544 else if(S_ISBLK(mode))
1545 return UNIX_TYPE_BLKDEV;
1548 else if(S_ISFIFO(mode))
1549 return UNIX_TYPE_FIFO;
1552 else if(S_ISSOCK(mode))
1553 return UNIX_TYPE_SOCKET;
1556 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1557 return UNIX_TYPE_UNKNOWN;
1560 /****************************************************************************
1561 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1562 ****************************************************************************/
1564 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1566 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1567 const SMB_STRUCT_STAT *psbuf,
1569 enum perm_type ptype,
1574 if (perms == SMB_MODE_NO_CHANGE) {
1575 if (!VALID_STAT(*psbuf)) {
1576 return NT_STATUS_INVALID_PARAMETER;
1578 *ret_perms = psbuf->st_ex_mode;
1579 return NT_STATUS_OK;
1583 ret = wire_perms_to_unix(perms);
1585 if (ptype == PERM_NEW_FILE) {
1587 * "create mask"/"force create mode" are
1588 * only applied to new files, not existing ones.
1590 ret &= lp_create_mask(SNUM(conn));
1591 /* Add in force bits */
1592 ret |= lp_force_create_mode(SNUM(conn));
1593 } else if (ptype == PERM_NEW_DIR) {
1595 * "directory mask"/"force directory mode" are
1596 * only applied to new directories, not existing ones.
1598 ret &= lp_directory_mask(SNUM(conn));
1599 /* Add in force bits */
1600 ret |= lp_force_directory_mode(SNUM(conn));
1604 return NT_STATUS_OK;
1607 /****************************************************************************
1608 Needed to show the msdfs symlinks as directories. Modifies psbuf
1609 to be a directory if it's a msdfs link.
1610 ****************************************************************************/
1612 static bool check_msdfs_link(connection_struct *conn,
1613 struct smb_filename *smb_fname)
1615 int saved_errno = errno;
1616 if(lp_host_msdfs() &&
1617 lp_msdfs_root(SNUM(conn)) &&
1618 is_msdfs_link(conn, smb_fname)) {
1620 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1622 smb_fname->base_name));
1623 smb_fname->st.st_ex_mode =
1624 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1625 errno = saved_errno;
1628 errno = saved_errno;
1633 /****************************************************************************
1634 Get a level dependent lanman2 dir entry.
1635 ****************************************************************************/
1637 struct smbd_dirptr_lanman2_state {
1638 connection_struct *conn;
1639 uint32_t info_level;
1640 bool check_mangled_names;
1642 bool got_exact_match;
1645 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1651 struct smbd_dirptr_lanman2_state *state =
1652 (struct smbd_dirptr_lanman2_state *)private_data;
1654 char mangled_name[13]; /* mangled 8.3 name. */
1658 /* Mangle fname if it's an illegal name. */
1659 if (mangle_must_mangle(dname, state->conn->params)) {
1661 * Slow path - ensure we can push the original name as UCS2. If
1662 * not, then just don't return this name.
1666 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1667 uint8_t *tmp = talloc_array(talloc_tos(),
1671 status = srvstr_push(NULL,
1672 FLAGS2_UNICODE_STRINGS,
1681 if (!NT_STATUS_IS_OK(status)) {
1685 ok = name_to_8_3(dname, mangled_name,
1686 true, state->conn->params);
1690 fname = mangled_name;
1695 got_match = exact_match(state->has_wild,
1696 state->conn->case_sensitive,
1698 state->got_exact_match = got_match;
1700 got_match = mask_match(fname, mask,
1701 state->conn->case_sensitive);
1704 if(!got_match && state->check_mangled_names &&
1705 !mangle_is_8_3(fname, false, state->conn->params)) {
1707 * It turns out that NT matches wildcards against
1708 * both long *and* short names. This may explain some
1709 * of the wildcard wierdness from old DOS clients
1710 * that some people have been seeing.... JRA.
1712 /* Force the mangling into 8.3. */
1713 ok = name_to_8_3(fname, mangled_name,
1714 false, state->conn->params);
1719 got_match = exact_match(state->has_wild,
1720 state->conn->case_sensitive,
1721 mangled_name, mask);
1722 state->got_exact_match = got_match;
1724 got_match = mask_match(mangled_name, mask,
1725 state->conn->case_sensitive);
1733 *_fname = talloc_strdup(ctx, fname);
1734 if (*_fname == NULL) {
1741 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1743 struct smb_filename *smb_fname,
1747 struct smbd_dirptr_lanman2_state *state =
1748 (struct smbd_dirptr_lanman2_state *)private_data;
1749 bool ms_dfs_link = false;
1752 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1753 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1754 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1755 "Couldn't lstat [%s] (%s)\n",
1756 smb_fname_str_dbg(smb_fname),
1760 } else if (!VALID_STAT(smb_fname->st) &&
1761 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1762 /* Needed to show the msdfs symlinks as
1765 ms_dfs_link = check_msdfs_link(state->conn,
1768 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1769 "Couldn't stat [%s] (%s)\n",
1770 smb_fname_str_dbg(smb_fname),
1777 mode = dos_mode_msdfs(state->conn, smb_fname);
1778 } else if (get_dosmode) {
1779 mode = dos_mode(state->conn, smb_fname);
1786 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1787 connection_struct *conn,
1789 uint32_t info_level,
1790 struct ea_list *name_list,
1791 bool check_mangled_names,
1792 bool requires_resume_key,
1795 const struct smb_filename *smb_fname,
1796 int space_remaining,
1802 uint64_t *last_entry_off)
1804 char *p, *q, *pdata = *ppdata;
1806 uint64_t file_size = 0;
1807 uint64_t allocation_size = 0;
1808 uint64_t file_id = 0;
1810 struct timespec mdate_ts = {0};
1811 struct timespec adate_ts = {0};
1812 struct timespec cdate_ts = {0};
1813 struct timespec create_date_ts = {0};
1814 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1816 char *last_entry_ptr;
1821 struct readdir_attr_data *readdir_attr_data = NULL;
1823 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1824 file_size = get_file_size_stat(&smb_fname->st);
1826 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1828 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1829 if (!NT_STATUS_IS_OK(status)) {
1830 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1835 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1837 mdate_ts = smb_fname->st.st_ex_mtime;
1838 adate_ts = smb_fname->st.st_ex_atime;
1839 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1840 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1842 if (lp_dos_filetime_resolution(SNUM(conn))) {
1843 dos_filetime_timespec(&create_date_ts);
1844 dos_filetime_timespec(&mdate_ts);
1845 dos_filetime_timespec(&adate_ts);
1846 dos_filetime_timespec(&cdate_ts);
1849 create_date = convert_timespec_to_time_t(create_date_ts);
1850 mdate = convert_timespec_to_time_t(mdate_ts);
1851 adate = convert_timespec_to_time_t(adate_ts);
1853 /* align the record */
1854 SMB_ASSERT(align >= 1);
1856 off = (int)PTR_DIFF(pdata, base_data);
1857 pad = (off + (align-1)) & ~(align-1);
1860 if (pad && pad > space_remaining) {
1861 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1862 "for padding (wanted %u, had %d)\n",
1865 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1869 /* initialize padding to 0 */
1871 memset(pdata, 0, pad);
1873 space_remaining -= pad;
1875 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1885 switch (info_level) {
1886 case SMB_FIND_INFO_STANDARD:
1887 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1888 if(requires_resume_key) {
1892 srv_put_dos_date2(p,0,create_date);
1893 srv_put_dos_date2(p,4,adate);
1894 srv_put_dos_date2(p,8,mdate);
1895 SIVAL(p,12,(uint32_t)file_size);
1896 SIVAL(p,16,(uint32_t)allocation_size);
1900 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1901 p += ucs2_align(base_data, p, 0);
1903 status = srvstr_push(base_data, flags2, p,
1904 fname, PTR_DIFF(end_data, p),
1905 STR_TERMINATE, &len);
1906 if (!NT_STATUS_IS_OK(status)) {
1909 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1911 SCVAL(nameptr, -1, len - 2);
1913 SCVAL(nameptr, -1, 0);
1917 SCVAL(nameptr, -1, len - 1);
1919 SCVAL(nameptr, -1, 0);
1925 case SMB_FIND_EA_SIZE:
1926 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1927 if (requires_resume_key) {
1931 srv_put_dos_date2(p,0,create_date);
1932 srv_put_dos_date2(p,4,adate);
1933 srv_put_dos_date2(p,8,mdate);
1934 SIVAL(p,12,(uint32_t)file_size);
1935 SIVAL(p,16,(uint32_t)allocation_size);
1938 unsigned int ea_size = estimate_ea_size(conn, NULL,
1940 SIVAL(p,22,ea_size); /* Extended attributes */
1944 status = srvstr_push(base_data, flags2,
1945 p, fname, PTR_DIFF(end_data, p),
1946 STR_TERMINATE | STR_NOALIGN, &len);
1947 if (!NT_STATUS_IS_OK(status)) {
1950 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1963 SCVAL(nameptr,0,len);
1965 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1968 case SMB_FIND_EA_LIST:
1970 struct ea_list *file_list = NULL;
1973 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1975 return NT_STATUS_INVALID_PARAMETER;
1977 if (requires_resume_key) {
1981 srv_put_dos_date2(p,0,create_date);
1982 srv_put_dos_date2(p,4,adate);
1983 srv_put_dos_date2(p,8,mdate);
1984 SIVAL(p,12,(uint32_t)file_size);
1985 SIVAL(p,16,(uint32_t)allocation_size);
1987 p += 22; /* p now points to the EA area. */
1989 status = get_ea_list_from_file(ctx, conn, NULL,
1991 &ea_len, &file_list);
1992 if (!NT_STATUS_IS_OK(status)) {
1995 name_list = ea_list_union(name_list, file_list, &ea_len);
1997 /* We need to determine if this entry will fit in the space available. */
1998 /* Max string size is 255 bytes. */
1999 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2000 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2001 "(wanted %u, had %d)\n",
2002 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2004 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2007 /* Push the ea_data followed by the name. */
2008 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2010 status = srvstr_push(base_data, flags2,
2011 p + 1, fname, PTR_DIFF(end_data, p+1),
2012 STR_TERMINATE | STR_NOALIGN, &len);
2013 if (!NT_STATUS_IS_OK(status)) {
2016 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2029 SCVAL(nameptr,0,len);
2031 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2035 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2036 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2037 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2039 SIVAL(p,0,reskey); p += 4;
2040 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2041 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2042 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2043 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2044 SOFF_T(p,0,file_size); p += 8;
2045 SOFF_T(p,0,allocation_size); p += 8;
2046 SIVAL(p,0,mode); p += 4;
2047 q = p; p += 4; /* q is placeholder for name length. */
2048 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2049 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2051 unsigned int ea_size = estimate_ea_size(conn, NULL,
2053 SIVAL(p,0,ea_size); /* Extended attributes */
2056 /* Clear the short name buffer. This is
2057 * IMPORTANT as not doing so will trigger
2058 * a Win2k client bug. JRA.
2060 if (!was_8_3 && check_mangled_names) {
2061 char mangled_name[13]; /* mangled 8.3 name. */
2062 if (!name_to_8_3(fname,mangled_name,True,
2064 /* Error - mangle failed ! */
2065 memset(mangled_name,'\0',12);
2067 mangled_name[12] = 0;
2068 status = srvstr_push(base_data, flags2,
2069 p+2, mangled_name, 24,
2070 STR_UPPER|STR_UNICODE, &len);
2071 if (!NT_STATUS_IS_OK(status)) {
2075 memset(p + 2 + len,'\0',24 - len);
2082 status = srvstr_push(base_data, flags2, p,
2083 fname, PTR_DIFF(end_data, p),
2084 STR_TERMINATE_ASCII, &len);
2085 if (!NT_STATUS_IS_OK(status)) {
2091 len = PTR_DIFF(p, pdata);
2092 pad = (len + (align-1)) & ~(align-1);
2094 * offset to the next entry, the caller
2095 * will overwrite it for the last entry
2096 * that's why we always include the padding
2100 * set padding to zero
2103 memset(p, 0, pad - len);
2110 case SMB_FIND_FILE_DIRECTORY_INFO:
2111 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2113 SIVAL(p,0,reskey); p += 4;
2114 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2115 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2116 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2117 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2118 SOFF_T(p,0,file_size); p += 8;
2119 SOFF_T(p,0,allocation_size); p += 8;
2120 SIVAL(p,0,mode); p += 4;
2121 status = srvstr_push(base_data, flags2,
2122 p + 4, fname, PTR_DIFF(end_data, p+4),
2123 STR_TERMINATE_ASCII, &len);
2124 if (!NT_STATUS_IS_OK(status)) {
2130 len = PTR_DIFF(p, pdata);
2131 pad = (len + (align-1)) & ~(align-1);
2133 * offset to the next entry, the caller
2134 * will overwrite it for the last entry
2135 * that's why we always include the padding
2139 * set padding to zero
2142 memset(p, 0, pad - len);
2149 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2150 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2152 SIVAL(p,0,reskey); p += 4;
2153 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2154 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2155 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2156 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2157 SOFF_T(p,0,file_size); p += 8;
2158 SOFF_T(p,0,allocation_size); p += 8;
2159 SIVAL(p,0,mode); p += 4;
2160 q = p; p += 4; /* q is placeholder for name length. */
2161 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2162 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2164 unsigned int ea_size = estimate_ea_size(conn, NULL,
2166 SIVAL(p,0,ea_size); /* Extended attributes */
2169 status = srvstr_push(base_data, flags2, p,
2170 fname, PTR_DIFF(end_data, p),
2171 STR_TERMINATE_ASCII, &len);
2172 if (!NT_STATUS_IS_OK(status)) {
2178 len = PTR_DIFF(p, pdata);
2179 pad = (len + (align-1)) & ~(align-1);
2181 * offset to the next entry, the caller
2182 * will overwrite it for the last entry
2183 * that's why we always include the padding
2187 * set padding to zero
2190 memset(p, 0, pad - len);
2197 case SMB_FIND_FILE_NAMES_INFO:
2198 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2200 SIVAL(p,0,reskey); p += 4;
2202 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2203 acl on a dir (tridge) */
2204 status = srvstr_push(base_data, flags2, p,
2205 fname, PTR_DIFF(end_data, p),
2206 STR_TERMINATE_ASCII, &len);
2207 if (!NT_STATUS_IS_OK(status)) {
2213 len = PTR_DIFF(p, pdata);
2214 pad = (len + (align-1)) & ~(align-1);
2216 * offset to the next entry, the caller
2217 * will overwrite it for the last entry
2218 * that's why we always include the padding
2222 * set padding to zero
2225 memset(p, 0, pad - len);
2232 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2233 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2235 SIVAL(p,0,reskey); p += 4;
2236 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2237 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2238 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2239 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2240 SOFF_T(p,0,file_size); p += 8;
2241 SOFF_T(p,0,allocation_size); p += 8;
2242 SIVAL(p,0,mode); p += 4;
2243 q = p; p += 4; /* q is placeholder for name length. */
2244 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2245 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2247 unsigned int ea_size = estimate_ea_size(conn, NULL,
2249 SIVAL(p,0,ea_size); /* Extended attributes */
2252 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2253 SBVAL(p,0,file_id); p += 8;
2254 status = srvstr_push(base_data, flags2, p,
2255 fname, PTR_DIFF(end_data, p),
2256 STR_TERMINATE_ASCII, &len);
2257 if (!NT_STATUS_IS_OK(status)) {
2263 len = PTR_DIFF(p, pdata);
2264 pad = (len + (align-1)) & ~(align-1);
2266 * offset to the next entry, the caller
2267 * will overwrite it for the last entry
2268 * that's why we always include the padding
2272 * set padding to zero
2275 memset(p, 0, pad - len);
2282 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2283 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2284 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2286 SIVAL(p,0,reskey); p += 4;
2287 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2288 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2289 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2290 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2291 SOFF_T(p,0,file_size); p += 8;
2292 SOFF_T(p,0,allocation_size); p += 8;
2293 SIVAL(p,0,mode); p += 4;
2294 q = p; p += 4; /* q is placeholder for name length */
2295 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2296 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2297 } else if (readdir_attr_data &&
2298 readdir_attr_data->type == RDATTR_AAPL) {
2300 * OS X specific SMB2 extension negotiated via
2301 * AAPL create context: return max_access in
2304 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2306 unsigned int ea_size = estimate_ea_size(conn, NULL,
2308 SIVAL(p,0,ea_size); /* Extended attributes */
2312 if (readdir_attr_data &&
2313 readdir_attr_data->type == RDATTR_AAPL) {
2315 * OS X specific SMB2 extension negotiated via
2316 * AAPL create context: return resource fork
2317 * length and compressed FinderInfo in
2320 * According to documentation short_name_len
2321 * should be 0, but on the wire behaviour
2322 * shows its set to 24 by clients.
2326 /* Resourefork length */
2327 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2329 /* Compressed FinderInfo */
2330 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2331 } else if (!was_8_3 && check_mangled_names) {
2332 char mangled_name[13]; /* mangled 8.3 name. */
2333 if (!name_to_8_3(fname,mangled_name,True,
2335 /* Error - mangle failed ! */
2336 memset(mangled_name,'\0',12);
2338 mangled_name[12] = 0;
2339 status = srvstr_push(base_data, flags2,
2340 p+2, mangled_name, 24,
2341 STR_UPPER|STR_UNICODE, &len);
2342 if (!NT_STATUS_IS_OK(status)) {
2347 memset(p + 2 + len,'\0',24 - len);
2351 /* Clear the short name buffer. This is
2352 * IMPORTANT as not doing so will trigger
2353 * a Win2k client bug. JRA.
2360 if (readdir_attr_data &&
2361 readdir_attr_data->type == RDATTR_AAPL) {
2363 * OS X specific SMB2 extension negotiated via
2364 * AAPL create context: return UNIX mode in
2367 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2368 SSVAL(p, 0, aapl_mode);
2374 SBVAL(p,0,file_id); p += 8;
2375 status = srvstr_push(base_data, flags2, p,
2376 fname, PTR_DIFF(end_data, p),
2377 STR_TERMINATE_ASCII, &len);
2378 if (!NT_STATUS_IS_OK(status)) {
2384 len = PTR_DIFF(p, pdata);
2385 pad = (len + (align-1)) & ~(align-1);
2387 * offset to the next entry, the caller
2388 * will overwrite it for the last entry
2389 * that's why we always include the padding
2393 * set padding to zero
2396 memset(p, 0, pad - len);
2403 /* CIFS UNIX Extension. */
2405 case SMB_FIND_FILE_UNIX:
2406 case SMB_FIND_FILE_UNIX_INFO2:
2408 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2410 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2412 if (info_level == SMB_FIND_FILE_UNIX) {
2413 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2414 p = store_file_unix_basic(conn, p,
2415 NULL, &smb_fname->st);
2416 status = srvstr_push(base_data, flags2, p,
2417 fname, PTR_DIFF(end_data, p),
2418 STR_TERMINATE, &len);
2419 if (!NT_STATUS_IS_OK(status)) {
2423 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2424 p = store_file_unix_basic_info2(conn, p,
2425 NULL, &smb_fname->st);
2428 status = srvstr_push(base_data, flags2, p, fname,
2429 PTR_DIFF(end_data, p), 0, &len);
2430 if (!NT_STATUS_IS_OK(status)) {
2433 SIVAL(nameptr, 0, len);
2438 len = PTR_DIFF(p, pdata);
2439 pad = (len + (align-1)) & ~(align-1);
2441 * offset to the next entry, the caller
2442 * will overwrite it for the last entry
2443 * that's why we always include the padding
2447 * set padding to zero
2450 memset(p, 0, pad - len);
2455 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2460 return NT_STATUS_INVALID_LEVEL;
2463 if (PTR_DIFF(p,pdata) > space_remaining) {
2464 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2465 "(wanted %u, had %d)\n",
2466 (unsigned int)PTR_DIFF(p,pdata),
2468 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2471 /* Setup the last entry pointer, as an offset from base_data */
2472 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2473 /* Advance the data pointer to the next slot */
2476 return NT_STATUS_OK;
2479 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2480 connection_struct *conn,
2481 struct dptr_struct *dirptr,
2483 const char *path_mask,
2486 int requires_resume_key,
2495 int space_remaining,
2496 struct smb_filename **_smb_fname,
2497 bool *got_exact_match,
2498 int *_last_entry_off,
2499 struct ea_list *name_list,
2500 struct file_id *file_id)
2503 const char *mask = NULL;
2504 long prev_dirpos = 0;
2507 struct smb_filename *smb_fname = NULL;
2508 struct smbd_dirptr_lanman2_state state;
2510 uint64_t last_entry_off = 0;
2512 enum mangled_names_options mangled_names;
2513 bool marshall_with_83_names;
2515 mangled_names = lp_mangled_names(conn->params);
2519 state.info_level = info_level;
2520 if (mangled_names != MANGLED_NAMES_NO) {
2521 state.check_mangled_names = true;
2523 state.has_wild = dptr_has_wild(dirptr);
2524 state.got_exact_match = false;
2526 *got_exact_match = false;
2528 p = strrchr_m(path_mask,'/');
2539 ok = smbd_dirptr_get_entry(ctx,
2546 smbd_dirptr_lanman2_match_fn,
2547 smbd_dirptr_lanman2_mode_fn,
2554 return NT_STATUS_END_OF_FILE;
2557 *got_exact_match = state.got_exact_match;
2559 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2561 status = smbd_marshall_dir_entry(ctx,
2566 marshall_with_83_names,
2567 requires_resume_key,
2578 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2579 DEBUG(1,("Conversion error: illegal character: %s\n",
2580 smb_fname_str_dbg(smb_fname)));
2583 if (file_id != NULL) {
2584 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2587 if (!NT_STATUS_IS_OK(status) &&
2588 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2590 TALLOC_FREE(smb_fname);
2595 if (_smb_fname != NULL) {
2596 struct smb_filename *name = NULL;
2598 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2600 TALLOC_FREE(smb_fname);
2602 return NT_STATUS_NO_MEMORY;
2607 TALLOC_FREE(smb_fname);
2610 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2611 dptr_SeekDir(dirptr, prev_dirpos);
2615 *_last_entry_off = last_entry_off;
2616 return NT_STATUS_OK;
2619 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2620 connection_struct *conn,
2621 struct dptr_struct *dirptr,
2623 const char *path_mask,
2626 bool requires_resume_key,
2632 int space_remaining,
2633 bool *got_exact_match,
2634 int *last_entry_off,
2635 struct ea_list *name_list)
2638 const bool do_pad = true;
2640 if (info_level >= 1 && info_level <= 3) {
2641 /* No alignment on earlier info levels. */
2645 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2646 path_mask, dirtype, info_level,
2647 requires_resume_key, dont_descend, ask_sharemode,
2648 true, align, do_pad,
2649 ppdata, base_data, end_data,
2653 last_entry_off, name_list, NULL);
2656 /****************************************************************************
2657 Reply to a TRANS2_FINDFIRST.
2658 ****************************************************************************/
2660 static void call_trans2findfirst(connection_struct *conn,
2661 struct smb_request *req,
2662 char **pparams, int total_params,
2663 char **ppdata, int total_data,
2664 unsigned int max_data_bytes)
2666 /* We must be careful here that we don't return more than the
2667 allowed number of data bytes. If this means returning fewer than
2668 maxentries then so be it. We assume that the redirector has
2669 enough room for the fixed number of parameter bytes it has
2671 struct smb_filename *smb_dname = NULL;
2672 char *params = *pparams;
2673 char *pdata = *ppdata;
2677 uint16_t findfirst_flags;
2678 bool close_after_first;
2680 bool requires_resume_key;
2682 char *directory = NULL;
2685 int last_entry_off=0;
2689 bool finished = False;
2690 bool dont_descend = False;
2691 bool out_of_space = False;
2692 int space_remaining;
2693 bool mask_contains_wcard = False;
2694 struct ea_list *ea_list = NULL;
2695 NTSTATUS ntstatus = NT_STATUS_OK;
2696 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2697 struct dptr_struct *dirptr = NULL;
2698 struct smbd_server_connection *sconn = req->sconn;
2699 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2700 ucf_flags_from_smb_request(req);
2701 bool backup_priv = false;
2702 bool as_root = false;
2704 if (total_params < 13) {
2705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2709 dirtype = SVAL(params,0);
2710 maxentries = SVAL(params,2);
2711 findfirst_flags = SVAL(params,4);
2712 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2713 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2714 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2715 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2716 security_token_has_privilege(get_current_nttok(conn),
2719 info_level = SVAL(params,6);
2721 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2722 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2723 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2725 info_level, max_data_bytes));
2728 /* W2K3 seems to treat zero as 1. */
2732 switch (info_level) {
2733 case SMB_FIND_INFO_STANDARD:
2734 case SMB_FIND_EA_SIZE:
2735 case SMB_FIND_EA_LIST:
2736 case SMB_FIND_FILE_DIRECTORY_INFO:
2737 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2738 case SMB_FIND_FILE_NAMES_INFO:
2739 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2740 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2741 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2743 case SMB_FIND_FILE_UNIX:
2744 case SMB_FIND_FILE_UNIX_INFO2:
2745 /* Always use filesystem for UNIX mtime query. */
2746 ask_sharemode = false;
2747 if (!lp_unix_extensions()) {
2748 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2751 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2754 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2758 if (req->posix_pathnames) {
2759 srvstr_get_path_wcard_posix(talloc_tos(),
2767 &mask_contains_wcard);
2769 srvstr_get_path_wcard(talloc_tos(),
2777 &mask_contains_wcard);
2779 if (!NT_STATUS_IS_OK(ntstatus)) {
2780 reply_nterror(req, ntstatus);
2787 ntstatus = filename_convert_with_privilege(talloc_tos(),
2792 &mask_contains_wcard,
2795 ntstatus = filename_convert(talloc_tos(), conn,
2799 &mask_contains_wcard,
2803 if (!NT_STATUS_IS_OK(ntstatus)) {
2804 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2805 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2806 ERRSRV, ERRbadpath);
2809 reply_nterror(req, ntstatus);
2813 mask = smb_dname->original_lcomp;
2815 directory = smb_dname->base_name;
2817 p = strrchr_m(directory,'/');
2819 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2820 if((directory[0] == '.') && (directory[1] == '\0')) {
2821 mask = talloc_strdup(talloc_tos(),"*");
2823 reply_nterror(req, NT_STATUS_NO_MEMORY);
2826 mask_contains_wcard = True;
2832 if (p == NULL || p == directory) {
2833 /* Ensure we don't have a directory name of "". */
2834 directory = talloc_strdup(talloc_tos(), ".");
2836 reply_nterror(req, NT_STATUS_NO_MEMORY);
2839 /* Ensure smb_dname->base_name matches. */
2840 smb_dname->base_name = directory;
2843 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2845 if (info_level == SMB_FIND_EA_LIST) {
2848 if (total_data < 4) {
2849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2853 ea_size = IVAL(pdata,0);
2854 if (ea_size != total_data) {
2855 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2856 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2861 if (!lp_ea_support(SNUM(conn))) {
2862 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2866 /* Pull out the list of names. */
2867 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2874 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2879 *ppdata = (char *)SMB_REALLOC(
2880 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2881 if(*ppdata == NULL ) {
2882 reply_nterror(req, NT_STATUS_NO_MEMORY);
2886 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2888 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2891 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2892 /* Realloc the params space */
2893 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2894 if (*pparams == NULL) {
2895 reply_nterror(req, NT_STATUS_NO_MEMORY);
2900 /* Save the wildcard match and attribs we are using on this directory -
2901 needed as lanman2 assumes these are being saved between calls */
2903 ntstatus = dptr_create(conn,
2911 mask_contains_wcard,
2915 if (!NT_STATUS_IS_OK(ntstatus)) {
2916 reply_nterror(req, ntstatus);
2921 /* Remember this in case we have
2922 to do a findnext. */
2923 dptr_set_priv(dirptr);
2926 dptr_num = dptr_dnum(dirptr);
2927 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2929 /* We don't need to check for VOL here as this is returned by
2930 a different TRANS2 call. */
2932 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2933 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2934 if (in_list(directory,
2935 lp_dont_descend(talloc_tos(), SNUM(conn)),
2936 conn->case_sensitive)) {
2937 dont_descend = True;
2941 space_remaining = max_data_bytes;
2942 out_of_space = False;
2944 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2945 bool got_exact_match = False;
2947 /* this is a heuristic to avoid seeking the dirptr except when
2948 absolutely necessary. It allows for a filename of about 40 chars */
2949 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2950 out_of_space = True;
2953 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2957 mask,dirtype,info_level,
2958 requires_resume_key,dont_descend,
2963 &last_entry_off, ea_list);
2964 if (NT_STATUS_EQUAL(ntstatus,
2965 NT_STATUS_ILLEGAL_CHARACTER)) {
2967 * Bad character conversion on name. Ignore this
2972 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2973 out_of_space = true;
2975 finished = !NT_STATUS_IS_OK(ntstatus);
2979 if (!finished && !out_of_space)
2983 * As an optimisation if we know we aren't looking
2984 * for a wildcard name (ie. the name matches the wildcard exactly)
2985 * then we can finish on any (first) match.
2986 * This speeds up large directory searches. JRA.
2992 /* Ensure space_remaining never goes -ve. */
2993 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2994 space_remaining = 0;
2995 out_of_space = true;
2997 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3001 /* Check if we can close the dirptr */
3002 if(close_after_first || (finished && close_if_end)) {
3003 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3004 dptr_close(sconn, &dptr_num);
3008 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3009 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3010 * the protocol level is less than NT1. Tested with smbclient. JRA.
3011 * This should fix the OS/2 client bug #2335.
3014 if(numentries == 0) {
3015 dptr_close(sconn, &dptr_num);
3016 if (get_Protocol() < PROTOCOL_NT1) {
3017 reply_force_doserror(req, ERRDOS, ERRnofiles);
3020 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3021 ERRDOS, ERRbadfile);
3026 /* At this point pdata points to numentries directory entries. */
3028 /* Set up the return parameter block */
3029 SSVAL(params,0,dptr_num);
3030 SSVAL(params,2,numentries);
3031 SSVAL(params,4,finished);
3032 SSVAL(params,6,0); /* Never an EA error */
3033 SSVAL(params,8,last_entry_off);
3035 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3038 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3039 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3041 reply_nterror(req, NT_STATUS_NO_MEMORY);
3045 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3046 smb_fn_name(req->cmd),
3047 mask, directory, dirtype, numentries ) );
3050 * Force a name mangle here to ensure that the
3051 * mask as an 8.3 name is top of the mangled cache.
3052 * The reasons for this are subtle. Don't remove
3053 * this code unless you know what you are doing
3054 * (see PR#13758). JRA.
3057 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3058 char mangled_name[13];
3059 name_to_8_3(mask, mangled_name, True, conn->params);
3067 TALLOC_FREE(smb_dname);
3071 /****************************************************************************
3072 Reply to a TRANS2_FINDNEXT.
3073 ****************************************************************************/
3075 static void call_trans2findnext(connection_struct *conn,
3076 struct smb_request *req,
3077 char **pparams, int total_params,
3078 char **ppdata, int total_data,
3079 unsigned int max_data_bytes)
3081 /* We must be careful here that we don't return more than the
3082 allowed number of data bytes. If this means returning fewer than
3083 maxentries then so be it. We assume that the redirector has
3084 enough room for the fixed number of parameter bytes it has
3086 char *params = *pparams;
3087 char *pdata = *ppdata;
3091 uint16_t info_level;
3092 uint32_t resume_key;
3093 uint16_t findnext_flags;
3094 bool close_after_request;
3096 bool requires_resume_key;
3098 bool mask_contains_wcard = False;
3099 char *resume_name = NULL;
3100 const char *mask = NULL;
3101 const char *directory = NULL;
3105 int i, last_entry_off=0;
3106 bool finished = False;
3107 bool dont_descend = False;
3108 bool out_of_space = False;
3109 int space_remaining;
3110 struct ea_list *ea_list = NULL;
3111 NTSTATUS ntstatus = NT_STATUS_OK;
3112 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3113 TALLOC_CTX *ctx = talloc_tos();
3114 struct dptr_struct *dirptr;
3115 struct smbd_server_connection *sconn = req->sconn;
3116 bool backup_priv = false;
3117 bool as_root = false;
3119 if (total_params < 13) {
3120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3124 dptr_num = SVAL(params,0);
3125 maxentries = SVAL(params,2);
3126 info_level = SVAL(params,4);
3127 resume_key = IVAL(params,6);
3128 findnext_flags = SVAL(params,10);
3129 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3130 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3131 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3132 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3134 if (!continue_bit) {
3135 /* We only need resume_name if continue_bit is zero. */
3136 if (req->posix_pathnames) {
3137 srvstr_get_path_wcard_posix(ctx,
3145 &mask_contains_wcard);
3147 srvstr_get_path_wcard(ctx,
3155 &mask_contains_wcard);
3157 if (!NT_STATUS_IS_OK(ntstatus)) {
3158 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3159 complain (it thinks we're asking for the directory above the shared
3160 path or an invalid name). Catch this as the resume name is only compared, never used in
3161 a file access. JRA. */
3162 srvstr_pull_talloc(ctx, params, req->flags2,
3163 &resume_name, params+12,
3167 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3168 reply_nterror(req, ntstatus);
3174 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3175 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3176 resume_key = %d resume name = %s continue=%d level = %d\n",
3177 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3178 requires_resume_key, resume_key,
3179 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3182 /* W2K3 seems to treat zero as 1. */
3186 switch (info_level) {
3187 case SMB_FIND_INFO_STANDARD:
3188 case SMB_FIND_EA_SIZE:
3189 case SMB_FIND_EA_LIST:
3190 case SMB_FIND_FILE_DIRECTORY_INFO:
3191 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3192 case SMB_FIND_FILE_NAMES_INFO:
3193 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3194 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3195 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3197 case SMB_FIND_FILE_UNIX:
3198 case SMB_FIND_FILE_UNIX_INFO2:
3199 /* Always use filesystem for UNIX mtime query. */
3200 ask_sharemode = false;
3201 if (!lp_unix_extensions()) {
3202 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3207 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3211 if (info_level == SMB_FIND_EA_LIST) {
3214 if (total_data < 4) {
3215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3219 ea_size = IVAL(pdata,0);
3220 if (ea_size != total_data) {
3221 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3222 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3223 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3227 if (!lp_ea_support(SNUM(conn))) {
3228 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3232 /* Pull out the list of names. */
3233 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3240 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3245 *ppdata = (char *)SMB_REALLOC(
3246 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3247 if(*ppdata == NULL) {
3248 reply_nterror(req, NT_STATUS_NO_MEMORY);
3253 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3256 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3259 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3260 /* Realloc the params space */
3261 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3262 if(*pparams == NULL ) {
3263 reply_nterror(req, NT_STATUS_NO_MEMORY);
3269 /* Check that the dptr is valid */
3270 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3271 reply_nterror(req, STATUS_NO_MORE_FILES);
3275 directory = dptr_path(sconn, dptr_num);
3277 /* Get the wildcard mask from the dptr */
3278 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3279 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3280 reply_nterror(req, STATUS_NO_MORE_FILES);
3284 /* Get the attr mask from the dptr */
3285 dirtype = dptr_attr(sconn, dptr_num);
3287 backup_priv = dptr_get_priv(dirptr);
3289 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3290 "backup_priv = %d\n",
3291 dptr_num, mask, dirtype,
3293 dptr_TellDir(dirptr),
3296 /* We don't need to check for VOL here as this is returned by
3297 a different TRANS2 call. */
3299 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3300 directory,lp_dont_descend(ctx, SNUM(conn))));
3301 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3302 dont_descend = True;
3305 space_remaining = max_data_bytes;
3306 out_of_space = False;
3314 * Seek to the correct position. We no longer use the resume key but
3315 * depend on the last file name instead.
3318 if(!continue_bit && resume_name && *resume_name) {
3321 long current_pos = 0;
3323 * Remember, name_to_8_3 is called by
3324 * get_lanman2_dir_entry(), so the resume name
3325 * could be mangled. Ensure we check the unmangled name.
3328 if (mangle_is_mangled(resume_name, conn->params)) {
3329 char *new_resume_name = NULL;
3330 mangle_lookup_name_from_8_3(ctx,
3334 if (new_resume_name) {
3335 resume_name = new_resume_name;
3340 * Fix for NT redirector problem triggered by resume key indexes
3341 * changing between directory scans. We now return a resume key of 0
3342 * and instead look for the filename to continue from (also given
3343 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3344 * findfirst/findnext (as is usual) then the directory pointer
3345 * should already be at the correct place.
3348 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3349 } /* end if resume_name && !continue_bit */
3351 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3352 bool got_exact_match = False;
3354 /* this is a heuristic to avoid seeking the dirptr except when
3355 absolutely necessary. It allows for a filename of about 40 chars */
3356 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3357 out_of_space = True;
3360 ntstatus = get_lanman2_dir_entry(ctx,
3364 mask,dirtype,info_level,
3365 requires_resume_key,dont_descend,
3370 &last_entry_off, ea_list);
3371 if (NT_STATUS_EQUAL(ntstatus,
3372 NT_STATUS_ILLEGAL_CHARACTER)) {
3374 * Bad character conversion on name. Ignore this
3379 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3380 out_of_space = true;
3382 finished = !NT_STATUS_IS_OK(ntstatus);
3386 if (!finished && !out_of_space)
3390 * As an optimisation if we know we aren't looking
3391 * for a wildcard name (ie. the name matches the wildcard exactly)
3392 * then we can finish on any (first) match.
3393 * This speeds up large directory searches. JRA.
3399 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3402 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3403 smb_fn_name(req->cmd),
3404 mask, directory, dirtype, numentries ) );
3406 /* Check if we can close the dirptr */
3407 if(close_after_request || (finished && close_if_end)) {
3408 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3409 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3416 /* Set up the return parameter block */
3417 SSVAL(params,0,numentries);
3418 SSVAL(params,2,finished);
3419 SSVAL(params,4,0); /* Never an EA error */
3420 SSVAL(params,6,last_entry_off);
3422 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3428 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3430 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3434 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3436 SMB_ASSERT(extended_info != NULL);
3438 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3439 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3440 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3441 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3442 #ifdef SAMBA_VERSION_REVISION
3443 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3445 extended_info->samba_subversion = 0;
3446 #ifdef SAMBA_VERSION_RC_RELEASE
3447 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3449 #ifdef SAMBA_VERSION_PRE_RELEASE
3450 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3453 #ifdef SAMBA_VERSION_VENDOR_PATCH
3454 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3456 extended_info->samba_gitcommitdate = 0;
3457 #ifdef SAMBA_VERSION_COMMIT_TIME
3458 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3461 memset(extended_info->samba_version_string, 0,
3462 sizeof(extended_info->samba_version_string));
3464 snprintf (extended_info->samba_version_string,
3465 sizeof(extended_info->samba_version_string),
3466 "%s", samba_version_string());
3469 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3470 connection_struct *conn,
3471 TALLOC_CTX *mem_ctx,
3472 uint16_t info_level,
3474 unsigned int max_data_bytes,
3475 size_t *fixed_portion,
3476 struct smb_filename *fname,
3480 char *pdata, *end_data;
3483 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3484 int snum = SNUM(conn);
3485 const char *fstype = lp_fstype(SNUM(conn));
3486 const char *filename = NULL;
3487 const uint64_t bytes_per_sector = 512;
3488 uint32_t additional_flags = 0;
3489 struct smb_filename smb_fname;
3491 NTSTATUS status = NT_STATUS_OK;
3494 if (fname == NULL || fname->base_name == NULL) {
3497 filename = fname->base_name;
3501 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3502 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3503 "info level (0x%x) on IPC$.\n",
3504 (unsigned int)info_level));
3505 return NT_STATUS_ACCESS_DENIED;
3509 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3511 ZERO_STRUCT(smb_fname);
3512 smb_fname.base_name = discard_const_p(char, filename);
3514 if(info_level != SMB_FS_QUOTA_INFORMATION
3515 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3516 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3517 return map_nt_error_from_unix(errno);
3522 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3523 return NT_STATUS_INVALID_PARAMETER;
3526 *ppdata = (char *)SMB_REALLOC(
3527 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3528 if (*ppdata == NULL) {
3529 return NT_STATUS_NO_MEMORY;
3533 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3534 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3538 switch (info_level) {
3539 case SMB_INFO_ALLOCATION:
3541 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3543 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3545 if (df_ret == (uint64_t)-1) {
3546 return map_nt_error_from_unix(errno);
3549 block_size = lp_block_size(snum);
3550 if (bsize < block_size) {
3551 uint64_t factor = block_size/bsize;
3556 if (bsize > block_size) {
3557 uint64_t factor = bsize/block_size;
3562 sectors_per_unit = bsize/bytes_per_sector;
3564 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3565 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3566 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3569 * For large drives, return max values and not modulo.
3571 dsize = MIN(dsize, UINT32_MAX);
3572 dfree = MIN(dfree, UINT32_MAX);
3574 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3575 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3576 SIVAL(pdata,l1_cUnit,dsize);
3577 SIVAL(pdata,l1_cUnitAvail,dfree);
3578 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3582 case SMB_INFO_VOLUME:
3583 /* Return volume name */
3585 * Add volume serial number - hash of a combination of
3586 * the called hostname and the service name.
3588 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3590 * Win2k3 and previous mess this up by sending a name length
3591 * one byte short. I believe only older clients (OS/2 Win9x) use
3592 * this call so try fixing this by adding a terminating null to
3593 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3595 status = srvstr_push(
3597 pdata+l2_vol_szVolLabel, vname,
3598 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3599 STR_NOALIGN|STR_TERMINATE, &len);
3600 if (!NT_STATUS_IS_OK(status)) {
3603 SCVAL(pdata,l2_vol_cch,len);
3604 data_len = l2_vol_szVolLabel + len;
3605 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3606 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3607 (unsigned)len, vname));
3610 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3611 case SMB_FS_ATTRIBUTE_INFORMATION:
3613 additional_flags = 0;
3614 #if defined(HAVE_SYS_QUOTAS)
3615 additional_flags |= FILE_VOLUME_QUOTAS;
3618 if(lp_nt_acl_support(SNUM(conn))) {
3619 additional_flags |= FILE_PERSISTENT_ACLS;
3622 /* Capabilities are filled in at connection time through STATVFS call */
3623 additional_flags |= conn->fs_capabilities;
3624 additional_flags |= lp_parm_int(conn->params->service,
3625 "share", "fake_fscaps",
3628 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3629 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3630 additional_flags); /* FS ATTRIBUTES */
3632 SIVAL(pdata,4,255); /* Max filename component length */
3633 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3634 and will think we can't do long filenames */
3635 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3636 PTR_DIFF(end_data, pdata+12),
3638 if (!NT_STATUS_IS_OK(status)) {
3642 data_len = 12 + len;
3643 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3644 /* the client only requested a portion of the
3646 data_len = max_data_bytes;
3647 status = STATUS_BUFFER_OVERFLOW;
3649 *fixed_portion = 16;
3652 case SMB_QUERY_FS_LABEL_INFO:
3653 case SMB_FS_LABEL_INFORMATION:
3654 status = srvstr_push(pdata, flags2, pdata+4, vname,
3655 PTR_DIFF(end_data, pdata+4), 0, &len);
3656 if (!NT_STATUS_IS_OK(status)) {
3663 case SMB_QUERY_FS_VOLUME_INFO:
3664 case SMB_FS_VOLUME_INFORMATION:
3667 * Add volume serial number - hash of a combination of
3668 * the called hostname and the service name.
3670 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3671 (str_checksum(get_local_machine_name())<<16));
3673 /* Max label len is 32 characters. */
3674 status = srvstr_push(pdata, flags2, pdata+18, vname,
3675 PTR_DIFF(end_data, pdata+18),
3677 if (!NT_STATUS_IS_OK(status)) {
3680 SIVAL(pdata,12,len);
3683 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3684 (int)strlen(vname),vname,
3685 lp_servicename(talloc_tos(), snum)));
3686 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3687 /* the client only requested a portion of the
3689 data_len = max_data_bytes;
3690 status = STATUS_BUFFER_OVERFLOW;
3692 *fixed_portion = 24;
3695 case SMB_QUERY_FS_SIZE_INFO:
3696 case SMB_FS_SIZE_INFORMATION:
3698 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3700 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3702 if (df_ret == (uint64_t)-1) {
3703 return map_nt_error_from_unix(errno);
3705 block_size = lp_block_size(snum);
3706 if (bsize < block_size) {
3707 uint64_t factor = block_size/bsize;
3712 if (bsize > block_size) {
3713 uint64_t factor = bsize/block_size;
3718 sectors_per_unit = bsize/bytes_per_sector;
3719 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3720 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3721 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3722 SBIG_UINT(pdata,0,dsize);
3723 SBIG_UINT(pdata,8,dfree);
3724 SIVAL(pdata,16,sectors_per_unit);
3725 SIVAL(pdata,20,bytes_per_sector);
3726 *fixed_portion = 24;
3730 case SMB_FS_FULL_SIZE_INFORMATION:
3732 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3734 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3736 if (df_ret == (uint64_t)-1) {
3737 return map_nt_error_from_unix(errno);
3739 block_size = lp_block_size(snum);
3740 if (bsize < block_size) {
3741 uint64_t factor = block_size/bsize;
3746 if (bsize > block_size) {
3747 uint64_t factor = bsize/block_size;
3752 sectors_per_unit = bsize/bytes_per_sector;
3753 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3754 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3755 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3756 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3757 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3758 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3759 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3760 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3761 *fixed_portion = 32;
3765 case SMB_QUERY_FS_DEVICE_INFO:
3766 case SMB_FS_DEVICE_INFORMATION:
3768 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3770 if (!CAN_WRITE(conn)) {
3771 characteristics |= FILE_READ_ONLY_DEVICE;
3774 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3775 SIVAL(pdata,4,characteristics);
3780 #ifdef HAVE_SYS_QUOTAS
3781 case SMB_FS_QUOTA_INFORMATION:
3783 * what we have to send --metze:
3785 * Unknown1: 24 NULL bytes
3786 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3787 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3788 * Quota Flags: 2 byte :
3789 * Unknown3: 6 NULL bytes
3793 * details for Quota Flags:
3795 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3796 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3797 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3798 * 0x0001 Enable Quotas: enable quota for this fs
3802 /* we need to fake up a fsp here,
3803 * because its not send in this call
3806 SMB_NTQUOTA_STRUCT quotas;
3809 ZERO_STRUCT(quotas);
3812 fsp.fnum = FNUM_FIELD_INVALID;
3815 if (get_current_uid(conn) != 0) {
3816 DEBUG(0,("get_user_quota: access_denied "
3817 "service [%s] user [%s]\n",
3818 lp_servicename(talloc_tos(), SNUM(conn)),
3819 conn->session_info->unix_info->unix_name));
3820 return NT_STATUS_ACCESS_DENIED;
3823 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3825 if (!NT_STATUS_IS_OK(status)) {
3826 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3832 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3833 lp_servicename(talloc_tos(), SNUM(conn))));
3835 /* Unknown1 24 NULL bytes*/
3836 SBIG_UINT(pdata,0,(uint64_t)0);
3837 SBIG_UINT(pdata,8,(uint64_t)0);
3838 SBIG_UINT(pdata,16,(uint64_t)0);
3840 /* Default Soft Quota 8 bytes */
3841 SBIG_UINT(pdata,24,quotas.softlim);
3843 /* Default Hard Quota 8 bytes */
3844 SBIG_UINT(pdata,32,quotas.hardlim);
3846 /* Quota flag 2 bytes */
3847 SSVAL(pdata,40,quotas.qflags);
3849 /* Unknown3 6 NULL bytes */
3855 #endif /* HAVE_SYS_QUOTAS */
3856 case SMB_FS_OBJECTID_INFORMATION:
3858 unsigned char objid[16];
3859 struct smb_extended_info extended_info;
3860 memcpy(pdata,create_volume_objectid(conn, objid),16);
3861 samba_extended_info_version (&extended_info);
3862 SIVAL(pdata,16,extended_info.samba_magic);
3863 SIVAL(pdata,20,extended_info.samba_version);
3864 SIVAL(pdata,24,extended_info.samba_subversion);
3865 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3866 memcpy(pdata+36,extended_info.samba_version_string,28);
3871 case SMB_FS_SECTOR_SIZE_INFORMATION:
3875 * These values match a physical Windows Server 2012
3876 * share backed by NTFS atop spinning rust.
3878 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3879 /* logical_bytes_per_sector */
3880 SIVAL(pdata, 0, bytes_per_sector);
3881 /* phys_bytes_per_sector_atomic */
3882 SIVAL(pdata, 4, bytes_per_sector);
3883 /* phys_bytes_per_sector_perf */
3884 SIVAL(pdata, 8, bytes_per_sector);
3885 /* fs_effective_phys_bytes_per_sector_atomic */
3886 SIVAL(pdata, 12, bytes_per_sector);
3888 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3889 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3890 /* byte_off_sector_align */
3891 SIVAL(pdata, 20, 0);
3892 /* byte_off_partition_align */
3893 SIVAL(pdata, 24, 0);
3894 *fixed_portion = 28;
3900 * Query the version and capabilities of the CIFS UNIX extensions
3904 case SMB_QUERY_CIFS_UNIX_INFO:
3906 bool large_write = lp_min_receive_file_size() &&
3907 !srv_is_signing_active(xconn);
3908 bool large_read = !srv_is_signing_active(xconn);
3909 int encrypt_caps = 0;
3911 if (!lp_unix_extensions()) {
3912 return NT_STATUS_INVALID_LEVEL;
3915 switch (conn->encrypt_level) {
3916 case SMB_SIGNING_OFF:
3919 case SMB_SIGNING_DESIRED:
3920 case SMB_SIGNING_IF_REQUIRED:
3921 case SMB_SIGNING_DEFAULT:
3922 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3924 case SMB_SIGNING_REQUIRED:
3925 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3926 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3927 large_write = false;
3933 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3934 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3936 /* We have POSIX ACLs, pathname, encryption,
3937 * large read/write, and locking capability. */
3939 SBIG_UINT(pdata,4,((uint64_t)(
3940 CIFS_UNIX_POSIX_ACLS_CAP|
3941 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3942 CIFS_UNIX_FCNTL_LOCKS_CAP|
3943 CIFS_UNIX_EXTATTR_CAP|
3944 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3946 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3948 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3952 case SMB_QUERY_POSIX_FS_INFO:
3955 vfs_statvfs_struct svfs;
3957 if (!lp_unix_extensions()) {
3958 return NT_STATUS_INVALID_LEVEL;
3961 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3965 SIVAL(pdata,0,svfs.OptimalTransferSize);
3966 SIVAL(pdata,4,svfs.BlockSize);
3967 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3968 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3969 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3970 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3971 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3972 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3973 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3975 } else if (rc == EOPNOTSUPP) {
3976 return NT_STATUS_INVALID_LEVEL;
3977 #endif /* EOPNOTSUPP */
3979 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3980 return NT_STATUS_DOS(ERRSRV, ERRerror);
3985 case SMB_QUERY_POSIX_WHOAMI:
3991 if (!lp_unix_extensions()) {
3992 return NT_STATUS_INVALID_LEVEL;
3995 if (max_data_bytes < 40) {
3996 return NT_STATUS_BUFFER_TOO_SMALL;
3999 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4000 flags |= SMB_WHOAMI_GUEST;
4003 /* NOTE: 8 bytes for UID/GID, irrespective of native
4004 * platform size. This matches
4005 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4007 data_len = 4 /* flags */
4014 + 4 /* pad/reserved */
4015 + (conn->session_info->unix_token->ngroups * 8)
4017 + (conn->session_info->security_token->num_sids *
4021 SIVAL(pdata, 0, flags);
4022 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4024 (uint64_t)conn->session_info->unix_token->uid);
4025 SBIG_UINT(pdata, 16,
4026 (uint64_t)conn->session_info->unix_token->gid);
4029 if (data_len >= max_data_bytes) {
4030 /* Potential overflow, skip the GIDs and SIDs. */
4032 SIVAL(pdata, 24, 0); /* num_groups */
4033 SIVAL(pdata, 28, 0); /* num_sids */
4034 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4035 SIVAL(pdata, 36, 0); /* reserved */
4041 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4042 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4044 /* We walk the SID list twice, but this call is fairly
4045 * infrequent, and I don't expect that it's performance
4046 * sensitive -- jpeach
4048 for (i = 0, sid_bytes = 0;
4049 i < conn->session_info->security_token->num_sids; ++i) {
4050 sid_bytes += ndr_size_dom_sid(
4051 &conn->session_info->security_token->sids[i],
4055 /* SID list byte count */
4056 SIVAL(pdata, 32, sid_bytes);
4058 /* 4 bytes pad/reserved - must be zero */
4059 SIVAL(pdata, 36, 0);
4063 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4064 SBIG_UINT(pdata, data_len,
4065 (uint64_t)conn->session_info->unix_token->groups[i]);
4071 i < conn->session_info->security_token->num_sids; ++i) {
4072 int sid_len = ndr_size_dom_sid(
4073 &conn->session_info->security_token->sids[i],
4076 sid_linearize((uint8_t *)(pdata + data_len),
4078 &conn->session_info->security_token->sids[i]);
4079 data_len += sid_len;
4085 case SMB_MAC_QUERY_FS_INFO:
4087 * Thursby MAC extension... ONLY on NTFS filesystems
4088 * once we do streams then we don't need this
4090 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4092 SIVAL(pdata,84,0x100); /* Don't support mac... */
4098 return NT_STATUS_INVALID_LEVEL;
4101 *ret_data_len = data_len;
4105 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4106 struct smb_request *req,
4108 const DATA_BLOB *qdata)
4111 SMB_NTQUOTA_STRUCT quotas;
4113 ZERO_STRUCT(quotas);
4116 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4117 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4118 lp_servicename(talloc_tos(), SNUM(conn)),
4119 conn->session_info->unix_info->unix_name));
4120 return NT_STATUS_ACCESS_DENIED;
4123 if (!check_fsp_ntquota_handle(conn, req,
4125 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4126 return NT_STATUS_INVALID_HANDLE;
4129 /* note: normally there're 48 bytes,
4130 * but we didn't use the last 6 bytes for now
4133 if (qdata->length < 42) {
4134 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4135 (unsigned int)qdata->length));
4136 return NT_STATUS_INVALID_PARAMETER;
4139 /* unknown_1 24 NULL bytes in pdata*/
4141 /* the soft quotas 8 bytes (uint64_t)*/
4142 quotas.softlim = BVAL(qdata->data,24);
4144 /* the hard quotas 8 bytes (uint64_t)*/
4145 quotas.hardlim = BVAL(qdata->data,32);
4147 /* quota_flags 2 bytes **/
4148 quotas.qflags = SVAL(qdata->data,40);
4150 /* unknown_2 6 NULL bytes follow*/
4152 /* now set the quotas */
4153 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4154 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4155 lp_servicename(talloc_tos(), SNUM(conn))));
4156 status = map_nt_error_from_unix(errno);
4158 status = NT_STATUS_OK;
4163 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4164 struct smb_request *req,
4165 TALLOC_CTX *mem_ctx,
4166 uint16_t info_level,
4168 const DATA_BLOB *pdata)
4170 switch (info_level) {
4171 case SMB_FS_QUOTA_INFORMATION:
4173 return smb_set_fsquota(conn,
4182 return NT_STATUS_INVALID_LEVEL;
4185 /****************************************************************************
4186 Reply to a TRANS2_QFSINFO (query filesystem info).
4187 ****************************************************************************/
4189 static void call_trans2qfsinfo(connection_struct *conn,
4190 struct smb_request *req,
4191 char **pparams, int total_params,
4192 char **ppdata, int total_data,
4193 unsigned int max_data_bytes)
4195 char *params = *pparams;
4196 uint16_t info_level;
4198 size_t fixed_portion;
4201 if (total_params < 2) {
4202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4206 info_level = SVAL(params,0);
4208 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4209 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4210 DEBUG(0,("call_trans2qfsinfo: encryption required "
4211 "and info level 0x%x sent.\n",
4212 (unsigned int)info_level));
4213 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4218 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4220 status = smbd_do_qfsinfo(req->xconn, conn, req,
4227 if (!NT_STATUS_IS_OK(status)) {
4228 reply_nterror(req, status);
4232 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4235 DEBUG( 4, ( "%s info_level = %d\n",
4236 smb_fn_name(req->cmd), info_level) );
4241 /****************************************************************************
4242 Reply to a TRANS2_SETFSINFO (set filesystem info).
4243 ****************************************************************************/
4245 static void call_trans2setfsinfo(connection_struct *conn,
4246 struct smb_request *req,
4247 char **pparams, int total_params,
4248 char **ppdata, int total_data,
4249 unsigned int max_data_bytes)
4251 struct smbXsrv_connection *xconn = req->xconn;
4252 char *pdata = *ppdata;
4253 char *params = *pparams;
4254 uint16_t info_level;
4256 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4257 lp_servicename(talloc_tos(), SNUM(conn))));
4260 if (total_params < 4) {
4261 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4267 info_level = SVAL(params,2);
4270 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4271 info_level != SMB_SET_CIFS_UNIX_INFO) {
4272 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4273 "info level (0x%x) on IPC$.\n",
4274 (unsigned int)info_level));
4275 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4280 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4281 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4282 DEBUG(0,("call_trans2setfsinfo: encryption required "
4283 "and info level 0x%x sent.\n",
4284 (unsigned int)info_level));
4285 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4290 switch(info_level) {
4291 case SMB_SET_CIFS_UNIX_INFO:
4292 if (!lp_unix_extensions()) {
4293 DEBUG(2,("call_trans2setfsinfo: "
4294 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4295 "unix extensions off\n"));
4297 NT_STATUS_INVALID_LEVEL);
4301 /* There should be 12 bytes of capabilities set. */
4302 if (total_data < 12) {
4305 NT_STATUS_INVALID_PARAMETER);
4308 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4309 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4310 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4311 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4312 /* Just print these values for now. */
4313 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4314 "major = %u, minor = %u cap_low = 0x%x, "
4316 (unsigned int)xconn->
4317 smb1.unix_info.client_major,
4318 (unsigned int)xconn->
4319 smb1.unix_info.client_minor,
4320 (unsigned int)xconn->
4321 smb1.unix_info.client_cap_low,
4322 (unsigned int)xconn->
4323 smb1.unix_info.client_cap_high));
4325 /* Here is where we must switch to posix pathname processing... */
4326 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4327 lp_set_posix_pathnames();
4328 mangle_change_to_posix();
4331 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4332 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4333 /* Client that knows how to do posix locks,
4334 * but not posix open/mkdir operations. Set a
4335 * default type for read/write checks. */
4337 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4342 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4345 size_t param_len = 0;
4346 size_t data_len = total_data;
4348 if (!lp_unix_extensions()) {
4351 NT_STATUS_INVALID_LEVEL);
4355 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4358 NT_STATUS_NOT_SUPPORTED);
4362 if (xconn->smb1.echo_handler.trusted_fde) {
4363 DEBUG( 2,("call_trans2setfsinfo: "
4364 "request transport encryption disabled"
4365 "with 'fork echo handler = yes'\n"));
4368 NT_STATUS_NOT_SUPPORTED);
4372 DEBUG( 4,("call_trans2setfsinfo: "
4373 "request transport encryption.\n"));
4375 status = srv_request_encryption_setup(conn,
4376 (unsigned char **)ppdata,
4378 (unsigned char **)pparams,
4381 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4382 !NT_STATUS_IS_OK(status)) {
4383 reply_nterror(req, status);
4387 send_trans2_replies(conn, req,
4395 if (NT_STATUS_IS_OK(status)) {
4396 /* Server-side transport
4397 * encryption is now *on*. */
4398 status = srv_encryption_start(conn);
4399 if (!NT_STATUS_IS_OK(status)) {
4400 char *reason = talloc_asprintf(talloc_tos(),
4401 "Failure in setting "
4402 "up encrypted transport: %s",
4404 exit_server_cleanly(reason);
4410 case SMB_FS_QUOTA_INFORMATION:
4414 .data = (uint8_t *)pdata,
4415 .length = total_data
4417 files_struct *fsp = NULL;
4418 fsp = file_fsp(req, SVAL(params,0));
4420 status = smb_set_fsquota(conn,
4424 if (!NT_STATUS_IS_OK(status)) {
4425 reply_nterror(req, status);
4431 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4433 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4439 * sending this reply works fine,
4440 * but I'm not sure it's the same
4441 * like windows do...
4444 reply_outbuf(req, 10, 0);
4447 #if defined(HAVE_POSIX_ACLS)
4448 /****************************************************************************
4449 Utility function to count the number of entries in a POSIX acl.
4450 ****************************************************************************/
4452 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4454 unsigned int ace_count = 0;
4455 int entry_id = SMB_ACL_FIRST_ENTRY;
4456 SMB_ACL_ENTRY_T entry;
4458 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4460 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4461 entry_id = SMB_ACL_NEXT_ENTRY;
4468 /****************************************************************************
4469 Utility function to marshall a POSIX acl into wire format.
4470 ****************************************************************************/
4472 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4474 int entry_id = SMB_ACL_FIRST_ENTRY;
4475 SMB_ACL_ENTRY_T entry;
4477 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4478 SMB_ACL_TAG_T tagtype;
4479 SMB_ACL_PERMSET_T permset;
4480 unsigned char perms = 0;
4481 unsigned int own_grp;
4484 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4485 entry_id = SMB_ACL_NEXT_ENTRY;
4488 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4489 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4493 if (sys_acl_get_permset(entry, &permset) == -1) {
4494 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4498 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4499 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4500 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4502 SCVAL(pdata,1,perms);
4505 case SMB_ACL_USER_OBJ:
4506 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4507 own_grp = (unsigned int)pst->st_ex_uid;
4508 SIVAL(pdata,2,own_grp);
4513 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4515 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4518 own_grp = (unsigned int)*puid;
4519 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4520 SIVAL(pdata,2,own_grp);
4524 case SMB_ACL_GROUP_OBJ:
4525 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4526 own_grp = (unsigned int)pst->st_ex_gid;
4527 SIVAL(pdata,2,own_grp);
4532 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4534 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4537 own_grp = (unsigned int)*pgid;
4538 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4539 SIVAL(pdata,2,own_grp);
4544 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4545 SIVAL(pdata,2,0xFFFFFFFF);
4546 SIVAL(pdata,6,0xFFFFFFFF);
4549 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4550 SIVAL(pdata,2,0xFFFFFFFF);
4551 SIVAL(pdata,6,0xFFFFFFFF);
4554 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4557 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4564 /****************************************************************************
4565 Store the FILE_UNIX_BASIC info.
4566 ****************************************************************************/
4568 static char *store_file_unix_basic(connection_struct *conn,
4571 const SMB_STRUCT_STAT *psbuf)
4575 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4576 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4578 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4581 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4584 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4585 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4586 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4589 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4593 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4597 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4600 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4601 devno = psbuf->st_ex_rdev;
4603 devno = psbuf->st_ex_dev;
4606 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4610 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4614 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4617 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4621 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4628 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4629 * the chflags(2) (or equivalent) flags.
4631 * XXX: this really should be behind the VFS interface. To do this, we would
4632 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4633 * Each VFS module could then implement its own mapping as appropriate for the
4634 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4636 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4640 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4644 { UF_IMMUTABLE, EXT_IMMUTABLE },
4648 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4652 { UF_HIDDEN, EXT_HIDDEN },
4655 /* Do not remove. We need to guarantee that this array has at least one
4656 * entry to build on HP-UX.
4662 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4663 uint32_t *smb_fflags, uint32_t *smb_fmask)
4667 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4668 *smb_fmask |= info2_flags_map[i].smb_fflag;
4669 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4670 *smb_fflags |= info2_flags_map[i].smb_fflag;
4675 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4676 const uint32_t smb_fflags,
4677 const uint32_t smb_fmask,
4680 uint32_t max_fmask = 0;
4683 *stat_fflags = psbuf->st_ex_flags;
4685 /* For each flags requested in smb_fmask, check the state of the
4686 * corresponding flag in smb_fflags and set or clear the matching
4690 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4691 max_fmask |= info2_flags_map[i].smb_fflag;
4692 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4693 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4694 *stat_fflags |= info2_flags_map[i].stat_fflag;
4696 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4701 /* If smb_fmask is asking to set any bits that are not supported by
4702 * our flag mappings, we should fail.
4704 if ((smb_fmask & max_fmask) != smb_fmask) {
4712 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4713 * of file flags and birth (create) time.
4715 static char *store_file_unix_basic_info2(connection_struct *conn,
4718 const SMB_STRUCT_STAT *psbuf)
4720 uint32_t file_flags = 0;
4721 uint32_t flags_mask = 0;
4723 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4725 /* Create (birth) time 64 bit */
4726 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4729 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4730 SIVAL(pdata, 0, file_flags); /* flags */
4731 SIVAL(pdata, 4, flags_mask); /* mask */
4737 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4738 const struct stream_struct *streams,
4740 unsigned int max_data_bytes,
4741 unsigned int *data_size)
4744 unsigned int ofs = 0;
4746 if (max_data_bytes < 32) {
4747 return NT_STATUS_INFO_LENGTH_MISMATCH;
4750 for (i = 0; i < num_streams; i++) {
4751 unsigned int next_offset;
4753 smb_ucs2_t *namebuf;
4755 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4756 streams[i].name, &namelen) ||
4759 return NT_STATUS_INVALID_PARAMETER;
4763 * name_buf is now null-terminated, we need to marshall as not
4770 * We cannot overflow ...
4772 if ((ofs + 24 + namelen) > max_data_bytes) {
4773 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4775 TALLOC_FREE(namebuf);
4776 return STATUS_BUFFER_OVERFLOW;
4779 SIVAL(data, ofs+4, namelen);
4780 SOFF_T(data, ofs+8, streams[i].size);
4781 SOFF_T(data, ofs+16, streams[i].alloc_size);
4782 memcpy(data+ofs+24, namebuf, namelen);
4783 TALLOC_FREE(namebuf);
4785 next_offset = ofs + 24 + namelen;
4787 if (i == num_streams-1) {
4788 SIVAL(data, ofs, 0);
4791 unsigned int align = ndr_align_size(next_offset, 8);
4793 if ((next_offset + align) > max_data_bytes) {
4794 DEBUG(10, ("refusing to overflow align "
4795 "reply at stream %u\n",
4797 TALLOC_FREE(namebuf);
4798 return STATUS_BUFFER_OVERFLOW;
4801 memset(data+next_offset, 0, align);
4802 next_offset += align;
4804 SIVAL(data, ofs, next_offset - ofs);
4811 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4815 return NT_STATUS_OK;
4818 #if defined(HAVE_POSIX_ACLS)
4819 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4820 struct smb_request *req,
4822 struct smb_filename *smb_fname,
4824 unsigned int data_size_in,
4825 unsigned int *pdata_size_out)
4827 SMB_ACL_T file_acl = NULL;
4828 SMB_ACL_T def_acl = NULL;
4829 uint16_t num_file_acls = 0;
4830 uint16_t num_def_acls = 0;
4831 unsigned int size_needed = 0;
4837 * Ensure we always operate on a file descriptor, not just
4841 uint32_t access_mask = SEC_STD_READ_CONTROL|
4842 FILE_READ_ATTRIBUTES|
4843 FILE_WRITE_ATTRIBUTES;
4845 status = get_posix_fsp(conn,
4851 if (!NT_STATUS_IS_OK(status)) {
4857 SMB_ASSERT(fsp != NULL);
4859 status = refuse_symlink(conn,
4862 if (!NT_STATUS_IS_OK(status)) {
4866 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4869 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4870 DBG_INFO("ACLs not implemented on "
4871 "filesystem containing %s\n",
4873 status = NT_STATUS_NOT_IMPLEMENTED;
4877 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4879 * We can only have default POSIX ACLs on
4882 if (!fsp->is_directory) {
4883 DBG_INFO("Non-directory open %s\n",
4885 status = NT_STATUS_INVALID_HANDLE;
4888 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
4890 SMB_ACL_TYPE_DEFAULT,
4892 def_acl = free_empty_sys_acl(conn, def_acl);
4895 num_file_acls = count_acl_entries(conn, file_acl);
4896 num_def_acls = count_acl_entries(conn, def_acl);
4899 if (num_file_acls + num_def_acls < num_file_acls) {
4900 status = NT_STATUS_INVALID_PARAMETER;
4904 size_needed = num_file_acls + num_def_acls;
4907 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4908 * than UINT_MAX, so check by division.
4910 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4911 status = NT_STATUS_INVALID_PARAMETER;
4915 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
4916 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
4917 status = NT_STATUS_INVALID_PARAMETER;
4920 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
4922 if ( data_size_in < size_needed) {
4923 DBG_INFO("data_size too small (%u) need %u\n",
4926 status = NT_STATUS_BUFFER_TOO_SMALL;
4930 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4931 SSVAL(pdata,2,num_file_acls);
4932 SSVAL(pdata,4,num_def_acls);
4933 pdata += SMB_POSIX_ACL_HEADER_SIZE;
4935 ok = marshall_posix_acl(conn,
4940 status = NT_STATUS_INTERNAL_ERROR;
4943 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
4945 ok = marshall_posix_acl(conn,
4950 status = NT_STATUS_INTERNAL_ERROR;
4954 *pdata_size_out = size_needed;
4955 status = NT_STATUS_OK;
4961 * Ensure the stat struct in smb_fname is up to
4962 * date. Structure copy.
4964 smb_fname->st = fsp->fsp_name->st;
4965 (void)close_file(req, fsp, NORMAL_CLOSE);
4969 TALLOC_FREE(file_acl);
4970 TALLOC_FREE(def_acl);
4975 /****************************************************************************
4976 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4977 ****************************************************************************/
4979 static void call_trans2qpipeinfo(connection_struct *conn,
4980 struct smb_request *req,
4981 unsigned int tran_call,
4982 char **pparams, int total_params,
4983 char **ppdata, int total_data,
4984 unsigned int max_data_bytes)
4986 char *params = *pparams;
4987 char *pdata = *ppdata;
4988 unsigned int data_size = 0;
4989 unsigned int param_size = 2;
4990 uint16_t info_level;
4994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4998 if (total_params < 4) {
4999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5003 fsp = file_fsp(req, SVAL(params,0));
5004 if (!fsp_is_np(fsp)) {
5005 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5009 info_level = SVAL(params,2);
5011 *pparams = (char *)SMB_REALLOC(*pparams,2);
5012 if (*pparams == NULL) {
5013 reply_nterror(req, NT_STATUS_NO_MEMORY);
5018 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5022 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5023 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5024 if (*ppdata == NULL ) {
5025 reply_nterror(req, NT_STATUS_NO_MEMORY);
5030 switch (info_level) {
5031 case SMB_FILE_STANDARD_INFORMATION:
5033 SOFF_T(pdata,0,4096LL);
5040 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5044 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5050 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5051 TALLOC_CTX *mem_ctx,
5052 struct smb_request *req,
5053 uint16_t info_level,
5055 struct smb_filename *smb_fname,
5056 bool delete_pending,
5057 struct timespec write_time_ts,
5058 struct ea_list *ea_list,
5059 int lock_data_count,
5062 unsigned int max_data_bytes,
5063 size_t *fixed_portion,
5065 unsigned int *pdata_size)
5067 char *pdata = *ppdata;
5068 char *dstart, *dend;
5069 unsigned int data_size;
5070 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5071 time_t create_time, mtime, atime, c_time;
5072 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5079 uint64_t file_size = 0;
5081 uint64_t allocation_size = 0;
5082 uint64_t file_id = 0;
5083 uint32_t access_mask = 0;
5086 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5087 return NT_STATUS_INVALID_LEVEL;
5090 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5091 smb_fname_str_dbg(smb_fname),
5093 info_level, max_data_bytes));
5095 mode = dos_mode(conn, smb_fname);
5096 nlink = psbuf->st_ex_nlink;
5098 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5102 if ((nlink > 0) && delete_pending) {
5106 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5107 return NT_STATUS_INVALID_PARAMETER;
5110 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5111 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5112 if (*ppdata == NULL) {
5113 return NT_STATUS_NO_MEMORY;
5117 dend = dstart + data_size - 1;
5119 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
5120 update_stat_ex_mtime(psbuf, write_time_ts);
5123 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5124 mtime_ts = psbuf->st_ex_mtime;
5125 atime_ts = psbuf->st_ex_atime;
5126 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5128 if (lp_dos_filetime_resolution(SNUM(conn))) {
5129 dos_filetime_timespec(&create_time_ts);
5130 dos_filetime_timespec(&mtime_ts);
5131 dos_filetime_timespec(&atime_ts);
5132 dos_filetime_timespec(&ctime_ts);
5135 create_time = convert_timespec_to_time_t(create_time_ts);
5136 mtime = convert_timespec_to_time_t(mtime_ts);
5137 atime = convert_timespec_to_time_t(atime_ts);
5138 c_time = convert_timespec_to_time_t(ctime_ts);
5140 p = strrchr_m(smb_fname->base_name,'/');
5142 base_name = smb_fname->base_name;
5146 /* NT expects the name to be in an exact form of the *full*
5147 filename. See the trans2 torture test */
5148 if (ISDOT(base_name)) {
5149 dos_fname = talloc_strdup(mem_ctx, "\\");
5151 return NT_STATUS_NO_MEMORY;
5154 dos_fname = talloc_asprintf(mem_ctx,
5156 smb_fname->base_name);
5158 return NT_STATUS_NO_MEMORY;
5160 if (is_ntfs_stream_smb_fname(smb_fname)) {
5161 dos_fname = talloc_asprintf(dos_fname, "%s",
5162 smb_fname->stream_name);
5164 return NT_STATUS_NO_MEMORY;
5168 string_replace(dos_fname, '/', '\\');
5171 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5174 /* Do we have this path open ? */
5176 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5177 fsp1 = file_find_di_first(conn->sconn, fileid);
5178 if (fsp1 && fsp1->initial_allocation_size) {
5179 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5183 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5184 file_size = get_file_size_stat(psbuf);
5188 pos = fsp->fh->position_information;
5192 access_mask = fsp->access_mask;
5194 /* GENERIC_EXECUTE mapping from Windows */
5195 access_mask = 0x12019F;
5198 /* This should be an index number - looks like
5201 I think this causes us to fail the IFSKIT
5202 BasicFileInformationTest. -tpot */
5203 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5207 switch (info_level) {
5208 case SMB_INFO_STANDARD:
5209 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5211 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5212 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5213 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5214 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5215 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5216 SSVAL(pdata,l1_attrFile,mode);
5219 case SMB_INFO_QUERY_EA_SIZE:
5221 unsigned int ea_size =
5222 estimate_ea_size(conn, fsp,
5224 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5226 srv_put_dos_date2(pdata,0,create_time);
5227 srv_put_dos_date2(pdata,4,atime);
5228 srv_put_dos_date2(pdata,8,mtime); /* write time */
5229 SIVAL(pdata,12,(uint32_t)file_size);
5230 SIVAL(pdata,16,(uint32_t)allocation_size);
5231 SSVAL(pdata,20,mode);
5232 SIVAL(pdata,22,ea_size);
5236 case SMB_INFO_IS_NAME_VALID:
5237 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5239 /* os/2 needs this ? really ?*/
5240 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5242 /* This is only reached for qpathinfo */
5246 case SMB_INFO_QUERY_EAS_FROM_LIST:
5248 size_t total_ea_len = 0;
5249 struct ea_list *ea_file_list = NULL;
5250 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5253 get_ea_list_from_file(mem_ctx, conn, fsp,
5255 &total_ea_len, &ea_file_list);
5256 if (!NT_STATUS_IS_OK(status)) {
5260 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5262 if (!ea_list || (total_ea_len > data_size)) {
5264 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5268 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5272 case SMB_INFO_QUERY_ALL_EAS:
5274 /* We have data_size bytes to put EA's into. */
5275 size_t total_ea_len = 0;
5276 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5278 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5280 &total_ea_len, &ea_list);
5281 if (!NT_STATUS_IS_OK(status)) {
5285 if (!ea_list || (total_ea_len > data_size)) {
5287 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5291 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5295 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5297 /* This is FileFullEaInformation - 0xF which maps to
5298 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5300 /* We have data_size bytes to put EA's into. */
5301 size_t total_ea_len = 0;
5302 struct ea_list *ea_file_list = NULL;
5304 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5306 /*TODO: add filtering and index handling */
5309 get_ea_list_from_file(mem_ctx, conn, fsp,
5311 &total_ea_len, &ea_file_list);
5312 if (!NT_STATUS_IS_OK(status)) {
5315 if (!ea_file_list) {
5316 return NT_STATUS_NO_EAS_ON_FILE;
5319 status = fill_ea_chained_buffer(mem_ctx,
5323 conn, ea_file_list);
5324 if (!NT_STATUS_IS_OK(status)) {
5330 case SMB_FILE_BASIC_INFORMATION:
5331 case SMB_QUERY_FILE_BASIC_INFO:
5333 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5334 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5335 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5337 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5341 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5342 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5343 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5344 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5345 SIVAL(pdata,32,mode);
5347 DEBUG(5,("SMB_QFBI - "));
5348 DEBUG(5,("create: %s ", ctime(&create_time)));
5349 DEBUG(5,("access: %s ", ctime(&atime)));
5350 DEBUG(5,("write: %s ", ctime(&mtime)));
5351 DEBUG(5,("change: %s ", ctime(&c_time)));
5352 DEBUG(5,("mode: %x\n", mode));
5353 *fixed_portion = data_size;
5356 case SMB_FILE_STANDARD_INFORMATION:
5357 case SMB_QUERY_FILE_STANDARD_INFO:
5359 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5361 SOFF_T(pdata,0,allocation_size);
5362 SOFF_T(pdata,8,file_size);
5363 SIVAL(pdata,16,nlink);
5364 SCVAL(pdata,20,delete_pending?1:0);
5365 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5366 SSVAL(pdata,22,0); /* Padding. */
5367 *fixed_portion = 24;
5370 case SMB_FILE_EA_INFORMATION:
5371 case SMB_QUERY_FILE_EA_INFO:
5373 unsigned int ea_size =
5374 estimate_ea_size(conn, fsp, smb_fname);
5375 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5378 SIVAL(pdata,0,ea_size);
5382 /* Get the 8.3 name - used if NT SMB was negotiated. */
5383 case SMB_QUERY_FILE_ALT_NAME_INFO:
5384 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5386 char mangled_name[13];
5387 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5388 if (!name_to_8_3(base_name,mangled_name,
5389 True,conn->params)) {
5390 return NT_STATUS_NO_MEMORY;
5392 status = srvstr_push(dstart, flags2,
5393 pdata+4, mangled_name,
5394 PTR_DIFF(dend, pdata+4),
5396 if (!NT_STATUS_IS_OK(status)) {
5399 data_size = 4 + len;
5405 case SMB_QUERY_FILE_NAME_INFO:
5408 this must be *exactly* right for ACLs on mapped drives to work
5410 status = srvstr_push(dstart, flags2,
5412 PTR_DIFF(dend, pdata+4),
5414 if (!NT_STATUS_IS_OK(status)) {
5417 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5418 data_size = 4 + len;
5423 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5425 char *nfname = NULL;
5427 if (!fsp->conn->sconn->using_smb2) {
5428 return NT_STATUS_INVALID_LEVEL;
5431 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5432 if (nfname == NULL) {
5433 return NT_STATUS_NO_MEMORY;
5436 if (ISDOT(nfname)) {
5439 string_replace(nfname, '/', '\\');
5441 if (smb_fname->stream_name != NULL) {
5442 const char *s = smb_fname->stream_name;
5443 const char *e = NULL;
5446 SMB_ASSERT(s[0] != '\0');
5449 * smb_fname->stream_name is in form
5450 * of ':StrEam:$DATA', but we should only
5451 * append ':StrEam' here.
5454 e = strchr(&s[1], ':');
5460 nfname = talloc_strndup_append(nfname, s, n);
5461 if (nfname == NULL) {
5462 return NT_STATUS_NO_MEMORY;
5466 status = srvstr_push(dstart, flags2,
5468 PTR_DIFF(dend, pdata+4),
5470 if (!NT_STATUS_IS_OK(status)) {
5473 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5474 data_size = 4 + len;
5480 case SMB_FILE_ALLOCATION_INFORMATION:
5481 case SMB_QUERY_FILE_ALLOCATION_INFO:
5482 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5484 SOFF_T(pdata,0,allocation_size);
5487 case SMB_FILE_END_OF_FILE_INFORMATION:
5488 case SMB_QUERY_FILE_END_OF_FILEINFO:
5489 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5491 SOFF_T(pdata,0,file_size);
5494 case SMB_QUERY_FILE_ALL_INFO:
5495 case SMB_FILE_ALL_INFORMATION:
5497 unsigned int ea_size =
5498 estimate_ea_size(conn, fsp, smb_fname);
5499 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5500 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5501 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5502 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5503 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5504 SIVAL(pdata,32,mode);
5505 SIVAL(pdata,36,0); /* padding. */
5507 SOFF_T(pdata,0,allocation_size);
5508 SOFF_T(pdata,8,file_size);
5509 SIVAL(pdata,16,nlink);
5510 SCVAL(pdata,20,delete_pending);
5511 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5514 SIVAL(pdata,0,ea_size);
5515 pdata += 4; /* EA info */
5516 status = srvstr_push(dstart, flags2,
5518 PTR_DIFF(dend, pdata+4),
5520 if (!NT_STATUS_IS_OK(status)) {
5525 data_size = PTR_DIFF(pdata,(*ppdata));
5526 *fixed_portion = 10;
5530 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5532 unsigned int ea_size =
5533 estimate_ea_size(conn, fsp, smb_fname);
5534 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5535 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5536 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5537 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5538 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5539 SIVAL(pdata, 0x20, mode);
5540 SIVAL(pdata, 0x24, 0); /* padding. */
5541 SBVAL(pdata, 0x28, allocation_size);
5542 SBVAL(pdata, 0x30, file_size);
5543 SIVAL(pdata, 0x38, nlink);
5544 SCVAL(pdata, 0x3C, delete_pending);
5545 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5546 SSVAL(pdata, 0x3E, 0); /* padding */
5547 SBVAL(pdata, 0x40, file_id);
5548 SIVAL(pdata, 0x48, ea_size);
5549 SIVAL(pdata, 0x4C, access_mask);
5550 SBVAL(pdata, 0x50, pos);
5551 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5552 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5556 status = srvstr_push(dstart, flags2,
5558 PTR_DIFF(dend, pdata+4),
5560 if (!NT_STATUS_IS_OK(status)) {
5565 data_size = PTR_DIFF(pdata,(*ppdata));
5566 *fixed_portion = 104;
5569 case SMB_FILE_INTERNAL_INFORMATION:
5571 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5572 SBVAL(pdata, 0, file_id);
5577 case SMB_FILE_ACCESS_INFORMATION:
5578 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5579 SIVAL(pdata, 0, access_mask);
5584 case SMB_FILE_NAME_INFORMATION:
5585 /* Pathname with leading '\'. */
5588 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5589 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5590 SIVAL(pdata,0,byte_len);
5591 data_size = 4 + byte_len;
5595 case SMB_FILE_DISPOSITION_INFORMATION:
5596 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5598 SCVAL(pdata,0,delete_pending);
5602 case SMB_FILE_POSITION_INFORMATION:
5603 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5605 SOFF_T(pdata,0,pos);
5609 case SMB_FILE_MODE_INFORMATION:
5610 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5611 SIVAL(pdata,0,mode);
5616 case SMB_FILE_ALIGNMENT_INFORMATION:
5617 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5618 SIVAL(pdata,0,0); /* No alignment needed. */
5624 * NT4 server just returns "invalid query" to this - if we try
5625 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5628 /* The first statement above is false - verified using Thursby
5629 * client against NT4 -- gcolley.
5631 case SMB_QUERY_FILE_STREAM_INFO:
5632 case SMB_FILE_STREAM_INFORMATION: {
5633 unsigned int num_streams = 0;
5634 struct stream_struct *streams = NULL;
5636 DEBUG(10,("smbd_do_qfilepathinfo: "
5637 "SMB_FILE_STREAM_INFORMATION\n"));
5639 if (is_ntfs_stream_smb_fname(smb_fname)) {
5640 return NT_STATUS_INVALID_PARAMETER;
5643 status = vfs_streaminfo(conn,
5650 if (!NT_STATUS_IS_OK(status)) {
5651 DEBUG(10, ("could not get stream info: %s\n",
5652 nt_errstr(status)));
5656 status = marshall_stream_info(num_streams, streams,
5657 pdata, max_data_bytes,
5660 if (!NT_STATUS_IS_OK(status)) {
5661 DEBUG(10, ("marshall_stream_info failed: %s\n",
5662 nt_errstr(status)));
5663 TALLOC_FREE(streams);
5667 TALLOC_FREE(streams);
5669 *fixed_portion = 32;
5673 case SMB_QUERY_COMPRESSION_INFO:
5674 case SMB_FILE_COMPRESSION_INFORMATION:
5675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5676 SOFF_T(pdata,0,file_size);
5677 SIVAL(pdata,8,0); /* ??? */
5678 SIVAL(pdata,12,0); /* ??? */
5680 *fixed_portion = 16;
5683 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5684 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5685 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5686 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5687 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5688 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5689 SOFF_T(pdata,32,allocation_size);
5690 SOFF_T(pdata,40,file_size);
5691 SIVAL(pdata,48,mode);
5692 SIVAL(pdata,52,0); /* ??? */
5694 *fixed_portion = 56;
5697 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5698 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5699 SIVAL(pdata,0,mode);
5706 * CIFS UNIX Extensions.
5709 case SMB_QUERY_FILE_UNIX_BASIC:
5711 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5712 data_size = PTR_DIFF(pdata,(*ppdata));
5714 DEBUG(4,("smbd_do_qfilepathinfo: "
5715 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5716 dump_data(4, (uint8_t *)(*ppdata), data_size);
5720 case SMB_QUERY_FILE_UNIX_INFO2:
5722 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5723 data_size = PTR_DIFF(pdata,(*ppdata));
5727 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5729 for (i=0; i<100; i++)
5730 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5736 case SMB_QUERY_FILE_UNIX_LINK:
5739 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5742 return NT_STATUS_NO_MEMORY;
5745 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5747 if(!S_ISLNK(psbuf->st_ex_mode)) {
5748 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5751 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5753 link_len = SMB_VFS_READLINK(conn,
5756 if (link_len == -1) {
5757 return map_nt_error_from_unix(errno);
5759 buffer[link_len] = 0;
5760 status = srvstr_push(dstart, flags2,
5762 PTR_DIFF(dend, pdata),
5763 STR_TERMINATE, &len);
5764 if (!NT_STATUS_IS_OK(status)) {
5768 data_size = PTR_DIFF(pdata,(*ppdata));
5773 #if defined(HAVE_POSIX_ACLS)
5774 case SMB_QUERY_POSIX_ACL:
5776 status = smb_query_posix_acl(conn,
5783 if (!NT_STATUS_IS_OK(status)) {
5791 case SMB_QUERY_POSIX_LOCK:
5796 enum brl_type lock_type;
5798 /* We need an open file with a real fd for this. */
5799 if (!fsp || fsp->fh->fd == -1) {
5800 return NT_STATUS_INVALID_LEVEL;
5803 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5804 return NT_STATUS_INVALID_PARAMETER;
5807 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5808 case POSIX_LOCK_TYPE_READ:
5809 lock_type = READ_LOCK;
5811 case POSIX_LOCK_TYPE_WRITE:
5812 lock_type = WRITE_LOCK;
5814 case POSIX_LOCK_TYPE_UNLOCK:
5816 /* There's no point in asking for an unlock... */
5817 return NT_STATUS_INVALID_PARAMETER;
5820 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5821 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5822 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5824 status = query_lock(fsp,
5831 if (ERROR_WAS_LOCK_DENIED(status)) {
5832 /* Here we need to report who has it locked... */
5833 data_size = POSIX_LOCK_DATA_SIZE;
5835 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5836 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5837 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5838 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5839 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5841 } else if (NT_STATUS_IS_OK(status)) {
5842 /* For success we just return a copy of what we sent
5843 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5844 data_size = POSIX_LOCK_DATA_SIZE;
5845 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5846 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5854 return NT_STATUS_INVALID_LEVEL;
5857 *pdata_size = data_size;
5858 return NT_STATUS_OK;
5861 /****************************************************************************
5862 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5863 file name or file id).
5864 ****************************************************************************/
5866 static void call_trans2qfilepathinfo(connection_struct *conn,
5867 struct smb_request *req,
5868 unsigned int tran_call,
5869 char **pparams, int total_params,
5870 char **ppdata, int total_data,
5871 unsigned int max_data_bytes)
5873 char *params = *pparams;
5874 char *pdata = *ppdata;
5875 uint16_t info_level;
5876 unsigned int data_size = 0;
5877 unsigned int param_size = 2;
5878 struct smb_filename *smb_fname = NULL;
5879 bool delete_pending = False;
5880 struct timespec write_time_ts;
5881 files_struct *fsp = NULL;
5882 struct file_id fileid;
5883 struct ea_list *ea_list = NULL;
5884 int lock_data_count = 0;
5885 char *lock_data = NULL;
5886 size_t fixed_portion;
5887 NTSTATUS status = NT_STATUS_OK;
5890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5894 ZERO_STRUCT(write_time_ts);
5896 if (tran_call == TRANSACT2_QFILEINFO) {
5897 if (total_params < 4) {
5898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5903 call_trans2qpipeinfo(conn, req, tran_call,
5904 pparams, total_params,
5910 fsp = file_fsp(req, SVAL(params,0));
5911 info_level = SVAL(params,2);
5913 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5915 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5916 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5920 /* Initial check for valid fsp ptr. */
5921 if (!check_fsp_open(conn, req, fsp)) {
5925 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5926 if (smb_fname == NULL) {
5927 reply_nterror(req, NT_STATUS_NO_MEMORY);
5931 if(fsp->fake_file_handle) {
5933 * This is actually for the QUOTA_FAKE_FILE --metze
5936 /* We know this name is ok, it's already passed the checks. */
5938 } else if(fsp->fh->fd == -1) {
5940 * This is actually a QFILEINFO on a directory
5941 * handle (returned from an NT SMB). NT5.0 seems
5942 * to do this call. JRA.
5945 if (INFO_LEVEL_IS_UNIX(info_level)) {
5946 /* Always do lstat for UNIX calls. */
5947 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5948 DEBUG(3,("call_trans2qfilepathinfo: "
5949 "SMB_VFS_LSTAT of %s failed "
5951 smb_fname_str_dbg(smb_fname),
5954 map_nt_error_from_unix(errno));
5957 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5958 DEBUG(3,("call_trans2qfilepathinfo: "
5959 "SMB_VFS_STAT of %s failed (%s)\n",
5960 smb_fname_str_dbg(smb_fname),
5963 map_nt_error_from_unix(errno));
5967 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5968 fileid = vfs_file_id_from_sbuf(
5969 conn, &smb_fname->st);
5970 get_file_infos(fileid, fsp->name_hash,
5976 * Original code - this is an open file.
5978 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5979 DEBUG(3, ("fstat of %s failed (%s)\n",
5980 fsp_fnum_dbg(fsp), strerror(errno)));
5982 map_nt_error_from_unix(errno));
5985 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5986 fileid = vfs_file_id_from_sbuf(
5987 conn, &smb_fname->st);
5988 get_file_infos(fileid, fsp->name_hash,
5997 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6000 if (total_params < 7) {
6001 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6005 info_level = SVAL(params,0);
6007 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6009 if (INFO_LEVEL_IS_UNIX(info_level)) {
6010 if (!lp_unix_extensions()) {
6011 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6014 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6015 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6016 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6017 req->posix_pathnames) {
6018 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6022 if (req->posix_pathnames) {
6023 srvstr_get_path_posix(req,
6032 srvstr_get_path(req,
6041 if (!NT_STATUS_IS_OK(status)) {
6042 reply_nterror(req, status);
6046 status = filename_convert(req,
6053 if (!NT_STATUS_IS_OK(status)) {
6054 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6055 reply_botherror(req,
6056 NT_STATUS_PATH_NOT_COVERED,
6057 ERRSRV, ERRbadpath);
6060 reply_nterror(req, status);
6064 /* If this is a stream, check if there is a delete_pending. */
6065 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6066 && is_ntfs_stream_smb_fname(smb_fname)) {
6067 struct smb_filename *smb_fname_base;
6069 /* Create an smb_filename with stream_name == NULL. */
6070 smb_fname_base = synthetic_smb_fname(
6072 smb_fname->base_name,
6076 if (smb_fname_base == NULL) {
6077 reply_nterror(req, NT_STATUS_NO_MEMORY);
6081 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6082 /* Always do lstat for UNIX calls. */
6083 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6084 DEBUG(3,("call_trans2qfilepathinfo: "
6085 "SMB_VFS_LSTAT of %s failed "
6087 smb_fname_str_dbg(smb_fname_base),
6089 TALLOC_FREE(smb_fname_base);
6091 map_nt_error_from_unix(errno));
6095 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6096 DEBUG(3,("call_trans2qfilepathinfo: "
6097 "fileinfo of %s failed "
6099 smb_fname_str_dbg(smb_fname_base),
6101 TALLOC_FREE(smb_fname_base);
6103 map_nt_error_from_unix(errno));
6108 status = file_name_hash(conn,
6109 smb_fname_str_dbg(smb_fname_base),
6111 if (!NT_STATUS_IS_OK(status)) {
6112 TALLOC_FREE(smb_fname_base);
6113 reply_nterror(req, status);
6117 fileid = vfs_file_id_from_sbuf(conn,
6118 &smb_fname_base->st);
6119 TALLOC_FREE(smb_fname_base);
6120 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6121 if (delete_pending) {
6122 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6127 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6128 /* Always do lstat for UNIX calls. */
6129 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6130 DEBUG(3,("call_trans2qfilepathinfo: "
6131 "SMB_VFS_LSTAT of %s failed (%s)\n",
6132 smb_fname_str_dbg(smb_fname),
6135 map_nt_error_from_unix(errno));
6140 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6141 DEBUG(3,("call_trans2qfilepathinfo: "
6142 "SMB_VFS_STAT of %s failed (%s)\n",
6143 smb_fname_str_dbg(smb_fname),
6146 map_nt_error_from_unix(errno));
6151 status = file_name_hash(conn,
6152 smb_fname_str_dbg(smb_fname),
6154 if (!NT_STATUS_IS_OK(status)) {
6155 reply_nterror(req, status);
6159 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6160 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6161 get_file_infos(fileid, name_hash, &delete_pending,
6165 if (delete_pending) {
6166 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6171 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6172 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6174 info_level,tran_call,total_data));
6176 /* Pull out any data sent here before we realloc. */
6177 switch (info_level) {
6178 case SMB_INFO_QUERY_EAS_FROM_LIST:
6180 /* Pull any EA list from the data portion. */
6183 if (total_data < 4) {
6185 req, NT_STATUS_INVALID_PARAMETER);
6188 ea_size = IVAL(pdata,0);
6190 if (total_data > 0 && ea_size != total_data) {
6191 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6192 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6194 req, NT_STATUS_INVALID_PARAMETER);
6198 if (!lp_ea_support(SNUM(conn))) {
6199 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6203 /* Pull out the list of names. */
6204 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6207 req, NT_STATUS_INVALID_PARAMETER);
6213 case SMB_QUERY_POSIX_LOCK:
6215 if (fsp == NULL || fsp->fh->fd == -1) {
6216 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6220 if (total_data != POSIX_LOCK_DATA_SIZE) {
6222 req, NT_STATUS_INVALID_PARAMETER);
6226 /* Copy the lock range data. */
6227 lock_data = (char *)talloc_memdup(
6228 req, pdata, total_data);
6230 reply_nterror(req, NT_STATUS_NO_MEMORY);
6233 lock_data_count = total_data;
6239 *pparams = (char *)SMB_REALLOC(*pparams,2);
6240 if (*pparams == NULL) {
6241 reply_nterror(req, NT_STATUS_NO_MEMORY);
6248 * draft-leach-cifs-v1-spec-02.txt
6249 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6252 * The requested information is placed in the Data portion of the
6253 * transaction response. For the information levels greater than 0x100,
6254 * the transaction response has 1 parameter word which should be
6255 * ignored by the client.
6257 * However Windows only follows this rule for the IS_NAME_VALID call.
6259 switch (info_level) {
6260 case SMB_INFO_IS_NAME_VALID:
6265 if ((info_level & 0xFF00) == 0xFF00) {
6267 * We use levels that start with 0xFF00
6268 * internally to represent SMB2 specific levels
6270 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6274 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6276 delete_pending, write_time_ts,
6278 lock_data_count, lock_data,
6279 req->flags2, max_data_bytes,
6281 ppdata, &data_size);
6282 if (!NT_STATUS_IS_OK(status)) {
6283 if (open_was_deferred(req->xconn, req->mid)) {
6284 /* We have re-scheduled this call. */
6287 reply_nterror(req, status);
6290 if (fixed_portion > max_data_bytes) {
6291 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6295 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6301 /****************************************************************************
6302 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6304 ****************************************************************************/
6306 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6307 connection_struct *conn,
6308 struct smb_request *req,
6309 bool overwrite_if_exists,
6310 const struct smb_filename *smb_fname_old,
6311 struct smb_filename *smb_fname_new)
6313 NTSTATUS status = NT_STATUS_OK;
6316 /* source must already exist. */
6317 if (!VALID_STAT(smb_fname_old->st)) {
6318 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6321 if (VALID_STAT(smb_fname_new->st)) {
6322 if (overwrite_if_exists) {
6323 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6324 return NT_STATUS_FILE_IS_A_DIRECTORY;
6326 status = unlink_internals(conn,
6328 FILE_ATTRIBUTE_NORMAL,
6331 if (!NT_STATUS_IS_OK(status)) {
6335 /* Disallow if newname already exists. */
6336 return NT_STATUS_OBJECT_NAME_COLLISION;
6340 /* No links from a directory. */
6341 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6342 return NT_STATUS_FILE_IS_A_DIRECTORY;
6345 /* Setting a hardlink to/from a stream isn't currently supported. */
6346 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6348 DBG_DEBUG("Old name has streams\n");
6349 return NT_STATUS_INVALID_PARAMETER;
6351 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6353 DBG_DEBUG("New name has streams\n");
6354 return NT_STATUS_INVALID_PARAMETER;
6357 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6358 smb_fname_old->base_name, smb_fname_new->base_name));
6360 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6361 status = map_nt_error_from_unix(errno);
6362 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6363 nt_errstr(status), smb_fname_old->base_name,
6364 smb_fname_new->base_name));
6369 /****************************************************************************
6370 Deal with setting the time from any of the setfilepathinfo functions.
6371 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6372 calling this function.
6373 ****************************************************************************/
6375 NTSTATUS smb_set_file_time(connection_struct *conn,
6377 const struct smb_filename *smb_fname,
6378 struct smb_file_time *ft,
6379 bool setting_write_time)
6381 struct smb_filename smb_fname_base;
6383 FILE_NOTIFY_CHANGE_LAST_ACCESS
6384 |FILE_NOTIFY_CHANGE_LAST_WRITE
6385 |FILE_NOTIFY_CHANGE_CREATION;
6387 if (!VALID_STAT(smb_fname->st)) {
6388 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6391 /* get some defaults (no modifications) if any info is zero or -1. */
6392 if (null_timespec(ft->create_time)) {
6393 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6396 if (null_timespec(ft->atime)) {
6397 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6400 if (null_timespec(ft->mtime)) {
6401 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6404 if (!setting_write_time) {
6405 /* ft->mtime comes from change time, not write time. */
6406 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6409 /* Ensure the resolution is the correct for
6410 * what we can store on this filesystem. */
6412 round_timespec(conn->ts_res, &ft->create_time);
6413 round_timespec(conn->ts_res, &ft->ctime);
6414 round_timespec(conn->ts_res, &ft->atime);
6415 round_timespec(conn->ts_res, &ft->mtime);
6417 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6418 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6419 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6420 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6421 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6422 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6423 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6424 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6426 if (setting_write_time) {
6428 * This was a Windows setfileinfo on an open file.
6429 * NT does this a lot. We also need to
6430 * set the time here, as it can be read by
6431 * FindFirst/FindNext and with the patch for bug #2045
6432 * in smbd/fileio.c it ensures that this timestamp is
6433 * kept sticky even after a write. We save the request
6434 * away and will set it on file close and after a write. JRA.
6437 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6438 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6441 if (fsp->base_fsp) {
6442 set_sticky_write_time_fsp(fsp->base_fsp,
6445 set_sticky_write_time_fsp(fsp, ft->mtime);
6448 set_sticky_write_time_path(
6449 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6454 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6456 /* Always call ntimes on the base, even if a stream was passed in. */
6457 smb_fname_base = *smb_fname;
6458 smb_fname_base.stream_name = NULL;
6460 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6461 return map_nt_error_from_unix(errno);
6464 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6465 smb_fname->base_name);
6466 return NT_STATUS_OK;
6469 /****************************************************************************
6470 Deal with setting the dosmode from any of the setfilepathinfo functions.
6471 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6472 done before calling this function.
6473 ****************************************************************************/
6475 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6476 const struct smb_filename *smb_fname,
6479 struct smb_filename *smb_fname_base;
6482 if (!VALID_STAT(smb_fname->st)) {
6483 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6486 /* Always operate on the base_name, even if a stream was passed in. */
6487 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6488 smb_fname->base_name,
6492 if (smb_fname_base == NULL) {
6493 return NT_STATUS_NO_MEMORY;
6497 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6498 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6500 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6504 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6506 /* check the mode isn't different, before changing it */
6507 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6508 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6509 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6510 (unsigned int)dosmode));
6512 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6514 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6516 smb_fname_str_dbg(smb_fname_base),
6518 status = map_nt_error_from_unix(errno);
6522 status = NT_STATUS_OK;
6524 TALLOC_FREE(smb_fname_base);
6528 /****************************************************************************
6529 Deal with setting the size from any of the setfilepathinfo functions.
6530 ****************************************************************************/
6532 static NTSTATUS smb_set_file_size(connection_struct *conn,
6533 struct smb_request *req,
6535 const struct smb_filename *smb_fname,
6536 const SMB_STRUCT_STAT *psbuf,
6538 bool fail_after_createfile)
6540 NTSTATUS status = NT_STATUS_OK;
6541 struct smb_filename *smb_fname_tmp = NULL;
6542 files_struct *new_fsp = NULL;
6544 if (!VALID_STAT(*psbuf)) {
6545 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6548 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6550 get_file_size_stat(psbuf));
6552 if (size == get_file_size_stat(psbuf)) {
6553 return NT_STATUS_OK;
6556 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6557 smb_fname_str_dbg(smb_fname), (double)size));
6559 if (fsp && fsp->fh->fd != -1) {
6560 /* Handle based call. */
6561 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6562 return NT_STATUS_ACCESS_DENIED;
6565 if (vfs_set_filelen(fsp, size) == -1) {
6566 return map_nt_error_from_unix(errno);
6568 trigger_write_time_update_immediate(fsp);
6569 return NT_STATUS_OK;
6572 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6573 if (smb_fname_tmp == NULL) {
6574 return NT_STATUS_NO_MEMORY;
6577 smb_fname_tmp->st = *psbuf;
6579 status = SMB_VFS_CREATE_FILE(
6582 0, /* root_dir_fid */
6583 smb_fname_tmp, /* fname */
6584 FILE_WRITE_DATA, /* access_mask */
6585 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6587 FILE_OPEN, /* create_disposition*/
6588 0, /* create_options */
6589 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6590 0, /* oplock_request */
6592 0, /* allocation_size */
6593 0, /* private_flags */
6596 &new_fsp, /* result */
6598 NULL, NULL); /* create context */
6600 TALLOC_FREE(smb_fname_tmp);
6602 if (!NT_STATUS_IS_OK(status)) {
6603 /* NB. We check for open_was_deferred in the caller. */
6607 /* See RAW-SFILEINFO-END-OF-FILE */
6608 if (fail_after_createfile) {
6609 close_file(req, new_fsp,NORMAL_CLOSE);
6610 return NT_STATUS_INVALID_LEVEL;
6613 if (vfs_set_filelen(new_fsp, size) == -1) {
6614 status = map_nt_error_from_unix(errno);
6615 close_file(req, new_fsp,NORMAL_CLOSE);
6619 trigger_write_time_update_immediate(new_fsp);
6620 close_file(req, new_fsp,NORMAL_CLOSE);
6621 return NT_STATUS_OK;
6624 /****************************************************************************
6625 Deal with SMB_INFO_SET_EA.
6626 ****************************************************************************/
6628 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6632 const struct smb_filename *smb_fname)
6634 struct ea_list *ea_list = NULL;
6635 TALLOC_CTX *ctx = NULL;
6636 NTSTATUS status = NT_STATUS_OK;
6638 if (total_data < 10) {
6640 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6641 length. They seem to have no effect. Bug #3212. JRA */
6643 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6644 /* We're done. We only get EA info in this call. */
6645 return NT_STATUS_OK;
6648 return NT_STATUS_INVALID_PARAMETER;
6651 if (IVAL(pdata,0) > total_data) {
6652 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6653 IVAL(pdata,0), (unsigned int)total_data));
6654 return NT_STATUS_INVALID_PARAMETER;
6658 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6660 return NT_STATUS_INVALID_PARAMETER;
6663 status = set_ea(conn, fsp, smb_fname, ea_list);
6668 /****************************************************************************
6669 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6670 ****************************************************************************/
6672 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6677 struct ea_list *ea_list = NULL;
6681 return NT_STATUS_INVALID_HANDLE;
6684 if (!lp_ea_support(SNUM(conn))) {
6685 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6686 "EA's not supported.\n",
6687 (unsigned int)total_data));
6688 return NT_STATUS_EAS_NOT_SUPPORTED;
6691 if (total_data < 10) {
6692 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6694 (unsigned int)total_data));
6695 return NT_STATUS_INVALID_PARAMETER;
6698 ea_list = read_nttrans_ea_list(talloc_tos(),
6703 return NT_STATUS_INVALID_PARAMETER;
6706 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6708 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6709 smb_fname_str_dbg(fsp->fsp_name),
6710 nt_errstr(status) ));
6716 /****************************************************************************
6717 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6718 ****************************************************************************/
6720 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6724 struct smb_filename *smb_fname)
6726 NTSTATUS status = NT_STATUS_OK;
6727 bool delete_on_close;
6728 uint32_t dosmode = 0;
6730 if (total_data < 1) {
6731 return NT_STATUS_INVALID_PARAMETER;
6735 return NT_STATUS_INVALID_HANDLE;
6738 delete_on_close = (CVAL(pdata,0) ? True : False);
6739 dosmode = dos_mode(conn, smb_fname);
6741 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6742 "delete_on_close = %u\n",
6743 smb_fname_str_dbg(smb_fname),
6744 (unsigned int)dosmode,
6745 (unsigned int)delete_on_close ));
6747 if (delete_on_close) {
6748 status = can_set_delete_on_close(fsp, dosmode);
6749 if (!NT_STATUS_IS_OK(status)) {
6754 /* The set is across all open files on this dev/inode pair. */
6755 if (!set_delete_on_close(fsp, delete_on_close,
6756 conn->session_info->security_token,
6757 conn->session_info->unix_token)) {
6758 return NT_STATUS_ACCESS_DENIED;
6760 return NT_STATUS_OK;
6763 /****************************************************************************
6764 Deal with SMB_FILE_POSITION_INFORMATION.
6765 ****************************************************************************/
6767 static NTSTATUS smb_file_position_information(connection_struct *conn,
6772 uint64_t position_information;
6774 if (total_data < 8) {
6775 return NT_STATUS_INVALID_PARAMETER;
6779 /* Ignore on pathname based set. */
6780 return NT_STATUS_OK;
6783 position_information = (uint64_t)IVAL(pdata,0);
6784 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6786 DEBUG(10,("smb_file_position_information: Set file position "
6787 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6788 (double)position_information));
6789 fsp->fh->position_information = position_information;
6790 return NT_STATUS_OK;
6793 /****************************************************************************
6794 Deal with SMB_FILE_MODE_INFORMATION.
6795 ****************************************************************************/
6797 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6803 if (total_data < 4) {
6804 return NT_STATUS_INVALID_PARAMETER;
6806 mode = IVAL(pdata,0);
6807 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6808 return NT_STATUS_INVALID_PARAMETER;
6810 return NT_STATUS_OK;
6813 /****************************************************************************
6814 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6815 ****************************************************************************/
6817 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6818 struct smb_request *req,
6821 const struct smb_filename *new_smb_fname)
6823 char *link_target = NULL;
6824 TALLOC_CTX *ctx = talloc_tos();
6826 /* Set a symbolic link. */
6827 /* Don't allow this if follow links is false. */
6829 if (total_data == 0) {
6830 return NT_STATUS_INVALID_PARAMETER;
6833 if (!lp_follow_symlinks(SNUM(conn))) {
6834 return NT_STATUS_ACCESS_DENIED;
6837 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6838 total_data, STR_TERMINATE);
6841 return NT_STATUS_INVALID_PARAMETER;
6844 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6845 new_smb_fname->base_name, link_target ));
6847 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6848 return map_nt_error_from_unix(errno);
6851 return NT_STATUS_OK;
6854 /****************************************************************************
6855 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6856 ****************************************************************************/
6858 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6859 struct smb_request *req,
6860 const char *pdata, int total_data,
6861 struct smb_filename *smb_fname_new)
6863 char *oldname = NULL;
6864 struct smb_filename *smb_fname_old = NULL;
6865 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6866 TALLOC_CTX *ctx = talloc_tos();
6867 NTSTATUS status = NT_STATUS_OK;
6869 /* Set a hard link. */
6870 if (total_data == 0) {
6871 return NT_STATUS_INVALID_PARAMETER;
6874 if (req->posix_pathnames) {
6875 srvstr_get_path_posix(ctx,
6884 srvstr_get_path(ctx,
6893 if (!NT_STATUS_IS_OK(status)) {
6897 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6898 smb_fname_str_dbg(smb_fname_new), oldname));
6900 status = filename_convert(ctx,
6907 if (!NT_STATUS_IS_OK(status)) {
6911 return hardlink_internals(ctx, conn, req, false,
6912 smb_fname_old, smb_fname_new);
6915 /****************************************************************************
6916 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6917 ****************************************************************************/
6919 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6920 struct smb_request *req,
6924 struct smb_filename *smb_fname_src)
6928 char *newname = NULL;
6929 struct smb_filename *smb_fname_dst = NULL;
6930 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6931 ucf_flags_from_smb_request(req);
6932 NTSTATUS status = NT_STATUS_OK;
6933 TALLOC_CTX *ctx = talloc_tos();
6936 return NT_STATUS_INVALID_HANDLE;
6939 if (total_data < 20) {
6940 return NT_STATUS_INVALID_PARAMETER;
6943 overwrite = (CVAL(pdata,0) ? True : False);
6944 len = IVAL(pdata,16);
6946 if (len > (total_data - 20) || (len == 0)) {
6947 return NT_STATUS_INVALID_PARAMETER;
6950 if (req->posix_pathnames) {
6951 srvstr_get_path_posix(ctx,
6960 srvstr_get_path(ctx,
6969 if (!NT_STATUS_IS_OK(status)) {
6973 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6976 status = filename_convert(ctx,
6983 if (!NT_STATUS_IS_OK(status)) {
6987 if (fsp->base_fsp) {
6988 /* newname must be a stream name. */
6989 if (newname[0] != ':') {
6990 return NT_STATUS_NOT_SUPPORTED;
6993 /* Create an smb_fname to call rename_internals_fsp() with. */
6994 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6995 fsp->base_fsp->fsp_name->base_name,
6998 fsp->base_fsp->fsp_name->flags);
6999 if (smb_fname_dst == NULL) {
7000 status = NT_STATUS_NO_MEMORY;
7005 * Set the original last component, since
7006 * rename_internals_fsp() requires it.
7008 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7010 if (smb_fname_dst->original_lcomp == NULL) {
7011 status = NT_STATUS_NO_MEMORY;
7017 DEBUG(10,("smb2_file_rename_information: "
7018 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7019 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7020 smb_fname_str_dbg(smb_fname_dst)));
7021 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7022 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7026 TALLOC_FREE(smb_fname_dst);
7030 static NTSTATUS smb_file_link_information(connection_struct *conn,
7031 struct smb_request *req,
7035 struct smb_filename *smb_fname_src)
7039 char *newname = NULL;
7040 struct smb_filename *smb_fname_dst = NULL;
7041 NTSTATUS status = NT_STATUS_OK;
7042 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7043 ucf_flags_from_smb_request(req);
7044 TALLOC_CTX *ctx = talloc_tos();
7047 return NT_STATUS_INVALID_HANDLE;
7050 if (total_data < 20) {
7051 return NT_STATUS_INVALID_PARAMETER;
7054 overwrite = (CVAL(pdata,0) ? true : false);
7055 len = IVAL(pdata,16);
7057 if (len > (total_data - 20) || (len == 0)) {
7058 return NT_STATUS_INVALID_PARAMETER;
7061 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7062 srvstr_get_path_posix(ctx,
7070 ucf_flags |= UCF_POSIX_PATHNAMES;
7072 srvstr_get_path(ctx,
7081 if (!NT_STATUS_IS_OK(status)) {
7085 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7088 status = filename_convert(ctx,
7095 if (!NT_STATUS_IS_OK(status)) {
7099 if (fsp->base_fsp) {
7100 /* No stream names. */
7101 return NT_STATUS_NOT_SUPPORTED;
7104 DEBUG(10,("smb_file_link_information: "
7105 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7106 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7107 smb_fname_str_dbg(smb_fname_dst)));
7108 status = hardlink_internals(ctx,
7115 TALLOC_FREE(smb_fname_dst);
7119 /****************************************************************************
7120 Deal with SMB_FILE_RENAME_INFORMATION.
7121 ****************************************************************************/
7123 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7124 struct smb_request *req,
7128 struct smb_filename *smb_fname_src)
7133 char *newname = NULL;
7134 struct smb_filename *smb_fname_dst = NULL;
7135 bool dest_has_wcard = False;
7136 NTSTATUS status = NT_STATUS_OK;
7138 TALLOC_CTX *ctx = talloc_tos();
7140 if (total_data < 13) {
7141 return NT_STATUS_INVALID_PARAMETER;
7144 overwrite = (CVAL(pdata,0) ? True : False);
7145 root_fid = IVAL(pdata,4);
7146 len = IVAL(pdata,8);
7148 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7149 return NT_STATUS_INVALID_PARAMETER;
7152 if (req->posix_pathnames) {
7153 srvstr_get_path_wcard_posix(ctx,
7163 srvstr_get_path_wcard(ctx,
7173 if (!NT_STATUS_IS_OK(status)) {
7177 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7180 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7181 status = resolve_dfspath_wcard(ctx, conn,
7183 UCF_COND_ALLOW_WCARD_LCOMP,
7184 !conn->sconn->using_smb2,
7187 if (!NT_STATUS_IS_OK(status)) {
7192 /* Check the new name has no '/' characters. */
7193 if (strchr_m(newname, '/')) {
7194 return NT_STATUS_NOT_SUPPORTED;
7197 if (fsp && fsp->base_fsp) {
7198 /* newname must be a stream name. */
7199 if (newname[0] != ':') {
7200 return NT_STATUS_NOT_SUPPORTED;
7203 /* Create an smb_fname to call rename_internals_fsp() with. */
7204 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7205 fsp->base_fsp->fsp_name->base_name,
7208 fsp->base_fsp->fsp_name->flags);
7209 if (smb_fname_dst == NULL) {
7210 status = NT_STATUS_NO_MEMORY;
7215 * Set the original last component, since
7216 * rename_internals_fsp() requires it.
7218 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7220 if (smb_fname_dst->original_lcomp == NULL) {
7221 status = NT_STATUS_NO_MEMORY;
7227 * Build up an smb_fname_dst based on the filename passed in.
7228 * We basically just strip off the last component, and put on
7229 * the newname instead.
7231 char *base_name = NULL;
7232 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7233 ucf_flags_from_smb_request(req);
7235 if (dest_has_wcard) {
7236 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7239 /* newname must *not* be a stream name. */
7240 if (newname[0] == ':') {
7241 return NT_STATUS_NOT_SUPPORTED;
7245 * Strip off the last component (filename) of the path passed
7248 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7250 return NT_STATUS_NO_MEMORY;
7252 p = strrchr_m(base_name, '/');
7256 base_name = talloc_strdup(ctx, "");
7258 return NT_STATUS_NO_MEMORY;
7261 /* Append the new name. */
7262 base_name = talloc_asprintf_append(base_name,
7266 return NT_STATUS_NO_MEMORY;
7269 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7272 /* If an error we expect this to be
7273 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7275 if (!NT_STATUS_IS_OK(status)) {
7276 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7280 /* Create an smb_fname to call rename_internals_fsp() */
7281 smb_fname_dst = synthetic_smb_fname(ctx,
7285 smb_fname_src->flags);
7286 if (smb_fname_dst == NULL) {
7287 status = NT_STATUS_NO_MEMORY;
7294 DEBUG(10,("smb_file_rename_information: "
7295 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7296 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7297 smb_fname_str_dbg(smb_fname_dst)));
7298 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7301 DEBUG(10,("smb_file_rename_information: "
7302 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7303 smb_fname_str_dbg(smb_fname_src),
7304 smb_fname_str_dbg(smb_fname_dst)));
7305 status = rename_internals(ctx, conn, req, smb_fname_src,
7306 smb_fname_dst, 0, overwrite, false,
7308 FILE_WRITE_ATTRIBUTES);
7311 TALLOC_FREE(smb_fname_dst);
7315 /****************************************************************************
7316 Deal with SMB_SET_POSIX_ACL.
7317 ****************************************************************************/
7319 #if defined(HAVE_POSIX_ACLS)
7320 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7321 struct smb_request *req,
7325 const struct smb_filename *smb_fname)
7327 uint16_t posix_acl_version;
7328 uint16_t num_file_acls;
7329 uint16_t num_def_acls;
7330 bool valid_file_acls = true;
7331 bool valid_def_acls = true;
7333 unsigned int size_needed;
7334 unsigned int total_data;
7335 bool close_fsp = false;
7337 if (total_data_in < 0) {
7338 status = NT_STATUS_INVALID_PARAMETER;
7342 total_data = total_data_in;
7344 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7345 status = NT_STATUS_INVALID_PARAMETER;
7348 posix_acl_version = SVAL(pdata,0);
7349 num_file_acls = SVAL(pdata,2);
7350 num_def_acls = SVAL(pdata,4);
7352 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7353 valid_file_acls = false;
7357 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7358 valid_def_acls = false;
7362 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7363 status = NT_STATUS_INVALID_PARAMETER;
7368 if (num_file_acls + num_def_acls < num_file_acls) {
7369 status = NT_STATUS_INVALID_PARAMETER;
7373 size_needed = num_file_acls + num_def_acls;
7376 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7377 * than UINT_MAX, so check by division.
7379 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7380 status = NT_STATUS_INVALID_PARAMETER;
7384 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7385 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7386 status = NT_STATUS_INVALID_PARAMETER;
7389 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7391 if (total_data < size_needed) {
7392 status = NT_STATUS_INVALID_PARAMETER;
7397 * Ensure we always operate on a file descriptor, not just
7401 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7403 SEC_STD_READ_CONTROL|
7404 FILE_READ_ATTRIBUTES|
7405 FILE_WRITE_ATTRIBUTES;
7407 status = get_posix_fsp(conn,
7413 if (!NT_STATUS_IS_OK(status)) {
7419 /* Here we know fsp != NULL */
7420 SMB_ASSERT(fsp != NULL);
7422 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7423 if (!NT_STATUS_IS_OK(status)) {
7427 /* If we have a default acl, this *must* be a directory. */
7428 if (valid_def_acls && !fsp->is_directory) {
7429 DBG_INFO("Can't set default acls on "
7430 "non-directory %s\n",
7432 return NT_STATUS_INVALID_HANDLE;
7435 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7436 "num_def_acls = %"PRIu16"\n",
7441 /* Move pdata to the start of the file ACL entries. */
7442 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7444 if (valid_file_acls) {
7445 status = set_unix_posix_acl(conn,
7449 if (!NT_STATUS_IS_OK(status)) {
7454 /* Move pdata to the start of the default ACL entries. */
7455 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7457 if (valid_def_acls) {
7458 status = set_unix_posix_default_acl(conn,
7462 if (!NT_STATUS_IS_OK(status)) {
7467 status = NT_STATUS_OK;
7472 (void)close_file(req, fsp, NORMAL_CLOSE);
7479 /****************************************************************************
7480 Deal with SMB_SET_POSIX_LOCK.
7481 ****************************************************************************/
7483 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7485 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7486 struct smb_request *req,
7491 struct tevent_req *subreq = NULL;
7492 struct smbd_lock_element *lck = NULL;
7496 bool blocking_lock = False;
7497 enum brl_type lock_type;
7499 NTSTATUS status = NT_STATUS_OK;
7501 if (fsp == NULL || fsp->fh->fd == -1) {
7502 return NT_STATUS_INVALID_HANDLE;
7505 if (total_data != POSIX_LOCK_DATA_SIZE) {
7506 return NT_STATUS_INVALID_PARAMETER;
7509 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7510 case POSIX_LOCK_TYPE_READ:
7511 lock_type = READ_LOCK;
7513 case POSIX_LOCK_TYPE_WRITE:
7514 /* Return the right POSIX-mappable error code for files opened read-only. */
7515 if (!fsp->can_write) {
7516 return NT_STATUS_INVALID_HANDLE;
7518 lock_type = WRITE_LOCK;
7520 case POSIX_LOCK_TYPE_UNLOCK:
7521 lock_type = UNLOCK_LOCK;
7524 return NT_STATUS_INVALID_PARAMETER;
7527 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7528 case POSIX_LOCK_FLAG_NOWAIT:
7529 blocking_lock = false;
7531 case POSIX_LOCK_FLAG_WAIT:
7532 blocking_lock = true;
7535 return NT_STATUS_INVALID_PARAMETER;
7538 if (!lp_blocking_locks(SNUM(conn))) {
7539 blocking_lock = False;
7542 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7543 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7544 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7545 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7546 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7548 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7549 "count = %"PRIu64", offset = %"PRIu64"\n",
7551 (unsigned int)lock_type,
7556 if (lock_type == UNLOCK_LOCK) {
7557 struct smbd_lock_element l = {
7559 .brltype = UNLOCK_LOCK,
7563 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7567 lck = talloc(req, struct smbd_lock_element);
7569 return NT_STATUS_NO_MEMORY;
7572 *lck = (struct smbd_lock_element) {
7574 .brltype = lock_type,
7579 subreq = smbd_smb1_do_locks_send(
7582 req->sconn->msg_ctx,
7585 blocking_lock ? UINT32_MAX : 0,
7586 true, /* large_offset */
7590 if (subreq == NULL) {
7592 return NT_STATUS_NO_MEMORY;
7594 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7595 return NT_STATUS_EVENT_PENDING;
7598 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7600 struct smb_request *req = NULL;
7604 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7607 status = smbd_smb1_do_locks_recv(subreq);
7608 TALLOC_FREE(subreq);
7610 if (NT_STATUS_IS_OK(status)) {
7611 char params[2] = {0};
7612 /* Fake up max_data_bytes here - we know it fits. */
7613 send_trans2_replies(
7623 reply_nterror(req, status);
7626 (char *)req->outbuf,
7629 IS_CONN_ENCRYPTED(req->conn),
7632 exit_server_cleanly("smb_set_posix_lock_done: "
7633 "srv_send_smb failed.");
7641 /****************************************************************************
7642 Deal with SMB_SET_FILE_BASIC_INFO.
7643 ****************************************************************************/
7645 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7649 const struct smb_filename *smb_fname)
7651 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7652 struct smb_file_time ft;
7653 uint32_t dosmode = 0;
7654 NTSTATUS status = NT_STATUS_OK;
7658 if (total_data < 36) {
7659 return NT_STATUS_INVALID_PARAMETER;
7662 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7663 if (!NT_STATUS_IS_OK(status)) {
7667 /* Set the attributes */
7668 dosmode = IVAL(pdata,32);
7669 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7670 if (!NT_STATUS_IS_OK(status)) {
7675 ft.create_time = interpret_long_date(pdata);
7678 ft.atime = interpret_long_date(pdata+8);
7681 ft.mtime = interpret_long_date(pdata+16);
7684 ft.ctime = interpret_long_date(pdata+24);
7686 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7687 smb_fname_str_dbg(smb_fname)));
7689 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7693 /****************************************************************************
7694 Deal with SMB_INFO_STANDARD.
7695 ****************************************************************************/
7697 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7701 const struct smb_filename *smb_fname)
7704 struct smb_file_time ft;
7708 if (total_data < 12) {
7709 return NT_STATUS_INVALID_PARAMETER;
7713 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7715 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7717 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7719 DEBUG(10,("smb_set_info_standard: file %s\n",
7720 smb_fname_str_dbg(smb_fname)));
7722 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7723 if (!NT_STATUS_IS_OK(status)) {
7727 return smb_set_file_time(conn,
7734 /****************************************************************************
7735 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7736 ****************************************************************************/
7738 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7739 struct smb_request *req,
7743 struct smb_filename *smb_fname)
7745 uint64_t allocation_size = 0;
7746 NTSTATUS status = NT_STATUS_OK;
7747 files_struct *new_fsp = NULL;
7749 if (!VALID_STAT(smb_fname->st)) {
7750 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7753 if (total_data < 8) {
7754 return NT_STATUS_INVALID_PARAMETER;
7757 allocation_size = (uint64_t)IVAL(pdata,0);
7758 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7759 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7760 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7761 (double)allocation_size));
7763 if (allocation_size) {
7764 allocation_size = smb_roundup(conn, allocation_size);
7767 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7768 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7769 (double)allocation_size));
7771 if (fsp && fsp->fh->fd != -1) {
7772 /* Open file handle. */
7773 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7774 return NT_STATUS_ACCESS_DENIED;
7777 /* Only change if needed. */
7778 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7779 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7780 return map_nt_error_from_unix(errno);
7783 /* But always update the time. */
7785 * This is equivalent to a write. Ensure it's seen immediately
7786 * if there are no pending writes.
7788 trigger_write_time_update_immediate(fsp);
7789 return NT_STATUS_OK;
7792 /* Pathname or stat or directory file. */
7793 status = SMB_VFS_CREATE_FILE(
7796 0, /* root_dir_fid */
7797 smb_fname, /* fname */
7798 FILE_WRITE_DATA, /* access_mask */
7799 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7801 FILE_OPEN, /* create_disposition*/
7802 0, /* create_options */
7803 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7804 0, /* oplock_request */
7806 0, /* allocation_size */
7807 0, /* private_flags */
7810 &new_fsp, /* result */
7812 NULL, NULL); /* create context */
7814 if (!NT_STATUS_IS_OK(status)) {
7815 /* NB. We check for open_was_deferred in the caller. */
7819 /* Only change if needed. */
7820 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7821 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7822 status = map_nt_error_from_unix(errno);
7823 close_file(req, new_fsp, NORMAL_CLOSE);
7828 /* Changing the allocation size should set the last mod time. */
7830 * This is equivalent to a write. Ensure it's seen immediately
7831 * if there are no pending writes.
7833 trigger_write_time_update_immediate(new_fsp);
7834 close_file(req, new_fsp, NORMAL_CLOSE);
7835 return NT_STATUS_OK;
7838 /****************************************************************************
7839 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7840 ****************************************************************************/
7842 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7843 struct smb_request *req,
7847 const struct smb_filename *smb_fname,
7848 bool fail_after_createfile)
7852 if (total_data < 8) {
7853 return NT_STATUS_INVALID_PARAMETER;
7856 size = IVAL(pdata,0);
7857 size |= (((off_t)IVAL(pdata,4)) << 32);
7858 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7859 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7862 return smb_set_file_size(conn, req,
7867 fail_after_createfile);
7870 /****************************************************************************
7871 Allow a UNIX info mknod.
7872 ****************************************************************************/
7874 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7877 const struct smb_filename *smb_fname)
7879 uint32_t file_type = IVAL(pdata,56);
7880 #if defined(HAVE_MAKEDEV)
7881 uint32_t dev_major = IVAL(pdata,60);
7882 uint32_t dev_minor = IVAL(pdata,68);
7884 SMB_DEV_T dev = (SMB_DEV_T)0;
7885 uint32_t raw_unixmode = IVAL(pdata,84);
7889 if (total_data < 100) {
7890 return NT_STATUS_INVALID_PARAMETER;
7893 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7894 PERM_NEW_FILE, &unixmode);
7895 if (!NT_STATUS_IS_OK(status)) {
7899 #if defined(HAVE_MAKEDEV)
7900 dev = makedev(dev_major, dev_minor);
7903 switch (file_type) {
7904 #if defined(S_IFIFO)
7905 case UNIX_TYPE_FIFO:
7906 unixmode |= S_IFIFO;
7909 #if defined(S_IFSOCK)
7910 case UNIX_TYPE_SOCKET:
7911 unixmode |= S_IFSOCK;
7914 #if defined(S_IFCHR)
7915 case UNIX_TYPE_CHARDEV:
7916 unixmode |= S_IFCHR;
7919 #if defined(S_IFBLK)
7920 case UNIX_TYPE_BLKDEV:
7921 unixmode |= S_IFBLK;
7925 return NT_STATUS_INVALID_PARAMETER;
7928 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7929 "%.0f mode 0%o for file %s\n", (double)dev,
7930 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7932 /* Ok - do the mknod. */
7933 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7934 return map_nt_error_from_unix(errno);
7937 /* If any of the other "set" calls fail we
7938 * don't want to end up with a half-constructed mknod.
7941 if (lp_inherit_permissions(SNUM(conn))) {
7943 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7945 return NT_STATUS_NO_MEMORY;
7947 inherit_access_posix_acl(conn, parent, smb_fname,
7949 TALLOC_FREE(parent);
7952 return NT_STATUS_OK;
7955 /****************************************************************************
7956 Deal with SMB_SET_FILE_UNIX_BASIC.
7957 ****************************************************************************/
7959 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7960 struct smb_request *req,
7964 const struct smb_filename *smb_fname)
7966 struct smb_file_time ft;
7967 uint32_t raw_unixmode;
7970 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7971 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7972 NTSTATUS status = NT_STATUS_OK;
7973 bool delete_on_fail = False;
7974 enum perm_type ptype;
7975 files_struct *all_fsps = NULL;
7976 bool modify_mtime = true;
7978 struct smb_filename *smb_fname_tmp = NULL;
7979 SMB_STRUCT_STAT sbuf;
7983 if (total_data < 100) {
7984 return NT_STATUS_INVALID_PARAMETER;
7987 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7988 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7989 size=IVAL(pdata,0); /* first 8 Bytes are size */
7990 size |= (((off_t)IVAL(pdata,4)) << 32);
7993 ft.atime = interpret_long_date(pdata+24); /* access_time */
7994 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7995 set_owner = (uid_t)IVAL(pdata,40);
7996 set_grp = (gid_t)IVAL(pdata,48);
7997 raw_unixmode = IVAL(pdata,84);
7999 if (VALID_STAT(smb_fname->st)) {
8000 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8001 ptype = PERM_EXISTING_DIR;
8003 ptype = PERM_EXISTING_FILE;
8006 ptype = PERM_NEW_FILE;
8009 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8011 if (!NT_STATUS_IS_OK(status)) {
8015 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8016 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8017 smb_fname_str_dbg(smb_fname), (double)size,
8018 (unsigned int)set_owner, (unsigned int)set_grp,
8019 (int)raw_unixmode));
8021 sbuf = smb_fname->st;
8023 if (!VALID_STAT(sbuf)) {
8025 * The only valid use of this is to create character and block
8026 * devices, and named pipes. This is deprecated (IMHO) and
8027 * a new info level should be used for mknod. JRA.
8030 status = smb_unix_mknod(conn,
8034 if (!NT_STATUS_IS_OK(status)) {
8038 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
8039 if (smb_fname_tmp == NULL) {
8040 return NT_STATUS_NO_MEMORY;
8043 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
8044 status = map_nt_error_from_unix(errno);
8045 TALLOC_FREE(smb_fname_tmp);
8046 SMB_VFS_UNLINK(conn, smb_fname);
8050 sbuf = smb_fname_tmp->st;
8051 smb_fname = smb_fname_tmp;
8053 /* Ensure we don't try and change anything else. */
8054 raw_unixmode = SMB_MODE_NO_CHANGE;
8055 size = get_file_size_stat(&sbuf);
8056 ft.atime = sbuf.st_ex_atime;
8057 ft.mtime = sbuf.st_ex_mtime;
8059 * We continue here as we might want to change the
8062 delete_on_fail = True;
8066 /* Horrible backwards compatibility hack as an old server bug
8067 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8071 size = get_file_size_stat(&sbuf);
8076 * Deal with the UNIX specific mode set.
8079 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8082 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8083 "setting mode 0%o for file %s\n",
8084 (unsigned int)unixmode,
8085 smb_fname_str_dbg(smb_fname)));
8086 if (fsp && fsp->fh->fd != -1) {
8087 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8089 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8092 return map_nt_error_from_unix(errno);
8097 * Deal with the UNIX specific uid set.
8100 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8101 (sbuf.st_ex_uid != set_owner)) {
8104 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8105 "changing owner %u for path %s\n",
8106 (unsigned int)set_owner,
8107 smb_fname_str_dbg(smb_fname)));
8109 if (fsp && fsp->fh->fd != -1) {
8110 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8113 * UNIX extensions calls must always operate
8116 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8117 set_owner, (gid_t)-1);
8121 status = map_nt_error_from_unix(errno);
8122 if (delete_on_fail) {
8123 SMB_VFS_UNLINK(conn, smb_fname);
8130 * Deal with the UNIX specific gid set.
8133 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8134 (sbuf.st_ex_gid != set_grp)) {
8137 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8138 "changing group %u for file %s\n",
8139 (unsigned int)set_grp,
8140 smb_fname_str_dbg(smb_fname)));
8141 if (fsp && fsp->fh->fd != -1) {
8142 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8145 * UNIX extensions calls must always operate
8148 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8152 status = map_nt_error_from_unix(errno);
8153 if (delete_on_fail) {
8154 SMB_VFS_UNLINK(conn, smb_fname);
8160 /* Deal with any size changes. */
8162 status = smb_set_file_size(conn, req,
8168 if (!NT_STATUS_IS_OK(status)) {
8172 /* Deal with any time changes. */
8173 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
8174 /* No change, don't cancel anything. */
8178 id = vfs_file_id_from_sbuf(conn, &sbuf);
8179 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8180 all_fsps = file_find_di_next(all_fsps)) {
8182 * We're setting the time explicitly for UNIX.
8183 * Cancel any pending changes over all handles.
8185 all_fsps->update_write_time_on_close = false;
8186 TALLOC_FREE(all_fsps->update_write_time_event);
8190 * Override the "setting_write_time"
8191 * parameter here as it almost does what
8192 * we need. Just remember if we modified
8193 * mtime and send the notify ourselves.
8195 if (null_timespec(ft.mtime)) {
8196 modify_mtime = false;
8199 status = smb_set_file_time(conn,
8205 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8206 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8211 /****************************************************************************
8212 Deal with SMB_SET_FILE_UNIX_INFO2.
8213 ****************************************************************************/
8215 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8216 struct smb_request *req,
8220 const struct smb_filename *smb_fname)
8223 uint32_t smb_fflags;
8226 if (total_data < 116) {
8227 return NT_STATUS_INVALID_PARAMETER;
8230 /* Start by setting all the fields that are common between UNIX_BASIC
8233 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8235 if (!NT_STATUS_IS_OK(status)) {
8239 smb_fflags = IVAL(pdata, 108);
8240 smb_fmask = IVAL(pdata, 112);
8242 /* NB: We should only attempt to alter the file flags if the client
8243 * sends a non-zero mask.
8245 if (smb_fmask != 0) {
8246 int stat_fflags = 0;
8248 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8249 smb_fmask, &stat_fflags)) {
8250 /* Client asked to alter a flag we don't understand. */
8251 return NT_STATUS_INVALID_PARAMETER;
8254 if (fsp && fsp->fh->fd != -1) {
8255 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8256 return NT_STATUS_NOT_SUPPORTED;
8258 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8259 stat_fflags) != 0) {
8260 return map_nt_error_from_unix(errno);
8265 /* XXX: need to add support for changing the create_time here. You
8266 * can do this for paths on Darwin with setattrlist(2). The right way
8267 * to hook this up is probably by extending the VFS utimes interface.
8270 return NT_STATUS_OK;
8273 /****************************************************************************
8274 Create a directory with POSIX semantics.
8275 ****************************************************************************/
8277 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8278 struct smb_request *req,
8281 struct smb_filename *smb_fname,
8282 int *pdata_return_size)
8284 NTSTATUS status = NT_STATUS_OK;
8285 uint32_t raw_unixmode = 0;
8286 uint32_t mod_unixmode = 0;
8287 mode_t unixmode = (mode_t)0;
8288 files_struct *fsp = NULL;
8289 uint16_t info_level_return = 0;
8291 char *pdata = *ppdata;
8293 if (total_data < 18) {
8294 return NT_STATUS_INVALID_PARAMETER;
8297 raw_unixmode = IVAL(pdata,8);
8298 /* Next 4 bytes are not yet defined. */
8300 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8301 PERM_NEW_DIR, &unixmode);
8302 if (!NT_STATUS_IS_OK(status)) {
8306 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8308 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8309 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8311 status = SMB_VFS_CREATE_FILE(
8314 0, /* root_dir_fid */
8315 smb_fname, /* fname */
8316 FILE_READ_ATTRIBUTES, /* access_mask */
8317 FILE_SHARE_NONE, /* share_access */
8318 FILE_CREATE, /* create_disposition*/
8319 FILE_DIRECTORY_FILE, /* create_options */
8320 mod_unixmode, /* file_attributes */
8321 0, /* oplock_request */
8323 0, /* allocation_size */
8324 0, /* private_flags */
8329 NULL, NULL); /* create context */
8331 if (NT_STATUS_IS_OK(status)) {
8332 close_file(req, fsp, NORMAL_CLOSE);
8335 info_level_return = SVAL(pdata,16);
8337 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8338 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8339 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8340 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8342 *pdata_return_size = 12;
8345 /* Realloc the data size */
8346 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8347 if (*ppdata == NULL) {
8348 *pdata_return_size = 0;
8349 return NT_STATUS_NO_MEMORY;
8353 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8354 SSVAL(pdata,2,0); /* No fnum. */
8355 SIVAL(pdata,4,info); /* Was directory created. */
8357 switch (info_level_return) {
8358 case SMB_QUERY_FILE_UNIX_BASIC:
8359 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8360 SSVAL(pdata,10,0); /* Padding. */
8361 store_file_unix_basic(conn, pdata + 12, fsp,
8364 case SMB_QUERY_FILE_UNIX_INFO2:
8365 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8366 SSVAL(pdata,10,0); /* Padding. */
8367 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8371 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8372 SSVAL(pdata,10,0); /* Padding. */
8379 /****************************************************************************
8380 Open/Create a file with POSIX semantics.
8381 ****************************************************************************/
8383 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8384 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8386 static NTSTATUS smb_posix_open(connection_struct *conn,
8387 struct smb_request *req,
8390 struct smb_filename *smb_fname,
8391 int *pdata_return_size)
8393 bool extended_oplock_granted = False;
8394 char *pdata = *ppdata;
8396 uint32_t wire_open_mode = 0;
8397 uint32_t raw_unixmode = 0;
8398 uint32_t mod_unixmode = 0;
8399 uint32_t create_disp = 0;
8400 uint32_t access_mask = 0;
8401 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8402 NTSTATUS status = NT_STATUS_OK;
8403 mode_t unixmode = (mode_t)0;
8404 files_struct *fsp = NULL;
8405 int oplock_request = 0;
8407 uint16_t info_level_return = 0;
8409 if (total_data < 18) {
8410 return NT_STATUS_INVALID_PARAMETER;
8413 flags = IVAL(pdata,0);
8414 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8415 if (oplock_request) {
8416 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8419 wire_open_mode = IVAL(pdata,4);
8421 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8422 return smb_posix_mkdir(conn, req,
8429 switch (wire_open_mode & SMB_ACCMODE) {
8431 access_mask = SMB_O_RDONLY_MAPPING;
8434 access_mask = SMB_O_WRONLY_MAPPING;
8437 access_mask = (SMB_O_RDONLY_MAPPING|
8438 SMB_O_WRONLY_MAPPING);
8441 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8442 (unsigned int)wire_open_mode ));
8443 return NT_STATUS_INVALID_PARAMETER;
8446 wire_open_mode &= ~SMB_ACCMODE;
8448 /* First take care of O_CREAT|O_EXCL interactions. */
8449 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8450 case (SMB_O_CREAT | SMB_O_EXCL):
8451 /* File exists fail. File not exist create. */
8452 create_disp = FILE_CREATE;
8455 /* File exists open. File not exist create. */
8456 create_disp = FILE_OPEN_IF;
8459 /* O_EXCL on its own without O_CREAT is undefined.
8460 We deliberately ignore it as some versions of
8461 Linux CIFSFS can send a bare O_EXCL on the
8462 wire which other filesystems in the kernel
8463 ignore. See bug 9519 for details. */
8468 /* File exists open. File not exist fail. */
8469 create_disp = FILE_OPEN;
8472 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8473 (unsigned int)wire_open_mode ));
8474 return NT_STATUS_INVALID_PARAMETER;
8477 /* Next factor in the effects of O_TRUNC. */
8478 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8480 if (wire_open_mode & SMB_O_TRUNC) {
8481 switch (create_disp) {
8483 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8484 /* Leave create_disp alone as
8485 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8487 /* File exists fail. File not exist create. */
8490 /* SMB_O_CREAT | SMB_O_TRUNC */
8491 /* File exists overwrite. File not exist create. */
8492 create_disp = FILE_OVERWRITE_IF;
8496 /* File exists overwrite. File not exist fail. */
8497 create_disp = FILE_OVERWRITE;
8500 /* Cannot get here. */
8501 smb_panic("smb_posix_open: logic error");
8502 return NT_STATUS_INVALID_PARAMETER;
8506 raw_unixmode = IVAL(pdata,8);
8507 /* Next 4 bytes are not yet defined. */
8509 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8510 (VALID_STAT(smb_fname->st) ?
8511 PERM_EXISTING_FILE : PERM_NEW_FILE),
8514 if (!NT_STATUS_IS_OK(status)) {
8518 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8520 if (wire_open_mode & SMB_O_SYNC) {
8521 create_options |= FILE_WRITE_THROUGH;
8523 if (wire_open_mode & SMB_O_APPEND) {
8524 access_mask |= FILE_APPEND_DATA;
8526 if (wire_open_mode & SMB_O_DIRECT) {
8527 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8530 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8531 VALID_STAT_OF_DIR(smb_fname->st)) {
8532 if (access_mask != SMB_O_RDONLY_MAPPING) {
8533 return NT_STATUS_FILE_IS_A_DIRECTORY;
8535 create_options &= ~FILE_NON_DIRECTORY_FILE;
8536 create_options |= FILE_DIRECTORY_FILE;
8539 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8540 smb_fname_str_dbg(smb_fname),
8541 (unsigned int)wire_open_mode,
8542 (unsigned int)unixmode ));
8544 status = SMB_VFS_CREATE_FILE(
8547 0, /* root_dir_fid */
8548 smb_fname, /* fname */
8549 access_mask, /* access_mask */
8550 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8552 create_disp, /* create_disposition*/
8553 create_options, /* create_options */
8554 mod_unixmode, /* file_attributes */
8555 oplock_request, /* oplock_request */
8557 0, /* allocation_size */
8558 0, /* private_flags */
8563 NULL, NULL); /* create context */
8565 if (!NT_STATUS_IS_OK(status)) {
8569 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8570 extended_oplock_granted = True;
8573 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8574 extended_oplock_granted = True;
8577 info_level_return = SVAL(pdata,16);
8579 /* Allocate the correct return size. */
8581 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8582 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8583 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8584 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8586 *pdata_return_size = 12;
8589 /* Realloc the data size */
8590 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8591 if (*ppdata == NULL) {
8592 close_file(req, fsp, ERROR_CLOSE);
8593 *pdata_return_size = 0;
8594 return NT_STATUS_NO_MEMORY;
8598 if (extended_oplock_granted) {
8599 if (flags & REQUEST_BATCH_OPLOCK) {
8600 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8602 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8604 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8605 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8607 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8610 SSVAL(pdata,2,fsp->fnum);
8611 SIVAL(pdata,4,info); /* Was file created etc. */
8613 switch (info_level_return) {
8614 case SMB_QUERY_FILE_UNIX_BASIC:
8615 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8616 SSVAL(pdata,10,0); /* padding. */
8617 store_file_unix_basic(conn, pdata + 12, fsp,
8620 case SMB_QUERY_FILE_UNIX_INFO2:
8621 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8622 SSVAL(pdata,10,0); /* padding. */
8623 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8627 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8628 SSVAL(pdata,10,0); /* padding. */
8631 return NT_STATUS_OK;
8634 /****************************************************************************
8635 Delete a file with POSIX semantics.
8636 ****************************************************************************/
8638 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8639 struct smb_request *req,
8642 struct smb_filename *smb_fname)
8644 struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
8645 NTSTATUS status = NT_STATUS_OK;
8646 files_struct *fsp = NULL;
8650 int create_options = 0;
8651 struct share_mode_lock *lck = NULL;
8652 bool other_nonposix_opens;
8654 if (total_data < 2) {
8655 return NT_STATUS_INVALID_PARAMETER;
8658 flags = SVAL(pdata,0);
8660 if (!VALID_STAT(smb_fname->st)) {
8661 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8664 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8665 !VALID_STAT_OF_DIR(smb_fname->st)) {
8666 return NT_STATUS_NOT_A_DIRECTORY;
8669 DEBUG(10,("smb_posix_unlink: %s %s\n",
8670 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8671 smb_fname_str_dbg(smb_fname)));
8673 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8674 create_options |= FILE_DIRECTORY_FILE;
8677 status = SMB_VFS_CREATE_FILE(
8680 0, /* root_dir_fid */
8681 smb_fname, /* fname */
8682 DELETE_ACCESS, /* access_mask */
8683 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8685 FILE_OPEN, /* create_disposition*/
8686 create_options, /* create_options */
8687 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8688 0, /* oplock_request */
8690 0, /* allocation_size */
8691 0, /* private_flags */
8696 NULL, NULL); /* create context */
8698 if (!NT_STATUS_IS_OK(status)) {
8703 * Don't lie to client. If we can't really delete due to
8704 * non-POSIX opens return SHARING_VIOLATION.
8707 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8709 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8710 "lock for file %s\n", fsp_str_dbg(fsp)));
8711 close_file(req, fsp, NORMAL_CLOSE);
8712 return NT_STATUS_INVALID_PARAMETER;
8715 other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
8716 if (other_nonposix_opens) {
8717 /* Fail with sharing violation. */
8719 close_file(req, fsp, NORMAL_CLOSE);
8720 return NT_STATUS_SHARING_VIOLATION;
8724 * Set the delete on close.
8726 status = smb_set_file_disposition_info(conn,
8734 if (!NT_STATUS_IS_OK(status)) {
8735 close_file(req, fsp, NORMAL_CLOSE);
8738 return close_file(req, fsp, NORMAL_CLOSE);
8741 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8742 struct smb_request *req,
8743 TALLOC_CTX *mem_ctx,
8744 uint16_t info_level,
8746 struct smb_filename *smb_fname,
8747 char **ppdata, int total_data,
8750 char *pdata = *ppdata;
8751 NTSTATUS status = NT_STATUS_OK;
8752 int data_return_size = 0;
8756 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8757 return NT_STATUS_INVALID_LEVEL;
8760 if (!CAN_WRITE(conn)) {
8761 /* Allow POSIX opens. The open path will deny
8762 * any non-readonly opens. */
8763 if (info_level != SMB_POSIX_PATH_OPEN) {
8764 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8768 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8769 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8771 info_level, total_data));
8773 switch (info_level) {
8775 case SMB_INFO_STANDARD:
8777 status = smb_set_info_standard(conn,
8785 case SMB_INFO_SET_EA:
8787 status = smb_info_set_ea(conn,
8795 case SMB_SET_FILE_BASIC_INFO:
8796 case SMB_FILE_BASIC_INFORMATION:
8798 status = smb_set_file_basic_info(conn,
8806 case SMB_FILE_ALLOCATION_INFORMATION:
8807 case SMB_SET_FILE_ALLOCATION_INFO:
8809 status = smb_set_file_allocation_info(conn, req,
8817 case SMB_FILE_END_OF_FILE_INFORMATION:
8818 case SMB_SET_FILE_END_OF_FILE_INFO:
8821 * XP/Win7 both fail after the createfile with
8822 * SMB_SET_FILE_END_OF_FILE_INFO but not
8823 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8824 * The level is known here, so pass it down
8828 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8830 status = smb_set_file_end_of_file_info(conn, req,
8839 case SMB_FILE_DISPOSITION_INFORMATION:
8840 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8843 /* JRA - We used to just ignore this on a path ?
8844 * Shouldn't this be invalid level on a pathname
8847 if (tran_call != TRANSACT2_SETFILEINFO) {
8848 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8851 status = smb_set_file_disposition_info(conn,
8859 case SMB_FILE_POSITION_INFORMATION:
8861 status = smb_file_position_information(conn,
8868 case SMB_FILE_FULL_EA_INFORMATION:
8870 status = smb_set_file_full_ea_info(conn,
8877 /* From tridge Samba4 :
8878 * MODE_INFORMATION in setfileinfo (I have no
8879 * idea what "mode information" on a file is - it takes a value of 0,
8880 * 2, 4 or 6. What could it be?).
8883 case SMB_FILE_MODE_INFORMATION:
8885 status = smb_file_mode_information(conn,
8891 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8892 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8893 case SMB_FILE_SHORT_NAME_INFORMATION:
8894 return NT_STATUS_NOT_SUPPORTED;
8897 * CIFS UNIX extensions.
8900 case SMB_SET_FILE_UNIX_BASIC:
8902 status = smb_set_file_unix_basic(conn, req,
8910 case SMB_SET_FILE_UNIX_INFO2:
8912 status = smb_set_file_unix_info2(conn, req,
8920 case SMB_SET_FILE_UNIX_LINK:
8923 /* We must have a pathname for this. */
8924 return NT_STATUS_INVALID_LEVEL;
8926 status = smb_set_file_unix_link(conn, req, pdata,
8927 total_data, smb_fname);
8931 case SMB_SET_FILE_UNIX_HLINK:
8934 /* We must have a pathname for this. */
8935 return NT_STATUS_INVALID_LEVEL;
8937 status = smb_set_file_unix_hlink(conn, req,
8943 case SMB_FILE_RENAME_INFORMATION:
8945 status = smb_file_rename_information(conn, req,
8951 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8953 /* SMB2 rename information. */
8954 status = smb2_file_rename_information(conn, req,
8960 case SMB_FILE_LINK_INFORMATION:
8962 status = smb_file_link_information(conn, req,
8968 #if defined(HAVE_POSIX_ACLS)
8969 case SMB_SET_POSIX_ACL:
8971 status = smb_set_posix_acl(conn,
8981 case SMB_SET_POSIX_LOCK:
8984 return NT_STATUS_INVALID_LEVEL;
8986 status = smb_set_posix_lock(conn, req,
8987 pdata, total_data, fsp);
8991 case SMB_POSIX_PATH_OPEN:
8994 /* We must have a pathname for this. */
8995 return NT_STATUS_INVALID_LEVEL;
8998 status = smb_posix_open(conn, req,
9006 case SMB_POSIX_PATH_UNLINK:
9009 /* We must have a pathname for this. */
9010 return NT_STATUS_INVALID_LEVEL;
9013 status = smb_posix_unlink(conn, req,
9021 return NT_STATUS_INVALID_LEVEL;
9024 if (!NT_STATUS_IS_OK(status)) {
9028 *ret_data_size = data_return_size;
9029 return NT_STATUS_OK;
9032 /****************************************************************************
9033 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9034 ****************************************************************************/
9036 static void call_trans2setfilepathinfo(connection_struct *conn,
9037 struct smb_request *req,
9038 unsigned int tran_call,
9039 char **pparams, int total_params,
9040 char **ppdata, int total_data,
9041 unsigned int max_data_bytes)
9043 char *params = *pparams;
9044 char *pdata = *ppdata;
9045 uint16_t info_level;
9046 struct smb_filename *smb_fname = NULL;
9047 files_struct *fsp = NULL;
9048 NTSTATUS status = NT_STATUS_OK;
9049 int data_return_size = 0;
9052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9056 if (tran_call == TRANSACT2_SETFILEINFO) {
9057 if (total_params < 4) {
9058 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9062 fsp = file_fsp(req, SVAL(params,0));
9063 /* Basic check for non-null fsp. */
9064 if (!check_fsp_open(conn, req, fsp)) {
9067 info_level = SVAL(params,2);
9069 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9070 if (smb_fname == NULL) {
9071 reply_nterror(req, NT_STATUS_NO_MEMORY);
9075 if(fsp->fh->fd == -1) {
9077 * This is actually a SETFILEINFO on a directory
9078 * handle (returned from an NT SMB). NT5.0 seems
9079 * to do this call. JRA.
9081 if (INFO_LEVEL_IS_UNIX(info_level)) {
9082 /* Always do lstat for UNIX calls. */
9083 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9084 DEBUG(3,("call_trans2setfilepathinfo: "
9085 "SMB_VFS_LSTAT of %s failed "
9087 smb_fname_str_dbg(smb_fname),
9089 reply_nterror(req, map_nt_error_from_unix(errno));
9093 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9094 DEBUG(3,("call_trans2setfilepathinfo: "
9095 "fileinfo of %s failed (%s)\n",
9096 smb_fname_str_dbg(smb_fname),
9098 reply_nterror(req, map_nt_error_from_unix(errno));
9102 } else if (fsp->print_file) {
9104 * Doing a DELETE_ON_CLOSE should cancel a print job.
9106 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9107 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9109 DEBUG(3,("call_trans2setfilepathinfo: "
9110 "Cancelling print job (%s)\n",
9114 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9120 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9125 * Original code - this is an open file.
9127 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9128 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9129 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9131 reply_nterror(req, map_nt_error_from_unix(errno));
9137 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9140 if (total_params < 7) {
9141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9145 info_level = SVAL(params,0);
9146 if (req->posix_pathnames) {
9147 srvstr_get_path_posix(req,
9156 srvstr_get_path(req,
9165 if (!NT_STATUS_IS_OK(status)) {
9166 reply_nterror(req, status);
9170 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9171 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9172 info_level == SMB_FILE_RENAME_INFORMATION ||
9173 info_level == SMB_POSIX_PATH_OPEN ||
9174 info_level == SMB_POSIX_PATH_UNLINK) {
9175 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9178 status = filename_convert(req, conn,
9184 if (!NT_STATUS_IS_OK(status)) {
9185 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9186 reply_botherror(req,
9187 NT_STATUS_PATH_NOT_COVERED,
9188 ERRSRV, ERRbadpath);
9191 reply_nterror(req, status);
9195 if (INFO_LEVEL_IS_UNIX(info_level)) {
9197 * For CIFS UNIX extensions the target name may not exist.
9200 /* Always do lstat for UNIX calls. */
9201 SMB_VFS_LSTAT(conn, smb_fname);
9203 } else if (!VALID_STAT(smb_fname->st) &&
9204 SMB_VFS_STAT(conn, smb_fname)) {
9205 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9207 smb_fname_str_dbg(smb_fname),
9209 reply_nterror(req, map_nt_error_from_unix(errno));
9214 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9215 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9217 info_level,total_data));
9219 /* Realloc the parameter size */
9220 *pparams = (char *)SMB_REALLOC(*pparams,2);
9221 if (*pparams == NULL) {
9222 reply_nterror(req, NT_STATUS_NO_MEMORY);
9229 status = smbd_do_setfilepathinfo(conn, req, req,
9235 if (!NT_STATUS_IS_OK(status)) {
9236 if (open_was_deferred(req->xconn, req->mid)) {
9237 /* We have re-scheduled this call. */
9240 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9241 /* We have re-scheduled this call. */
9244 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9245 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9246 ERRSRV, ERRbadpath);
9249 if (info_level == SMB_POSIX_PATH_OPEN) {
9250 reply_openerror(req, status);
9255 * Invalid EA name needs to return 2 param bytes,
9256 * not a zero-length error packet.
9258 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9259 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9262 reply_nterror(req, status);
9267 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9273 /****************************************************************************
9274 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9275 ****************************************************************************/
9277 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9278 char **pparams, int total_params,
9279 char **ppdata, int total_data,
9280 unsigned int max_data_bytes)
9282 struct smb_filename *smb_dname = NULL;
9283 char *params = *pparams;
9284 char *pdata = *ppdata;
9285 char *directory = NULL;
9286 NTSTATUS status = NT_STATUS_OK;
9287 struct ea_list *ea_list = NULL;
9288 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9289 TALLOC_CTX *ctx = talloc_tos();
9291 if (!CAN_WRITE(conn)) {
9292 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9296 if (total_params < 5) {
9297 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9301 if (req->posix_pathnames) {
9302 srvstr_get_path_posix(ctx,
9311 srvstr_get_path(ctx,
9320 if (!NT_STATUS_IS_OK(status)) {
9321 reply_nterror(req, status);
9325 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9327 status = filename_convert(ctx,
9335 if (!NT_STATUS_IS_OK(status)) {
9336 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9337 reply_botherror(req,
9338 NT_STATUS_PATH_NOT_COVERED,
9339 ERRSRV, ERRbadpath);
9342 reply_nterror(req, status);
9347 * OS/2 workplace shell seems to send SET_EA requests of "null"
9348 * length (4 bytes containing IVAL 4).
9349 * They seem to have no effect. Bug #3212. JRA.
9352 if (total_data && (total_data != 4)) {
9353 /* Any data in this call is an EA list. */
9354 if (total_data < 10) {
9355 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9359 if (IVAL(pdata,0) > total_data) {
9360 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9361 IVAL(pdata,0), (unsigned int)total_data));
9362 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9366 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9373 if (!lp_ea_support(SNUM(conn))) {
9374 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9378 /* If total_data == 4 Windows doesn't care what values
9379 * are placed in that field, it just ignores them.
9380 * The System i QNTC IBM SMB client puts bad values here,
9381 * so ignore them. */
9383 status = create_directory(conn, req, smb_dname);
9385 if (!NT_STATUS_IS_OK(status)) {
9386 reply_nterror(req, status);
9390 /* Try and set any given EA. */
9392 status = set_ea(conn, NULL, smb_dname, ea_list);
9393 if (!NT_STATUS_IS_OK(status)) {
9394 reply_nterror(req, status);
9399 /* Realloc the parameter and data sizes */
9400 *pparams = (char *)SMB_REALLOC(*pparams,2);
9401 if(*pparams == NULL) {
9402 reply_nterror(req, NT_STATUS_NO_MEMORY);
9409 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9412 TALLOC_FREE(smb_dname);
9416 /****************************************************************************
9417 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9418 We don't actually do this - we just send a null response.
9419 ****************************************************************************/
9421 static void call_trans2findnotifyfirst(connection_struct *conn,
9422 struct smb_request *req,
9423 char **pparams, int total_params,
9424 char **ppdata, int total_data,
9425 unsigned int max_data_bytes)
9427 char *params = *pparams;
9428 uint16_t info_level;
9430 if (total_params < 6) {
9431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9435 info_level = SVAL(params,4);
9436 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9438 switch (info_level) {
9443 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9447 /* Realloc the parameter and data sizes */
9448 *pparams = (char *)SMB_REALLOC(*pparams,6);
9449 if (*pparams == NULL) {
9450 reply_nterror(req, NT_STATUS_NO_MEMORY);
9455 SSVAL(params,0,fnf_handle);
9456 SSVAL(params,2,0); /* No changes */
9457 SSVAL(params,4,0); /* No EA errors */
9464 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9469 /****************************************************************************
9470 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9471 changes). Currently this does nothing.
9472 ****************************************************************************/
9474 static void call_trans2findnotifynext(connection_struct *conn,
9475 struct smb_request *req,
9476 char **pparams, int total_params,
9477 char **ppdata, int total_data,
9478 unsigned int max_data_bytes)
9480 char *params = *pparams;
9482 DEBUG(3,("call_trans2findnotifynext\n"));
9484 /* Realloc the parameter and data sizes */
9485 *pparams = (char *)SMB_REALLOC(*pparams,4);
9486 if (*pparams == NULL) {
9487 reply_nterror(req, NT_STATUS_NO_MEMORY);
9492 SSVAL(params,0,0); /* No changes */
9493 SSVAL(params,2,0); /* No EA errors */
9495 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9500 /****************************************************************************
9501 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9502 ****************************************************************************/
9504 static void call_trans2getdfsreferral(connection_struct *conn,
9505 struct smb_request *req,
9506 char **pparams, int total_params,
9507 char **ppdata, int total_data,
9508 unsigned int max_data_bytes)
9510 char *params = *pparams;
9511 char *pathname = NULL;
9513 int max_referral_level;
9514 NTSTATUS status = NT_STATUS_OK;
9515 TALLOC_CTX *ctx = talloc_tos();
9517 DEBUG(10,("call_trans2getdfsreferral\n"));
9519 if (total_params < 3) {
9520 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9524 max_referral_level = SVAL(params,0);
9526 if(!lp_host_msdfs()) {
9527 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9531 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9532 total_params - 2, STR_TERMINATE);
9534 reply_nterror(req, NT_STATUS_NOT_FOUND);
9537 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9538 ppdata,&status)) < 0) {
9539 reply_nterror(req, status);
9543 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9544 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9545 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9550 #define LMCAT_SPL 0x53
9551 #define LMFUNC_GETJOBID 0x60
9553 /****************************************************************************
9554 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9555 ****************************************************************************/
9557 static void call_trans2ioctl(connection_struct *conn,
9558 struct smb_request *req,
9559 char **pparams, int total_params,
9560 char **ppdata, int total_data,
9561 unsigned int max_data_bytes)
9563 char *pdata = *ppdata;
9564 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9568 /* check for an invalid fid before proceeding */
9571 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9575 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9576 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9577 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9578 if (*ppdata == NULL) {
9579 reply_nterror(req, NT_STATUS_NO_MEMORY);
9584 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9585 CAN ACCEPT THIS IN UNICODE. JRA. */
9588 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9590 status = srvstr_push(pdata, req->flags2, pdata + 2,
9591 lp_netbios_name(), 15,
9592 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9593 if (!NT_STATUS_IS_OK(status)) {
9594 reply_nterror(req, status);
9597 status = srvstr_push(pdata, req->flags2, pdata+18,
9598 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9599 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9600 if (!NT_STATUS_IS_OK(status)) {
9601 reply_nterror(req, status);
9604 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9609 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9610 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9613 /****************************************************************************
9614 Reply to a SMBfindclose (stop trans2 directory search).
9615 ****************************************************************************/
9617 void reply_findclose(struct smb_request *req)
9620 struct smbd_server_connection *sconn = req->sconn;
9622 START_PROFILE(SMBfindclose);
9625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9626 END_PROFILE(SMBfindclose);
9630 dptr_num = SVALS(req->vwv+0, 0);
9632 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9634 dptr_close(sconn, &dptr_num);
9636 reply_outbuf(req, 0, 0);
9638 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9640 END_PROFILE(SMBfindclose);
9644 /****************************************************************************
9645 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9646 ****************************************************************************/
9648 void reply_findnclose(struct smb_request *req)
9652 START_PROFILE(SMBfindnclose);
9655 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9656 END_PROFILE(SMBfindnclose);
9660 dptr_num = SVAL(req->vwv+0, 0);
9662 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9664 /* We never give out valid handles for a
9665 findnotifyfirst - so any dptr_num is ok here.
9668 reply_outbuf(req, 0, 0);
9670 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9672 END_PROFILE(SMBfindnclose);
9676 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9677 struct trans_state *state)
9679 if (get_Protocol() >= PROTOCOL_NT1) {
9680 req->flags2 |= 0x40; /* IS_LONG_NAME */
9681 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9684 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9685 if (state->call != TRANSACT2_QFSINFO &&
9686 state->call != TRANSACT2_SETFSINFO) {
9687 DEBUG(0,("handle_trans2: encryption required "
9689 (unsigned int)state->call));
9690 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9695 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9697 /* Now we must call the relevant TRANS2 function */
9698 switch(state->call) {
9699 case TRANSACT2_OPEN:
9701 START_PROFILE(Trans2_open);
9702 call_trans2open(conn, req,
9703 &state->param, state->total_param,
9704 &state->data, state->total_data,
9705 state->max_data_return);
9706 END_PROFILE(Trans2_open);
9710 case TRANSACT2_FINDFIRST:
9712 START_PROFILE(Trans2_findfirst);
9713 call_trans2findfirst(conn, req,
9714 &state->param, state->total_param,
9715 &state->data, state->total_data,
9716 state->max_data_return);
9717 END_PROFILE(Trans2_findfirst);
9721 case TRANSACT2_FINDNEXT:
9723 START_PROFILE(Trans2_findnext);
9724 call_trans2findnext(conn, req,
9725 &state->param, state->total_param,
9726 &state->data, state->total_data,
9727 state->max_data_return);
9728 END_PROFILE(Trans2_findnext);
9732 case TRANSACT2_QFSINFO:
9734 START_PROFILE(Trans2_qfsinfo);
9735 call_trans2qfsinfo(conn, req,
9736 &state->param, state->total_param,
9737 &state->data, state->total_data,
9738 state->max_data_return);
9739 END_PROFILE(Trans2_qfsinfo);
9743 case TRANSACT2_SETFSINFO:
9745 START_PROFILE(Trans2_setfsinfo);
9746 call_trans2setfsinfo(conn, req,
9747 &state->param, state->total_param,
9748 &state->data, state->total_data,
9749 state->max_data_return);
9750 END_PROFILE(Trans2_setfsinfo);
9754 case TRANSACT2_QPATHINFO:
9755 case TRANSACT2_QFILEINFO:
9757 START_PROFILE(Trans2_qpathinfo);
9758 call_trans2qfilepathinfo(conn, req, state->call,
9759 &state->param, state->total_param,
9760 &state->data, state->total_data,
9761 state->max_data_return);
9762 END_PROFILE(Trans2_qpathinfo);
9766 case TRANSACT2_SETPATHINFO:
9767 case TRANSACT2_SETFILEINFO:
9769 START_PROFILE(Trans2_setpathinfo);
9770 call_trans2setfilepathinfo(conn, req, state->call,
9771 &state->param, state->total_param,
9772 &state->data, state->total_data,
9773 state->max_data_return);
9774 END_PROFILE(Trans2_setpathinfo);
9778 case TRANSACT2_FINDNOTIFYFIRST:
9780 START_PROFILE(Trans2_findnotifyfirst);
9781 call_trans2findnotifyfirst(conn, req,
9782 &state->param, state->total_param,
9783 &state->data, state->total_data,
9784 state->max_data_return);
9785 END_PROFILE(Trans2_findnotifyfirst);
9789 case TRANSACT2_FINDNOTIFYNEXT:
9791 START_PROFILE(Trans2_findnotifynext);
9792 call_trans2findnotifynext(conn, req,
9793 &state->param, state->total_param,
9794 &state->data, state->total_data,
9795 state->max_data_return);
9796 END_PROFILE(Trans2_findnotifynext);
9800 case TRANSACT2_MKDIR:
9802 START_PROFILE(Trans2_mkdir);
9803 call_trans2mkdir(conn, req,
9804 &state->param, state->total_param,
9805 &state->data, state->total_data,
9806 state->max_data_return);
9807 END_PROFILE(Trans2_mkdir);
9811 case TRANSACT2_GET_DFS_REFERRAL:
9813 START_PROFILE(Trans2_get_dfs_referral);
9814 call_trans2getdfsreferral(conn, req,
9815 &state->param, state->total_param,
9816 &state->data, state->total_data,
9817 state->max_data_return);
9818 END_PROFILE(Trans2_get_dfs_referral);
9822 case TRANSACT2_IOCTL:
9824 START_PROFILE(Trans2_ioctl);
9825 call_trans2ioctl(conn, req,
9826 &state->param, state->total_param,
9827 &state->data, state->total_data,
9828 state->max_data_return);
9829 END_PROFILE(Trans2_ioctl);
9834 /* Error in request */
9835 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9836 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9840 /****************************************************************************
9841 Reply to a SMBtrans2.
9842 ****************************************************************************/
9844 void reply_trans2(struct smb_request *req)
9846 connection_struct *conn = req->conn;
9851 unsigned int tran_call;
9852 struct trans_state *state;
9855 START_PROFILE(SMBtrans2);
9857 if (req->wct < 14) {
9858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9859 END_PROFILE(SMBtrans2);
9863 dsoff = SVAL(req->vwv+12, 0);
9864 dscnt = SVAL(req->vwv+11, 0);
9865 psoff = SVAL(req->vwv+10, 0);
9866 pscnt = SVAL(req->vwv+9, 0);
9867 tran_call = SVAL(req->vwv+14, 0);
9869 result = allow_new_trans(conn->pending_trans, req->mid);
9870 if (!NT_STATUS_IS_OK(result)) {
9871 DEBUG(2, ("Got invalid trans2 request: %s\n",
9872 nt_errstr(result)));
9873 reply_nterror(req, result);
9874 END_PROFILE(SMBtrans2);
9879 switch (tran_call) {
9880 /* List the allowed trans2 calls on IPC$ */
9881 case TRANSACT2_OPEN:
9882 case TRANSACT2_GET_DFS_REFERRAL:
9883 case TRANSACT2_QFILEINFO:
9884 case TRANSACT2_QFSINFO:
9885 case TRANSACT2_SETFSINFO:
9888 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9889 END_PROFILE(SMBtrans2);
9894 if ((state = talloc(conn, struct trans_state)) == NULL) {
9895 DEBUG(0, ("talloc failed\n"));
9896 reply_nterror(req, NT_STATUS_NO_MEMORY);
9897 END_PROFILE(SMBtrans2);
9901 state->cmd = SMBtrans2;
9903 state->mid = req->mid;
9904 state->vuid = req->vuid;
9905 state->setup_count = SVAL(req->vwv+13, 0);
9906 state->setup = NULL;
9907 state->total_param = SVAL(req->vwv+0, 0);
9908 state->param = NULL;
9909 state->total_data = SVAL(req->vwv+1, 0);
9911 state->max_param_return = SVAL(req->vwv+2, 0);
9912 state->max_data_return = SVAL(req->vwv+3, 0);
9913 state->max_setup_return = SVAL(req->vwv+4, 0);
9914 state->close_on_completion = BITSETW(req->vwv+5, 0);
9915 state->one_way = BITSETW(req->vwv+5, 1);
9917 state->call = tran_call;
9919 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9920 is so as a sanity check */
9921 if (state->setup_count != 1) {
9923 * Need to have rc=0 for ioctl to get job id for OS/2.
9924 * Network printing will fail if function is not successful.
9925 * Similar function in reply.c will be used if protocol
9926 * is LANMAN1.0 instead of LM1.2X002.
9927 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9928 * outbuf doesn't have to be set(only job id is used).
9930 if ( (state->setup_count == 4)
9931 && (tran_call == TRANSACT2_IOCTL)
9932 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9933 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9934 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9936 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9937 DEBUG(2,("Transaction is %d\n",tran_call));
9939 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9940 END_PROFILE(SMBtrans2);
9945 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9948 if (state->total_data) {
9950 if (trans_oob(state->total_data, 0, dscnt)
9951 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9955 /* Can't use talloc here, the core routines do realloc on the
9956 * params and data. */
9957 state->data = (char *)SMB_MALLOC(state->total_data);
9958 if (state->data == NULL) {
9959 DEBUG(0,("reply_trans2: data malloc fail for %u "
9960 "bytes !\n", (unsigned int)state->total_data));
9962 reply_nterror(req, NT_STATUS_NO_MEMORY);
9963 END_PROFILE(SMBtrans2);
9967 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9970 if (state->total_param) {
9972 if (trans_oob(state->total_param, 0, pscnt)
9973 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9977 /* Can't use talloc here, the core routines do realloc on the
9978 * params and data. */
9979 state->param = (char *)SMB_MALLOC(state->total_param);
9980 if (state->param == NULL) {
9981 DEBUG(0,("reply_trans: param malloc fail for %u "
9982 "bytes !\n", (unsigned int)state->total_param));
9983 SAFE_FREE(state->data);
9985 reply_nterror(req, NT_STATUS_NO_MEMORY);
9986 END_PROFILE(SMBtrans2);
9990 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9993 state->received_data = dscnt;
9994 state->received_param = pscnt;
9996 if ((state->received_param == state->total_param) &&
9997 (state->received_data == state->total_data)) {
9999 handle_trans2(conn, req, state);
10001 SAFE_FREE(state->data);
10002 SAFE_FREE(state->param);
10003 TALLOC_FREE(state);
10004 END_PROFILE(SMBtrans2);
10008 DLIST_ADD(conn->pending_trans, state);
10010 /* We need to send an interim response then receive the rest
10011 of the parameter/data bytes */
10012 reply_outbuf(req, 0, 0);
10013 show_msg((char *)req->outbuf);
10014 END_PROFILE(SMBtrans2);
10019 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10020 SAFE_FREE(state->data);
10021 SAFE_FREE(state->param);
10022 TALLOC_FREE(state);
10023 END_PROFILE(SMBtrans2);
10024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10028 /****************************************************************************
10029 Reply to a SMBtranss2
10030 ****************************************************************************/
10032 void reply_transs2(struct smb_request *req)
10034 connection_struct *conn = req->conn;
10035 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10036 struct trans_state *state;
10038 START_PROFILE(SMBtranss2);
10040 show_msg((const char *)req->inbuf);
10042 /* Windows clients expect all replies to
10043 a transact secondary (SMBtranss2 0x33)
10044 to have a command code of transact
10045 (SMBtrans2 0x32). See bug #8989
10046 and also [MS-CIFS] section 2.2.4.47.2
10049 req->cmd = SMBtrans2;
10051 if (req->wct < 8) {
10052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10053 END_PROFILE(SMBtranss2);
10057 for (state = conn->pending_trans; state != NULL;
10058 state = state->next) {
10059 if (state->mid == req->mid) {
10064 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10065 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10066 END_PROFILE(SMBtranss2);
10070 /* Revise state->total_param and state->total_data in case they have
10071 changed downwards */
10073 if (SVAL(req->vwv+0, 0) < state->total_param)
10074 state->total_param = SVAL(req->vwv+0, 0);
10075 if (SVAL(req->vwv+1, 0) < state->total_data)
10076 state->total_data = SVAL(req->vwv+1, 0);
10078 pcnt = SVAL(req->vwv+2, 0);
10079 poff = SVAL(req->vwv+3, 0);
10080 pdisp = SVAL(req->vwv+4, 0);
10082 dcnt = SVAL(req->vwv+5, 0);
10083 doff = SVAL(req->vwv+6, 0);
10084 ddisp = SVAL(req->vwv+7, 0);
10086 state->received_param += pcnt;
10087 state->received_data += dcnt;
10089 if ((state->received_data > state->total_data) ||
10090 (state->received_param > state->total_param))
10094 if (trans_oob(state->total_param, pdisp, pcnt)
10095 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10098 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10102 if (trans_oob(state->total_data, ddisp, dcnt)
10103 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10106 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10109 if ((state->received_param < state->total_param) ||
10110 (state->received_data < state->total_data)) {
10111 END_PROFILE(SMBtranss2);
10115 handle_trans2(conn, req, state);
10117 DLIST_REMOVE(conn->pending_trans, state);
10118 SAFE_FREE(state->data);
10119 SAFE_FREE(state->param);
10120 TALLOC_FREE(state);
10122 END_PROFILE(SMBtranss2);
10127 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10128 DLIST_REMOVE(conn->pending_trans, state);
10129 SAFE_FREE(state->data);
10130 SAFE_FREE(state->param);
10131 TALLOC_FREE(state);
10132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10133 END_PROFILE(SMBtranss2);