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 Create a 64 bit FileIndex. If the file is on the same device as
218 the root of the share, just return the 64-bit inode. If it isn't,
219 mangle as we used to do.
220 ********************************************************************/
222 uint64_t get_fs_file_id(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
225 if (conn->sconn->aapl_zero_file_id) {
228 if (conn->base_share_dev == psbuf->st_ex_dev) {
229 return (uint64_t)psbuf->st_ex_ino;
231 file_id = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIDLow */
232 file_id |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIDHigh */
237 /********************************************************************
238 Globally (for this connection / multi-channel) disable file-ID
239 calculation. This is required to be global because it serves
240 Macs in AAPL mode, which is globally set.
241 ********************************************************************/
242 void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
244 sconn->aapl_zero_file_id = true;
247 /****************************************************************************
248 Utility functions for dealing with extended attributes.
249 ****************************************************************************/
251 /****************************************************************************
252 Refuse to allow clients to overwrite our private xattrs.
253 ****************************************************************************/
255 bool samba_private_attr_name(const char *unix_ea_name)
257 static const char * const prohibited_ea_names[] = {
258 SAMBA_POSIX_INHERITANCE_EA_NAME,
259 SAMBA_XATTR_DOS_ATTRIB,
267 for (i = 0; prohibited_ea_names[i]; i++) {
268 if (strequal( prohibited_ea_names[i], unix_ea_name))
271 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
272 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
278 /****************************************************************************
279 Get one EA value. Fill in a struct ea_struct.
280 ****************************************************************************/
282 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
283 connection_struct *conn,
285 const struct smb_filename *smb_fname,
287 struct ea_struct *pea)
289 /* Get the value of this xattr. Max size is 64k. */
290 size_t attr_size = 256;
296 val = talloc_realloc(mem_ctx, val, char, attr_size);
298 return NT_STATUS_NO_MEMORY;
301 if (fsp && fsp->fh->fd != -1) {
302 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
304 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
305 ea_name, val, attr_size);
308 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
314 return map_nt_error_from_unix(errno);
317 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
318 dump_data(10, (uint8_t *)val, sizeret);
321 if (strnequal(ea_name, "user.", 5)) {
322 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
324 pea->name = talloc_strdup(mem_ctx, ea_name);
326 if (pea->name == NULL) {
328 return NT_STATUS_NO_MEMORY;
330 pea->value.data = (unsigned char *)val;
331 pea->value.length = (size_t)sizeret;
335 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
336 connection_struct *conn,
338 const struct smb_filename *smb_fname,
343 /* Get a list of all xattrs. Max namesize is 64k. */
344 size_t ea_namelist_size = 1024;
345 char *ea_namelist = smallbuf;
346 char *to_free = NULL;
351 ssize_t sizeret = -1;
359 status = refuse_symlink(conn, fsp, smb_fname);
360 if (!NT_STATUS_IS_OK(status)) {
362 * Just return no EA's on a symlink.
367 if (fsp && fsp->fh->fd != -1) {
368 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
371 sizeret = SMB_VFS_LISTXATTR(conn,
377 if ((sizeret == -1) && (errno == ERANGE)) {
378 ea_namelist_size = 65536;
379 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
380 if (ea_namelist == NULL) {
381 return NT_STATUS_NO_MEMORY;
383 to_free = ea_namelist;
385 if (fsp && fsp->fh->fd != -1) {
386 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
389 sizeret = SMB_VFS_LISTXATTR(conn,
397 status = map_nt_error_from_unix(errno);
398 TALLOC_FREE(to_free);
402 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
405 TALLOC_FREE(to_free);
410 * Ensure the result is 0-terminated
413 if (ea_namelist[sizeret-1] != '\0') {
414 TALLOC_FREE(to_free);
415 return NT_STATUS_INTERNAL_ERROR;
423 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
427 *pnum_names = num_names;
429 if (pnames == NULL) {
430 TALLOC_FREE(to_free);
434 names = talloc_array(mem_ctx, char *, num_names);
436 DEBUG(0, ("talloc failed\n"));
437 TALLOC_FREE(to_free);
438 return NT_STATUS_NO_MEMORY;
441 if (ea_namelist == smallbuf) {
442 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
443 if (ea_namelist == NULL) {
445 return NT_STATUS_NO_MEMORY;
448 talloc_steal(names, ea_namelist);
450 ea_namelist = talloc_realloc(names, ea_namelist, char,
452 if (ea_namelist == NULL) {
454 return NT_STATUS_NO_MEMORY;
460 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
461 names[num_names++] = p;
469 /****************************************************************************
470 Return a linked list of the total EA's. Plus the total size
471 ****************************************************************************/
473 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
474 connection_struct *conn,
476 const struct smb_filename *smb_fname,
477 size_t *pea_total_len,
478 struct ea_list **ea_list)
480 /* Get a list of all xattrs. Max namesize is 64k. */
483 struct ea_list *ea_list_head = NULL;
484 bool posix_pathnames = false;
490 if (!lp_ea_support(SNUM(conn))) {
496 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
498 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
501 status = get_ea_names_from_file(talloc_tos(),
508 if (!NT_STATUS_IS_OK(status)) {
512 if (num_names == 0) {
516 for (i=0; i<num_names; i++) {
517 struct ea_list *listp;
520 if (strnequal(names[i], "system.", 7)
521 || samba_private_attr_name(names[i]))
525 * Filter out any underlying POSIX EA names
526 * that a Windows client can't handle.
528 if (!posix_pathnames &&
529 is_invalid_windows_ea_name(names[i])) {
533 listp = talloc(mem_ctx, struct ea_list);
535 return NT_STATUS_NO_MEMORY;
538 status = get_ea_value(listp,
545 if (!NT_STATUS_IS_OK(status)) {
550 if (listp->ea.value.length == 0) {
552 * We can never return a zero length EA.
553 * Windows reports the EA's as corrupted.
559 push_ascii_fstring(dos_ea_name, listp->ea.name);
562 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
564 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
565 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
566 (unsigned int)listp->ea.value.length));
568 DLIST_ADD_END(ea_list_head, listp);
572 /* Add on 4 for total length. */
573 if (*pea_total_len) {
577 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
578 (unsigned int)*pea_total_len));
580 *ea_list = ea_list_head;
584 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
585 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
590 if (!lp_ea_support(SNUM(conn))) {
594 if (is_ntfs_stream_smb_fname(smb_fname)) {
595 return NT_STATUS_INVALID_PARAMETER;
598 return get_ea_list_from_file_path(mem_ctx,
606 /****************************************************************************
607 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
609 ****************************************************************************/
611 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
612 connection_struct *conn, struct ea_list *ea_list)
614 unsigned int ret_data_size = 4;
617 SMB_ASSERT(total_data_size >= 4);
619 if (!lp_ea_support(SNUM(conn))) {
624 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
627 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
628 dos_namelen = strlen(dos_ea_name);
629 if (dos_namelen > 255 || dos_namelen == 0) {
632 if (ea_list->ea.value.length > 65535) {
635 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
639 /* We know we have room. */
640 SCVAL(p,0,ea_list->ea.flags);
641 SCVAL(p,1,dos_namelen);
642 SSVAL(p,2,ea_list->ea.value.length);
643 strlcpy(p+4, dos_ea_name, dos_namelen+1);
644 if (ea_list->ea.value.length > 0) {
645 memcpy(p + 4 + dos_namelen + 1,
646 ea_list->ea.value.data,
647 ea_list->ea.value.length);
650 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
651 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
654 ret_data_size = PTR_DIFF(p, pdata);
655 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
656 SIVAL(pdata,0,ret_data_size);
657 return ret_data_size;
660 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
662 unsigned int total_data_size,
663 unsigned int *ret_data_size,
664 connection_struct *conn,
665 struct ea_list *ea_list)
667 uint8_t *p = (uint8_t *)pdata;
668 uint8_t *last_start = NULL;
669 bool do_store_data = (pdata != NULL);
673 if (!lp_ea_support(SNUM(conn))) {
674 return NT_STATUS_NO_EAS_ON_FILE;
677 for (; ea_list; ea_list = ea_list->next) {
683 if (last_start != NULL && do_store_data) {
684 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
688 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
689 dos_namelen = strlen(dos_ea_name);
690 if (dos_namelen > 255 || dos_namelen == 0) {
691 return NT_STATUS_INTERNAL_ERROR;
693 if (ea_list->ea.value.length > 65535) {
694 return NT_STATUS_INTERNAL_ERROR;
697 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
700 pad = (4 - (this_size % 4)) % 4;
705 if (this_size > total_data_size) {
706 return NT_STATUS_INFO_LENGTH_MISMATCH;
709 /* We know we have room. */
710 SIVAL(p, 0x00, 0); /* next offset */
711 SCVAL(p, 0x04, ea_list->ea.flags);
712 SCVAL(p, 0x05, dos_namelen);
713 SSVAL(p, 0x06, ea_list->ea.value.length);
714 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
715 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
717 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
721 total_data_size -= this_size;
727 *ret_data_size = PTR_DIFF(p, pdata);
728 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
732 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
734 size_t total_ea_len = 0;
736 struct ea_list *ea_list = NULL;
738 if (!lp_ea_support(SNUM(conn))) {
741 mem_ctx = talloc_stackframe();
743 /* If this is a stream fsp, then we need to instead find the
744 * estimated ea len from the main file, not the stream
745 * (streams cannot have EAs), but the estimate isn't just 0 in
747 if (is_ntfs_stream_smb_fname(smb_fname)) {
750 (void)get_ea_list_from_file_path(mem_ctx,
756 if(conn->sconn->using_smb2) {
758 unsigned int ret_data_size;
760 * We're going to be using fill_ea_chained_buffer() to
761 * marshall EA's - this size is significantly larger
762 * than the SMB1 buffer. Re-calculate the size without
765 status = fill_ea_chained_buffer(mem_ctx,
771 if (!NT_STATUS_IS_OK(status)) {
774 total_ea_len = ret_data_size;
776 TALLOC_FREE(mem_ctx);
780 /****************************************************************************
781 Ensure the EA name is case insensitive by matching any existing EA name.
782 ****************************************************************************/
784 static void canonicalize_ea_name(connection_struct *conn,
786 const struct smb_filename *smb_fname,
787 fstring unix_ea_name)
790 TALLOC_CTX *mem_ctx = talloc_tos();
791 struct ea_list *ea_list;
792 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
798 if (!NT_STATUS_IS_OK(status)) {
802 for (; ea_list; ea_list = ea_list->next) {
803 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
804 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
805 &unix_ea_name[5], ea_list->ea.name));
806 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
812 /****************************************************************************
813 Set or delete an extended attribute.
814 ****************************************************************************/
816 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
817 const struct smb_filename *smb_fname, struct ea_list *ea_list)
820 bool posix_pathnames = false;
822 if (!lp_ea_support(SNUM(conn))) {
823 return NT_STATUS_EAS_NOT_SUPPORTED;
828 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
830 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
833 status = refuse_symlink(conn, fsp, smb_fname);
834 if (!NT_STATUS_IS_OK(status)) {
838 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
839 if (!NT_STATUS_IS_OK(status)) {
843 /* Setting EAs on streams isn't supported. */
844 if (is_ntfs_stream_smb_fname(smb_fname)) {
845 return NT_STATUS_INVALID_PARAMETER;
849 * Filter out invalid Windows EA names - before
850 * we set *any* of them.
853 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
854 return STATUS_INVALID_EA_NAME;
857 for (;ea_list; ea_list = ea_list->next) {
859 fstring unix_ea_name;
861 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
862 fstrcat(unix_ea_name, ea_list->ea.name);
864 canonicalize_ea_name(conn,
869 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
871 if (samba_private_attr_name(unix_ea_name)) {
872 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
873 return NT_STATUS_ACCESS_DENIED;
876 if (ea_list->ea.value.length == 0) {
877 /* Remove the attribute. */
878 if (fsp && (fsp->fh->fd != -1)) {
879 DEBUG(10,("set_ea: deleting ea name %s on "
880 "file %s by file descriptor.\n",
881 unix_ea_name, fsp_str_dbg(fsp)));
882 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
884 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
885 unix_ea_name, smb_fname->base_name));
886 ret = SMB_VFS_REMOVEXATTR(conn,
891 /* Removing a non existent attribute always succeeds. */
892 if (ret == -1 && errno == ENOATTR) {
893 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
899 if (fsp && (fsp->fh->fd != -1)) {
900 DEBUG(10,("set_ea: setting ea name %s on file "
901 "%s by file descriptor.\n",
902 unix_ea_name, fsp_str_dbg(fsp)));
903 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
904 ea_list->ea.value.data, ea_list->ea.value.length, 0);
906 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
907 unix_ea_name, smb_fname->base_name));
908 ret = SMB_VFS_SETXATTR(conn,
911 ea_list->ea.value.data,
912 ea_list->ea.value.length,
919 if (errno == ENOTSUP) {
920 return NT_STATUS_EAS_NOT_SUPPORTED;
923 return map_nt_error_from_unix(errno);
929 /****************************************************************************
930 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
931 ****************************************************************************/
933 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
935 struct ea_list *ea_list_head = NULL;
936 size_t converted_size, offset = 0;
938 while (offset + 2 < data_size) {
939 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
940 unsigned int namelen = CVAL(pdata,offset);
942 offset++; /* Go past the namelen byte. */
944 /* integer wrap paranioa. */
945 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
946 (offset > data_size) || (namelen > data_size) ||
947 (offset + namelen >= data_size)) {
950 /* Ensure the name is null terminated. */
951 if (pdata[offset + namelen] != '\0') {
954 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
956 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
957 "failed: %s", strerror(errno)));
963 offset += (namelen + 1); /* Go past the name + terminating zero. */
964 DLIST_ADD_END(ea_list_head, eal);
965 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
971 /****************************************************************************
972 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
973 ****************************************************************************/
975 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
977 struct ea_list *ea_list_head = NULL;
979 size_t bytes_used = 0;
981 while (offset < data_size) {
982 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
988 DLIST_ADD_END(ea_list_head, eal);
989 offset += bytes_used;
995 /****************************************************************************
996 Count the total EA size needed.
997 ****************************************************************************/
999 static size_t ea_list_size(struct ea_list *ealist)
1001 fstring dos_ea_name;
1002 struct ea_list *listp;
1005 for (listp = ealist; listp; listp = listp->next) {
1006 push_ascii_fstring(dos_ea_name, listp->ea.name);
1007 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
1009 /* Add on 4 for total length. */
1017 /****************************************************************************
1018 Return a union of EA's from a file list and a list of names.
1019 The TALLOC context for the two lists *MUST* be identical as we steal
1020 memory from one list to add to another. JRA.
1021 ****************************************************************************/
1023 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
1025 struct ea_list *nlistp, *flistp;
1027 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
1028 for (flistp = file_list; flistp; flistp = flistp->next) {
1029 if (strequal(nlistp->ea.name, flistp->ea.name)) {
1035 /* Copy the data from this entry. */
1036 nlistp->ea.flags = flistp->ea.flags;
1037 nlistp->ea.value = flistp->ea.value;
1040 nlistp->ea.flags = 0;
1041 ZERO_STRUCT(nlistp->ea.value);
1045 *total_ea_len = ea_list_size(name_list);
1049 /****************************************************************************
1050 Send the required number of replies back.
1051 We assume all fields other than the data fields are
1052 set correctly for the type of call.
1053 HACK ! Always assumes smb_setup field is zero.
1054 ****************************************************************************/
1056 void send_trans2_replies(connection_struct *conn,
1057 struct smb_request *req,
1065 /* As we are using a protocol > LANMAN1 then the max_send
1066 variable must have been set in the sessetupX call.
1067 This takes precedence over the max_xmit field in the
1068 global struct. These different max_xmit variables should
1069 be merged as this is now too confusing */
1071 int data_to_send = datasize;
1072 int params_to_send = paramsize;
1074 const char *pp = params;
1075 const char *pd = pdata;
1076 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1077 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1078 int data_alignment_offset = 0;
1079 bool overflow = False;
1080 struct smbXsrv_connection *xconn = req->xconn;
1081 int max_send = xconn->smb1.sessions.max_send;
1083 /* Modify the data_to_send and datasize and set the error if
1084 we're trying to send more than max_data_bytes. We still send
1085 the part of the packet(s) that fit. Strange, but needed
1088 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1089 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1090 max_data_bytes, datasize ));
1091 datasize = data_to_send = max_data_bytes;
1095 /* If there genuinely are no parameters or data to send just send the empty packet */
1097 if(params_to_send == 0 && data_to_send == 0) {
1098 reply_outbuf(req, 10, 0);
1099 if (NT_STATUS_V(status)) {
1102 ntstatus_to_dos(status, &eclass, &ecode);
1103 error_packet_set((char *)req->outbuf,
1104 eclass, ecode, status,
1107 show_msg((char *)req->outbuf);
1108 if (!srv_send_smb(xconn,
1109 (char *)req->outbuf,
1110 true, req->seqnum+1,
1111 IS_CONN_ENCRYPTED(conn),
1113 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1115 TALLOC_FREE(req->outbuf);
1119 /* When sending params and data ensure that both are nicely aligned */
1120 /* Only do this alignment when there is also data to send - else
1121 can cause NT redirector problems. */
1123 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1124 data_alignment_offset = 4 - (params_to_send % 4);
1126 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1127 /* The alignment_offset is to align the param bytes on an even byte
1128 boundary. NT 4.0 Beta needs this to work correctly. */
1130 useable_space = max_send - (smb_size
1133 + data_alignment_offset);
1135 if (useable_space < 0) {
1136 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1137 "= %d!!!", useable_space));
1138 exit_server_cleanly("send_trans2_replies: Not enough space");
1141 while (params_to_send || data_to_send) {
1142 /* Calculate whether we will totally or partially fill this packet */
1144 total_sent_thistime = params_to_send + data_to_send;
1146 /* We can never send more than useable_space */
1148 * Note that 'useable_space' does not include the alignment offsets,
1149 * but we must include the alignment offsets in the calculation of
1150 * the length of the data we send over the wire, as the alignment offsets
1151 * are sent here. Fix from Marc_Jacobsen@hp.com.
1154 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1156 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1157 + data_alignment_offset);
1159 /* Set total params and data to be sent */
1160 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1161 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1163 /* Calculate how many parameters and data we can fit into
1164 * this packet. Parameters get precedence
1167 params_sent_thistime = MIN(params_to_send,useable_space);
1168 data_sent_thistime = useable_space - params_sent_thistime;
1169 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1171 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1173 /* smb_proff is the offset from the start of the SMB header to the
1174 parameter bytes, however the first 4 bytes of outbuf are
1175 the Netbios over TCP header. Thus use smb_base() to subtract
1176 them from the calculation */
1178 SSVAL(req->outbuf,smb_proff,
1179 ((smb_buf(req->outbuf)+alignment_offset)
1180 - smb_base(req->outbuf)));
1182 if(params_sent_thistime == 0)
1183 SSVAL(req->outbuf,smb_prdisp,0);
1185 /* Absolute displacement of param bytes sent in this packet */
1186 SSVAL(req->outbuf,smb_prdisp,pp - params);
1188 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1189 if(data_sent_thistime == 0) {
1190 SSVAL(req->outbuf,smb_droff,0);
1191 SSVAL(req->outbuf,smb_drdisp, 0);
1193 /* The offset of the data bytes is the offset of the
1194 parameter bytes plus the number of parameters being sent this time */
1195 SSVAL(req->outbuf, smb_droff,
1196 ((smb_buf(req->outbuf)+alignment_offset)
1197 - smb_base(req->outbuf))
1198 + params_sent_thistime + data_alignment_offset);
1199 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1202 /* Initialize the padding for alignment */
1204 if (alignment_offset != 0) {
1205 memset(smb_buf(req->outbuf), 0, alignment_offset);
1208 /* Copy the param bytes into the packet */
1210 if(params_sent_thistime) {
1211 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1212 params_sent_thistime);
1215 /* Copy in the data bytes */
1216 if(data_sent_thistime) {
1217 if (data_alignment_offset != 0) {
1218 memset((smb_buf(req->outbuf)+alignment_offset+
1219 params_sent_thistime), 0,
1220 data_alignment_offset);
1222 memcpy(smb_buf(req->outbuf)+alignment_offset
1223 +params_sent_thistime+data_alignment_offset,
1224 pd,data_sent_thistime);
1227 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1228 params_sent_thistime, data_sent_thistime, useable_space));
1229 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1230 params_to_send, data_to_send, paramsize, datasize));
1233 error_packet_set((char *)req->outbuf,
1234 ERRDOS,ERRbufferoverflow,
1235 STATUS_BUFFER_OVERFLOW,
1237 } else if (NT_STATUS_V(status)) {
1240 ntstatus_to_dos(status, &eclass, &ecode);
1241 error_packet_set((char *)req->outbuf,
1242 eclass, ecode, status,
1246 /* Send the packet */
1247 show_msg((char *)req->outbuf);
1248 if (!srv_send_smb(xconn,
1249 (char *)req->outbuf,
1250 true, req->seqnum+1,
1251 IS_CONN_ENCRYPTED(conn),
1253 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1255 TALLOC_FREE(req->outbuf);
1257 pp += params_sent_thistime;
1258 pd += data_sent_thistime;
1260 params_to_send -= params_sent_thistime;
1261 data_to_send -= data_sent_thistime;
1264 if(params_to_send < 0 || data_to_send < 0) {
1265 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1266 params_to_send, data_to_send));
1274 /****************************************************************************
1275 Reply to a TRANSACT2_OPEN.
1276 ****************************************************************************/
1278 static void call_trans2open(connection_struct *conn,
1279 struct smb_request *req,
1280 char **pparams, int total_params,
1281 char **ppdata, int total_data,
1282 unsigned int max_data_bytes)
1284 struct smb_filename *smb_fname = NULL;
1285 char *params = *pparams;
1286 char *pdata = *ppdata;
1289 bool oplock_request;
1291 bool return_additional_info;
1300 int fattr=0,mtime=0;
1301 SMB_INO_T inode = 0;
1304 struct ea_list *ea_list = NULL;
1307 uint32_t access_mask;
1308 uint32_t share_mode;
1309 uint32_t create_disposition;
1310 uint32_t create_options = 0;
1311 uint32_t private_flags = 0;
1312 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1313 TALLOC_CTX *ctx = talloc_tos();
1316 * Ensure we have enough parameters to perform the operation.
1319 if (total_params < 29) {
1320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1324 flags = SVAL(params, 0);
1325 deny_mode = SVAL(params, 2);
1326 open_attr = SVAL(params,6);
1327 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1328 if (oplock_request) {
1329 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1333 return_additional_info = BITSETW(params,0);
1334 open_sattr = SVAL(params, 4);
1335 open_time = make_unix_date3(params+8);
1337 open_ofun = SVAL(params,12);
1338 open_size = IVAL(params,14);
1339 pname = ¶ms[28];
1342 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1346 if (req->posix_pathnames) {
1347 srvstr_get_path_posix(ctx,
1356 srvstr_get_path(ctx,
1365 if (!NT_STATUS_IS_OK(status)) {
1366 reply_nterror(req, status);
1370 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1371 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1372 (unsigned int)open_ofun, open_size));
1374 status = filename_convert(ctx,
1381 if (!NT_STATUS_IS_OK(status)) {
1382 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1383 reply_botherror(req,
1384 NT_STATUS_PATH_NOT_COVERED,
1385 ERRSRV, ERRbadpath);
1388 reply_nterror(req, status);
1392 if (open_ofun == 0) {
1393 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1397 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1399 &access_mask, &share_mode,
1400 &create_disposition,
1403 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1407 /* Any data in this call is an EA list. */
1408 if (total_data && (total_data != 4)) {
1409 if (total_data < 10) {
1410 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1414 if (IVAL(pdata,0) > total_data) {
1415 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1416 IVAL(pdata,0), (unsigned int)total_data));
1417 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1421 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1428 if (!lp_ea_support(SNUM(conn))) {
1429 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1433 if (!req->posix_pathnames &&
1434 ea_list_has_invalid_name(ea_list)) {
1436 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1437 if(*pparams == NULL ) {
1438 reply_nterror(req, NT_STATUS_NO_MEMORY);
1442 memset(params, '\0', param_len);
1443 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1444 params, param_len, NULL, 0, max_data_bytes);
1449 status = SMB_VFS_CREATE_FILE(
1452 0, /* root_dir_fid */
1453 smb_fname, /* fname */
1454 access_mask, /* access_mask */
1455 share_mode, /* share_access */
1456 create_disposition, /* create_disposition*/
1457 create_options, /* create_options */
1458 open_attr, /* file_attributes */
1459 oplock_request, /* oplock_request */
1461 open_size, /* allocation_size */
1464 ea_list, /* ea_list */
1466 &smb_action, /* psbuf */
1467 NULL, NULL); /* create context */
1469 if (!NT_STATUS_IS_OK(status)) {
1470 if (open_was_deferred(req->xconn, req->mid)) {
1471 /* We have re-scheduled this call. */
1474 reply_openerror(req, status);
1478 size = get_file_size_stat(&smb_fname->st);
1479 fattr = dos_mode(conn, smb_fname);
1480 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1481 inode = smb_fname->st.st_ex_ino;
1482 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1483 close_file(req, fsp, ERROR_CLOSE);
1484 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1488 /* Realloc the size of parameters and data we will return */
1489 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1490 if(*pparams == NULL ) {
1491 reply_nterror(req, NT_STATUS_NO_MEMORY);
1496 SSVAL(params,0,fsp->fnum);
1497 SSVAL(params,2,fattr);
1498 srv_put_dos_date2(params,4, mtime);
1499 SIVAL(params,8, (uint32_t)size);
1500 SSVAL(params,12,deny_mode);
1501 SSVAL(params,14,0); /* open_type - file or directory. */
1502 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1504 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1505 smb_action |= EXTENDED_OPLOCK_GRANTED;
1508 SSVAL(params,18,smb_action);
1511 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1513 SIVAL(params,20,inode);
1514 SSVAL(params,24,0); /* Padding. */
1516 uint32_t ea_size = estimate_ea_size(conn, fsp,
1518 SIVAL(params, 26, ea_size);
1520 SIVAL(params, 26, 0);
1523 /* Send the required number of replies */
1524 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1526 TALLOC_FREE(smb_fname);
1529 /*********************************************************
1530 Routine to check if a given string matches exactly.
1531 as a special case a mask of "." does NOT match. That
1532 is required for correct wildcard semantics
1533 Case can be significant or not.
1534 **********************************************************/
1536 static bool exact_match(bool has_wild,
1537 bool case_sensitive,
1541 if (mask[0] == '.' && mask[1] == 0) {
1549 if (case_sensitive) {
1550 return strcmp(str,mask)==0;
1552 return strcasecmp_m(str,mask) == 0;
1556 /****************************************************************************
1557 Return the filetype for UNIX extensions.
1558 ****************************************************************************/
1560 static uint32_t unix_filetype(mode_t mode)
1563 return UNIX_TYPE_FILE;
1564 else if(S_ISDIR(mode))
1565 return UNIX_TYPE_DIR;
1567 else if(S_ISLNK(mode))
1568 return UNIX_TYPE_SYMLINK;
1571 else if(S_ISCHR(mode))
1572 return UNIX_TYPE_CHARDEV;
1575 else if(S_ISBLK(mode))
1576 return UNIX_TYPE_BLKDEV;
1579 else if(S_ISFIFO(mode))
1580 return UNIX_TYPE_FIFO;
1583 else if(S_ISSOCK(mode))
1584 return UNIX_TYPE_SOCKET;
1587 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1588 return UNIX_TYPE_UNKNOWN;
1591 /****************************************************************************
1592 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1593 ****************************************************************************/
1595 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1597 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1598 const SMB_STRUCT_STAT *psbuf,
1600 enum perm_type ptype,
1605 if (perms == SMB_MODE_NO_CHANGE) {
1606 if (!VALID_STAT(*psbuf)) {
1607 return NT_STATUS_INVALID_PARAMETER;
1609 *ret_perms = psbuf->st_ex_mode;
1610 return NT_STATUS_OK;
1614 ret = wire_perms_to_unix(perms);
1616 if (ptype == PERM_NEW_FILE) {
1618 * "create mask"/"force create mode" are
1619 * only applied to new files, not existing ones.
1621 ret &= lp_create_mask(SNUM(conn));
1622 /* Add in force bits */
1623 ret |= lp_force_create_mode(SNUM(conn));
1624 } else if (ptype == PERM_NEW_DIR) {
1626 * "directory mask"/"force directory mode" are
1627 * only applied to new directories, not existing ones.
1629 ret &= lp_directory_mask(SNUM(conn));
1630 /* Add in force bits */
1631 ret |= lp_force_directory_mode(SNUM(conn));
1635 return NT_STATUS_OK;
1638 /****************************************************************************
1639 Needed to show the msdfs symlinks as directories. Modifies psbuf
1640 to be a directory if it's a msdfs link.
1641 ****************************************************************************/
1643 static bool check_msdfs_link(connection_struct *conn,
1644 struct smb_filename *smb_fname)
1646 int saved_errno = errno;
1647 if(lp_host_msdfs() &&
1648 lp_msdfs_root(SNUM(conn)) &&
1649 is_msdfs_link(conn, smb_fname)) {
1651 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1653 smb_fname->base_name));
1654 smb_fname->st.st_ex_mode =
1655 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1656 errno = saved_errno;
1659 errno = saved_errno;
1664 /****************************************************************************
1665 Get a level dependent lanman2 dir entry.
1666 ****************************************************************************/
1668 struct smbd_dirptr_lanman2_state {
1669 connection_struct *conn;
1670 uint32_t info_level;
1671 bool check_mangled_names;
1673 bool got_exact_match;
1676 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1682 struct smbd_dirptr_lanman2_state *state =
1683 (struct smbd_dirptr_lanman2_state *)private_data;
1685 char mangled_name[13]; /* mangled 8.3 name. */
1689 /* Mangle fname if it's an illegal name. */
1690 if (mangle_must_mangle(dname, state->conn->params)) {
1692 * Slow path - ensure we can push the original name as UCS2. If
1693 * not, then just don't return this name.
1697 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1698 uint8_t *tmp = talloc_array(talloc_tos(),
1702 status = srvstr_push(NULL,
1703 FLAGS2_UNICODE_STRINGS,
1712 if (!NT_STATUS_IS_OK(status)) {
1716 ok = name_to_8_3(dname, mangled_name,
1717 true, state->conn->params);
1721 fname = mangled_name;
1726 got_match = exact_match(state->has_wild,
1727 state->conn->case_sensitive,
1729 state->got_exact_match = got_match;
1731 got_match = mask_match(fname, mask,
1732 state->conn->case_sensitive);
1735 if(!got_match && state->check_mangled_names &&
1736 !mangle_is_8_3(fname, false, state->conn->params)) {
1738 * It turns out that NT matches wildcards against
1739 * both long *and* short names. This may explain some
1740 * of the wildcard wierdness from old DOS clients
1741 * that some people have been seeing.... JRA.
1743 /* Force the mangling into 8.3. */
1744 ok = name_to_8_3(fname, mangled_name,
1745 false, state->conn->params);
1750 got_match = exact_match(state->has_wild,
1751 state->conn->case_sensitive,
1752 mangled_name, mask);
1753 state->got_exact_match = got_match;
1755 got_match = mask_match(mangled_name, mask,
1756 state->conn->case_sensitive);
1764 *_fname = talloc_strdup(ctx, fname);
1765 if (*_fname == NULL) {
1772 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1774 struct smb_filename *smb_fname,
1778 struct smbd_dirptr_lanman2_state *state =
1779 (struct smbd_dirptr_lanman2_state *)private_data;
1780 bool ms_dfs_link = false;
1783 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1784 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1785 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1786 "Couldn't lstat [%s] (%s)\n",
1787 smb_fname_str_dbg(smb_fname),
1791 } else if (!VALID_STAT(smb_fname->st) &&
1792 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1793 /* Needed to show the msdfs symlinks as
1796 ms_dfs_link = check_msdfs_link(state->conn,
1799 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1800 "Couldn't stat [%s] (%s)\n",
1801 smb_fname_str_dbg(smb_fname),
1808 mode = dos_mode_msdfs(state->conn, smb_fname);
1809 } else if (get_dosmode) {
1810 mode = dos_mode(state->conn, smb_fname);
1817 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1818 connection_struct *conn,
1820 uint32_t info_level,
1821 struct ea_list *name_list,
1822 bool check_mangled_names,
1823 bool requires_resume_key,
1826 const struct smb_filename *smb_fname,
1827 int space_remaining,
1833 uint64_t *last_entry_off)
1835 char *p, *q, *pdata = *ppdata;
1837 uint64_t file_size = 0;
1838 uint64_t allocation_size = 0;
1839 uint64_t file_id = 0;
1841 struct timespec mdate_ts = {0};
1842 struct timespec adate_ts = {0};
1843 struct timespec cdate_ts = {0};
1844 struct timespec create_date_ts = {0};
1845 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1847 char *last_entry_ptr;
1852 struct readdir_attr_data *readdir_attr_data = NULL;
1854 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1855 file_size = get_file_size_stat(&smb_fname->st);
1857 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1859 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1860 if (!NT_STATUS_IS_OK(status)) {
1861 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1866 file_id = get_fs_file_id(conn, &smb_fname->st);
1868 mdate_ts = smb_fname->st.st_ex_mtime;
1869 adate_ts = smb_fname->st.st_ex_atime;
1870 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1871 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1873 if (lp_dos_filetime_resolution(SNUM(conn))) {
1874 dos_filetime_timespec(&create_date_ts);
1875 dos_filetime_timespec(&mdate_ts);
1876 dos_filetime_timespec(&adate_ts);
1877 dos_filetime_timespec(&cdate_ts);
1880 create_date = convert_timespec_to_time_t(create_date_ts);
1881 mdate = convert_timespec_to_time_t(mdate_ts);
1882 adate = convert_timespec_to_time_t(adate_ts);
1884 /* align the record */
1885 SMB_ASSERT(align >= 1);
1887 off = (int)PTR_DIFF(pdata, base_data);
1888 pad = (off + (align-1)) & ~(align-1);
1891 if (pad && pad > space_remaining) {
1892 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1893 "for padding (wanted %u, had %d)\n",
1896 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1900 /* initialize padding to 0 */
1902 memset(pdata, 0, pad);
1904 space_remaining -= pad;
1906 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1916 switch (info_level) {
1917 case SMB_FIND_INFO_STANDARD:
1918 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1919 if(requires_resume_key) {
1923 srv_put_dos_date2(p,0,create_date);
1924 srv_put_dos_date2(p,4,adate);
1925 srv_put_dos_date2(p,8,mdate);
1926 SIVAL(p,12,(uint32_t)file_size);
1927 SIVAL(p,16,(uint32_t)allocation_size);
1931 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1932 p += ucs2_align(base_data, p, 0);
1934 status = srvstr_push(base_data, flags2, p,
1935 fname, PTR_DIFF(end_data, p),
1936 STR_TERMINATE, &len);
1937 if (!NT_STATUS_IS_OK(status)) {
1940 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1942 SCVAL(nameptr, -1, len - 2);
1944 SCVAL(nameptr, -1, 0);
1948 SCVAL(nameptr, -1, len - 1);
1950 SCVAL(nameptr, -1, 0);
1956 case SMB_FIND_EA_SIZE:
1957 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1958 if (requires_resume_key) {
1962 srv_put_dos_date2(p,0,create_date);
1963 srv_put_dos_date2(p,4,adate);
1964 srv_put_dos_date2(p,8,mdate);
1965 SIVAL(p,12,(uint32_t)file_size);
1966 SIVAL(p,16,(uint32_t)allocation_size);
1969 unsigned int ea_size = estimate_ea_size(conn, NULL,
1971 SIVAL(p,22,ea_size); /* Extended attributes */
1975 status = srvstr_push(base_data, flags2,
1976 p, fname, PTR_DIFF(end_data, p),
1977 STR_TERMINATE | STR_NOALIGN, &len);
1978 if (!NT_STATUS_IS_OK(status)) {
1981 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1994 SCVAL(nameptr,0,len);
1996 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1999 case SMB_FIND_EA_LIST:
2001 struct ea_list *file_list = NULL;
2004 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
2006 return NT_STATUS_INVALID_PARAMETER;
2008 if (requires_resume_key) {
2012 srv_put_dos_date2(p,0,create_date);
2013 srv_put_dos_date2(p,4,adate);
2014 srv_put_dos_date2(p,8,mdate);
2015 SIVAL(p,12,(uint32_t)file_size);
2016 SIVAL(p,16,(uint32_t)allocation_size);
2018 p += 22; /* p now points to the EA area. */
2020 status = get_ea_list_from_file(ctx, conn, NULL,
2022 &ea_len, &file_list);
2023 if (!NT_STATUS_IS_OK(status)) {
2026 name_list = ea_list_union(name_list, file_list, &ea_len);
2028 /* We need to determine if this entry will fit in the space available. */
2029 /* Max string size is 255 bytes. */
2030 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2031 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2032 "(wanted %u, had %d)\n",
2033 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2035 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2038 /* Push the ea_data followed by the name. */
2039 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2041 status = srvstr_push(base_data, flags2,
2042 p + 1, fname, PTR_DIFF(end_data, p+1),
2043 STR_TERMINATE | STR_NOALIGN, &len);
2044 if (!NT_STATUS_IS_OK(status)) {
2047 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2060 SCVAL(nameptr,0,len);
2062 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2066 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2067 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2068 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2070 SIVAL(p,0,reskey); p += 4;
2071 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2072 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2073 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2074 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2075 SOFF_T(p,0,file_size); p += 8;
2076 SOFF_T(p,0,allocation_size); p += 8;
2077 SIVAL(p,0,mode); p += 4;
2078 q = p; p += 4; /* q is placeholder for name length. */
2079 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2080 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2082 unsigned int ea_size = estimate_ea_size(conn, NULL,
2084 SIVAL(p,0,ea_size); /* Extended attributes */
2087 /* Clear the short name buffer. This is
2088 * IMPORTANT as not doing so will trigger
2089 * a Win2k client bug. JRA.
2091 if (!was_8_3 && check_mangled_names) {
2092 char mangled_name[13]; /* mangled 8.3 name. */
2093 if (!name_to_8_3(fname,mangled_name,True,
2095 /* Error - mangle failed ! */
2096 memset(mangled_name,'\0',12);
2098 mangled_name[12] = 0;
2099 status = srvstr_push(base_data, flags2,
2100 p+2, mangled_name, 24,
2101 STR_UPPER|STR_UNICODE, &len);
2102 if (!NT_STATUS_IS_OK(status)) {
2106 memset(p + 2 + len,'\0',24 - len);
2113 status = srvstr_push(base_data, flags2, p,
2114 fname, PTR_DIFF(end_data, p),
2115 STR_TERMINATE_ASCII, &len);
2116 if (!NT_STATUS_IS_OK(status)) {
2122 len = PTR_DIFF(p, pdata);
2123 pad = (len + (align-1)) & ~(align-1);
2125 * offset to the next entry, the caller
2126 * will overwrite it for the last entry
2127 * that's why we always include the padding
2131 * set padding to zero
2134 memset(p, 0, pad - len);
2141 case SMB_FIND_FILE_DIRECTORY_INFO:
2142 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2144 SIVAL(p,0,reskey); p += 4;
2145 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2146 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2147 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2148 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2149 SOFF_T(p,0,file_size); p += 8;
2150 SOFF_T(p,0,allocation_size); p += 8;
2151 SIVAL(p,0,mode); p += 4;
2152 status = srvstr_push(base_data, flags2,
2153 p + 4, fname, PTR_DIFF(end_data, p+4),
2154 STR_TERMINATE_ASCII, &len);
2155 if (!NT_STATUS_IS_OK(status)) {
2161 len = PTR_DIFF(p, pdata);
2162 pad = (len + (align-1)) & ~(align-1);
2164 * offset to the next entry, the caller
2165 * will overwrite it for the last entry
2166 * that's why we always include the padding
2170 * set padding to zero
2173 memset(p, 0, pad - len);
2180 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2181 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2183 SIVAL(p,0,reskey); p += 4;
2184 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2185 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2186 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2187 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2188 SOFF_T(p,0,file_size); p += 8;
2189 SOFF_T(p,0,allocation_size); p += 8;
2190 SIVAL(p,0,mode); p += 4;
2191 q = p; p += 4; /* q is placeholder for name length. */
2192 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2193 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2195 unsigned int ea_size = estimate_ea_size(conn, NULL,
2197 SIVAL(p,0,ea_size); /* Extended attributes */
2200 status = srvstr_push(base_data, flags2, p,
2201 fname, PTR_DIFF(end_data, p),
2202 STR_TERMINATE_ASCII, &len);
2203 if (!NT_STATUS_IS_OK(status)) {
2209 len = PTR_DIFF(p, pdata);
2210 pad = (len + (align-1)) & ~(align-1);
2212 * offset to the next entry, the caller
2213 * will overwrite it for the last entry
2214 * that's why we always include the padding
2218 * set padding to zero
2221 memset(p, 0, pad - len);
2228 case SMB_FIND_FILE_NAMES_INFO:
2229 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2231 SIVAL(p,0,reskey); p += 4;
2233 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2234 acl on a dir (tridge) */
2235 status = srvstr_push(base_data, flags2, p,
2236 fname, PTR_DIFF(end_data, p),
2237 STR_TERMINATE_ASCII, &len);
2238 if (!NT_STATUS_IS_OK(status)) {
2244 len = PTR_DIFF(p, pdata);
2245 pad = (len + (align-1)) & ~(align-1);
2247 * offset to the next entry, the caller
2248 * will overwrite it for the last entry
2249 * that's why we always include the padding
2253 * set padding to zero
2256 memset(p, 0, pad - len);
2263 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2264 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2266 SIVAL(p,0,reskey); p += 4;
2267 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2268 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2269 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2270 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2271 SOFF_T(p,0,file_size); p += 8;
2272 SOFF_T(p,0,allocation_size); p += 8;
2273 SIVAL(p,0,mode); p += 4;
2274 q = p; p += 4; /* q is placeholder for name length. */
2275 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2276 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2278 unsigned int ea_size = estimate_ea_size(conn, NULL,
2280 SIVAL(p,0,ea_size); /* Extended attributes */
2283 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2284 SBVAL(p,0,file_id); p += 8;
2285 status = srvstr_push(base_data, flags2, p,
2286 fname, PTR_DIFF(end_data, p),
2287 STR_TERMINATE_ASCII, &len);
2288 if (!NT_STATUS_IS_OK(status)) {
2294 len = PTR_DIFF(p, pdata);
2295 pad = (len + (align-1)) & ~(align-1);
2297 * offset to the next entry, the caller
2298 * will overwrite it for the last entry
2299 * that's why we always include the padding
2303 * set padding to zero
2306 memset(p, 0, pad - len);
2313 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2314 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2315 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2317 SIVAL(p,0,reskey); p += 4;
2318 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2319 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2320 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2321 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2322 SOFF_T(p,0,file_size); p += 8;
2323 SOFF_T(p,0,allocation_size); p += 8;
2324 SIVAL(p,0,mode); p += 4;
2325 q = p; p += 4; /* q is placeholder for name length */
2326 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2327 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2328 } else if (readdir_attr_data &&
2329 readdir_attr_data->type == RDATTR_AAPL) {
2331 * OS X specific SMB2 extension negotiated via
2332 * AAPL create context: return max_access in
2335 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2337 unsigned int ea_size = estimate_ea_size(conn, NULL,
2339 SIVAL(p,0,ea_size); /* Extended attributes */
2343 if (readdir_attr_data &&
2344 readdir_attr_data->type == RDATTR_AAPL) {
2346 * OS X specific SMB2 extension negotiated via
2347 * AAPL create context: return resource fork
2348 * length and compressed FinderInfo in
2351 * According to documentation short_name_len
2352 * should be 0, but on the wire behaviour
2353 * shows its set to 24 by clients.
2357 /* Resourefork length */
2358 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2360 /* Compressed FinderInfo */
2361 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2362 } else if (!was_8_3 && check_mangled_names) {
2363 char mangled_name[13]; /* mangled 8.3 name. */
2364 if (!name_to_8_3(fname,mangled_name,True,
2366 /* Error - mangle failed ! */
2367 memset(mangled_name,'\0',12);
2369 mangled_name[12] = 0;
2370 status = srvstr_push(base_data, flags2,
2371 p+2, mangled_name, 24,
2372 STR_UPPER|STR_UNICODE, &len);
2373 if (!NT_STATUS_IS_OK(status)) {
2378 memset(p + 2 + len,'\0',24 - len);
2382 /* Clear the short name buffer. This is
2383 * IMPORTANT as not doing so will trigger
2384 * a Win2k client bug. JRA.
2391 if (readdir_attr_data &&
2392 readdir_attr_data->type == RDATTR_AAPL) {
2394 * OS X specific SMB2 extension negotiated via
2395 * AAPL create context: return UNIX mode in
2398 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2399 SSVAL(p, 0, aapl_mode);
2405 SBVAL(p,0,file_id); p += 8;
2406 status = srvstr_push(base_data, flags2, p,
2407 fname, PTR_DIFF(end_data, p),
2408 STR_TERMINATE_ASCII, &len);
2409 if (!NT_STATUS_IS_OK(status)) {
2415 len = PTR_DIFF(p, pdata);
2416 pad = (len + (align-1)) & ~(align-1);
2418 * offset to the next entry, the caller
2419 * will overwrite it for the last entry
2420 * that's why we always include the padding
2424 * set padding to zero
2427 memset(p, 0, pad - len);
2434 /* CIFS UNIX Extension. */
2436 case SMB_FIND_FILE_UNIX:
2437 case SMB_FIND_FILE_UNIX_INFO2:
2439 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2441 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2443 if (info_level == SMB_FIND_FILE_UNIX) {
2444 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2445 p = store_file_unix_basic(conn, p,
2446 NULL, &smb_fname->st);
2447 status = srvstr_push(base_data, flags2, p,
2448 fname, PTR_DIFF(end_data, p),
2449 STR_TERMINATE, &len);
2450 if (!NT_STATUS_IS_OK(status)) {
2454 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2455 p = store_file_unix_basic_info2(conn, p,
2456 NULL, &smb_fname->st);
2459 status = srvstr_push(base_data, flags2, p, fname,
2460 PTR_DIFF(end_data, p), 0, &len);
2461 if (!NT_STATUS_IS_OK(status)) {
2464 SIVAL(nameptr, 0, len);
2469 len = PTR_DIFF(p, pdata);
2470 pad = (len + (align-1)) & ~(align-1);
2472 * offset to the next entry, the caller
2473 * will overwrite it for the last entry
2474 * that's why we always include the padding
2478 * set padding to zero
2481 memset(p, 0, pad - len);
2486 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2491 return NT_STATUS_INVALID_LEVEL;
2494 if (PTR_DIFF(p,pdata) > space_remaining) {
2495 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2496 "(wanted %u, had %d)\n",
2497 (unsigned int)PTR_DIFF(p,pdata),
2499 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2502 /* Setup the last entry pointer, as an offset from base_data */
2503 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2504 /* Advance the data pointer to the next slot */
2507 return NT_STATUS_OK;
2510 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2511 connection_struct *conn,
2512 struct dptr_struct *dirptr,
2514 const char *path_mask,
2517 int requires_resume_key,
2526 int space_remaining,
2527 struct smb_filename **_smb_fname,
2528 bool *got_exact_match,
2529 int *_last_entry_off,
2530 struct ea_list *name_list,
2531 struct file_id *file_id)
2534 const char *mask = NULL;
2535 long prev_dirpos = 0;
2538 struct smb_filename *smb_fname = NULL;
2539 struct smbd_dirptr_lanman2_state state;
2541 uint64_t last_entry_off = 0;
2543 enum mangled_names_options mangled_names;
2544 bool marshall_with_83_names;
2546 mangled_names = lp_mangled_names(conn->params);
2550 state.info_level = info_level;
2551 if (mangled_names != MANGLED_NAMES_NO) {
2552 state.check_mangled_names = true;
2554 state.has_wild = dptr_has_wild(dirptr);
2555 state.got_exact_match = false;
2557 *got_exact_match = false;
2559 p = strrchr_m(path_mask,'/');
2570 ok = smbd_dirptr_get_entry(ctx,
2577 smbd_dirptr_lanman2_match_fn,
2578 smbd_dirptr_lanman2_mode_fn,
2585 return NT_STATUS_END_OF_FILE;
2588 *got_exact_match = state.got_exact_match;
2590 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2592 status = smbd_marshall_dir_entry(ctx,
2597 marshall_with_83_names,
2598 requires_resume_key,
2609 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2610 DEBUG(1,("Conversion error: illegal character: %s\n",
2611 smb_fname_str_dbg(smb_fname)));
2614 if (file_id != NULL) {
2615 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2618 if (!NT_STATUS_IS_OK(status) &&
2619 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2621 TALLOC_FREE(smb_fname);
2626 if (_smb_fname != NULL) {
2627 struct smb_filename *name = NULL;
2629 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2631 TALLOC_FREE(smb_fname);
2633 return NT_STATUS_NO_MEMORY;
2638 TALLOC_FREE(smb_fname);
2641 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2642 dptr_SeekDir(dirptr, prev_dirpos);
2646 *_last_entry_off = last_entry_off;
2647 return NT_STATUS_OK;
2650 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2651 connection_struct *conn,
2652 struct dptr_struct *dirptr,
2654 const char *path_mask,
2657 bool requires_resume_key,
2663 int space_remaining,
2664 bool *got_exact_match,
2665 int *last_entry_off,
2666 struct ea_list *name_list)
2669 const bool do_pad = true;
2671 if (info_level >= 1 && info_level <= 3) {
2672 /* No alignment on earlier info levels. */
2676 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2677 path_mask, dirtype, info_level,
2678 requires_resume_key, dont_descend, ask_sharemode,
2679 true, align, do_pad,
2680 ppdata, base_data, end_data,
2684 last_entry_off, name_list, NULL);
2687 /****************************************************************************
2688 Reply to a TRANS2_FINDFIRST.
2689 ****************************************************************************/
2691 static void call_trans2findfirst(connection_struct *conn,
2692 struct smb_request *req,
2693 char **pparams, int total_params,
2694 char **ppdata, int total_data,
2695 unsigned int max_data_bytes)
2697 /* We must be careful here that we don't return more than the
2698 allowed number of data bytes. If this means returning fewer than
2699 maxentries then so be it. We assume that the redirector has
2700 enough room for the fixed number of parameter bytes it has
2702 struct smb_filename *smb_dname = NULL;
2703 char *params = *pparams;
2704 char *pdata = *ppdata;
2708 uint16_t findfirst_flags;
2709 bool close_after_first;
2711 bool requires_resume_key;
2713 char *directory = NULL;
2716 int last_entry_off=0;
2720 bool finished = False;
2721 bool dont_descend = False;
2722 bool out_of_space = False;
2723 int space_remaining;
2724 bool mask_contains_wcard = False;
2725 struct ea_list *ea_list = NULL;
2726 NTSTATUS ntstatus = NT_STATUS_OK;
2727 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2728 struct dptr_struct *dirptr = NULL;
2729 struct smbd_server_connection *sconn = req->sconn;
2730 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2731 ucf_flags_from_smb_request(req);
2732 bool backup_priv = false;
2733 bool as_root = false;
2735 if (total_params < 13) {
2736 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2740 dirtype = SVAL(params,0);
2741 maxentries = SVAL(params,2);
2742 findfirst_flags = SVAL(params,4);
2743 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2744 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2745 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2746 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2747 security_token_has_privilege(get_current_nttok(conn),
2750 info_level = SVAL(params,6);
2752 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2753 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2754 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2756 info_level, max_data_bytes));
2759 /* W2K3 seems to treat zero as 1. */
2763 switch (info_level) {
2764 case SMB_FIND_INFO_STANDARD:
2765 case SMB_FIND_EA_SIZE:
2766 case SMB_FIND_EA_LIST:
2767 case SMB_FIND_FILE_DIRECTORY_INFO:
2768 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2769 case SMB_FIND_FILE_NAMES_INFO:
2770 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2771 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2772 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2774 case SMB_FIND_FILE_UNIX:
2775 case SMB_FIND_FILE_UNIX_INFO2:
2776 /* Always use filesystem for UNIX mtime query. */
2777 ask_sharemode = false;
2778 if (!lp_unix_extensions()) {
2779 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2782 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2785 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2789 if (req->posix_pathnames) {
2790 srvstr_get_path_wcard_posix(talloc_tos(),
2798 &mask_contains_wcard);
2800 srvstr_get_path_wcard(talloc_tos(),
2808 &mask_contains_wcard);
2810 if (!NT_STATUS_IS_OK(ntstatus)) {
2811 reply_nterror(req, ntstatus);
2818 ntstatus = filename_convert_with_privilege(talloc_tos(),
2823 &mask_contains_wcard,
2826 ntstatus = filename_convert(talloc_tos(), conn,
2830 &mask_contains_wcard,
2834 if (!NT_STATUS_IS_OK(ntstatus)) {
2835 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2836 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2837 ERRSRV, ERRbadpath);
2840 reply_nterror(req, ntstatus);
2844 mask = smb_dname->original_lcomp;
2846 directory = smb_dname->base_name;
2848 p = strrchr_m(directory,'/');
2850 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2851 if((directory[0] == '.') && (directory[1] == '\0')) {
2852 mask = talloc_strdup(talloc_tos(),"*");
2854 reply_nterror(req, NT_STATUS_NO_MEMORY);
2857 mask_contains_wcard = True;
2863 if (p == NULL || p == directory) {
2864 /* Ensure we don't have a directory name of "". */
2865 directory = talloc_strdup(talloc_tos(), ".");
2867 reply_nterror(req, NT_STATUS_NO_MEMORY);
2870 /* Ensure smb_dname->base_name matches. */
2871 smb_dname->base_name = directory;
2874 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2876 if (info_level == SMB_FIND_EA_LIST) {
2879 if (total_data < 4) {
2880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2884 ea_size = IVAL(pdata,0);
2885 if (ea_size != total_data) {
2886 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2887 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2892 if (!lp_ea_support(SNUM(conn))) {
2893 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2897 /* Pull out the list of names. */
2898 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2905 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2910 *ppdata = (char *)SMB_REALLOC(
2911 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2912 if(*ppdata == NULL ) {
2913 reply_nterror(req, NT_STATUS_NO_MEMORY);
2917 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2919 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2922 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2923 /* Realloc the params space */
2924 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2925 if (*pparams == NULL) {
2926 reply_nterror(req, NT_STATUS_NO_MEMORY);
2931 /* Save the wildcard match and attribs we are using on this directory -
2932 needed as lanman2 assumes these are being saved between calls */
2934 ntstatus = dptr_create(conn,
2942 mask_contains_wcard,
2946 if (!NT_STATUS_IS_OK(ntstatus)) {
2947 reply_nterror(req, ntstatus);
2952 /* Remember this in case we have
2953 to do a findnext. */
2954 dptr_set_priv(dirptr);
2957 dptr_num = dptr_dnum(dirptr);
2958 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2960 /* We don't need to check for VOL here as this is returned by
2961 a different TRANS2 call. */
2963 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2964 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2965 if (in_list(directory,
2966 lp_dont_descend(talloc_tos(), SNUM(conn)),
2967 conn->case_sensitive)) {
2968 dont_descend = True;
2972 space_remaining = max_data_bytes;
2973 out_of_space = False;
2975 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2976 bool got_exact_match = False;
2978 /* this is a heuristic to avoid seeking the dirptr except when
2979 absolutely necessary. It allows for a filename of about 40 chars */
2980 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2981 out_of_space = True;
2984 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2988 mask,dirtype,info_level,
2989 requires_resume_key,dont_descend,
2994 &last_entry_off, ea_list);
2995 if (NT_STATUS_EQUAL(ntstatus,
2996 NT_STATUS_ILLEGAL_CHARACTER)) {
2998 * Bad character conversion on name. Ignore this
3003 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3004 out_of_space = true;
3006 finished = !NT_STATUS_IS_OK(ntstatus);
3010 if (!finished && !out_of_space)
3014 * As an optimisation if we know we aren't looking
3015 * for a wildcard name (ie. the name matches the wildcard exactly)
3016 * then we can finish on any (first) match.
3017 * This speeds up large directory searches. JRA.
3023 /* Ensure space_remaining never goes -ve. */
3024 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3025 space_remaining = 0;
3026 out_of_space = true;
3028 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3032 /* Check if we can close the dirptr */
3033 if(close_after_first || (finished && close_if_end)) {
3034 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3035 dptr_close(sconn, &dptr_num);
3039 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3040 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3041 * the protocol level is less than NT1. Tested with smbclient. JRA.
3042 * This should fix the OS/2 client bug #2335.
3045 if(numentries == 0) {
3046 dptr_close(sconn, &dptr_num);
3047 if (get_Protocol() < PROTOCOL_NT1) {
3048 reply_force_doserror(req, ERRDOS, ERRnofiles);
3051 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3052 ERRDOS, ERRbadfile);
3057 /* At this point pdata points to numentries directory entries. */
3059 /* Set up the return parameter block */
3060 SSVAL(params,0,dptr_num);
3061 SSVAL(params,2,numentries);
3062 SSVAL(params,4,finished);
3063 SSVAL(params,6,0); /* Never an EA error */
3064 SSVAL(params,8,last_entry_off);
3066 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3069 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3070 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3072 reply_nterror(req, NT_STATUS_NO_MEMORY);
3076 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3077 smb_fn_name(req->cmd),
3078 mask, directory, dirtype, numentries ) );
3081 * Force a name mangle here to ensure that the
3082 * mask as an 8.3 name is top of the mangled cache.
3083 * The reasons for this are subtle. Don't remove
3084 * this code unless you know what you are doing
3085 * (see PR#13758). JRA.
3088 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3089 char mangled_name[13];
3090 name_to_8_3(mask, mangled_name, True, conn->params);
3098 TALLOC_FREE(smb_dname);
3102 /****************************************************************************
3103 Reply to a TRANS2_FINDNEXT.
3104 ****************************************************************************/
3106 static void call_trans2findnext(connection_struct *conn,
3107 struct smb_request *req,
3108 char **pparams, int total_params,
3109 char **ppdata, int total_data,
3110 unsigned int max_data_bytes)
3112 /* We must be careful here that we don't return more than the
3113 allowed number of data bytes. If this means returning fewer than
3114 maxentries then so be it. We assume that the redirector has
3115 enough room for the fixed number of parameter bytes it has
3117 char *params = *pparams;
3118 char *pdata = *ppdata;
3122 uint16_t info_level;
3123 uint32_t resume_key;
3124 uint16_t findnext_flags;
3125 bool close_after_request;
3127 bool requires_resume_key;
3129 bool mask_contains_wcard = False;
3130 char *resume_name = NULL;
3131 const char *mask = NULL;
3132 const char *directory = NULL;
3136 int i, last_entry_off=0;
3137 bool finished = False;
3138 bool dont_descend = False;
3139 bool out_of_space = False;
3140 int space_remaining;
3141 struct ea_list *ea_list = NULL;
3142 NTSTATUS ntstatus = NT_STATUS_OK;
3143 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3144 TALLOC_CTX *ctx = talloc_tos();
3145 struct dptr_struct *dirptr;
3146 struct smbd_server_connection *sconn = req->sconn;
3147 bool backup_priv = false;
3148 bool as_root = false;
3150 if (total_params < 13) {
3151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3155 dptr_num = SVAL(params,0);
3156 maxentries = SVAL(params,2);
3157 info_level = SVAL(params,4);
3158 resume_key = IVAL(params,6);
3159 findnext_flags = SVAL(params,10);
3160 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3161 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3162 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3163 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3165 if (!continue_bit) {
3166 /* We only need resume_name if continue_bit is zero. */
3167 if (req->posix_pathnames) {
3168 srvstr_get_path_wcard_posix(ctx,
3176 &mask_contains_wcard);
3178 srvstr_get_path_wcard(ctx,
3186 &mask_contains_wcard);
3188 if (!NT_STATUS_IS_OK(ntstatus)) {
3189 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3190 complain (it thinks we're asking for the directory above the shared
3191 path or an invalid name). Catch this as the resume name is only compared, never used in
3192 a file access. JRA. */
3193 srvstr_pull_talloc(ctx, params, req->flags2,
3194 &resume_name, params+12,
3198 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3199 reply_nterror(req, ntstatus);
3205 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3206 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3207 resume_key = %d resume name = %s continue=%d level = %d\n",
3208 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3209 requires_resume_key, resume_key,
3210 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3213 /* W2K3 seems to treat zero as 1. */
3217 switch (info_level) {
3218 case SMB_FIND_INFO_STANDARD:
3219 case SMB_FIND_EA_SIZE:
3220 case SMB_FIND_EA_LIST:
3221 case SMB_FIND_FILE_DIRECTORY_INFO:
3222 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3223 case SMB_FIND_FILE_NAMES_INFO:
3224 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3225 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3226 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3228 case SMB_FIND_FILE_UNIX:
3229 case SMB_FIND_FILE_UNIX_INFO2:
3230 /* Always use filesystem for UNIX mtime query. */
3231 ask_sharemode = false;
3232 if (!lp_unix_extensions()) {
3233 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3238 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3242 if (info_level == SMB_FIND_EA_LIST) {
3245 if (total_data < 4) {
3246 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3250 ea_size = IVAL(pdata,0);
3251 if (ea_size != total_data) {
3252 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3253 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3258 if (!lp_ea_support(SNUM(conn))) {
3259 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3263 /* Pull out the list of names. */
3264 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3266 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3271 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3272 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3276 *ppdata = (char *)SMB_REALLOC(
3277 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3278 if(*ppdata == NULL) {
3279 reply_nterror(req, NT_STATUS_NO_MEMORY);
3284 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3287 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3290 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3291 /* Realloc the params space */
3292 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3293 if(*pparams == NULL ) {
3294 reply_nterror(req, NT_STATUS_NO_MEMORY);
3300 /* Check that the dptr is valid */
3301 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3302 reply_nterror(req, STATUS_NO_MORE_FILES);
3306 directory = dptr_path(sconn, dptr_num);
3308 /* Get the wildcard mask from the dptr */
3309 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3310 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3311 reply_nterror(req, STATUS_NO_MORE_FILES);
3315 /* Get the attr mask from the dptr */
3316 dirtype = dptr_attr(sconn, dptr_num);
3318 backup_priv = dptr_get_priv(dirptr);
3320 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3321 "backup_priv = %d\n",
3322 dptr_num, mask, dirtype,
3324 dptr_TellDir(dirptr),
3327 /* We don't need to check for VOL here as this is returned by
3328 a different TRANS2 call. */
3330 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3331 directory,lp_dont_descend(ctx, SNUM(conn))));
3332 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3333 dont_descend = True;
3336 space_remaining = max_data_bytes;
3337 out_of_space = False;
3345 * Seek to the correct position. We no longer use the resume key but
3346 * depend on the last file name instead.
3349 if(!continue_bit && resume_name && *resume_name) {
3352 long current_pos = 0;
3354 * Remember, name_to_8_3 is called by
3355 * get_lanman2_dir_entry(), so the resume name
3356 * could be mangled. Ensure we check the unmangled name.
3359 if (mangle_is_mangled(resume_name, conn->params)) {
3360 char *new_resume_name = NULL;
3361 mangle_lookup_name_from_8_3(ctx,
3365 if (new_resume_name) {
3366 resume_name = new_resume_name;
3371 * Fix for NT redirector problem triggered by resume key indexes
3372 * changing between directory scans. We now return a resume key of 0
3373 * and instead look for the filename to continue from (also given
3374 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3375 * findfirst/findnext (as is usual) then the directory pointer
3376 * should already be at the correct place.
3379 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3380 } /* end if resume_name && !continue_bit */
3382 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3383 bool got_exact_match = False;
3385 /* this is a heuristic to avoid seeking the dirptr except when
3386 absolutely necessary. It allows for a filename of about 40 chars */
3387 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3388 out_of_space = True;
3391 ntstatus = get_lanman2_dir_entry(ctx,
3395 mask,dirtype,info_level,
3396 requires_resume_key,dont_descend,
3401 &last_entry_off, ea_list);
3402 if (NT_STATUS_EQUAL(ntstatus,
3403 NT_STATUS_ILLEGAL_CHARACTER)) {
3405 * Bad character conversion on name. Ignore this
3410 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3411 out_of_space = true;
3413 finished = !NT_STATUS_IS_OK(ntstatus);
3417 if (!finished && !out_of_space)
3421 * As an optimisation if we know we aren't looking
3422 * for a wildcard name (ie. the name matches the wildcard exactly)
3423 * then we can finish on any (first) match.
3424 * This speeds up large directory searches. JRA.
3430 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3433 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3434 smb_fn_name(req->cmd),
3435 mask, directory, dirtype, numentries ) );
3437 /* Check if we can close the dirptr */
3438 if(close_after_request || (finished && close_if_end)) {
3439 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3440 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3447 /* Set up the return parameter block */
3448 SSVAL(params,0,numentries);
3449 SSVAL(params,2,finished);
3450 SSVAL(params,4,0); /* Never an EA error */
3451 SSVAL(params,6,last_entry_off);
3453 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3459 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3461 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3465 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3467 SMB_ASSERT(extended_info != NULL);
3469 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3470 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3471 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3472 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3473 #ifdef SAMBA_VERSION_REVISION
3474 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3476 extended_info->samba_subversion = 0;
3477 #ifdef SAMBA_VERSION_RC_RELEASE
3478 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3480 #ifdef SAMBA_VERSION_PRE_RELEASE
3481 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3484 #ifdef SAMBA_VERSION_VENDOR_PATCH
3485 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3487 extended_info->samba_gitcommitdate = 0;
3488 #ifdef SAMBA_VERSION_COMMIT_TIME
3489 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3492 memset(extended_info->samba_version_string, 0,
3493 sizeof(extended_info->samba_version_string));
3495 snprintf (extended_info->samba_version_string,
3496 sizeof(extended_info->samba_version_string),
3497 "%s", samba_version_string());
3500 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3501 connection_struct *conn,
3502 TALLOC_CTX *mem_ctx,
3503 uint16_t info_level,
3505 unsigned int max_data_bytes,
3506 size_t *fixed_portion,
3507 struct smb_filename *fname,
3511 char *pdata, *end_data;
3514 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3515 int snum = SNUM(conn);
3516 const char *fstype = lp_fstype(SNUM(conn));
3517 const char *filename = NULL;
3518 const uint64_t bytes_per_sector = 512;
3519 uint32_t additional_flags = 0;
3520 struct smb_filename smb_fname;
3522 NTSTATUS status = NT_STATUS_OK;
3525 if (fname == NULL || fname->base_name == NULL) {
3528 filename = fname->base_name;
3532 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3533 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3534 "info level (0x%x) on IPC$.\n",
3535 (unsigned int)info_level));
3536 return NT_STATUS_ACCESS_DENIED;
3540 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3542 ZERO_STRUCT(smb_fname);
3543 smb_fname.base_name = discard_const_p(char, filename);
3545 if(info_level != SMB_FS_QUOTA_INFORMATION
3546 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3547 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3548 return map_nt_error_from_unix(errno);
3553 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3554 return NT_STATUS_INVALID_PARAMETER;
3557 *ppdata = (char *)SMB_REALLOC(
3558 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3559 if (*ppdata == NULL) {
3560 return NT_STATUS_NO_MEMORY;
3564 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3565 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3569 switch (info_level) {
3570 case SMB_INFO_ALLOCATION:
3572 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3574 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3576 if (df_ret == (uint64_t)-1) {
3577 return map_nt_error_from_unix(errno);
3580 block_size = lp_block_size(snum);
3581 if (bsize < block_size) {
3582 uint64_t factor = block_size/bsize;
3587 if (bsize > block_size) {
3588 uint64_t factor = bsize/block_size;
3593 sectors_per_unit = bsize/bytes_per_sector;
3595 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3596 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3597 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3600 * For large drives, return max values and not modulo.
3602 dsize = MIN(dsize, UINT32_MAX);
3603 dfree = MIN(dfree, UINT32_MAX);
3605 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3606 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3607 SIVAL(pdata,l1_cUnit,dsize);
3608 SIVAL(pdata,l1_cUnitAvail,dfree);
3609 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3613 case SMB_INFO_VOLUME:
3614 /* Return volume name */
3616 * Add volume serial number - hash of a combination of
3617 * the called hostname and the service name.
3619 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3621 * Win2k3 and previous mess this up by sending a name length
3622 * one byte short. I believe only older clients (OS/2 Win9x) use
3623 * this call so try fixing this by adding a terminating null to
3624 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3626 status = srvstr_push(
3628 pdata+l2_vol_szVolLabel, vname,
3629 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3630 STR_NOALIGN|STR_TERMINATE, &len);
3631 if (!NT_STATUS_IS_OK(status)) {
3634 SCVAL(pdata,l2_vol_cch,len);
3635 data_len = l2_vol_szVolLabel + len;
3636 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3637 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3638 (unsigned)len, vname));
3641 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3642 case SMB_FS_ATTRIBUTE_INFORMATION:
3644 additional_flags = 0;
3645 #if defined(HAVE_SYS_QUOTAS)
3646 additional_flags |= FILE_VOLUME_QUOTAS;
3649 if(lp_nt_acl_support(SNUM(conn))) {
3650 additional_flags |= FILE_PERSISTENT_ACLS;
3653 /* Capabilities are filled in at connection time through STATVFS call */
3654 additional_flags |= conn->fs_capabilities;
3655 additional_flags |= lp_parm_int(conn->params->service,
3656 "share", "fake_fscaps",
3659 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3660 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3661 additional_flags); /* FS ATTRIBUTES */
3663 SIVAL(pdata,4,255); /* Max filename component length */
3664 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3665 and will think we can't do long filenames */
3666 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3667 PTR_DIFF(end_data, pdata+12),
3669 if (!NT_STATUS_IS_OK(status)) {
3673 data_len = 12 + len;
3674 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3675 /* the client only requested a portion of the
3677 data_len = max_data_bytes;
3678 status = STATUS_BUFFER_OVERFLOW;
3680 *fixed_portion = 16;
3683 case SMB_QUERY_FS_LABEL_INFO:
3684 case SMB_FS_LABEL_INFORMATION:
3685 status = srvstr_push(pdata, flags2, pdata+4, vname,
3686 PTR_DIFF(end_data, pdata+4), 0, &len);
3687 if (!NT_STATUS_IS_OK(status)) {
3694 case SMB_QUERY_FS_VOLUME_INFO:
3695 case SMB_FS_VOLUME_INFORMATION:
3698 * Add volume serial number - hash of a combination of
3699 * the called hostname and the service name.
3701 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3702 (str_checksum(get_local_machine_name())<<16));
3704 /* Max label len is 32 characters. */
3705 status = srvstr_push(pdata, flags2, pdata+18, vname,
3706 PTR_DIFF(end_data, pdata+18),
3708 if (!NT_STATUS_IS_OK(status)) {
3711 SIVAL(pdata,12,len);
3714 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3715 (int)strlen(vname),vname,
3716 lp_servicename(talloc_tos(), snum)));
3717 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3718 /* the client only requested a portion of the
3720 data_len = max_data_bytes;
3721 status = STATUS_BUFFER_OVERFLOW;
3723 *fixed_portion = 24;
3726 case SMB_QUERY_FS_SIZE_INFO:
3727 case SMB_FS_SIZE_INFORMATION:
3729 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3731 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3733 if (df_ret == (uint64_t)-1) {
3734 return map_nt_error_from_unix(errno);
3736 block_size = lp_block_size(snum);
3737 if (bsize < block_size) {
3738 uint64_t factor = block_size/bsize;
3743 if (bsize > block_size) {
3744 uint64_t factor = bsize/block_size;
3749 sectors_per_unit = bsize/bytes_per_sector;
3750 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3751 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3752 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3753 SBIG_UINT(pdata,0,dsize);
3754 SBIG_UINT(pdata,8,dfree);
3755 SIVAL(pdata,16,sectors_per_unit);
3756 SIVAL(pdata,20,bytes_per_sector);
3757 *fixed_portion = 24;
3761 case SMB_FS_FULL_SIZE_INFORMATION:
3763 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3765 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3767 if (df_ret == (uint64_t)-1) {
3768 return map_nt_error_from_unix(errno);
3770 block_size = lp_block_size(snum);
3771 if (bsize < block_size) {
3772 uint64_t factor = block_size/bsize;
3777 if (bsize > block_size) {
3778 uint64_t factor = bsize/block_size;
3783 sectors_per_unit = bsize/bytes_per_sector;
3784 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3785 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3786 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3787 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3788 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3789 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3790 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3791 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3792 *fixed_portion = 32;
3796 case SMB_QUERY_FS_DEVICE_INFO:
3797 case SMB_FS_DEVICE_INFORMATION:
3799 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3801 if (!CAN_WRITE(conn)) {
3802 characteristics |= FILE_READ_ONLY_DEVICE;
3805 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3806 SIVAL(pdata,4,characteristics);
3811 #ifdef HAVE_SYS_QUOTAS
3812 case SMB_FS_QUOTA_INFORMATION:
3814 * what we have to send --metze:
3816 * Unknown1: 24 NULL bytes
3817 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3818 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3819 * Quota Flags: 2 byte :
3820 * Unknown3: 6 NULL bytes
3824 * details for Quota Flags:
3826 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3827 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3828 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3829 * 0x0001 Enable Quotas: enable quota for this fs
3833 /* we need to fake up a fsp here,
3834 * because its not send in this call
3837 SMB_NTQUOTA_STRUCT quotas;
3840 ZERO_STRUCT(quotas);
3843 fsp.fnum = FNUM_FIELD_INVALID;
3846 if (get_current_uid(conn) != 0) {
3847 DEBUG(0,("get_user_quota: access_denied "
3848 "service [%s] user [%s]\n",
3849 lp_servicename(talloc_tos(), SNUM(conn)),
3850 conn->session_info->unix_info->unix_name));
3851 return NT_STATUS_ACCESS_DENIED;
3854 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3856 if (!NT_STATUS_IS_OK(status)) {
3857 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3863 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3864 lp_servicename(talloc_tos(), SNUM(conn))));
3866 /* Unknown1 24 NULL bytes*/
3867 SBIG_UINT(pdata,0,(uint64_t)0);
3868 SBIG_UINT(pdata,8,(uint64_t)0);
3869 SBIG_UINT(pdata,16,(uint64_t)0);
3871 /* Default Soft Quota 8 bytes */
3872 SBIG_UINT(pdata,24,quotas.softlim);
3874 /* Default Hard Quota 8 bytes */
3875 SBIG_UINT(pdata,32,quotas.hardlim);
3877 /* Quota flag 2 bytes */
3878 SSVAL(pdata,40,quotas.qflags);
3880 /* Unknown3 6 NULL bytes */
3886 #endif /* HAVE_SYS_QUOTAS */
3887 case SMB_FS_OBJECTID_INFORMATION:
3889 unsigned char objid[16];
3890 struct smb_extended_info extended_info;
3891 memcpy(pdata,create_volume_objectid(conn, objid),16);
3892 samba_extended_info_version (&extended_info);
3893 SIVAL(pdata,16,extended_info.samba_magic);
3894 SIVAL(pdata,20,extended_info.samba_version);
3895 SIVAL(pdata,24,extended_info.samba_subversion);
3896 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3897 memcpy(pdata+36,extended_info.samba_version_string,28);
3902 case SMB_FS_SECTOR_SIZE_INFORMATION:
3906 * These values match a physical Windows Server 2012
3907 * share backed by NTFS atop spinning rust.
3909 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3910 /* logical_bytes_per_sector */
3911 SIVAL(pdata, 0, bytes_per_sector);
3912 /* phys_bytes_per_sector_atomic */
3913 SIVAL(pdata, 4, bytes_per_sector);
3914 /* phys_bytes_per_sector_perf */
3915 SIVAL(pdata, 8, bytes_per_sector);
3916 /* fs_effective_phys_bytes_per_sector_atomic */
3917 SIVAL(pdata, 12, bytes_per_sector);
3919 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3920 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3921 /* byte_off_sector_align */
3922 SIVAL(pdata, 20, 0);
3923 /* byte_off_partition_align */
3924 SIVAL(pdata, 24, 0);
3925 *fixed_portion = 28;
3931 * Query the version and capabilities of the CIFS UNIX extensions
3935 case SMB_QUERY_CIFS_UNIX_INFO:
3937 bool large_write = lp_min_receive_file_size() &&
3938 !srv_is_signing_active(xconn);
3939 bool large_read = !srv_is_signing_active(xconn);
3940 int encrypt_caps = 0;
3942 if (!lp_unix_extensions()) {
3943 return NT_STATUS_INVALID_LEVEL;
3946 switch (conn->encrypt_level) {
3947 case SMB_SIGNING_OFF:
3950 case SMB_SIGNING_DESIRED:
3951 case SMB_SIGNING_IF_REQUIRED:
3952 case SMB_SIGNING_DEFAULT:
3953 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3955 case SMB_SIGNING_REQUIRED:
3956 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3957 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3958 large_write = false;
3964 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3965 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3967 /* We have POSIX ACLs, pathname, encryption,
3968 * large read/write, and locking capability. */
3970 SBIG_UINT(pdata,4,((uint64_t)(
3971 CIFS_UNIX_POSIX_ACLS_CAP|
3972 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3973 CIFS_UNIX_FCNTL_LOCKS_CAP|
3974 CIFS_UNIX_EXTATTR_CAP|
3975 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3977 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3979 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3983 case SMB_QUERY_POSIX_FS_INFO:
3986 vfs_statvfs_struct svfs;
3988 if (!lp_unix_extensions()) {
3989 return NT_STATUS_INVALID_LEVEL;
3992 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3996 SIVAL(pdata,0,svfs.OptimalTransferSize);
3997 SIVAL(pdata,4,svfs.BlockSize);
3998 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3999 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4000 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4001 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4002 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4003 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4004 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4006 } else if (rc == EOPNOTSUPP) {
4007 return NT_STATUS_INVALID_LEVEL;
4008 #endif /* EOPNOTSUPP */
4010 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4011 return NT_STATUS_DOS(ERRSRV, ERRerror);
4016 case SMB_QUERY_POSIX_WHOAMI:
4022 if (!lp_unix_extensions()) {
4023 return NT_STATUS_INVALID_LEVEL;
4026 if (max_data_bytes < 40) {
4027 return NT_STATUS_BUFFER_TOO_SMALL;
4030 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4031 flags |= SMB_WHOAMI_GUEST;
4034 /* NOTE: 8 bytes for UID/GID, irrespective of native
4035 * platform size. This matches
4036 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4038 data_len = 4 /* flags */
4045 + 4 /* pad/reserved */
4046 + (conn->session_info->unix_token->ngroups * 8)
4048 + (conn->session_info->security_token->num_sids *
4052 SIVAL(pdata, 0, flags);
4053 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4055 (uint64_t)conn->session_info->unix_token->uid);
4056 SBIG_UINT(pdata, 16,
4057 (uint64_t)conn->session_info->unix_token->gid);
4060 if (data_len >= max_data_bytes) {
4061 /* Potential overflow, skip the GIDs and SIDs. */
4063 SIVAL(pdata, 24, 0); /* num_groups */
4064 SIVAL(pdata, 28, 0); /* num_sids */
4065 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4066 SIVAL(pdata, 36, 0); /* reserved */
4072 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4073 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4075 /* We walk the SID list twice, but this call is fairly
4076 * infrequent, and I don't expect that it's performance
4077 * sensitive -- jpeach
4079 for (i = 0, sid_bytes = 0;
4080 i < conn->session_info->security_token->num_sids; ++i) {
4081 sid_bytes += ndr_size_dom_sid(
4082 &conn->session_info->security_token->sids[i],
4086 /* SID list byte count */
4087 SIVAL(pdata, 32, sid_bytes);
4089 /* 4 bytes pad/reserved - must be zero */
4090 SIVAL(pdata, 36, 0);
4094 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4095 SBIG_UINT(pdata, data_len,
4096 (uint64_t)conn->session_info->unix_token->groups[i]);
4102 i < conn->session_info->security_token->num_sids; ++i) {
4103 int sid_len = ndr_size_dom_sid(
4104 &conn->session_info->security_token->sids[i],
4107 sid_linearize((uint8_t *)(pdata + data_len),
4109 &conn->session_info->security_token->sids[i]);
4110 data_len += sid_len;
4116 case SMB_MAC_QUERY_FS_INFO:
4118 * Thursby MAC extension... ONLY on NTFS filesystems
4119 * once we do streams then we don't need this
4121 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4123 SIVAL(pdata,84,0x100); /* Don't support mac... */
4129 return NT_STATUS_INVALID_LEVEL;
4132 *ret_data_len = data_len;
4136 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4137 struct smb_request *req,
4139 const DATA_BLOB *qdata)
4142 SMB_NTQUOTA_STRUCT quotas;
4144 ZERO_STRUCT(quotas);
4147 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4148 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4149 lp_servicename(talloc_tos(), SNUM(conn)),
4150 conn->session_info->unix_info->unix_name));
4151 return NT_STATUS_ACCESS_DENIED;
4154 if (!check_fsp_ntquota_handle(conn, req,
4156 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4157 return NT_STATUS_INVALID_HANDLE;
4160 /* note: normally there're 48 bytes,
4161 * but we didn't use the last 6 bytes for now
4164 if (qdata->length < 42) {
4165 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4166 (unsigned int)qdata->length));
4167 return NT_STATUS_INVALID_PARAMETER;
4170 /* unknown_1 24 NULL bytes in pdata*/
4172 /* the soft quotas 8 bytes (uint64_t)*/
4173 quotas.softlim = BVAL(qdata->data,24);
4175 /* the hard quotas 8 bytes (uint64_t)*/
4176 quotas.hardlim = BVAL(qdata->data,32);
4178 /* quota_flags 2 bytes **/
4179 quotas.qflags = SVAL(qdata->data,40);
4181 /* unknown_2 6 NULL bytes follow*/
4183 /* now set the quotas */
4184 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4185 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4186 lp_servicename(talloc_tos(), SNUM(conn))));
4187 status = map_nt_error_from_unix(errno);
4189 status = NT_STATUS_OK;
4194 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4195 struct smb_request *req,
4196 TALLOC_CTX *mem_ctx,
4197 uint16_t info_level,
4199 const DATA_BLOB *pdata)
4201 switch (info_level) {
4202 case SMB_FS_QUOTA_INFORMATION:
4204 return smb_set_fsquota(conn,
4213 return NT_STATUS_INVALID_LEVEL;
4216 /****************************************************************************
4217 Reply to a TRANS2_QFSINFO (query filesystem info).
4218 ****************************************************************************/
4220 static void call_trans2qfsinfo(connection_struct *conn,
4221 struct smb_request *req,
4222 char **pparams, int total_params,
4223 char **ppdata, int total_data,
4224 unsigned int max_data_bytes)
4226 char *params = *pparams;
4227 uint16_t info_level;
4229 size_t fixed_portion;
4232 if (total_params < 2) {
4233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4237 info_level = SVAL(params,0);
4239 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4240 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4241 DEBUG(0,("call_trans2qfsinfo: encryption required "
4242 "and info level 0x%x sent.\n",
4243 (unsigned int)info_level));
4244 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4249 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4251 status = smbd_do_qfsinfo(req->xconn, conn, req,
4258 if (!NT_STATUS_IS_OK(status)) {
4259 reply_nterror(req, status);
4263 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4266 DEBUG( 4, ( "%s info_level = %d\n",
4267 smb_fn_name(req->cmd), info_level) );
4272 /****************************************************************************
4273 Reply to a TRANS2_SETFSINFO (set filesystem info).
4274 ****************************************************************************/
4276 static void call_trans2setfsinfo(connection_struct *conn,
4277 struct smb_request *req,
4278 char **pparams, int total_params,
4279 char **ppdata, int total_data,
4280 unsigned int max_data_bytes)
4282 struct smbXsrv_connection *xconn = req->xconn;
4283 char *pdata = *ppdata;
4284 char *params = *pparams;
4285 uint16_t info_level;
4287 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4288 lp_servicename(talloc_tos(), SNUM(conn))));
4291 if (total_params < 4) {
4292 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4294 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4298 info_level = SVAL(params,2);
4301 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4302 info_level != SMB_SET_CIFS_UNIX_INFO) {
4303 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4304 "info level (0x%x) on IPC$.\n",
4305 (unsigned int)info_level));
4306 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4311 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4312 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4313 DEBUG(0,("call_trans2setfsinfo: encryption required "
4314 "and info level 0x%x sent.\n",
4315 (unsigned int)info_level));
4316 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4321 switch(info_level) {
4322 case SMB_SET_CIFS_UNIX_INFO:
4323 if (!lp_unix_extensions()) {
4324 DEBUG(2,("call_trans2setfsinfo: "
4325 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4326 "unix extensions off\n"));
4328 NT_STATUS_INVALID_LEVEL);
4332 /* There should be 12 bytes of capabilities set. */
4333 if (total_data < 12) {
4336 NT_STATUS_INVALID_PARAMETER);
4339 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4340 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4341 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4342 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4343 /* Just print these values for now. */
4344 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4345 "major = %u, minor = %u cap_low = 0x%x, "
4347 (unsigned int)xconn->
4348 smb1.unix_info.client_major,
4349 (unsigned int)xconn->
4350 smb1.unix_info.client_minor,
4351 (unsigned int)xconn->
4352 smb1.unix_info.client_cap_low,
4353 (unsigned int)xconn->
4354 smb1.unix_info.client_cap_high));
4356 /* Here is where we must switch to posix pathname processing... */
4357 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4358 lp_set_posix_pathnames();
4359 mangle_change_to_posix();
4362 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4363 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4364 /* Client that knows how to do posix locks,
4365 * but not posix open/mkdir operations. Set a
4366 * default type for read/write checks. */
4368 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4373 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4376 size_t param_len = 0;
4377 size_t data_len = total_data;
4379 if (!lp_unix_extensions()) {
4382 NT_STATUS_INVALID_LEVEL);
4386 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4389 NT_STATUS_NOT_SUPPORTED);
4393 if (xconn->smb1.echo_handler.trusted_fde) {
4394 DEBUG( 2,("call_trans2setfsinfo: "
4395 "request transport encryption disabled"
4396 "with 'fork echo handler = yes'\n"));
4399 NT_STATUS_NOT_SUPPORTED);
4403 DEBUG( 4,("call_trans2setfsinfo: "
4404 "request transport encryption.\n"));
4406 status = srv_request_encryption_setup(conn,
4407 (unsigned char **)ppdata,
4409 (unsigned char **)pparams,
4412 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4413 !NT_STATUS_IS_OK(status)) {
4414 reply_nterror(req, status);
4418 send_trans2_replies(conn, req,
4426 if (NT_STATUS_IS_OK(status)) {
4427 /* Server-side transport
4428 * encryption is now *on*. */
4429 status = srv_encryption_start(conn);
4430 if (!NT_STATUS_IS_OK(status)) {
4431 char *reason = talloc_asprintf(talloc_tos(),
4432 "Failure in setting "
4433 "up encrypted transport: %s",
4435 exit_server_cleanly(reason);
4441 case SMB_FS_QUOTA_INFORMATION:
4445 .data = (uint8_t *)pdata,
4446 .length = total_data
4448 files_struct *fsp = NULL;
4449 fsp = file_fsp(req, SVAL(params,0));
4451 status = smb_set_fsquota(conn,
4455 if (!NT_STATUS_IS_OK(status)) {
4456 reply_nterror(req, status);
4462 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4464 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4470 * sending this reply works fine,
4471 * but I'm not sure it's the same
4472 * like windows do...
4475 reply_outbuf(req, 10, 0);
4478 #if defined(HAVE_POSIX_ACLS)
4479 /****************************************************************************
4480 Utility function to count the number of entries in a POSIX acl.
4481 ****************************************************************************/
4483 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4485 unsigned int ace_count = 0;
4486 int entry_id = SMB_ACL_FIRST_ENTRY;
4487 SMB_ACL_ENTRY_T entry;
4489 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4491 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4492 entry_id = SMB_ACL_NEXT_ENTRY;
4499 /****************************************************************************
4500 Utility function to marshall a POSIX acl into wire format.
4501 ****************************************************************************/
4503 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4505 int entry_id = SMB_ACL_FIRST_ENTRY;
4506 SMB_ACL_ENTRY_T entry;
4508 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4509 SMB_ACL_TAG_T tagtype;
4510 SMB_ACL_PERMSET_T permset;
4511 unsigned char perms = 0;
4512 unsigned int own_grp;
4515 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4516 entry_id = SMB_ACL_NEXT_ENTRY;
4519 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4520 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4524 if (sys_acl_get_permset(entry, &permset) == -1) {
4525 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4529 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4530 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4531 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4533 SCVAL(pdata,1,perms);
4536 case SMB_ACL_USER_OBJ:
4537 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4538 own_grp = (unsigned int)pst->st_ex_uid;
4539 SIVAL(pdata,2,own_grp);
4544 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4546 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4549 own_grp = (unsigned int)*puid;
4550 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4551 SIVAL(pdata,2,own_grp);
4555 case SMB_ACL_GROUP_OBJ:
4556 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4557 own_grp = (unsigned int)pst->st_ex_gid;
4558 SIVAL(pdata,2,own_grp);
4563 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4565 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4568 own_grp = (unsigned int)*pgid;
4569 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4570 SIVAL(pdata,2,own_grp);
4575 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4576 SIVAL(pdata,2,0xFFFFFFFF);
4577 SIVAL(pdata,6,0xFFFFFFFF);
4580 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4581 SIVAL(pdata,2,0xFFFFFFFF);
4582 SIVAL(pdata,6,0xFFFFFFFF);
4585 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4588 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4595 /****************************************************************************
4596 Store the FILE_UNIX_BASIC info.
4597 ****************************************************************************/
4599 static char *store_file_unix_basic(connection_struct *conn,
4602 const SMB_STRUCT_STAT *psbuf)
4606 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4607 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4609 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4612 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4615 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4616 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4617 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4620 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4624 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4628 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4631 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4632 devno = psbuf->st_ex_rdev;
4634 devno = psbuf->st_ex_dev;
4637 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4641 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4645 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4648 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4652 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4659 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4660 * the chflags(2) (or equivalent) flags.
4662 * XXX: this really should be behind the VFS interface. To do this, we would
4663 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4664 * Each VFS module could then implement its own mapping as appropriate for the
4665 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4667 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4671 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4675 { UF_IMMUTABLE, EXT_IMMUTABLE },
4679 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4683 { UF_HIDDEN, EXT_HIDDEN },
4686 /* Do not remove. We need to guarantee that this array has at least one
4687 * entry to build on HP-UX.
4693 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4694 uint32_t *smb_fflags, uint32_t *smb_fmask)
4698 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4699 *smb_fmask |= info2_flags_map[i].smb_fflag;
4700 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4701 *smb_fflags |= info2_flags_map[i].smb_fflag;
4706 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4707 const uint32_t smb_fflags,
4708 const uint32_t smb_fmask,
4711 uint32_t max_fmask = 0;
4714 *stat_fflags = psbuf->st_ex_flags;
4716 /* For each flags requested in smb_fmask, check the state of the
4717 * corresponding flag in smb_fflags and set or clear the matching
4721 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4722 max_fmask |= info2_flags_map[i].smb_fflag;
4723 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4724 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4725 *stat_fflags |= info2_flags_map[i].stat_fflag;
4727 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4732 /* If smb_fmask is asking to set any bits that are not supported by
4733 * our flag mappings, we should fail.
4735 if ((smb_fmask & max_fmask) != smb_fmask) {
4743 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4744 * of file flags and birth (create) time.
4746 static char *store_file_unix_basic_info2(connection_struct *conn,
4749 const SMB_STRUCT_STAT *psbuf)
4751 uint32_t file_flags = 0;
4752 uint32_t flags_mask = 0;
4754 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4756 /* Create (birth) time 64 bit */
4757 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4760 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4761 SIVAL(pdata, 0, file_flags); /* flags */
4762 SIVAL(pdata, 4, flags_mask); /* mask */
4768 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4769 const struct stream_struct *streams,
4771 unsigned int max_data_bytes,
4772 unsigned int *data_size)
4775 unsigned int ofs = 0;
4777 if (max_data_bytes < 32) {
4778 return NT_STATUS_INFO_LENGTH_MISMATCH;
4781 for (i = 0; i < num_streams; i++) {
4782 unsigned int next_offset;
4784 smb_ucs2_t *namebuf;
4786 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4787 streams[i].name, &namelen) ||
4790 return NT_STATUS_INVALID_PARAMETER;
4794 * name_buf is now null-terminated, we need to marshall as not
4801 * We cannot overflow ...
4803 if ((ofs + 24 + namelen) > max_data_bytes) {
4804 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4806 TALLOC_FREE(namebuf);
4807 return STATUS_BUFFER_OVERFLOW;
4810 SIVAL(data, ofs+4, namelen);
4811 SOFF_T(data, ofs+8, streams[i].size);
4812 SOFF_T(data, ofs+16, streams[i].alloc_size);
4813 memcpy(data+ofs+24, namebuf, namelen);
4814 TALLOC_FREE(namebuf);
4816 next_offset = ofs + 24 + namelen;
4818 if (i == num_streams-1) {
4819 SIVAL(data, ofs, 0);
4822 unsigned int align = ndr_align_size(next_offset, 8);
4824 if ((next_offset + align) > max_data_bytes) {
4825 DEBUG(10, ("refusing to overflow align "
4826 "reply at stream %u\n",
4828 TALLOC_FREE(namebuf);
4829 return STATUS_BUFFER_OVERFLOW;
4832 memset(data+next_offset, 0, align);
4833 next_offset += align;
4835 SIVAL(data, ofs, next_offset - ofs);
4842 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4846 return NT_STATUS_OK;
4849 #if defined(HAVE_POSIX_ACLS)
4850 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4851 struct smb_request *req,
4853 struct smb_filename *smb_fname,
4855 unsigned int data_size_in,
4856 unsigned int *pdata_size_out)
4858 SMB_ACL_T file_acl = NULL;
4859 SMB_ACL_T def_acl = NULL;
4860 uint16_t num_file_acls = 0;
4861 uint16_t num_def_acls = 0;
4862 unsigned int size_needed = 0;
4868 * Ensure we always operate on a file descriptor, not just
4872 uint32_t access_mask = SEC_STD_READ_CONTROL|
4873 FILE_READ_ATTRIBUTES|
4874 FILE_WRITE_ATTRIBUTES;
4876 status = get_posix_fsp(conn,
4882 if (!NT_STATUS_IS_OK(status)) {
4888 SMB_ASSERT(fsp != NULL);
4890 status = refuse_symlink(conn,
4893 if (!NT_STATUS_IS_OK(status)) {
4897 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4900 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4901 DBG_INFO("ACLs not implemented on "
4902 "filesystem containing %s\n",
4904 status = NT_STATUS_NOT_IMPLEMENTED;
4908 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4910 * We can only have default POSIX ACLs on
4913 if (!fsp->is_directory) {
4914 DBG_INFO("Non-directory open %s\n",
4916 status = NT_STATUS_INVALID_HANDLE;
4919 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
4921 SMB_ACL_TYPE_DEFAULT,
4923 def_acl = free_empty_sys_acl(conn, def_acl);
4926 num_file_acls = count_acl_entries(conn, file_acl);
4927 num_def_acls = count_acl_entries(conn, def_acl);
4930 if (num_file_acls + num_def_acls < num_file_acls) {
4931 status = NT_STATUS_INVALID_PARAMETER;
4935 size_needed = num_file_acls + num_def_acls;
4938 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4939 * than UINT_MAX, so check by division.
4941 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4942 status = NT_STATUS_INVALID_PARAMETER;
4946 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
4947 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
4948 status = NT_STATUS_INVALID_PARAMETER;
4951 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
4953 if ( data_size_in < size_needed) {
4954 DBG_INFO("data_size too small (%u) need %u\n",
4957 status = NT_STATUS_BUFFER_TOO_SMALL;
4961 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4962 SSVAL(pdata,2,num_file_acls);
4963 SSVAL(pdata,4,num_def_acls);
4964 pdata += SMB_POSIX_ACL_HEADER_SIZE;
4966 ok = marshall_posix_acl(conn,
4971 status = NT_STATUS_INTERNAL_ERROR;
4974 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
4976 ok = marshall_posix_acl(conn,
4981 status = NT_STATUS_INTERNAL_ERROR;
4985 *pdata_size_out = size_needed;
4986 status = NT_STATUS_OK;
4992 * Ensure the stat struct in smb_fname is up to
4993 * date. Structure copy.
4995 smb_fname->st = fsp->fsp_name->st;
4996 (void)close_file(req, fsp, NORMAL_CLOSE);
5000 TALLOC_FREE(file_acl);
5001 TALLOC_FREE(def_acl);
5006 /****************************************************************************
5007 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5008 ****************************************************************************/
5010 static void call_trans2qpipeinfo(connection_struct *conn,
5011 struct smb_request *req,
5012 unsigned int tran_call,
5013 char **pparams, int total_params,
5014 char **ppdata, int total_data,
5015 unsigned int max_data_bytes)
5017 char *params = *pparams;
5018 char *pdata = *ppdata;
5019 unsigned int data_size = 0;
5020 unsigned int param_size = 2;
5021 uint16_t info_level;
5025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5029 if (total_params < 4) {
5030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5034 fsp = file_fsp(req, SVAL(params,0));
5035 if (!fsp_is_np(fsp)) {
5036 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5040 info_level = SVAL(params,2);
5042 *pparams = (char *)SMB_REALLOC(*pparams,2);
5043 if (*pparams == NULL) {
5044 reply_nterror(req, NT_STATUS_NO_MEMORY);
5049 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5050 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5053 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5054 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5055 if (*ppdata == NULL ) {
5056 reply_nterror(req, NT_STATUS_NO_MEMORY);
5061 switch (info_level) {
5062 case SMB_FILE_STANDARD_INFORMATION:
5064 SOFF_T(pdata,0,4096LL);
5071 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5075 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5081 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5082 TALLOC_CTX *mem_ctx,
5083 struct smb_request *req,
5084 uint16_t info_level,
5086 struct smb_filename *smb_fname,
5087 bool delete_pending,
5088 struct timespec write_time_ts,
5089 struct ea_list *ea_list,
5090 int lock_data_count,
5093 unsigned int max_data_bytes,
5094 size_t *fixed_portion,
5096 unsigned int *pdata_size)
5098 char *pdata = *ppdata;
5099 char *dstart, *dend;
5100 unsigned int data_size;
5101 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5102 time_t create_time, mtime, atime, c_time;
5103 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5110 uint64_t file_size = 0;
5112 uint64_t allocation_size = 0;
5113 uint64_t file_id = 0;
5114 uint32_t access_mask = 0;
5117 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5118 return NT_STATUS_INVALID_LEVEL;
5121 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5122 smb_fname_str_dbg(smb_fname),
5124 info_level, max_data_bytes));
5126 mode = dos_mode(conn, smb_fname);
5127 nlink = psbuf->st_ex_nlink;
5129 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5133 if ((nlink > 0) && delete_pending) {
5137 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5138 return NT_STATUS_INVALID_PARAMETER;
5141 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5142 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5143 if (*ppdata == NULL) {
5144 return NT_STATUS_NO_MEMORY;
5148 dend = dstart + data_size - 1;
5150 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
5151 update_stat_ex_mtime(psbuf, write_time_ts);
5154 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5155 mtime_ts = psbuf->st_ex_mtime;
5156 atime_ts = psbuf->st_ex_atime;
5157 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5159 if (lp_dos_filetime_resolution(SNUM(conn))) {
5160 dos_filetime_timespec(&create_time_ts);
5161 dos_filetime_timespec(&mtime_ts);
5162 dos_filetime_timespec(&atime_ts);
5163 dos_filetime_timespec(&ctime_ts);
5166 create_time = convert_timespec_to_time_t(create_time_ts);
5167 mtime = convert_timespec_to_time_t(mtime_ts);
5168 atime = convert_timespec_to_time_t(atime_ts);
5169 c_time = convert_timespec_to_time_t(ctime_ts);
5171 p = strrchr_m(smb_fname->base_name,'/');
5173 base_name = smb_fname->base_name;
5177 /* NT expects the name to be in an exact form of the *full*
5178 filename. See the trans2 torture test */
5179 if (ISDOT(base_name)) {
5180 dos_fname = talloc_strdup(mem_ctx, "\\");
5182 return NT_STATUS_NO_MEMORY;
5185 dos_fname = talloc_asprintf(mem_ctx,
5187 smb_fname->base_name);
5189 return NT_STATUS_NO_MEMORY;
5191 if (is_ntfs_stream_smb_fname(smb_fname)) {
5192 dos_fname = talloc_asprintf(dos_fname, "%s",
5193 smb_fname->stream_name);
5195 return NT_STATUS_NO_MEMORY;
5199 string_replace(dos_fname, '/', '\\');
5202 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5205 /* Do we have this path open ? */
5207 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5208 fsp1 = file_find_di_first(conn->sconn, fileid);
5209 if (fsp1 && fsp1->initial_allocation_size) {
5210 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5214 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5215 file_size = get_file_size_stat(psbuf);
5219 pos = fsp->fh->position_information;
5223 access_mask = fsp->access_mask;
5225 /* GENERIC_EXECUTE mapping from Windows */
5226 access_mask = 0x12019F;
5229 /* This should be an index number - looks like
5232 I think this causes us to fail the IFSKIT
5233 BasicFileInformationTest. -tpot */
5234 file_id = get_fs_file_id(conn, psbuf);
5238 switch (info_level) {
5239 case SMB_INFO_STANDARD:
5240 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5242 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5243 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5244 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5245 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5246 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5247 SSVAL(pdata,l1_attrFile,mode);
5250 case SMB_INFO_QUERY_EA_SIZE:
5252 unsigned int ea_size =
5253 estimate_ea_size(conn, fsp,
5255 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5257 srv_put_dos_date2(pdata,0,create_time);
5258 srv_put_dos_date2(pdata,4,atime);
5259 srv_put_dos_date2(pdata,8,mtime); /* write time */
5260 SIVAL(pdata,12,(uint32_t)file_size);
5261 SIVAL(pdata,16,(uint32_t)allocation_size);
5262 SSVAL(pdata,20,mode);
5263 SIVAL(pdata,22,ea_size);
5267 case SMB_INFO_IS_NAME_VALID:
5268 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5270 /* os/2 needs this ? really ?*/
5271 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5273 /* This is only reached for qpathinfo */
5277 case SMB_INFO_QUERY_EAS_FROM_LIST:
5279 size_t total_ea_len = 0;
5280 struct ea_list *ea_file_list = NULL;
5281 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5284 get_ea_list_from_file(mem_ctx, conn, fsp,
5286 &total_ea_len, &ea_file_list);
5287 if (!NT_STATUS_IS_OK(status)) {
5291 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5293 if (!ea_list || (total_ea_len > data_size)) {
5295 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5299 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5303 case SMB_INFO_QUERY_ALL_EAS:
5305 /* We have data_size bytes to put EA's into. */
5306 size_t total_ea_len = 0;
5307 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5309 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5311 &total_ea_len, &ea_list);
5312 if (!NT_STATUS_IS_OK(status)) {
5316 if (!ea_list || (total_ea_len > data_size)) {
5318 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5322 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5326 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5328 /* This is FileFullEaInformation - 0xF which maps to
5329 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5331 /* We have data_size bytes to put EA's into. */
5332 size_t total_ea_len = 0;
5333 struct ea_list *ea_file_list = NULL;
5335 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5337 /*TODO: add filtering and index handling */
5340 get_ea_list_from_file(mem_ctx, conn, fsp,
5342 &total_ea_len, &ea_file_list);
5343 if (!NT_STATUS_IS_OK(status)) {
5346 if (!ea_file_list) {
5347 return NT_STATUS_NO_EAS_ON_FILE;
5350 status = fill_ea_chained_buffer(mem_ctx,
5354 conn, ea_file_list);
5355 if (!NT_STATUS_IS_OK(status)) {
5361 case SMB_FILE_BASIC_INFORMATION:
5362 case SMB_QUERY_FILE_BASIC_INFO:
5364 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5365 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5366 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5368 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5372 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5373 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5374 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5375 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5376 SIVAL(pdata,32,mode);
5378 DEBUG(5,("SMB_QFBI - "));
5379 DEBUG(5,("create: %s ", ctime(&create_time)));
5380 DEBUG(5,("access: %s ", ctime(&atime)));
5381 DEBUG(5,("write: %s ", ctime(&mtime)));
5382 DEBUG(5,("change: %s ", ctime(&c_time)));
5383 DEBUG(5,("mode: %x\n", mode));
5384 *fixed_portion = data_size;
5387 case SMB_FILE_STANDARD_INFORMATION:
5388 case SMB_QUERY_FILE_STANDARD_INFO:
5390 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5392 SOFF_T(pdata,0,allocation_size);
5393 SOFF_T(pdata,8,file_size);
5394 SIVAL(pdata,16,nlink);
5395 SCVAL(pdata,20,delete_pending?1:0);
5396 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5397 SSVAL(pdata,22,0); /* Padding. */
5398 *fixed_portion = 24;
5401 case SMB_FILE_EA_INFORMATION:
5402 case SMB_QUERY_FILE_EA_INFO:
5404 unsigned int ea_size =
5405 estimate_ea_size(conn, fsp, smb_fname);
5406 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5409 SIVAL(pdata,0,ea_size);
5413 /* Get the 8.3 name - used if NT SMB was negotiated. */
5414 case SMB_QUERY_FILE_ALT_NAME_INFO:
5415 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5417 char mangled_name[13];
5418 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5419 if (!name_to_8_3(base_name,mangled_name,
5420 True,conn->params)) {
5421 return NT_STATUS_NO_MEMORY;
5423 status = srvstr_push(dstart, flags2,
5424 pdata+4, mangled_name,
5425 PTR_DIFF(dend, pdata+4),
5427 if (!NT_STATUS_IS_OK(status)) {
5430 data_size = 4 + len;
5436 case SMB_QUERY_FILE_NAME_INFO:
5439 this must be *exactly* right for ACLs on mapped drives to work
5441 status = srvstr_push(dstart, flags2,
5443 PTR_DIFF(dend, pdata+4),
5445 if (!NT_STATUS_IS_OK(status)) {
5448 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5449 data_size = 4 + len;
5454 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5456 char *nfname = NULL;
5458 if (!fsp->conn->sconn->using_smb2) {
5459 return NT_STATUS_INVALID_LEVEL;
5462 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5463 if (nfname == NULL) {
5464 return NT_STATUS_NO_MEMORY;
5467 if (ISDOT(nfname)) {
5470 string_replace(nfname, '/', '\\');
5472 if (smb_fname->stream_name != NULL) {
5473 const char *s = smb_fname->stream_name;
5474 const char *e = NULL;
5477 SMB_ASSERT(s[0] != '\0');
5480 * smb_fname->stream_name is in form
5481 * of ':StrEam:$DATA', but we should only
5482 * append ':StrEam' here.
5485 e = strchr(&s[1], ':');
5491 nfname = talloc_strndup_append(nfname, s, n);
5492 if (nfname == NULL) {
5493 return NT_STATUS_NO_MEMORY;
5497 status = srvstr_push(dstart, flags2,
5499 PTR_DIFF(dend, pdata+4),
5501 if (!NT_STATUS_IS_OK(status)) {
5504 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5505 data_size = 4 + len;
5511 case SMB_FILE_ALLOCATION_INFORMATION:
5512 case SMB_QUERY_FILE_ALLOCATION_INFO:
5513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5515 SOFF_T(pdata,0,allocation_size);
5518 case SMB_FILE_END_OF_FILE_INFORMATION:
5519 case SMB_QUERY_FILE_END_OF_FILEINFO:
5520 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5522 SOFF_T(pdata,0,file_size);
5525 case SMB_QUERY_FILE_ALL_INFO:
5526 case SMB_FILE_ALL_INFORMATION:
5528 unsigned int ea_size =
5529 estimate_ea_size(conn, fsp, smb_fname);
5530 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5531 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5532 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5533 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5534 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5535 SIVAL(pdata,32,mode);
5536 SIVAL(pdata,36,0); /* padding. */
5538 SOFF_T(pdata,0,allocation_size);
5539 SOFF_T(pdata,8,file_size);
5540 SIVAL(pdata,16,nlink);
5541 SCVAL(pdata,20,delete_pending);
5542 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5545 SIVAL(pdata,0,ea_size);
5546 pdata += 4; /* EA info */
5547 status = srvstr_push(dstart, flags2,
5549 PTR_DIFF(dend, pdata+4),
5551 if (!NT_STATUS_IS_OK(status)) {
5556 data_size = PTR_DIFF(pdata,(*ppdata));
5557 *fixed_portion = 10;
5561 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5563 unsigned int ea_size =
5564 estimate_ea_size(conn, fsp, smb_fname);
5565 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5566 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5567 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5568 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5569 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5570 SIVAL(pdata, 0x20, mode);
5571 SIVAL(pdata, 0x24, 0); /* padding. */
5572 SBVAL(pdata, 0x28, allocation_size);
5573 SBVAL(pdata, 0x30, file_size);
5574 SIVAL(pdata, 0x38, nlink);
5575 SCVAL(pdata, 0x3C, delete_pending);
5576 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5577 SSVAL(pdata, 0x3E, 0); /* padding */
5578 SBVAL(pdata, 0x40, file_id);
5579 SIVAL(pdata, 0x48, ea_size);
5580 SIVAL(pdata, 0x4C, access_mask);
5581 SBVAL(pdata, 0x50, pos);
5582 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5583 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5587 status = srvstr_push(dstart, flags2,
5589 PTR_DIFF(dend, pdata+4),
5591 if (!NT_STATUS_IS_OK(status)) {
5596 data_size = PTR_DIFF(pdata,(*ppdata));
5597 *fixed_portion = 104;
5600 case SMB_FILE_INTERNAL_INFORMATION:
5602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5603 SBVAL(pdata, 0, file_id);
5608 case SMB_FILE_ACCESS_INFORMATION:
5609 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5610 SIVAL(pdata, 0, access_mask);
5615 case SMB_FILE_NAME_INFORMATION:
5616 /* Pathname with leading '\'. */
5619 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5621 SIVAL(pdata,0,byte_len);
5622 data_size = 4 + byte_len;
5626 case SMB_FILE_DISPOSITION_INFORMATION:
5627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5629 SCVAL(pdata,0,delete_pending);
5633 case SMB_FILE_POSITION_INFORMATION:
5634 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5636 SOFF_T(pdata,0,pos);
5640 case SMB_FILE_MODE_INFORMATION:
5641 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5642 SIVAL(pdata,0,mode);
5647 case SMB_FILE_ALIGNMENT_INFORMATION:
5648 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5649 SIVAL(pdata,0,0); /* No alignment needed. */
5655 * NT4 server just returns "invalid query" to this - if we try
5656 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5659 /* The first statement above is false - verified using Thursby
5660 * client against NT4 -- gcolley.
5662 case SMB_QUERY_FILE_STREAM_INFO:
5663 case SMB_FILE_STREAM_INFORMATION: {
5664 unsigned int num_streams = 0;
5665 struct stream_struct *streams = NULL;
5667 DEBUG(10,("smbd_do_qfilepathinfo: "
5668 "SMB_FILE_STREAM_INFORMATION\n"));
5670 if (is_ntfs_stream_smb_fname(smb_fname)) {
5671 return NT_STATUS_INVALID_PARAMETER;
5674 status = vfs_streaminfo(conn,
5681 if (!NT_STATUS_IS_OK(status)) {
5682 DEBUG(10, ("could not get stream info: %s\n",
5683 nt_errstr(status)));
5687 status = marshall_stream_info(num_streams, streams,
5688 pdata, max_data_bytes,
5691 if (!NT_STATUS_IS_OK(status)) {
5692 DEBUG(10, ("marshall_stream_info failed: %s\n",
5693 nt_errstr(status)));
5694 TALLOC_FREE(streams);
5698 TALLOC_FREE(streams);
5700 *fixed_portion = 32;
5704 case SMB_QUERY_COMPRESSION_INFO:
5705 case SMB_FILE_COMPRESSION_INFORMATION:
5706 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5707 SOFF_T(pdata,0,file_size);
5708 SIVAL(pdata,8,0); /* ??? */
5709 SIVAL(pdata,12,0); /* ??? */
5711 *fixed_portion = 16;
5714 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5715 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5716 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5717 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5718 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5719 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5720 SOFF_T(pdata,32,allocation_size);
5721 SOFF_T(pdata,40,file_size);
5722 SIVAL(pdata,48,mode);
5723 SIVAL(pdata,52,0); /* ??? */
5725 *fixed_portion = 56;
5728 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5729 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5730 SIVAL(pdata,0,mode);
5737 * CIFS UNIX Extensions.
5740 case SMB_QUERY_FILE_UNIX_BASIC:
5742 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5743 data_size = PTR_DIFF(pdata,(*ppdata));
5745 DEBUG(4,("smbd_do_qfilepathinfo: "
5746 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5747 dump_data(4, (uint8_t *)(*ppdata), data_size);
5751 case SMB_QUERY_FILE_UNIX_INFO2:
5753 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5754 data_size = PTR_DIFF(pdata,(*ppdata));
5758 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5760 for (i=0; i<100; i++)
5761 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5767 case SMB_QUERY_FILE_UNIX_LINK:
5770 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5773 return NT_STATUS_NO_MEMORY;
5776 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5778 if(!S_ISLNK(psbuf->st_ex_mode)) {
5779 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5782 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5784 link_len = SMB_VFS_READLINK(conn,
5787 if (link_len == -1) {
5788 return map_nt_error_from_unix(errno);
5790 buffer[link_len] = 0;
5791 status = srvstr_push(dstart, flags2,
5793 PTR_DIFF(dend, pdata),
5794 STR_TERMINATE, &len);
5795 if (!NT_STATUS_IS_OK(status)) {
5799 data_size = PTR_DIFF(pdata,(*ppdata));
5804 #if defined(HAVE_POSIX_ACLS)
5805 case SMB_QUERY_POSIX_ACL:
5807 status = smb_query_posix_acl(conn,
5814 if (!NT_STATUS_IS_OK(status)) {
5822 case SMB_QUERY_POSIX_LOCK:
5827 enum brl_type lock_type;
5829 /* We need an open file with a real fd for this. */
5830 if (!fsp || fsp->fh->fd == -1) {
5831 return NT_STATUS_INVALID_LEVEL;
5834 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5835 return NT_STATUS_INVALID_PARAMETER;
5838 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5839 case POSIX_LOCK_TYPE_READ:
5840 lock_type = READ_LOCK;
5842 case POSIX_LOCK_TYPE_WRITE:
5843 lock_type = WRITE_LOCK;
5845 case POSIX_LOCK_TYPE_UNLOCK:
5847 /* There's no point in asking for an unlock... */
5848 return NT_STATUS_INVALID_PARAMETER;
5851 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5852 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5853 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5855 status = query_lock(fsp,
5862 if (ERROR_WAS_LOCK_DENIED(status)) {
5863 /* Here we need to report who has it locked... */
5864 data_size = POSIX_LOCK_DATA_SIZE;
5866 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5867 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5868 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5869 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5870 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5872 } else if (NT_STATUS_IS_OK(status)) {
5873 /* For success we just return a copy of what we sent
5874 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5875 data_size = POSIX_LOCK_DATA_SIZE;
5876 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5877 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5885 return NT_STATUS_INVALID_LEVEL;
5888 *pdata_size = data_size;
5889 return NT_STATUS_OK;
5892 /****************************************************************************
5893 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5894 file name or file id).
5895 ****************************************************************************/
5897 static void call_trans2qfilepathinfo(connection_struct *conn,
5898 struct smb_request *req,
5899 unsigned int tran_call,
5900 char **pparams, int total_params,
5901 char **ppdata, int total_data,
5902 unsigned int max_data_bytes)
5904 char *params = *pparams;
5905 char *pdata = *ppdata;
5906 uint16_t info_level;
5907 unsigned int data_size = 0;
5908 unsigned int param_size = 2;
5909 struct smb_filename *smb_fname = NULL;
5910 bool delete_pending = False;
5911 struct timespec write_time_ts;
5912 files_struct *fsp = NULL;
5913 struct file_id fileid;
5914 struct ea_list *ea_list = NULL;
5915 int lock_data_count = 0;
5916 char *lock_data = NULL;
5917 size_t fixed_portion;
5918 NTSTATUS status = NT_STATUS_OK;
5921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5925 ZERO_STRUCT(write_time_ts);
5927 if (tran_call == TRANSACT2_QFILEINFO) {
5928 if (total_params < 4) {
5929 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5934 call_trans2qpipeinfo(conn, req, tran_call,
5935 pparams, total_params,
5941 fsp = file_fsp(req, SVAL(params,0));
5942 info_level = SVAL(params,2);
5944 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5946 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5947 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5951 /* Initial check for valid fsp ptr. */
5952 if (!check_fsp_open(conn, req, fsp)) {
5956 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5957 if (smb_fname == NULL) {
5958 reply_nterror(req, NT_STATUS_NO_MEMORY);
5962 if(fsp->fake_file_handle) {
5964 * This is actually for the QUOTA_FAKE_FILE --metze
5967 /* We know this name is ok, it's already passed the checks. */
5969 } else if(fsp->fh->fd == -1) {
5971 * This is actually a QFILEINFO on a directory
5972 * handle (returned from an NT SMB). NT5.0 seems
5973 * to do this call. JRA.
5976 if (INFO_LEVEL_IS_UNIX(info_level)) {
5977 /* Always do lstat for UNIX calls. */
5978 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5979 DEBUG(3,("call_trans2qfilepathinfo: "
5980 "SMB_VFS_LSTAT of %s failed "
5982 smb_fname_str_dbg(smb_fname),
5985 map_nt_error_from_unix(errno));
5988 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5989 DEBUG(3,("call_trans2qfilepathinfo: "
5990 "SMB_VFS_STAT of %s failed (%s)\n",
5991 smb_fname_str_dbg(smb_fname),
5994 map_nt_error_from_unix(errno));
5998 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5999 fileid = vfs_file_id_from_sbuf(
6000 conn, &smb_fname->st);
6001 get_file_infos(fileid, fsp->name_hash,
6007 * Original code - this is an open file.
6009 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6010 DEBUG(3, ("fstat of %s failed (%s)\n",
6011 fsp_fnum_dbg(fsp), strerror(errno)));
6013 map_nt_error_from_unix(errno));
6016 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6017 fileid = vfs_file_id_from_sbuf(
6018 conn, &smb_fname->st);
6019 get_file_infos(fileid, fsp->name_hash,
6028 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6031 if (total_params < 7) {
6032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6036 info_level = SVAL(params,0);
6038 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6040 if (INFO_LEVEL_IS_UNIX(info_level)) {
6041 if (!lp_unix_extensions()) {
6042 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6045 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6046 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6047 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6048 req->posix_pathnames) {
6049 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6053 if (req->posix_pathnames) {
6054 srvstr_get_path_posix(req,
6063 srvstr_get_path(req,
6072 if (!NT_STATUS_IS_OK(status)) {
6073 reply_nterror(req, status);
6077 status = filename_convert(req,
6084 if (!NT_STATUS_IS_OK(status)) {
6085 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6086 reply_botherror(req,
6087 NT_STATUS_PATH_NOT_COVERED,
6088 ERRSRV, ERRbadpath);
6091 reply_nterror(req, status);
6095 /* If this is a stream, check if there is a delete_pending. */
6096 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6097 && is_ntfs_stream_smb_fname(smb_fname)) {
6098 struct smb_filename *smb_fname_base;
6100 /* Create an smb_filename with stream_name == NULL. */
6101 smb_fname_base = synthetic_smb_fname(
6103 smb_fname->base_name,
6107 if (smb_fname_base == NULL) {
6108 reply_nterror(req, NT_STATUS_NO_MEMORY);
6112 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6113 /* Always do lstat for UNIX calls. */
6114 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6115 DEBUG(3,("call_trans2qfilepathinfo: "
6116 "SMB_VFS_LSTAT of %s failed "
6118 smb_fname_str_dbg(smb_fname_base),
6120 TALLOC_FREE(smb_fname_base);
6122 map_nt_error_from_unix(errno));
6126 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6127 DEBUG(3,("call_trans2qfilepathinfo: "
6128 "fileinfo of %s failed "
6130 smb_fname_str_dbg(smb_fname_base),
6132 TALLOC_FREE(smb_fname_base);
6134 map_nt_error_from_unix(errno));
6139 status = file_name_hash(conn,
6140 smb_fname_str_dbg(smb_fname_base),
6142 if (!NT_STATUS_IS_OK(status)) {
6143 TALLOC_FREE(smb_fname_base);
6144 reply_nterror(req, status);
6148 fileid = vfs_file_id_from_sbuf(conn,
6149 &smb_fname_base->st);
6150 TALLOC_FREE(smb_fname_base);
6151 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6152 if (delete_pending) {
6153 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6158 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6159 /* Always do lstat for UNIX calls. */
6160 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6161 DEBUG(3,("call_trans2qfilepathinfo: "
6162 "SMB_VFS_LSTAT of %s failed (%s)\n",
6163 smb_fname_str_dbg(smb_fname),
6166 map_nt_error_from_unix(errno));
6171 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6172 DEBUG(3,("call_trans2qfilepathinfo: "
6173 "SMB_VFS_STAT of %s failed (%s)\n",
6174 smb_fname_str_dbg(smb_fname),
6177 map_nt_error_from_unix(errno));
6182 status = file_name_hash(conn,
6183 smb_fname_str_dbg(smb_fname),
6185 if (!NT_STATUS_IS_OK(status)) {
6186 reply_nterror(req, status);
6190 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6191 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6192 get_file_infos(fileid, name_hash, &delete_pending,
6196 if (delete_pending) {
6197 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6202 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6203 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6205 info_level,tran_call,total_data));
6207 /* Pull out any data sent here before we realloc. */
6208 switch (info_level) {
6209 case SMB_INFO_QUERY_EAS_FROM_LIST:
6211 /* Pull any EA list from the data portion. */
6214 if (total_data < 4) {
6216 req, NT_STATUS_INVALID_PARAMETER);
6219 ea_size = IVAL(pdata,0);
6221 if (total_data > 0 && ea_size != total_data) {
6222 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6223 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6225 req, NT_STATUS_INVALID_PARAMETER);
6229 if (!lp_ea_support(SNUM(conn))) {
6230 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6234 /* Pull out the list of names. */
6235 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6238 req, NT_STATUS_INVALID_PARAMETER);
6244 case SMB_QUERY_POSIX_LOCK:
6246 if (fsp == NULL || fsp->fh->fd == -1) {
6247 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6251 if (total_data != POSIX_LOCK_DATA_SIZE) {
6253 req, NT_STATUS_INVALID_PARAMETER);
6257 /* Copy the lock range data. */
6258 lock_data = (char *)talloc_memdup(
6259 req, pdata, total_data);
6261 reply_nterror(req, NT_STATUS_NO_MEMORY);
6264 lock_data_count = total_data;
6270 *pparams = (char *)SMB_REALLOC(*pparams,2);
6271 if (*pparams == NULL) {
6272 reply_nterror(req, NT_STATUS_NO_MEMORY);
6279 * draft-leach-cifs-v1-spec-02.txt
6280 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6283 * The requested information is placed in the Data portion of the
6284 * transaction response. For the information levels greater than 0x100,
6285 * the transaction response has 1 parameter word which should be
6286 * ignored by the client.
6288 * However Windows only follows this rule for the IS_NAME_VALID call.
6290 switch (info_level) {
6291 case SMB_INFO_IS_NAME_VALID:
6296 if ((info_level & 0xFF00) == 0xFF00) {
6298 * We use levels that start with 0xFF00
6299 * internally to represent SMB2 specific levels
6301 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6305 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6307 delete_pending, write_time_ts,
6309 lock_data_count, lock_data,
6310 req->flags2, max_data_bytes,
6312 ppdata, &data_size);
6313 if (!NT_STATUS_IS_OK(status)) {
6314 if (open_was_deferred(req->xconn, req->mid)) {
6315 /* We have re-scheduled this call. */
6318 reply_nterror(req, status);
6321 if (fixed_portion > max_data_bytes) {
6322 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6326 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6332 /****************************************************************************
6333 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6335 ****************************************************************************/
6337 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6338 connection_struct *conn,
6339 struct smb_request *req,
6340 bool overwrite_if_exists,
6341 const struct smb_filename *smb_fname_old,
6342 struct smb_filename *smb_fname_new)
6344 NTSTATUS status = NT_STATUS_OK;
6347 /* source must already exist. */
6348 if (!VALID_STAT(smb_fname_old->st)) {
6349 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6352 if (VALID_STAT(smb_fname_new->st)) {
6353 if (overwrite_if_exists) {
6354 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6355 return NT_STATUS_FILE_IS_A_DIRECTORY;
6357 status = unlink_internals(conn,
6359 FILE_ATTRIBUTE_NORMAL,
6362 if (!NT_STATUS_IS_OK(status)) {
6366 /* Disallow if newname already exists. */
6367 return NT_STATUS_OBJECT_NAME_COLLISION;
6371 /* No links from a directory. */
6372 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6373 return NT_STATUS_FILE_IS_A_DIRECTORY;
6376 /* Setting a hardlink to/from a stream isn't currently supported. */
6377 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6379 DBG_DEBUG("Old name has streams\n");
6380 return NT_STATUS_INVALID_PARAMETER;
6382 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6384 DBG_DEBUG("New name has streams\n");
6385 return NT_STATUS_INVALID_PARAMETER;
6388 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6389 smb_fname_old->base_name, smb_fname_new->base_name));
6391 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6392 status = map_nt_error_from_unix(errno);
6393 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6394 nt_errstr(status), smb_fname_old->base_name,
6395 smb_fname_new->base_name));
6400 /****************************************************************************
6401 Deal with setting the time from any of the setfilepathinfo functions.
6402 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6403 calling this function.
6404 ****************************************************************************/
6406 NTSTATUS smb_set_file_time(connection_struct *conn,
6408 const struct smb_filename *smb_fname,
6409 struct smb_file_time *ft,
6410 bool setting_write_time)
6412 struct smb_filename smb_fname_base;
6414 FILE_NOTIFY_CHANGE_LAST_ACCESS
6415 |FILE_NOTIFY_CHANGE_LAST_WRITE
6416 |FILE_NOTIFY_CHANGE_CREATION;
6418 if (!VALID_STAT(smb_fname->st)) {
6419 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6422 /* get some defaults (no modifications) if any info is zero or -1. */
6423 if (null_timespec(ft->create_time)) {
6424 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6427 if (null_timespec(ft->atime)) {
6428 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6431 if (null_timespec(ft->mtime)) {
6432 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6435 if (!setting_write_time) {
6436 /* ft->mtime comes from change time, not write time. */
6437 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6440 /* Ensure the resolution is the correct for
6441 * what we can store on this filesystem. */
6443 round_timespec(conn->ts_res, &ft->create_time);
6444 round_timespec(conn->ts_res, &ft->ctime);
6445 round_timespec(conn->ts_res, &ft->atime);
6446 round_timespec(conn->ts_res, &ft->mtime);
6448 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6449 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6450 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6451 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6452 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6453 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6454 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6455 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6457 if (setting_write_time) {
6459 * This was a Windows setfileinfo on an open file.
6460 * NT does this a lot. We also need to
6461 * set the time here, as it can be read by
6462 * FindFirst/FindNext and with the patch for bug #2045
6463 * in smbd/fileio.c it ensures that this timestamp is
6464 * kept sticky even after a write. We save the request
6465 * away and will set it on file close and after a write. JRA.
6468 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6469 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6472 if (fsp->base_fsp) {
6473 set_sticky_write_time_fsp(fsp->base_fsp,
6476 set_sticky_write_time_fsp(fsp, ft->mtime);
6479 set_sticky_write_time_path(
6480 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6485 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6487 /* Always call ntimes on the base, even if a stream was passed in. */
6488 smb_fname_base = *smb_fname;
6489 smb_fname_base.stream_name = NULL;
6491 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6492 return map_nt_error_from_unix(errno);
6495 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6496 smb_fname->base_name);
6497 return NT_STATUS_OK;
6500 /****************************************************************************
6501 Deal with setting the dosmode from any of the setfilepathinfo functions.
6502 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6503 done before calling this function.
6504 ****************************************************************************/
6506 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6507 const struct smb_filename *smb_fname,
6510 struct smb_filename *smb_fname_base;
6513 if (!VALID_STAT(smb_fname->st)) {
6514 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6517 /* Always operate on the base_name, even if a stream was passed in. */
6518 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6519 smb_fname->base_name,
6523 if (smb_fname_base == NULL) {
6524 return NT_STATUS_NO_MEMORY;
6528 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6529 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6531 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6535 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6537 /* check the mode isn't different, before changing it */
6538 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6539 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6540 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6541 (unsigned int)dosmode));
6543 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6545 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6547 smb_fname_str_dbg(smb_fname_base),
6549 status = map_nt_error_from_unix(errno);
6553 status = NT_STATUS_OK;
6555 TALLOC_FREE(smb_fname_base);
6559 /****************************************************************************
6560 Deal with setting the size from any of the setfilepathinfo functions.
6561 ****************************************************************************/
6563 static NTSTATUS smb_set_file_size(connection_struct *conn,
6564 struct smb_request *req,
6566 const struct smb_filename *smb_fname,
6567 const SMB_STRUCT_STAT *psbuf,
6569 bool fail_after_createfile)
6571 NTSTATUS status = NT_STATUS_OK;
6572 struct smb_filename *smb_fname_tmp = NULL;
6573 files_struct *new_fsp = NULL;
6575 if (!VALID_STAT(*psbuf)) {
6576 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6579 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6581 get_file_size_stat(psbuf));
6583 if (size == get_file_size_stat(psbuf)) {
6584 return NT_STATUS_OK;
6587 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6588 smb_fname_str_dbg(smb_fname), (double)size));
6590 if (fsp && fsp->fh->fd != -1) {
6591 /* Handle based call. */
6592 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6593 return NT_STATUS_ACCESS_DENIED;
6596 if (vfs_set_filelen(fsp, size) == -1) {
6597 return map_nt_error_from_unix(errno);
6599 trigger_write_time_update_immediate(fsp);
6600 return NT_STATUS_OK;
6603 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6604 if (smb_fname_tmp == NULL) {
6605 return NT_STATUS_NO_MEMORY;
6608 smb_fname_tmp->st = *psbuf;
6610 status = SMB_VFS_CREATE_FILE(
6613 0, /* root_dir_fid */
6614 smb_fname_tmp, /* fname */
6615 FILE_WRITE_DATA, /* access_mask */
6616 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6618 FILE_OPEN, /* create_disposition*/
6619 0, /* create_options */
6620 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6621 0, /* oplock_request */
6623 0, /* allocation_size */
6624 0, /* private_flags */
6627 &new_fsp, /* result */
6629 NULL, NULL); /* create context */
6631 TALLOC_FREE(smb_fname_tmp);
6633 if (!NT_STATUS_IS_OK(status)) {
6634 /* NB. We check for open_was_deferred in the caller. */
6638 /* See RAW-SFILEINFO-END-OF-FILE */
6639 if (fail_after_createfile) {
6640 close_file(req, new_fsp,NORMAL_CLOSE);
6641 return NT_STATUS_INVALID_LEVEL;
6644 if (vfs_set_filelen(new_fsp, size) == -1) {
6645 status = map_nt_error_from_unix(errno);
6646 close_file(req, new_fsp,NORMAL_CLOSE);
6650 trigger_write_time_update_immediate(new_fsp);
6651 close_file(req, new_fsp,NORMAL_CLOSE);
6652 return NT_STATUS_OK;
6655 /****************************************************************************
6656 Deal with SMB_INFO_SET_EA.
6657 ****************************************************************************/
6659 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6663 const struct smb_filename *smb_fname)
6665 struct ea_list *ea_list = NULL;
6666 TALLOC_CTX *ctx = NULL;
6667 NTSTATUS status = NT_STATUS_OK;
6669 if (total_data < 10) {
6671 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6672 length. They seem to have no effect. Bug #3212. JRA */
6674 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6675 /* We're done. We only get EA info in this call. */
6676 return NT_STATUS_OK;
6679 return NT_STATUS_INVALID_PARAMETER;
6682 if (IVAL(pdata,0) > total_data) {
6683 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6684 IVAL(pdata,0), (unsigned int)total_data));
6685 return NT_STATUS_INVALID_PARAMETER;
6689 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6691 return NT_STATUS_INVALID_PARAMETER;
6694 status = set_ea(conn, fsp, smb_fname, ea_list);
6699 /****************************************************************************
6700 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6701 ****************************************************************************/
6703 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6708 struct ea_list *ea_list = NULL;
6712 return NT_STATUS_INVALID_HANDLE;
6715 if (!lp_ea_support(SNUM(conn))) {
6716 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6717 "EA's not supported.\n",
6718 (unsigned int)total_data));
6719 return NT_STATUS_EAS_NOT_SUPPORTED;
6722 if (total_data < 10) {
6723 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6725 (unsigned int)total_data));
6726 return NT_STATUS_INVALID_PARAMETER;
6729 ea_list = read_nttrans_ea_list(talloc_tos(),
6734 return NT_STATUS_INVALID_PARAMETER;
6737 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6739 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6740 smb_fname_str_dbg(fsp->fsp_name),
6741 nt_errstr(status) ));
6747 /****************************************************************************
6748 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6749 ****************************************************************************/
6751 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6755 struct smb_filename *smb_fname)
6757 NTSTATUS status = NT_STATUS_OK;
6758 bool delete_on_close;
6759 uint32_t dosmode = 0;
6761 if (total_data < 1) {
6762 return NT_STATUS_INVALID_PARAMETER;
6766 return NT_STATUS_INVALID_HANDLE;
6769 delete_on_close = (CVAL(pdata,0) ? True : False);
6770 dosmode = dos_mode(conn, smb_fname);
6772 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6773 "delete_on_close = %u\n",
6774 smb_fname_str_dbg(smb_fname),
6775 (unsigned int)dosmode,
6776 (unsigned int)delete_on_close ));
6778 if (delete_on_close) {
6779 status = can_set_delete_on_close(fsp, dosmode);
6780 if (!NT_STATUS_IS_OK(status)) {
6785 /* The set is across all open files on this dev/inode pair. */
6786 if (!set_delete_on_close(fsp, delete_on_close,
6787 conn->session_info->security_token,
6788 conn->session_info->unix_token)) {
6789 return NT_STATUS_ACCESS_DENIED;
6791 return NT_STATUS_OK;
6794 /****************************************************************************
6795 Deal with SMB_FILE_POSITION_INFORMATION.
6796 ****************************************************************************/
6798 static NTSTATUS smb_file_position_information(connection_struct *conn,
6803 uint64_t position_information;
6805 if (total_data < 8) {
6806 return NT_STATUS_INVALID_PARAMETER;
6810 /* Ignore on pathname based set. */
6811 return NT_STATUS_OK;
6814 position_information = (uint64_t)IVAL(pdata,0);
6815 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6817 DEBUG(10,("smb_file_position_information: Set file position "
6818 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6819 (double)position_information));
6820 fsp->fh->position_information = position_information;
6821 return NT_STATUS_OK;
6824 /****************************************************************************
6825 Deal with SMB_FILE_MODE_INFORMATION.
6826 ****************************************************************************/
6828 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6834 if (total_data < 4) {
6835 return NT_STATUS_INVALID_PARAMETER;
6837 mode = IVAL(pdata,0);
6838 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6839 return NT_STATUS_INVALID_PARAMETER;
6841 return NT_STATUS_OK;
6844 /****************************************************************************
6845 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6846 ****************************************************************************/
6848 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6849 struct smb_request *req,
6852 const struct smb_filename *new_smb_fname)
6854 char *link_target = NULL;
6855 TALLOC_CTX *ctx = talloc_tos();
6857 /* Set a symbolic link. */
6858 /* Don't allow this if follow links is false. */
6860 if (total_data == 0) {
6861 return NT_STATUS_INVALID_PARAMETER;
6864 if (!lp_follow_symlinks(SNUM(conn))) {
6865 return NT_STATUS_ACCESS_DENIED;
6868 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6869 total_data, STR_TERMINATE);
6872 return NT_STATUS_INVALID_PARAMETER;
6875 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6876 new_smb_fname->base_name, link_target ));
6878 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6879 return map_nt_error_from_unix(errno);
6882 return NT_STATUS_OK;
6885 /****************************************************************************
6886 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6887 ****************************************************************************/
6889 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6890 struct smb_request *req,
6891 const char *pdata, int total_data,
6892 struct smb_filename *smb_fname_new)
6894 char *oldname = NULL;
6895 struct smb_filename *smb_fname_old = NULL;
6896 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6897 TALLOC_CTX *ctx = talloc_tos();
6898 NTSTATUS status = NT_STATUS_OK;
6900 /* Set a hard link. */
6901 if (total_data == 0) {
6902 return NT_STATUS_INVALID_PARAMETER;
6905 if (req->posix_pathnames) {
6906 srvstr_get_path_posix(ctx,
6915 srvstr_get_path(ctx,
6924 if (!NT_STATUS_IS_OK(status)) {
6928 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6929 smb_fname_str_dbg(smb_fname_new), oldname));
6931 status = filename_convert(ctx,
6938 if (!NT_STATUS_IS_OK(status)) {
6942 return hardlink_internals(ctx, conn, req, false,
6943 smb_fname_old, smb_fname_new);
6946 /****************************************************************************
6947 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6948 ****************************************************************************/
6950 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6951 struct smb_request *req,
6955 struct smb_filename *smb_fname_src)
6959 char *newname = NULL;
6960 struct smb_filename *smb_fname_dst = NULL;
6961 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6962 ucf_flags_from_smb_request(req);
6963 NTSTATUS status = NT_STATUS_OK;
6964 TALLOC_CTX *ctx = talloc_tos();
6967 return NT_STATUS_INVALID_HANDLE;
6970 if (total_data < 20) {
6971 return NT_STATUS_INVALID_PARAMETER;
6974 overwrite = (CVAL(pdata,0) ? True : False);
6975 len = IVAL(pdata,16);
6977 if (len > (total_data - 20) || (len == 0)) {
6978 return NT_STATUS_INVALID_PARAMETER;
6981 if (req->posix_pathnames) {
6982 srvstr_get_path_posix(ctx,
6991 srvstr_get_path(ctx,
7000 if (!NT_STATUS_IS_OK(status)) {
7004 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7007 status = filename_convert(ctx,
7014 if (!NT_STATUS_IS_OK(status)) {
7018 if (fsp->base_fsp) {
7019 /* newname must be a stream name. */
7020 if (newname[0] != ':') {
7021 return NT_STATUS_NOT_SUPPORTED;
7024 /* Create an smb_fname to call rename_internals_fsp() with. */
7025 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7026 fsp->base_fsp->fsp_name->base_name,
7029 fsp->base_fsp->fsp_name->flags);
7030 if (smb_fname_dst == NULL) {
7031 status = NT_STATUS_NO_MEMORY;
7036 * Set the original last component, since
7037 * rename_internals_fsp() requires it.
7039 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7041 if (smb_fname_dst->original_lcomp == NULL) {
7042 status = NT_STATUS_NO_MEMORY;
7048 DEBUG(10,("smb2_file_rename_information: "
7049 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7050 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7051 smb_fname_str_dbg(smb_fname_dst)));
7052 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7053 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7057 TALLOC_FREE(smb_fname_dst);
7061 static NTSTATUS smb_file_link_information(connection_struct *conn,
7062 struct smb_request *req,
7066 struct smb_filename *smb_fname_src)
7070 char *newname = NULL;
7071 struct smb_filename *smb_fname_dst = NULL;
7072 NTSTATUS status = NT_STATUS_OK;
7073 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7074 ucf_flags_from_smb_request(req);
7075 TALLOC_CTX *ctx = talloc_tos();
7078 return NT_STATUS_INVALID_HANDLE;
7081 if (total_data < 20) {
7082 return NT_STATUS_INVALID_PARAMETER;
7085 overwrite = (CVAL(pdata,0) ? true : false);
7086 len = IVAL(pdata,16);
7088 if (len > (total_data - 20) || (len == 0)) {
7089 return NT_STATUS_INVALID_PARAMETER;
7092 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7093 srvstr_get_path_posix(ctx,
7101 ucf_flags |= UCF_POSIX_PATHNAMES;
7103 srvstr_get_path(ctx,
7112 if (!NT_STATUS_IS_OK(status)) {
7116 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7119 status = filename_convert(ctx,
7126 if (!NT_STATUS_IS_OK(status)) {
7130 if (fsp->base_fsp) {
7131 /* No stream names. */
7132 return NT_STATUS_NOT_SUPPORTED;
7135 DEBUG(10,("smb_file_link_information: "
7136 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7137 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7138 smb_fname_str_dbg(smb_fname_dst)));
7139 status = hardlink_internals(ctx,
7146 TALLOC_FREE(smb_fname_dst);
7150 /****************************************************************************
7151 Deal with SMB_FILE_RENAME_INFORMATION.
7152 ****************************************************************************/
7154 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7155 struct smb_request *req,
7159 struct smb_filename *smb_fname_src)
7164 char *newname = NULL;
7165 struct smb_filename *smb_fname_dst = NULL;
7166 bool dest_has_wcard = False;
7167 NTSTATUS status = NT_STATUS_OK;
7169 TALLOC_CTX *ctx = talloc_tos();
7171 if (total_data < 13) {
7172 return NT_STATUS_INVALID_PARAMETER;
7175 overwrite = (CVAL(pdata,0) ? True : False);
7176 root_fid = IVAL(pdata,4);
7177 len = IVAL(pdata,8);
7179 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7180 return NT_STATUS_INVALID_PARAMETER;
7183 if (req->posix_pathnames) {
7184 srvstr_get_path_wcard_posix(ctx,
7194 srvstr_get_path_wcard(ctx,
7204 if (!NT_STATUS_IS_OK(status)) {
7208 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7211 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7212 status = resolve_dfspath_wcard(ctx, conn,
7214 UCF_COND_ALLOW_WCARD_LCOMP,
7215 !conn->sconn->using_smb2,
7218 if (!NT_STATUS_IS_OK(status)) {
7223 /* Check the new name has no '/' characters. */
7224 if (strchr_m(newname, '/')) {
7225 return NT_STATUS_NOT_SUPPORTED;
7228 if (fsp && fsp->base_fsp) {
7229 /* newname must be a stream name. */
7230 if (newname[0] != ':') {
7231 return NT_STATUS_NOT_SUPPORTED;
7234 /* Create an smb_fname to call rename_internals_fsp() with. */
7235 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7236 fsp->base_fsp->fsp_name->base_name,
7239 fsp->base_fsp->fsp_name->flags);
7240 if (smb_fname_dst == NULL) {
7241 status = NT_STATUS_NO_MEMORY;
7246 * Set the original last component, since
7247 * rename_internals_fsp() requires it.
7249 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7251 if (smb_fname_dst->original_lcomp == NULL) {
7252 status = NT_STATUS_NO_MEMORY;
7258 * Build up an smb_fname_dst based on the filename passed in.
7259 * We basically just strip off the last component, and put on
7260 * the newname instead.
7262 char *base_name = NULL;
7263 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7264 ucf_flags_from_smb_request(req);
7266 if (dest_has_wcard) {
7267 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7270 /* newname must *not* be a stream name. */
7271 if (newname[0] == ':') {
7272 return NT_STATUS_NOT_SUPPORTED;
7276 * Strip off the last component (filename) of the path passed
7279 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7281 return NT_STATUS_NO_MEMORY;
7283 p = strrchr_m(base_name, '/');
7287 base_name = talloc_strdup(ctx, "");
7289 return NT_STATUS_NO_MEMORY;
7292 /* Append the new name. */
7293 base_name = talloc_asprintf_append(base_name,
7297 return NT_STATUS_NO_MEMORY;
7300 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7303 /* If an error we expect this to be
7304 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7306 if (!NT_STATUS_IS_OK(status)) {
7307 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7311 /* Create an smb_fname to call rename_internals_fsp() */
7312 smb_fname_dst = synthetic_smb_fname(ctx,
7316 smb_fname_src->flags);
7317 if (smb_fname_dst == NULL) {
7318 status = NT_STATUS_NO_MEMORY;
7325 DEBUG(10,("smb_file_rename_information: "
7326 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7327 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7328 smb_fname_str_dbg(smb_fname_dst)));
7329 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7332 DEBUG(10,("smb_file_rename_information: "
7333 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7334 smb_fname_str_dbg(smb_fname_src),
7335 smb_fname_str_dbg(smb_fname_dst)));
7336 status = rename_internals(ctx, conn, req, smb_fname_src,
7337 smb_fname_dst, 0, overwrite, false,
7339 FILE_WRITE_ATTRIBUTES);
7342 TALLOC_FREE(smb_fname_dst);
7346 /****************************************************************************
7347 Deal with SMB_SET_POSIX_ACL.
7348 ****************************************************************************/
7350 #if defined(HAVE_POSIX_ACLS)
7351 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7352 struct smb_request *req,
7356 const struct smb_filename *smb_fname)
7358 uint16_t posix_acl_version;
7359 uint16_t num_file_acls;
7360 uint16_t num_def_acls;
7361 bool valid_file_acls = true;
7362 bool valid_def_acls = true;
7364 unsigned int size_needed;
7365 unsigned int total_data;
7366 bool close_fsp = false;
7368 if (total_data_in < 0) {
7369 status = NT_STATUS_INVALID_PARAMETER;
7373 total_data = total_data_in;
7375 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7376 status = NT_STATUS_INVALID_PARAMETER;
7379 posix_acl_version = SVAL(pdata,0);
7380 num_file_acls = SVAL(pdata,2);
7381 num_def_acls = SVAL(pdata,4);
7383 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7384 valid_file_acls = false;
7388 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7389 valid_def_acls = false;
7393 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7394 status = NT_STATUS_INVALID_PARAMETER;
7399 if (num_file_acls + num_def_acls < num_file_acls) {
7400 status = NT_STATUS_INVALID_PARAMETER;
7404 size_needed = num_file_acls + num_def_acls;
7407 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7408 * than UINT_MAX, so check by division.
7410 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7411 status = NT_STATUS_INVALID_PARAMETER;
7415 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7416 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7417 status = NT_STATUS_INVALID_PARAMETER;
7420 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7422 if (total_data < size_needed) {
7423 status = NT_STATUS_INVALID_PARAMETER;
7428 * Ensure we always operate on a file descriptor, not just
7432 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7434 SEC_STD_READ_CONTROL|
7435 FILE_READ_ATTRIBUTES|
7436 FILE_WRITE_ATTRIBUTES;
7438 status = get_posix_fsp(conn,
7444 if (!NT_STATUS_IS_OK(status)) {
7450 /* Here we know fsp != NULL */
7451 SMB_ASSERT(fsp != NULL);
7453 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7454 if (!NT_STATUS_IS_OK(status)) {
7458 /* If we have a default acl, this *must* be a directory. */
7459 if (valid_def_acls && !fsp->is_directory) {
7460 DBG_INFO("Can't set default acls on "
7461 "non-directory %s\n",
7463 return NT_STATUS_INVALID_HANDLE;
7466 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7467 "num_def_acls = %"PRIu16"\n",
7472 /* Move pdata to the start of the file ACL entries. */
7473 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7475 if (valid_file_acls) {
7476 status = set_unix_posix_acl(conn,
7480 if (!NT_STATUS_IS_OK(status)) {
7485 /* Move pdata to the start of the default ACL entries. */
7486 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7488 if (valid_def_acls) {
7489 status = set_unix_posix_default_acl(conn,
7493 if (!NT_STATUS_IS_OK(status)) {
7498 status = NT_STATUS_OK;
7503 (void)close_file(req, fsp, NORMAL_CLOSE);
7510 /****************************************************************************
7511 Deal with SMB_SET_POSIX_LOCK.
7512 ****************************************************************************/
7514 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7516 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7517 struct smb_request *req,
7522 struct tevent_req *subreq = NULL;
7523 struct smbd_lock_element *lck = NULL;
7527 bool blocking_lock = False;
7528 enum brl_type lock_type;
7530 NTSTATUS status = NT_STATUS_OK;
7532 if (fsp == NULL || fsp->fh->fd == -1) {
7533 return NT_STATUS_INVALID_HANDLE;
7536 if (total_data != POSIX_LOCK_DATA_SIZE) {
7537 return NT_STATUS_INVALID_PARAMETER;
7540 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7541 case POSIX_LOCK_TYPE_READ:
7542 lock_type = READ_LOCK;
7544 case POSIX_LOCK_TYPE_WRITE:
7545 /* Return the right POSIX-mappable error code for files opened read-only. */
7546 if (!fsp->can_write) {
7547 return NT_STATUS_INVALID_HANDLE;
7549 lock_type = WRITE_LOCK;
7551 case POSIX_LOCK_TYPE_UNLOCK:
7552 lock_type = UNLOCK_LOCK;
7555 return NT_STATUS_INVALID_PARAMETER;
7558 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7559 case POSIX_LOCK_FLAG_NOWAIT:
7560 blocking_lock = false;
7562 case POSIX_LOCK_FLAG_WAIT:
7563 blocking_lock = true;
7566 return NT_STATUS_INVALID_PARAMETER;
7569 if (!lp_blocking_locks(SNUM(conn))) {
7570 blocking_lock = False;
7573 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7574 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7575 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7576 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7577 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7579 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7580 "count = %"PRIu64", offset = %"PRIu64"\n",
7582 (unsigned int)lock_type,
7587 if (lock_type == UNLOCK_LOCK) {
7588 struct smbd_lock_element l = {
7590 .brltype = UNLOCK_LOCK,
7594 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7598 lck = talloc(req, struct smbd_lock_element);
7600 return NT_STATUS_NO_MEMORY;
7603 *lck = (struct smbd_lock_element) {
7605 .brltype = lock_type,
7610 subreq = smbd_smb1_do_locks_send(
7613 req->sconn->msg_ctx,
7616 blocking_lock ? UINT32_MAX : 0,
7617 true, /* large_offset */
7621 if (subreq == NULL) {
7623 return NT_STATUS_NO_MEMORY;
7625 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7626 return NT_STATUS_EVENT_PENDING;
7629 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7631 struct smb_request *req = NULL;
7635 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7638 status = smbd_smb1_do_locks_recv(subreq);
7639 TALLOC_FREE(subreq);
7641 if (NT_STATUS_IS_OK(status)) {
7642 char params[2] = {0};
7643 /* Fake up max_data_bytes here - we know it fits. */
7644 send_trans2_replies(
7654 reply_nterror(req, status);
7657 (char *)req->outbuf,
7660 IS_CONN_ENCRYPTED(req->conn),
7663 exit_server_cleanly("smb_set_posix_lock_done: "
7664 "srv_send_smb failed.");
7672 /****************************************************************************
7673 Deal with SMB_SET_FILE_BASIC_INFO.
7674 ****************************************************************************/
7676 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7680 const struct smb_filename *smb_fname)
7682 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7683 struct smb_file_time ft;
7684 uint32_t dosmode = 0;
7685 NTSTATUS status = NT_STATUS_OK;
7689 if (total_data < 36) {
7690 return NT_STATUS_INVALID_PARAMETER;
7693 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7694 if (!NT_STATUS_IS_OK(status)) {
7698 /* Set the attributes */
7699 dosmode = IVAL(pdata,32);
7700 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7701 if (!NT_STATUS_IS_OK(status)) {
7706 ft.create_time = interpret_long_date(pdata);
7709 ft.atime = interpret_long_date(pdata+8);
7712 ft.mtime = interpret_long_date(pdata+16);
7715 ft.ctime = interpret_long_date(pdata+24);
7717 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7718 smb_fname_str_dbg(smb_fname)));
7720 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7724 /****************************************************************************
7725 Deal with SMB_INFO_STANDARD.
7726 ****************************************************************************/
7728 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7732 const struct smb_filename *smb_fname)
7735 struct smb_file_time ft;
7739 if (total_data < 12) {
7740 return NT_STATUS_INVALID_PARAMETER;
7744 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7746 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7748 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7750 DEBUG(10,("smb_set_info_standard: file %s\n",
7751 smb_fname_str_dbg(smb_fname)));
7753 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7754 if (!NT_STATUS_IS_OK(status)) {
7758 return smb_set_file_time(conn,
7765 /****************************************************************************
7766 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7767 ****************************************************************************/
7769 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7770 struct smb_request *req,
7774 struct smb_filename *smb_fname)
7776 uint64_t allocation_size = 0;
7777 NTSTATUS status = NT_STATUS_OK;
7778 files_struct *new_fsp = NULL;
7780 if (!VALID_STAT(smb_fname->st)) {
7781 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7784 if (total_data < 8) {
7785 return NT_STATUS_INVALID_PARAMETER;
7788 allocation_size = (uint64_t)IVAL(pdata,0);
7789 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7790 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7791 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7792 (double)allocation_size));
7794 if (allocation_size) {
7795 allocation_size = smb_roundup(conn, allocation_size);
7798 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7799 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7800 (double)allocation_size));
7802 if (fsp && fsp->fh->fd != -1) {
7803 /* Open file handle. */
7804 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7805 return NT_STATUS_ACCESS_DENIED;
7808 /* Only change if needed. */
7809 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7810 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7811 return map_nt_error_from_unix(errno);
7814 /* But always update the time. */
7816 * This is equivalent to a write. Ensure it's seen immediately
7817 * if there are no pending writes.
7819 trigger_write_time_update_immediate(fsp);
7820 return NT_STATUS_OK;
7823 /* Pathname or stat or directory file. */
7824 status = SMB_VFS_CREATE_FILE(
7827 0, /* root_dir_fid */
7828 smb_fname, /* fname */
7829 FILE_WRITE_DATA, /* access_mask */
7830 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7832 FILE_OPEN, /* create_disposition*/
7833 0, /* create_options */
7834 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7835 0, /* oplock_request */
7837 0, /* allocation_size */
7838 0, /* private_flags */
7841 &new_fsp, /* result */
7843 NULL, NULL); /* create context */
7845 if (!NT_STATUS_IS_OK(status)) {
7846 /* NB. We check for open_was_deferred in the caller. */
7850 /* Only change if needed. */
7851 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7852 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7853 status = map_nt_error_from_unix(errno);
7854 close_file(req, new_fsp, NORMAL_CLOSE);
7859 /* Changing the allocation size should set the last mod time. */
7861 * This is equivalent to a write. Ensure it's seen immediately
7862 * if there are no pending writes.
7864 trigger_write_time_update_immediate(new_fsp);
7865 close_file(req, new_fsp, NORMAL_CLOSE);
7866 return NT_STATUS_OK;
7869 /****************************************************************************
7870 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7871 ****************************************************************************/
7873 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7874 struct smb_request *req,
7878 const struct smb_filename *smb_fname,
7879 bool fail_after_createfile)
7883 if (total_data < 8) {
7884 return NT_STATUS_INVALID_PARAMETER;
7887 size = IVAL(pdata,0);
7888 size |= (((off_t)IVAL(pdata,4)) << 32);
7889 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7890 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7893 return smb_set_file_size(conn, req,
7898 fail_after_createfile);
7901 /****************************************************************************
7902 Allow a UNIX info mknod.
7903 ****************************************************************************/
7905 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7908 const struct smb_filename *smb_fname)
7910 uint32_t file_type = IVAL(pdata,56);
7911 #if defined(HAVE_MAKEDEV)
7912 uint32_t dev_major = IVAL(pdata,60);
7913 uint32_t dev_minor = IVAL(pdata,68);
7915 SMB_DEV_T dev = (SMB_DEV_T)0;
7916 uint32_t raw_unixmode = IVAL(pdata,84);
7920 if (total_data < 100) {
7921 return NT_STATUS_INVALID_PARAMETER;
7924 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7925 PERM_NEW_FILE, &unixmode);
7926 if (!NT_STATUS_IS_OK(status)) {
7930 #if defined(HAVE_MAKEDEV)
7931 dev = makedev(dev_major, dev_minor);
7934 switch (file_type) {
7935 #if defined(S_IFIFO)
7936 case UNIX_TYPE_FIFO:
7937 unixmode |= S_IFIFO;
7940 #if defined(S_IFSOCK)
7941 case UNIX_TYPE_SOCKET:
7942 unixmode |= S_IFSOCK;
7945 #if defined(S_IFCHR)
7946 case UNIX_TYPE_CHARDEV:
7947 unixmode |= S_IFCHR;
7950 #if defined(S_IFBLK)
7951 case UNIX_TYPE_BLKDEV:
7952 unixmode |= S_IFBLK;
7956 return NT_STATUS_INVALID_PARAMETER;
7959 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7960 "%.0f mode 0%o for file %s\n", (double)dev,
7961 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7963 /* Ok - do the mknod. */
7964 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7965 return map_nt_error_from_unix(errno);
7968 /* If any of the other "set" calls fail we
7969 * don't want to end up with a half-constructed mknod.
7972 if (lp_inherit_permissions(SNUM(conn))) {
7974 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7976 return NT_STATUS_NO_MEMORY;
7978 inherit_access_posix_acl(conn, parent, smb_fname,
7980 TALLOC_FREE(parent);
7983 return NT_STATUS_OK;
7986 /****************************************************************************
7987 Deal with SMB_SET_FILE_UNIX_BASIC.
7988 ****************************************************************************/
7990 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7991 struct smb_request *req,
7995 const struct smb_filename *smb_fname)
7997 struct smb_file_time ft;
7998 uint32_t raw_unixmode;
8001 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8002 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8003 NTSTATUS status = NT_STATUS_OK;
8004 bool delete_on_fail = False;
8005 enum perm_type ptype;
8006 files_struct *all_fsps = NULL;
8007 bool modify_mtime = true;
8009 struct smb_filename *smb_fname_tmp = NULL;
8010 SMB_STRUCT_STAT sbuf;
8014 if (total_data < 100) {
8015 return NT_STATUS_INVALID_PARAMETER;
8018 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8019 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8020 size=IVAL(pdata,0); /* first 8 Bytes are size */
8021 size |= (((off_t)IVAL(pdata,4)) << 32);
8024 ft.atime = interpret_long_date(pdata+24); /* access_time */
8025 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
8026 set_owner = (uid_t)IVAL(pdata,40);
8027 set_grp = (gid_t)IVAL(pdata,48);
8028 raw_unixmode = IVAL(pdata,84);
8030 if (VALID_STAT(smb_fname->st)) {
8031 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8032 ptype = PERM_EXISTING_DIR;
8034 ptype = PERM_EXISTING_FILE;
8037 ptype = PERM_NEW_FILE;
8040 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8042 if (!NT_STATUS_IS_OK(status)) {
8046 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8047 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8048 smb_fname_str_dbg(smb_fname), (double)size,
8049 (unsigned int)set_owner, (unsigned int)set_grp,
8050 (int)raw_unixmode));
8052 sbuf = smb_fname->st;
8054 if (!VALID_STAT(sbuf)) {
8056 * The only valid use of this is to create character and block
8057 * devices, and named pipes. This is deprecated (IMHO) and
8058 * a new info level should be used for mknod. JRA.
8061 status = smb_unix_mknod(conn,
8065 if (!NT_STATUS_IS_OK(status)) {
8069 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
8070 if (smb_fname_tmp == NULL) {
8071 return NT_STATUS_NO_MEMORY;
8074 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
8075 status = map_nt_error_from_unix(errno);
8076 TALLOC_FREE(smb_fname_tmp);
8077 SMB_VFS_UNLINK(conn, smb_fname);
8081 sbuf = smb_fname_tmp->st;
8082 smb_fname = smb_fname_tmp;
8084 /* Ensure we don't try and change anything else. */
8085 raw_unixmode = SMB_MODE_NO_CHANGE;
8086 size = get_file_size_stat(&sbuf);
8087 ft.atime = sbuf.st_ex_atime;
8088 ft.mtime = sbuf.st_ex_mtime;
8090 * We continue here as we might want to change the
8093 delete_on_fail = True;
8097 /* Horrible backwards compatibility hack as an old server bug
8098 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8102 size = get_file_size_stat(&sbuf);
8107 * Deal with the UNIX specific mode set.
8110 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8113 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8114 "setting mode 0%o for file %s\n",
8115 (unsigned int)unixmode,
8116 smb_fname_str_dbg(smb_fname)));
8117 if (fsp && fsp->fh->fd != -1) {
8118 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8120 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8123 return map_nt_error_from_unix(errno);
8128 * Deal with the UNIX specific uid set.
8131 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8132 (sbuf.st_ex_uid != set_owner)) {
8135 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8136 "changing owner %u for path %s\n",
8137 (unsigned int)set_owner,
8138 smb_fname_str_dbg(smb_fname)));
8140 if (fsp && fsp->fh->fd != -1) {
8141 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8144 * UNIX extensions calls must always operate
8147 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8148 set_owner, (gid_t)-1);
8152 status = map_nt_error_from_unix(errno);
8153 if (delete_on_fail) {
8154 SMB_VFS_UNLINK(conn, smb_fname);
8161 * Deal with the UNIX specific gid set.
8164 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8165 (sbuf.st_ex_gid != set_grp)) {
8168 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8169 "changing group %u for file %s\n",
8170 (unsigned int)set_grp,
8171 smb_fname_str_dbg(smb_fname)));
8172 if (fsp && fsp->fh->fd != -1) {
8173 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8176 * UNIX extensions calls must always operate
8179 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8183 status = map_nt_error_from_unix(errno);
8184 if (delete_on_fail) {
8185 SMB_VFS_UNLINK(conn, smb_fname);
8191 /* Deal with any size changes. */
8193 status = smb_set_file_size(conn, req,
8199 if (!NT_STATUS_IS_OK(status)) {
8203 /* Deal with any time changes. */
8204 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
8205 /* No change, don't cancel anything. */
8209 id = vfs_file_id_from_sbuf(conn, &sbuf);
8210 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8211 all_fsps = file_find_di_next(all_fsps)) {
8213 * We're setting the time explicitly for UNIX.
8214 * Cancel any pending changes over all handles.
8216 all_fsps->update_write_time_on_close = false;
8217 TALLOC_FREE(all_fsps->update_write_time_event);
8221 * Override the "setting_write_time"
8222 * parameter here as it almost does what
8223 * we need. Just remember if we modified
8224 * mtime and send the notify ourselves.
8226 if (null_timespec(ft.mtime)) {
8227 modify_mtime = false;
8230 status = smb_set_file_time(conn,
8236 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8237 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8242 /****************************************************************************
8243 Deal with SMB_SET_FILE_UNIX_INFO2.
8244 ****************************************************************************/
8246 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8247 struct smb_request *req,
8251 const struct smb_filename *smb_fname)
8254 uint32_t smb_fflags;
8257 if (total_data < 116) {
8258 return NT_STATUS_INVALID_PARAMETER;
8261 /* Start by setting all the fields that are common between UNIX_BASIC
8264 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8266 if (!NT_STATUS_IS_OK(status)) {
8270 smb_fflags = IVAL(pdata, 108);
8271 smb_fmask = IVAL(pdata, 112);
8273 /* NB: We should only attempt to alter the file flags if the client
8274 * sends a non-zero mask.
8276 if (smb_fmask != 0) {
8277 int stat_fflags = 0;
8279 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8280 smb_fmask, &stat_fflags)) {
8281 /* Client asked to alter a flag we don't understand. */
8282 return NT_STATUS_INVALID_PARAMETER;
8285 if (fsp && fsp->fh->fd != -1) {
8286 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8287 return NT_STATUS_NOT_SUPPORTED;
8289 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8290 stat_fflags) != 0) {
8291 return map_nt_error_from_unix(errno);
8296 /* XXX: need to add support for changing the create_time here. You
8297 * can do this for paths on Darwin with setattrlist(2). The right way
8298 * to hook this up is probably by extending the VFS utimes interface.
8301 return NT_STATUS_OK;
8304 /****************************************************************************
8305 Create a directory with POSIX semantics.
8306 ****************************************************************************/
8308 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8309 struct smb_request *req,
8312 struct smb_filename *smb_fname,
8313 int *pdata_return_size)
8315 NTSTATUS status = NT_STATUS_OK;
8316 uint32_t raw_unixmode = 0;
8317 uint32_t mod_unixmode = 0;
8318 mode_t unixmode = (mode_t)0;
8319 files_struct *fsp = NULL;
8320 uint16_t info_level_return = 0;
8322 char *pdata = *ppdata;
8324 if (total_data < 18) {
8325 return NT_STATUS_INVALID_PARAMETER;
8328 raw_unixmode = IVAL(pdata,8);
8329 /* Next 4 bytes are not yet defined. */
8331 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8332 PERM_NEW_DIR, &unixmode);
8333 if (!NT_STATUS_IS_OK(status)) {
8337 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8339 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8340 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8342 status = SMB_VFS_CREATE_FILE(
8345 0, /* root_dir_fid */
8346 smb_fname, /* fname */
8347 FILE_READ_ATTRIBUTES, /* access_mask */
8348 FILE_SHARE_NONE, /* share_access */
8349 FILE_CREATE, /* create_disposition*/
8350 FILE_DIRECTORY_FILE, /* create_options */
8351 mod_unixmode, /* file_attributes */
8352 0, /* oplock_request */
8354 0, /* allocation_size */
8355 0, /* private_flags */
8360 NULL, NULL); /* create context */
8362 if (NT_STATUS_IS_OK(status)) {
8363 close_file(req, fsp, NORMAL_CLOSE);
8366 info_level_return = SVAL(pdata,16);
8368 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8369 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8370 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8371 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8373 *pdata_return_size = 12;
8376 /* Realloc the data size */
8377 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8378 if (*ppdata == NULL) {
8379 *pdata_return_size = 0;
8380 return NT_STATUS_NO_MEMORY;
8384 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8385 SSVAL(pdata,2,0); /* No fnum. */
8386 SIVAL(pdata,4,info); /* Was directory created. */
8388 switch (info_level_return) {
8389 case SMB_QUERY_FILE_UNIX_BASIC:
8390 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8391 SSVAL(pdata,10,0); /* Padding. */
8392 store_file_unix_basic(conn, pdata + 12, fsp,
8395 case SMB_QUERY_FILE_UNIX_INFO2:
8396 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8397 SSVAL(pdata,10,0); /* Padding. */
8398 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8402 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8403 SSVAL(pdata,10,0); /* Padding. */
8410 /****************************************************************************
8411 Open/Create a file with POSIX semantics.
8412 ****************************************************************************/
8414 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8415 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8417 static NTSTATUS smb_posix_open(connection_struct *conn,
8418 struct smb_request *req,
8421 struct smb_filename *smb_fname,
8422 int *pdata_return_size)
8424 bool extended_oplock_granted = False;
8425 char *pdata = *ppdata;
8427 uint32_t wire_open_mode = 0;
8428 uint32_t raw_unixmode = 0;
8429 uint32_t mod_unixmode = 0;
8430 uint32_t create_disp = 0;
8431 uint32_t access_mask = 0;
8432 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8433 NTSTATUS status = NT_STATUS_OK;
8434 mode_t unixmode = (mode_t)0;
8435 files_struct *fsp = NULL;
8436 int oplock_request = 0;
8438 uint16_t info_level_return = 0;
8440 if (total_data < 18) {
8441 return NT_STATUS_INVALID_PARAMETER;
8444 flags = IVAL(pdata,0);
8445 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8446 if (oplock_request) {
8447 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8450 wire_open_mode = IVAL(pdata,4);
8452 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8453 return smb_posix_mkdir(conn, req,
8460 switch (wire_open_mode & SMB_ACCMODE) {
8462 access_mask = SMB_O_RDONLY_MAPPING;
8465 access_mask = SMB_O_WRONLY_MAPPING;
8468 access_mask = (SMB_O_RDONLY_MAPPING|
8469 SMB_O_WRONLY_MAPPING);
8472 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8473 (unsigned int)wire_open_mode ));
8474 return NT_STATUS_INVALID_PARAMETER;
8477 wire_open_mode &= ~SMB_ACCMODE;
8479 /* First take care of O_CREAT|O_EXCL interactions. */
8480 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8481 case (SMB_O_CREAT | SMB_O_EXCL):
8482 /* File exists fail. File not exist create. */
8483 create_disp = FILE_CREATE;
8486 /* File exists open. File not exist create. */
8487 create_disp = FILE_OPEN_IF;
8490 /* O_EXCL on its own without O_CREAT is undefined.
8491 We deliberately ignore it as some versions of
8492 Linux CIFSFS can send a bare O_EXCL on the
8493 wire which other filesystems in the kernel
8494 ignore. See bug 9519 for details. */
8499 /* File exists open. File not exist fail. */
8500 create_disp = FILE_OPEN;
8503 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8504 (unsigned int)wire_open_mode ));
8505 return NT_STATUS_INVALID_PARAMETER;
8508 /* Next factor in the effects of O_TRUNC. */
8509 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8511 if (wire_open_mode & SMB_O_TRUNC) {
8512 switch (create_disp) {
8514 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8515 /* Leave create_disp alone as
8516 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8518 /* File exists fail. File not exist create. */
8521 /* SMB_O_CREAT | SMB_O_TRUNC */
8522 /* File exists overwrite. File not exist create. */
8523 create_disp = FILE_OVERWRITE_IF;
8527 /* File exists overwrite. File not exist fail. */
8528 create_disp = FILE_OVERWRITE;
8531 /* Cannot get here. */
8532 smb_panic("smb_posix_open: logic error");
8533 return NT_STATUS_INVALID_PARAMETER;
8537 raw_unixmode = IVAL(pdata,8);
8538 /* Next 4 bytes are not yet defined. */
8540 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8541 (VALID_STAT(smb_fname->st) ?
8542 PERM_EXISTING_FILE : PERM_NEW_FILE),
8545 if (!NT_STATUS_IS_OK(status)) {
8549 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8551 if (wire_open_mode & SMB_O_SYNC) {
8552 create_options |= FILE_WRITE_THROUGH;
8554 if (wire_open_mode & SMB_O_APPEND) {
8555 access_mask |= FILE_APPEND_DATA;
8557 if (wire_open_mode & SMB_O_DIRECT) {
8558 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8561 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8562 VALID_STAT_OF_DIR(smb_fname->st)) {
8563 if (access_mask != SMB_O_RDONLY_MAPPING) {
8564 return NT_STATUS_FILE_IS_A_DIRECTORY;
8566 create_options &= ~FILE_NON_DIRECTORY_FILE;
8567 create_options |= FILE_DIRECTORY_FILE;
8570 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8571 smb_fname_str_dbg(smb_fname),
8572 (unsigned int)wire_open_mode,
8573 (unsigned int)unixmode ));
8575 status = SMB_VFS_CREATE_FILE(
8578 0, /* root_dir_fid */
8579 smb_fname, /* fname */
8580 access_mask, /* access_mask */
8581 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8583 create_disp, /* create_disposition*/
8584 create_options, /* create_options */
8585 mod_unixmode, /* file_attributes */
8586 oplock_request, /* oplock_request */
8588 0, /* allocation_size */
8589 0, /* private_flags */
8594 NULL, NULL); /* create context */
8596 if (!NT_STATUS_IS_OK(status)) {
8600 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8601 extended_oplock_granted = True;
8604 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8605 extended_oplock_granted = True;
8608 info_level_return = SVAL(pdata,16);
8610 /* Allocate the correct return size. */
8612 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8613 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8614 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8615 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8617 *pdata_return_size = 12;
8620 /* Realloc the data size */
8621 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8622 if (*ppdata == NULL) {
8623 close_file(req, fsp, ERROR_CLOSE);
8624 *pdata_return_size = 0;
8625 return NT_STATUS_NO_MEMORY;
8629 if (extended_oplock_granted) {
8630 if (flags & REQUEST_BATCH_OPLOCK) {
8631 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8633 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8635 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8636 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8638 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8641 SSVAL(pdata,2,fsp->fnum);
8642 SIVAL(pdata,4,info); /* Was file created etc. */
8644 switch (info_level_return) {
8645 case SMB_QUERY_FILE_UNIX_BASIC:
8646 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8647 SSVAL(pdata,10,0); /* padding. */
8648 store_file_unix_basic(conn, pdata + 12, fsp,
8651 case SMB_QUERY_FILE_UNIX_INFO2:
8652 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8653 SSVAL(pdata,10,0); /* padding. */
8654 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8658 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8659 SSVAL(pdata,10,0); /* padding. */
8662 return NT_STATUS_OK;
8665 /****************************************************************************
8666 Delete a file with POSIX semantics.
8667 ****************************************************************************/
8669 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8670 struct smb_request *req,
8673 struct smb_filename *smb_fname)
8675 struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
8676 NTSTATUS status = NT_STATUS_OK;
8677 files_struct *fsp = NULL;
8681 int create_options = 0;
8682 struct share_mode_lock *lck = NULL;
8683 bool other_nonposix_opens;
8685 if (total_data < 2) {
8686 return NT_STATUS_INVALID_PARAMETER;
8689 flags = SVAL(pdata,0);
8691 if (!VALID_STAT(smb_fname->st)) {
8692 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8695 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8696 !VALID_STAT_OF_DIR(smb_fname->st)) {
8697 return NT_STATUS_NOT_A_DIRECTORY;
8700 DEBUG(10,("smb_posix_unlink: %s %s\n",
8701 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8702 smb_fname_str_dbg(smb_fname)));
8704 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8705 create_options |= FILE_DIRECTORY_FILE;
8708 status = SMB_VFS_CREATE_FILE(
8711 0, /* root_dir_fid */
8712 smb_fname, /* fname */
8713 DELETE_ACCESS, /* access_mask */
8714 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8716 FILE_OPEN, /* create_disposition*/
8717 create_options, /* create_options */
8718 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8719 0, /* oplock_request */
8721 0, /* allocation_size */
8722 0, /* private_flags */
8727 NULL, NULL); /* create context */
8729 if (!NT_STATUS_IS_OK(status)) {
8734 * Don't lie to client. If we can't really delete due to
8735 * non-POSIX opens return SHARING_VIOLATION.
8738 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8740 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8741 "lock for file %s\n", fsp_str_dbg(fsp)));
8742 close_file(req, fsp, NORMAL_CLOSE);
8743 return NT_STATUS_INVALID_PARAMETER;
8746 other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
8747 if (other_nonposix_opens) {
8748 /* Fail with sharing violation. */
8750 close_file(req, fsp, NORMAL_CLOSE);
8751 return NT_STATUS_SHARING_VIOLATION;
8755 * Set the delete on close.
8757 status = smb_set_file_disposition_info(conn,
8765 if (!NT_STATUS_IS_OK(status)) {
8766 close_file(req, fsp, NORMAL_CLOSE);
8769 return close_file(req, fsp, NORMAL_CLOSE);
8772 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8773 struct smb_request *req,
8774 TALLOC_CTX *mem_ctx,
8775 uint16_t info_level,
8777 struct smb_filename *smb_fname,
8778 char **ppdata, int total_data,
8781 char *pdata = *ppdata;
8782 NTSTATUS status = NT_STATUS_OK;
8783 int data_return_size = 0;
8787 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8788 return NT_STATUS_INVALID_LEVEL;
8791 if (!CAN_WRITE(conn)) {
8792 /* Allow POSIX opens. The open path will deny
8793 * any non-readonly opens. */
8794 if (info_level != SMB_POSIX_PATH_OPEN) {
8795 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8799 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8800 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8802 info_level, total_data));
8804 switch (info_level) {
8806 case SMB_INFO_STANDARD:
8808 status = smb_set_info_standard(conn,
8816 case SMB_INFO_SET_EA:
8818 status = smb_info_set_ea(conn,
8826 case SMB_SET_FILE_BASIC_INFO:
8827 case SMB_FILE_BASIC_INFORMATION:
8829 status = smb_set_file_basic_info(conn,
8837 case SMB_FILE_ALLOCATION_INFORMATION:
8838 case SMB_SET_FILE_ALLOCATION_INFO:
8840 status = smb_set_file_allocation_info(conn, req,
8848 case SMB_FILE_END_OF_FILE_INFORMATION:
8849 case SMB_SET_FILE_END_OF_FILE_INFO:
8852 * XP/Win7 both fail after the createfile with
8853 * SMB_SET_FILE_END_OF_FILE_INFO but not
8854 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8855 * The level is known here, so pass it down
8859 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8861 status = smb_set_file_end_of_file_info(conn, req,
8870 case SMB_FILE_DISPOSITION_INFORMATION:
8871 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8874 /* JRA - We used to just ignore this on a path ?
8875 * Shouldn't this be invalid level on a pathname
8878 if (tran_call != TRANSACT2_SETFILEINFO) {
8879 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8882 status = smb_set_file_disposition_info(conn,
8890 case SMB_FILE_POSITION_INFORMATION:
8892 status = smb_file_position_information(conn,
8899 case SMB_FILE_FULL_EA_INFORMATION:
8901 status = smb_set_file_full_ea_info(conn,
8908 /* From tridge Samba4 :
8909 * MODE_INFORMATION in setfileinfo (I have no
8910 * idea what "mode information" on a file is - it takes a value of 0,
8911 * 2, 4 or 6. What could it be?).
8914 case SMB_FILE_MODE_INFORMATION:
8916 status = smb_file_mode_information(conn,
8922 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8923 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8924 case SMB_FILE_SHORT_NAME_INFORMATION:
8925 return NT_STATUS_NOT_SUPPORTED;
8928 * CIFS UNIX extensions.
8931 case SMB_SET_FILE_UNIX_BASIC:
8933 status = smb_set_file_unix_basic(conn, req,
8941 case SMB_SET_FILE_UNIX_INFO2:
8943 status = smb_set_file_unix_info2(conn, req,
8951 case SMB_SET_FILE_UNIX_LINK:
8954 /* We must have a pathname for this. */
8955 return NT_STATUS_INVALID_LEVEL;
8957 status = smb_set_file_unix_link(conn, req, pdata,
8958 total_data, smb_fname);
8962 case SMB_SET_FILE_UNIX_HLINK:
8965 /* We must have a pathname for this. */
8966 return NT_STATUS_INVALID_LEVEL;
8968 status = smb_set_file_unix_hlink(conn, req,
8974 case SMB_FILE_RENAME_INFORMATION:
8976 status = smb_file_rename_information(conn, req,
8982 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8984 /* SMB2 rename information. */
8985 status = smb2_file_rename_information(conn, req,
8991 case SMB_FILE_LINK_INFORMATION:
8993 status = smb_file_link_information(conn, req,
8999 #if defined(HAVE_POSIX_ACLS)
9000 case SMB_SET_POSIX_ACL:
9002 status = smb_set_posix_acl(conn,
9012 case SMB_SET_POSIX_LOCK:
9015 return NT_STATUS_INVALID_LEVEL;
9017 status = smb_set_posix_lock(conn, req,
9018 pdata, total_data, fsp);
9022 case SMB_POSIX_PATH_OPEN:
9025 /* We must have a pathname for this. */
9026 return NT_STATUS_INVALID_LEVEL;
9029 status = smb_posix_open(conn, req,
9037 case SMB_POSIX_PATH_UNLINK:
9040 /* We must have a pathname for this. */
9041 return NT_STATUS_INVALID_LEVEL;
9044 status = smb_posix_unlink(conn, req,
9052 return NT_STATUS_INVALID_LEVEL;
9055 if (!NT_STATUS_IS_OK(status)) {
9059 *ret_data_size = data_return_size;
9060 return NT_STATUS_OK;
9063 /****************************************************************************
9064 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9065 ****************************************************************************/
9067 static void call_trans2setfilepathinfo(connection_struct *conn,
9068 struct smb_request *req,
9069 unsigned int tran_call,
9070 char **pparams, int total_params,
9071 char **ppdata, int total_data,
9072 unsigned int max_data_bytes)
9074 char *params = *pparams;
9075 char *pdata = *ppdata;
9076 uint16_t info_level;
9077 struct smb_filename *smb_fname = NULL;
9078 files_struct *fsp = NULL;
9079 NTSTATUS status = NT_STATUS_OK;
9080 int data_return_size = 0;
9083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9087 if (tran_call == TRANSACT2_SETFILEINFO) {
9088 if (total_params < 4) {
9089 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9093 fsp = file_fsp(req, SVAL(params,0));
9094 /* Basic check for non-null fsp. */
9095 if (!check_fsp_open(conn, req, fsp)) {
9098 info_level = SVAL(params,2);
9100 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9101 if (smb_fname == NULL) {
9102 reply_nterror(req, NT_STATUS_NO_MEMORY);
9106 if(fsp->fh->fd == -1) {
9108 * This is actually a SETFILEINFO on a directory
9109 * handle (returned from an NT SMB). NT5.0 seems
9110 * to do this call. JRA.
9112 if (INFO_LEVEL_IS_UNIX(info_level)) {
9113 /* Always do lstat for UNIX calls. */
9114 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9115 DEBUG(3,("call_trans2setfilepathinfo: "
9116 "SMB_VFS_LSTAT of %s failed "
9118 smb_fname_str_dbg(smb_fname),
9120 reply_nterror(req, map_nt_error_from_unix(errno));
9124 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9125 DEBUG(3,("call_trans2setfilepathinfo: "
9126 "fileinfo of %s failed (%s)\n",
9127 smb_fname_str_dbg(smb_fname),
9129 reply_nterror(req, map_nt_error_from_unix(errno));
9133 } else if (fsp->print_file) {
9135 * Doing a DELETE_ON_CLOSE should cancel a print job.
9137 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9138 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9140 DEBUG(3,("call_trans2setfilepathinfo: "
9141 "Cancelling print job (%s)\n",
9145 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9151 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9156 * Original code - this is an open file.
9158 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9159 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9160 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9162 reply_nterror(req, map_nt_error_from_unix(errno));
9168 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9171 if (total_params < 7) {
9172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9176 info_level = SVAL(params,0);
9177 if (req->posix_pathnames) {
9178 srvstr_get_path_posix(req,
9187 srvstr_get_path(req,
9196 if (!NT_STATUS_IS_OK(status)) {
9197 reply_nterror(req, status);
9201 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9202 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9203 info_level == SMB_FILE_RENAME_INFORMATION ||
9204 info_level == SMB_POSIX_PATH_OPEN ||
9205 info_level == SMB_POSIX_PATH_UNLINK) {
9206 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9209 status = filename_convert(req, conn,
9215 if (!NT_STATUS_IS_OK(status)) {
9216 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9217 reply_botherror(req,
9218 NT_STATUS_PATH_NOT_COVERED,
9219 ERRSRV, ERRbadpath);
9222 reply_nterror(req, status);
9226 if (INFO_LEVEL_IS_UNIX(info_level)) {
9228 * For CIFS UNIX extensions the target name may not exist.
9231 /* Always do lstat for UNIX calls. */
9232 SMB_VFS_LSTAT(conn, smb_fname);
9234 } else if (!VALID_STAT(smb_fname->st) &&
9235 SMB_VFS_STAT(conn, smb_fname)) {
9236 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9238 smb_fname_str_dbg(smb_fname),
9240 reply_nterror(req, map_nt_error_from_unix(errno));
9245 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9246 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9248 info_level,total_data));
9250 /* Realloc the parameter size */
9251 *pparams = (char *)SMB_REALLOC(*pparams,2);
9252 if (*pparams == NULL) {
9253 reply_nterror(req, NT_STATUS_NO_MEMORY);
9260 status = smbd_do_setfilepathinfo(conn, req, req,
9266 if (!NT_STATUS_IS_OK(status)) {
9267 if (open_was_deferred(req->xconn, req->mid)) {
9268 /* We have re-scheduled this call. */
9271 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9272 /* We have re-scheduled this call. */
9275 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9276 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9277 ERRSRV, ERRbadpath);
9280 if (info_level == SMB_POSIX_PATH_OPEN) {
9281 reply_openerror(req, status);
9286 * Invalid EA name needs to return 2 param bytes,
9287 * not a zero-length error packet.
9289 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9290 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9293 reply_nterror(req, status);
9298 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9304 /****************************************************************************
9305 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9306 ****************************************************************************/
9308 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9309 char **pparams, int total_params,
9310 char **ppdata, int total_data,
9311 unsigned int max_data_bytes)
9313 struct smb_filename *smb_dname = NULL;
9314 char *params = *pparams;
9315 char *pdata = *ppdata;
9316 char *directory = NULL;
9317 NTSTATUS status = NT_STATUS_OK;
9318 struct ea_list *ea_list = NULL;
9319 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9320 TALLOC_CTX *ctx = talloc_tos();
9322 if (!CAN_WRITE(conn)) {
9323 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9327 if (total_params < 5) {
9328 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9332 if (req->posix_pathnames) {
9333 srvstr_get_path_posix(ctx,
9342 srvstr_get_path(ctx,
9351 if (!NT_STATUS_IS_OK(status)) {
9352 reply_nterror(req, status);
9356 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9358 status = filename_convert(ctx,
9366 if (!NT_STATUS_IS_OK(status)) {
9367 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9368 reply_botherror(req,
9369 NT_STATUS_PATH_NOT_COVERED,
9370 ERRSRV, ERRbadpath);
9373 reply_nterror(req, status);
9378 * OS/2 workplace shell seems to send SET_EA requests of "null"
9379 * length (4 bytes containing IVAL 4).
9380 * They seem to have no effect. Bug #3212. JRA.
9383 if (total_data && (total_data != 4)) {
9384 /* Any data in this call is an EA list. */
9385 if (total_data < 10) {
9386 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9390 if (IVAL(pdata,0) > total_data) {
9391 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9392 IVAL(pdata,0), (unsigned int)total_data));
9393 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9397 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9404 if (!lp_ea_support(SNUM(conn))) {
9405 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9409 /* If total_data == 4 Windows doesn't care what values
9410 * are placed in that field, it just ignores them.
9411 * The System i QNTC IBM SMB client puts bad values here,
9412 * so ignore them. */
9414 status = create_directory(conn, req, smb_dname);
9416 if (!NT_STATUS_IS_OK(status)) {
9417 reply_nterror(req, status);
9421 /* Try and set any given EA. */
9423 status = set_ea(conn, NULL, smb_dname, ea_list);
9424 if (!NT_STATUS_IS_OK(status)) {
9425 reply_nterror(req, status);
9430 /* Realloc the parameter and data sizes */
9431 *pparams = (char *)SMB_REALLOC(*pparams,2);
9432 if(*pparams == NULL) {
9433 reply_nterror(req, NT_STATUS_NO_MEMORY);
9440 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9443 TALLOC_FREE(smb_dname);
9447 /****************************************************************************
9448 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9449 We don't actually do this - we just send a null response.
9450 ****************************************************************************/
9452 static void call_trans2findnotifyfirst(connection_struct *conn,
9453 struct smb_request *req,
9454 char **pparams, int total_params,
9455 char **ppdata, int total_data,
9456 unsigned int max_data_bytes)
9458 char *params = *pparams;
9459 uint16_t info_level;
9461 if (total_params < 6) {
9462 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9466 info_level = SVAL(params,4);
9467 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9469 switch (info_level) {
9474 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9478 /* Realloc the parameter and data sizes */
9479 *pparams = (char *)SMB_REALLOC(*pparams,6);
9480 if (*pparams == NULL) {
9481 reply_nterror(req, NT_STATUS_NO_MEMORY);
9486 SSVAL(params,0,fnf_handle);
9487 SSVAL(params,2,0); /* No changes */
9488 SSVAL(params,4,0); /* No EA errors */
9495 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9500 /****************************************************************************
9501 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9502 changes). Currently this does nothing.
9503 ****************************************************************************/
9505 static void call_trans2findnotifynext(connection_struct *conn,
9506 struct smb_request *req,
9507 char **pparams, int total_params,
9508 char **ppdata, int total_data,
9509 unsigned int max_data_bytes)
9511 char *params = *pparams;
9513 DEBUG(3,("call_trans2findnotifynext\n"));
9515 /* Realloc the parameter and data sizes */
9516 *pparams = (char *)SMB_REALLOC(*pparams,4);
9517 if (*pparams == NULL) {
9518 reply_nterror(req, NT_STATUS_NO_MEMORY);
9523 SSVAL(params,0,0); /* No changes */
9524 SSVAL(params,2,0); /* No EA errors */
9526 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9531 /****************************************************************************
9532 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9533 ****************************************************************************/
9535 static void call_trans2getdfsreferral(connection_struct *conn,
9536 struct smb_request *req,
9537 char **pparams, int total_params,
9538 char **ppdata, int total_data,
9539 unsigned int max_data_bytes)
9541 char *params = *pparams;
9542 char *pathname = NULL;
9544 int max_referral_level;
9545 NTSTATUS status = NT_STATUS_OK;
9546 TALLOC_CTX *ctx = talloc_tos();
9548 DEBUG(10,("call_trans2getdfsreferral\n"));
9550 if (total_params < 3) {
9551 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9555 max_referral_level = SVAL(params,0);
9557 if(!lp_host_msdfs()) {
9558 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9562 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9563 total_params - 2, STR_TERMINATE);
9565 reply_nterror(req, NT_STATUS_NOT_FOUND);
9568 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9569 ppdata,&status)) < 0) {
9570 reply_nterror(req, status);
9574 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9575 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9576 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9581 #define LMCAT_SPL 0x53
9582 #define LMFUNC_GETJOBID 0x60
9584 /****************************************************************************
9585 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9586 ****************************************************************************/
9588 static void call_trans2ioctl(connection_struct *conn,
9589 struct smb_request *req,
9590 char **pparams, int total_params,
9591 char **ppdata, int total_data,
9592 unsigned int max_data_bytes)
9594 char *pdata = *ppdata;
9595 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9599 /* check for an invalid fid before proceeding */
9602 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9606 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9607 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9608 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9609 if (*ppdata == NULL) {
9610 reply_nterror(req, NT_STATUS_NO_MEMORY);
9615 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9616 CAN ACCEPT THIS IN UNICODE. JRA. */
9619 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9621 status = srvstr_push(pdata, req->flags2, pdata + 2,
9622 lp_netbios_name(), 15,
9623 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9624 if (!NT_STATUS_IS_OK(status)) {
9625 reply_nterror(req, status);
9628 status = srvstr_push(pdata, req->flags2, pdata+18,
9629 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9630 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9631 if (!NT_STATUS_IS_OK(status)) {
9632 reply_nterror(req, status);
9635 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9640 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9641 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9644 /****************************************************************************
9645 Reply to a SMBfindclose (stop trans2 directory search).
9646 ****************************************************************************/
9648 void reply_findclose(struct smb_request *req)
9651 struct smbd_server_connection *sconn = req->sconn;
9653 START_PROFILE(SMBfindclose);
9656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9657 END_PROFILE(SMBfindclose);
9661 dptr_num = SVALS(req->vwv+0, 0);
9663 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9665 dptr_close(sconn, &dptr_num);
9667 reply_outbuf(req, 0, 0);
9669 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9671 END_PROFILE(SMBfindclose);
9675 /****************************************************************************
9676 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9677 ****************************************************************************/
9679 void reply_findnclose(struct smb_request *req)
9683 START_PROFILE(SMBfindnclose);
9686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9687 END_PROFILE(SMBfindnclose);
9691 dptr_num = SVAL(req->vwv+0, 0);
9693 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9695 /* We never give out valid handles for a
9696 findnotifyfirst - so any dptr_num is ok here.
9699 reply_outbuf(req, 0, 0);
9701 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9703 END_PROFILE(SMBfindnclose);
9707 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9708 struct trans_state *state)
9710 if (get_Protocol() >= PROTOCOL_NT1) {
9711 req->flags2 |= 0x40; /* IS_LONG_NAME */
9712 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9715 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9716 if (state->call != TRANSACT2_QFSINFO &&
9717 state->call != TRANSACT2_SETFSINFO) {
9718 DEBUG(0,("handle_trans2: encryption required "
9720 (unsigned int)state->call));
9721 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9726 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9728 /* Now we must call the relevant TRANS2 function */
9729 switch(state->call) {
9730 case TRANSACT2_OPEN:
9732 START_PROFILE(Trans2_open);
9733 call_trans2open(conn, req,
9734 &state->param, state->total_param,
9735 &state->data, state->total_data,
9736 state->max_data_return);
9737 END_PROFILE(Trans2_open);
9741 case TRANSACT2_FINDFIRST:
9743 START_PROFILE(Trans2_findfirst);
9744 call_trans2findfirst(conn, req,
9745 &state->param, state->total_param,
9746 &state->data, state->total_data,
9747 state->max_data_return);
9748 END_PROFILE(Trans2_findfirst);
9752 case TRANSACT2_FINDNEXT:
9754 START_PROFILE(Trans2_findnext);
9755 call_trans2findnext(conn, req,
9756 &state->param, state->total_param,
9757 &state->data, state->total_data,
9758 state->max_data_return);
9759 END_PROFILE(Trans2_findnext);
9763 case TRANSACT2_QFSINFO:
9765 START_PROFILE(Trans2_qfsinfo);
9766 call_trans2qfsinfo(conn, req,
9767 &state->param, state->total_param,
9768 &state->data, state->total_data,
9769 state->max_data_return);
9770 END_PROFILE(Trans2_qfsinfo);
9774 case TRANSACT2_SETFSINFO:
9776 START_PROFILE(Trans2_setfsinfo);
9777 call_trans2setfsinfo(conn, req,
9778 &state->param, state->total_param,
9779 &state->data, state->total_data,
9780 state->max_data_return);
9781 END_PROFILE(Trans2_setfsinfo);
9785 case TRANSACT2_QPATHINFO:
9786 case TRANSACT2_QFILEINFO:
9788 START_PROFILE(Trans2_qpathinfo);
9789 call_trans2qfilepathinfo(conn, req, state->call,
9790 &state->param, state->total_param,
9791 &state->data, state->total_data,
9792 state->max_data_return);
9793 END_PROFILE(Trans2_qpathinfo);
9797 case TRANSACT2_SETPATHINFO:
9798 case TRANSACT2_SETFILEINFO:
9800 START_PROFILE(Trans2_setpathinfo);
9801 call_trans2setfilepathinfo(conn, req, state->call,
9802 &state->param, state->total_param,
9803 &state->data, state->total_data,
9804 state->max_data_return);
9805 END_PROFILE(Trans2_setpathinfo);
9809 case TRANSACT2_FINDNOTIFYFIRST:
9811 START_PROFILE(Trans2_findnotifyfirst);
9812 call_trans2findnotifyfirst(conn, req,
9813 &state->param, state->total_param,
9814 &state->data, state->total_data,
9815 state->max_data_return);
9816 END_PROFILE(Trans2_findnotifyfirst);
9820 case TRANSACT2_FINDNOTIFYNEXT:
9822 START_PROFILE(Trans2_findnotifynext);
9823 call_trans2findnotifynext(conn, req,
9824 &state->param, state->total_param,
9825 &state->data, state->total_data,
9826 state->max_data_return);
9827 END_PROFILE(Trans2_findnotifynext);
9831 case TRANSACT2_MKDIR:
9833 START_PROFILE(Trans2_mkdir);
9834 call_trans2mkdir(conn, req,
9835 &state->param, state->total_param,
9836 &state->data, state->total_data,
9837 state->max_data_return);
9838 END_PROFILE(Trans2_mkdir);
9842 case TRANSACT2_GET_DFS_REFERRAL:
9844 START_PROFILE(Trans2_get_dfs_referral);
9845 call_trans2getdfsreferral(conn, req,
9846 &state->param, state->total_param,
9847 &state->data, state->total_data,
9848 state->max_data_return);
9849 END_PROFILE(Trans2_get_dfs_referral);
9853 case TRANSACT2_IOCTL:
9855 START_PROFILE(Trans2_ioctl);
9856 call_trans2ioctl(conn, req,
9857 &state->param, state->total_param,
9858 &state->data, state->total_data,
9859 state->max_data_return);
9860 END_PROFILE(Trans2_ioctl);
9865 /* Error in request */
9866 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9867 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9871 /****************************************************************************
9872 Reply to a SMBtrans2.
9873 ****************************************************************************/
9875 void reply_trans2(struct smb_request *req)
9877 connection_struct *conn = req->conn;
9882 unsigned int tran_call;
9883 struct trans_state *state;
9886 START_PROFILE(SMBtrans2);
9888 if (req->wct < 14) {
9889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9890 END_PROFILE(SMBtrans2);
9894 dsoff = SVAL(req->vwv+12, 0);
9895 dscnt = SVAL(req->vwv+11, 0);
9896 psoff = SVAL(req->vwv+10, 0);
9897 pscnt = SVAL(req->vwv+9, 0);
9898 tran_call = SVAL(req->vwv+14, 0);
9900 result = allow_new_trans(conn->pending_trans, req->mid);
9901 if (!NT_STATUS_IS_OK(result)) {
9902 DEBUG(2, ("Got invalid trans2 request: %s\n",
9903 nt_errstr(result)));
9904 reply_nterror(req, result);
9905 END_PROFILE(SMBtrans2);
9910 switch (tran_call) {
9911 /* List the allowed trans2 calls on IPC$ */
9912 case TRANSACT2_OPEN:
9913 case TRANSACT2_GET_DFS_REFERRAL:
9914 case TRANSACT2_QFILEINFO:
9915 case TRANSACT2_QFSINFO:
9916 case TRANSACT2_SETFSINFO:
9919 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9920 END_PROFILE(SMBtrans2);
9925 if ((state = talloc(conn, struct trans_state)) == NULL) {
9926 DEBUG(0, ("talloc failed\n"));
9927 reply_nterror(req, NT_STATUS_NO_MEMORY);
9928 END_PROFILE(SMBtrans2);
9932 state->cmd = SMBtrans2;
9934 state->mid = req->mid;
9935 state->vuid = req->vuid;
9936 state->setup_count = SVAL(req->vwv+13, 0);
9937 state->setup = NULL;
9938 state->total_param = SVAL(req->vwv+0, 0);
9939 state->param = NULL;
9940 state->total_data = SVAL(req->vwv+1, 0);
9942 state->max_param_return = SVAL(req->vwv+2, 0);
9943 state->max_data_return = SVAL(req->vwv+3, 0);
9944 state->max_setup_return = SVAL(req->vwv+4, 0);
9945 state->close_on_completion = BITSETW(req->vwv+5, 0);
9946 state->one_way = BITSETW(req->vwv+5, 1);
9948 state->call = tran_call;
9950 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9951 is so as a sanity check */
9952 if (state->setup_count != 1) {
9954 * Need to have rc=0 for ioctl to get job id for OS/2.
9955 * Network printing will fail if function is not successful.
9956 * Similar function in reply.c will be used if protocol
9957 * is LANMAN1.0 instead of LM1.2X002.
9958 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9959 * outbuf doesn't have to be set(only job id is used).
9961 if ( (state->setup_count == 4)
9962 && (tran_call == TRANSACT2_IOCTL)
9963 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9964 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9965 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9967 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9968 DEBUG(2,("Transaction is %d\n",tran_call));
9970 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9971 END_PROFILE(SMBtrans2);
9976 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9979 if (state->total_data) {
9981 if (trans_oob(state->total_data, 0, dscnt)
9982 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9986 /* Can't use talloc here, the core routines do realloc on the
9987 * params and data. */
9988 state->data = (char *)SMB_MALLOC(state->total_data);
9989 if (state->data == NULL) {
9990 DEBUG(0,("reply_trans2: data malloc fail for %u "
9991 "bytes !\n", (unsigned int)state->total_data));
9993 reply_nterror(req, NT_STATUS_NO_MEMORY);
9994 END_PROFILE(SMBtrans2);
9998 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10001 if (state->total_param) {
10003 if (trans_oob(state->total_param, 0, pscnt)
10004 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10008 /* Can't use talloc here, the core routines do realloc on the
10009 * params and data. */
10010 state->param = (char *)SMB_MALLOC(state->total_param);
10011 if (state->param == NULL) {
10012 DEBUG(0,("reply_trans: param malloc fail for %u "
10013 "bytes !\n", (unsigned int)state->total_param));
10014 SAFE_FREE(state->data);
10015 TALLOC_FREE(state);
10016 reply_nterror(req, NT_STATUS_NO_MEMORY);
10017 END_PROFILE(SMBtrans2);
10021 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10024 state->received_data = dscnt;
10025 state->received_param = pscnt;
10027 if ((state->received_param == state->total_param) &&
10028 (state->received_data == state->total_data)) {
10030 handle_trans2(conn, req, state);
10032 SAFE_FREE(state->data);
10033 SAFE_FREE(state->param);
10034 TALLOC_FREE(state);
10035 END_PROFILE(SMBtrans2);
10039 DLIST_ADD(conn->pending_trans, state);
10041 /* We need to send an interim response then receive the rest
10042 of the parameter/data bytes */
10043 reply_outbuf(req, 0, 0);
10044 show_msg((char *)req->outbuf);
10045 END_PROFILE(SMBtrans2);
10050 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10051 SAFE_FREE(state->data);
10052 SAFE_FREE(state->param);
10053 TALLOC_FREE(state);
10054 END_PROFILE(SMBtrans2);
10055 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10059 /****************************************************************************
10060 Reply to a SMBtranss2
10061 ****************************************************************************/
10063 void reply_transs2(struct smb_request *req)
10065 connection_struct *conn = req->conn;
10066 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10067 struct trans_state *state;
10069 START_PROFILE(SMBtranss2);
10071 show_msg((const char *)req->inbuf);
10073 /* Windows clients expect all replies to
10074 a transact secondary (SMBtranss2 0x33)
10075 to have a command code of transact
10076 (SMBtrans2 0x32). See bug #8989
10077 and also [MS-CIFS] section 2.2.4.47.2
10080 req->cmd = SMBtrans2;
10082 if (req->wct < 8) {
10083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10084 END_PROFILE(SMBtranss2);
10088 for (state = conn->pending_trans; state != NULL;
10089 state = state->next) {
10090 if (state->mid == req->mid) {
10095 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10097 END_PROFILE(SMBtranss2);
10101 /* Revise state->total_param and state->total_data in case they have
10102 changed downwards */
10104 if (SVAL(req->vwv+0, 0) < state->total_param)
10105 state->total_param = SVAL(req->vwv+0, 0);
10106 if (SVAL(req->vwv+1, 0) < state->total_data)
10107 state->total_data = SVAL(req->vwv+1, 0);
10109 pcnt = SVAL(req->vwv+2, 0);
10110 poff = SVAL(req->vwv+3, 0);
10111 pdisp = SVAL(req->vwv+4, 0);
10113 dcnt = SVAL(req->vwv+5, 0);
10114 doff = SVAL(req->vwv+6, 0);
10115 ddisp = SVAL(req->vwv+7, 0);
10117 state->received_param += pcnt;
10118 state->received_data += dcnt;
10120 if ((state->received_data > state->total_data) ||
10121 (state->received_param > state->total_param))
10125 if (trans_oob(state->total_param, pdisp, pcnt)
10126 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10129 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10133 if (trans_oob(state->total_data, ddisp, dcnt)
10134 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10137 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10140 if ((state->received_param < state->total_param) ||
10141 (state->received_data < state->total_data)) {
10142 END_PROFILE(SMBtranss2);
10146 handle_trans2(conn, req, state);
10148 DLIST_REMOVE(conn->pending_trans, state);
10149 SAFE_FREE(state->data);
10150 SAFE_FREE(state->param);
10151 TALLOC_FREE(state);
10153 END_PROFILE(SMBtranss2);
10158 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10159 DLIST_REMOVE(conn->pending_trans, state);
10160 SAFE_FREE(state->data);
10161 SAFE_FREE(state->param);
10162 TALLOC_FREE(state);
10163 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10164 END_PROFILE(SMBtranss2);