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_FileIndex(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_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
232 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
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_index = 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_index = get_FileIndex(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_index); 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_index); 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)
4604 uint64_t file_index = get_FileIndex(conn, psbuf);
4607 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4608 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4610 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4613 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4616 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4617 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4618 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4621 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4625 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4629 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4632 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4633 devno = psbuf->st_ex_rdev;
4635 devno = psbuf->st_ex_dev;
4638 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4642 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4646 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4649 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4653 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4660 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4661 * the chflags(2) (or equivalent) flags.
4663 * XXX: this really should be behind the VFS interface. To do this, we would
4664 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4665 * Each VFS module could then implement its own mapping as appropriate for the
4666 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4668 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4672 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4676 { UF_IMMUTABLE, EXT_IMMUTABLE },
4680 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4684 { UF_HIDDEN, EXT_HIDDEN },
4687 /* Do not remove. We need to guarantee that this array has at least one
4688 * entry to build on HP-UX.
4694 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4695 uint32_t *smb_fflags, uint32_t *smb_fmask)
4699 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4700 *smb_fmask |= info2_flags_map[i].smb_fflag;
4701 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4702 *smb_fflags |= info2_flags_map[i].smb_fflag;
4707 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4708 const uint32_t smb_fflags,
4709 const uint32_t smb_fmask,
4712 uint32_t max_fmask = 0;
4715 *stat_fflags = psbuf->st_ex_flags;
4717 /* For each flags requested in smb_fmask, check the state of the
4718 * corresponding flag in smb_fflags and set or clear the matching
4722 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4723 max_fmask |= info2_flags_map[i].smb_fflag;
4724 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4725 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4726 *stat_fflags |= info2_flags_map[i].stat_fflag;
4728 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4733 /* If smb_fmask is asking to set any bits that are not supported by
4734 * our flag mappings, we should fail.
4736 if ((smb_fmask & max_fmask) != smb_fmask) {
4744 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4745 * of file flags and birth (create) time.
4747 static char *store_file_unix_basic_info2(connection_struct *conn,
4750 const SMB_STRUCT_STAT *psbuf)
4752 uint32_t file_flags = 0;
4753 uint32_t flags_mask = 0;
4755 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4757 /* Create (birth) time 64 bit */
4758 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4761 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4762 SIVAL(pdata, 0, file_flags); /* flags */
4763 SIVAL(pdata, 4, flags_mask); /* mask */
4769 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4770 const struct stream_struct *streams,
4772 unsigned int max_data_bytes,
4773 unsigned int *data_size)
4776 unsigned int ofs = 0;
4778 if (max_data_bytes < 32) {
4779 return NT_STATUS_INFO_LENGTH_MISMATCH;
4782 for (i = 0; i < num_streams; i++) {
4783 unsigned int next_offset;
4785 smb_ucs2_t *namebuf;
4787 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4788 streams[i].name, &namelen) ||
4791 return NT_STATUS_INVALID_PARAMETER;
4795 * name_buf is now null-terminated, we need to marshall as not
4802 * We cannot overflow ...
4804 if ((ofs + 24 + namelen) > max_data_bytes) {
4805 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4807 TALLOC_FREE(namebuf);
4808 return STATUS_BUFFER_OVERFLOW;
4811 SIVAL(data, ofs+4, namelen);
4812 SOFF_T(data, ofs+8, streams[i].size);
4813 SOFF_T(data, ofs+16, streams[i].alloc_size);
4814 memcpy(data+ofs+24, namebuf, namelen);
4815 TALLOC_FREE(namebuf);
4817 next_offset = ofs + 24 + namelen;
4819 if (i == num_streams-1) {
4820 SIVAL(data, ofs, 0);
4823 unsigned int align = ndr_align_size(next_offset, 8);
4825 if ((next_offset + align) > max_data_bytes) {
4826 DEBUG(10, ("refusing to overflow align "
4827 "reply at stream %u\n",
4829 TALLOC_FREE(namebuf);
4830 return STATUS_BUFFER_OVERFLOW;
4833 memset(data+next_offset, 0, align);
4834 next_offset += align;
4836 SIVAL(data, ofs, next_offset - ofs);
4843 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4847 return NT_STATUS_OK;
4850 /****************************************************************************
4851 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4852 ****************************************************************************/
4854 static void call_trans2qpipeinfo(connection_struct *conn,
4855 struct smb_request *req,
4856 unsigned int tran_call,
4857 char **pparams, int total_params,
4858 char **ppdata, int total_data,
4859 unsigned int max_data_bytes)
4861 char *params = *pparams;
4862 char *pdata = *ppdata;
4863 unsigned int data_size = 0;
4864 unsigned int param_size = 2;
4865 uint16_t info_level;
4869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4873 if (total_params < 4) {
4874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4878 fsp = file_fsp(req, SVAL(params,0));
4879 if (!fsp_is_np(fsp)) {
4880 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4884 info_level = SVAL(params,2);
4886 *pparams = (char *)SMB_REALLOC(*pparams,2);
4887 if (*pparams == NULL) {
4888 reply_nterror(req, NT_STATUS_NO_MEMORY);
4893 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4894 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4897 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4898 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4899 if (*ppdata == NULL ) {
4900 reply_nterror(req, NT_STATUS_NO_MEMORY);
4905 switch (info_level) {
4906 case SMB_FILE_STANDARD_INFORMATION:
4908 SOFF_T(pdata,0,4096LL);
4915 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4919 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4925 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4926 TALLOC_CTX *mem_ctx,
4927 uint16_t info_level,
4929 struct smb_filename *smb_fname,
4930 bool delete_pending,
4931 struct timespec write_time_ts,
4932 struct ea_list *ea_list,
4933 int lock_data_count,
4936 unsigned int max_data_bytes,
4937 size_t *fixed_portion,
4939 unsigned int *pdata_size)
4941 char *pdata = *ppdata;
4942 char *dstart, *dend;
4943 unsigned int data_size;
4944 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4945 time_t create_time, mtime, atime, c_time;
4946 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4953 uint64_t file_size = 0;
4955 uint64_t allocation_size = 0;
4956 uint64_t file_index = 0;
4957 uint32_t access_mask = 0;
4960 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4961 return NT_STATUS_INVALID_LEVEL;
4964 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4965 smb_fname_str_dbg(smb_fname),
4967 info_level, max_data_bytes));
4969 mode = dos_mode(conn, smb_fname);
4970 nlink = psbuf->st_ex_nlink;
4972 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4976 if ((nlink > 0) && delete_pending) {
4980 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4981 return NT_STATUS_INVALID_PARAMETER;
4984 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4985 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4986 if (*ppdata == NULL) {
4987 return NT_STATUS_NO_MEMORY;
4991 dend = dstart + data_size - 1;
4993 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4994 update_stat_ex_mtime(psbuf, write_time_ts);
4997 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4998 mtime_ts = psbuf->st_ex_mtime;
4999 atime_ts = psbuf->st_ex_atime;
5000 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5002 if (lp_dos_filetime_resolution(SNUM(conn))) {
5003 dos_filetime_timespec(&create_time_ts);
5004 dos_filetime_timespec(&mtime_ts);
5005 dos_filetime_timespec(&atime_ts);
5006 dos_filetime_timespec(&ctime_ts);
5009 create_time = convert_timespec_to_time_t(create_time_ts);
5010 mtime = convert_timespec_to_time_t(mtime_ts);
5011 atime = convert_timespec_to_time_t(atime_ts);
5012 c_time = convert_timespec_to_time_t(ctime_ts);
5014 p = strrchr_m(smb_fname->base_name,'/');
5016 base_name = smb_fname->base_name;
5020 /* NT expects the name to be in an exact form of the *full*
5021 filename. See the trans2 torture test */
5022 if (ISDOT(base_name)) {
5023 dos_fname = talloc_strdup(mem_ctx, "\\");
5025 return NT_STATUS_NO_MEMORY;
5028 dos_fname = talloc_asprintf(mem_ctx,
5030 smb_fname->base_name);
5032 return NT_STATUS_NO_MEMORY;
5034 if (is_ntfs_stream_smb_fname(smb_fname)) {
5035 dos_fname = talloc_asprintf(dos_fname, "%s",
5036 smb_fname->stream_name);
5038 return NT_STATUS_NO_MEMORY;
5042 string_replace(dos_fname, '/', '\\');
5045 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5048 /* Do we have this path open ? */
5050 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5051 fsp1 = file_find_di_first(conn->sconn, fileid);
5052 if (fsp1 && fsp1->initial_allocation_size) {
5053 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5057 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5058 file_size = get_file_size_stat(psbuf);
5062 pos = fsp->fh->position_information;
5066 access_mask = fsp->access_mask;
5068 /* GENERIC_EXECUTE mapping from Windows */
5069 access_mask = 0x12019F;
5072 /* This should be an index number - looks like
5075 I think this causes us to fail the IFSKIT
5076 BasicFileInformationTest. -tpot */
5077 file_index = get_FileIndex(conn, psbuf);
5081 switch (info_level) {
5082 case SMB_INFO_STANDARD:
5083 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5085 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5086 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5087 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5088 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5089 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5090 SSVAL(pdata,l1_attrFile,mode);
5093 case SMB_INFO_QUERY_EA_SIZE:
5095 unsigned int ea_size =
5096 estimate_ea_size(conn, fsp,
5098 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5100 srv_put_dos_date2(pdata,0,create_time);
5101 srv_put_dos_date2(pdata,4,atime);
5102 srv_put_dos_date2(pdata,8,mtime); /* write time */
5103 SIVAL(pdata,12,(uint32_t)file_size);
5104 SIVAL(pdata,16,(uint32_t)allocation_size);
5105 SSVAL(pdata,20,mode);
5106 SIVAL(pdata,22,ea_size);
5110 case SMB_INFO_IS_NAME_VALID:
5111 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5113 /* os/2 needs this ? really ?*/
5114 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5116 /* This is only reached for qpathinfo */
5120 case SMB_INFO_QUERY_EAS_FROM_LIST:
5122 size_t total_ea_len = 0;
5123 struct ea_list *ea_file_list = NULL;
5124 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5127 get_ea_list_from_file(mem_ctx, conn, fsp,
5129 &total_ea_len, &ea_file_list);
5130 if (!NT_STATUS_IS_OK(status)) {
5134 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5136 if (!ea_list || (total_ea_len > data_size)) {
5138 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5142 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5146 case SMB_INFO_QUERY_ALL_EAS:
5148 /* We have data_size bytes to put EA's into. */
5149 size_t total_ea_len = 0;
5150 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5152 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5154 &total_ea_len, &ea_list);
5155 if (!NT_STATUS_IS_OK(status)) {
5159 if (!ea_list || (total_ea_len > data_size)) {
5161 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5165 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5169 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5171 /* This is FileFullEaInformation - 0xF which maps to
5172 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5174 /* We have data_size bytes to put EA's into. */
5175 size_t total_ea_len = 0;
5176 struct ea_list *ea_file_list = NULL;
5178 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5180 /*TODO: add filtering and index handling */
5183 get_ea_list_from_file(mem_ctx, conn, fsp,
5185 &total_ea_len, &ea_file_list);
5186 if (!NT_STATUS_IS_OK(status)) {
5189 if (!ea_file_list) {
5190 return NT_STATUS_NO_EAS_ON_FILE;
5193 status = fill_ea_chained_buffer(mem_ctx,
5197 conn, ea_file_list);
5198 if (!NT_STATUS_IS_OK(status)) {
5204 case SMB_FILE_BASIC_INFORMATION:
5205 case SMB_QUERY_FILE_BASIC_INFO:
5207 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5208 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5209 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5211 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5215 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5216 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5217 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5218 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5219 SIVAL(pdata,32,mode);
5221 DEBUG(5,("SMB_QFBI - "));
5222 DEBUG(5,("create: %s ", ctime(&create_time)));
5223 DEBUG(5,("access: %s ", ctime(&atime)));
5224 DEBUG(5,("write: %s ", ctime(&mtime)));
5225 DEBUG(5,("change: %s ", ctime(&c_time)));
5226 DEBUG(5,("mode: %x\n", mode));
5227 *fixed_portion = data_size;
5230 case SMB_FILE_STANDARD_INFORMATION:
5231 case SMB_QUERY_FILE_STANDARD_INFO:
5233 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5235 SOFF_T(pdata,0,allocation_size);
5236 SOFF_T(pdata,8,file_size);
5237 SIVAL(pdata,16,nlink);
5238 SCVAL(pdata,20,delete_pending?1:0);
5239 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5240 SSVAL(pdata,22,0); /* Padding. */
5241 *fixed_portion = 24;
5244 case SMB_FILE_EA_INFORMATION:
5245 case SMB_QUERY_FILE_EA_INFO:
5247 unsigned int ea_size =
5248 estimate_ea_size(conn, fsp, smb_fname);
5249 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5252 SIVAL(pdata,0,ea_size);
5256 /* Get the 8.3 name - used if NT SMB was negotiated. */
5257 case SMB_QUERY_FILE_ALT_NAME_INFO:
5258 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5260 char mangled_name[13];
5261 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5262 if (!name_to_8_3(base_name,mangled_name,
5263 True,conn->params)) {
5264 return NT_STATUS_NO_MEMORY;
5266 status = srvstr_push(dstart, flags2,
5267 pdata+4, mangled_name,
5268 PTR_DIFF(dend, pdata+4),
5270 if (!NT_STATUS_IS_OK(status)) {
5273 data_size = 4 + len;
5279 case SMB_QUERY_FILE_NAME_INFO:
5282 this must be *exactly* right for ACLs on mapped drives to work
5284 status = srvstr_push(dstart, flags2,
5286 PTR_DIFF(dend, pdata+4),
5288 if (!NT_STATUS_IS_OK(status)) {
5291 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5292 data_size = 4 + len;
5297 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5299 char *nfname = NULL;
5301 if (!fsp->conn->sconn->using_smb2) {
5302 return NT_STATUS_INVALID_LEVEL;
5305 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5306 if (nfname == NULL) {
5307 return NT_STATUS_NO_MEMORY;
5310 if (ISDOT(nfname)) {
5313 string_replace(nfname, '/', '\\');
5315 if (smb_fname->stream_name != NULL) {
5316 const char *s = smb_fname->stream_name;
5317 const char *e = NULL;
5320 SMB_ASSERT(s[0] != '\0');
5323 * smb_fname->stream_name is in form
5324 * of ':StrEam:$DATA', but we should only
5325 * append ':StrEam' here.
5328 e = strchr(&s[1], ':');
5334 nfname = talloc_strndup_append(nfname, s, n);
5335 if (nfname == NULL) {
5336 return NT_STATUS_NO_MEMORY;
5340 status = srvstr_push(dstart, flags2,
5342 PTR_DIFF(dend, pdata+4),
5344 if (!NT_STATUS_IS_OK(status)) {
5347 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5348 data_size = 4 + len;
5354 case SMB_FILE_ALLOCATION_INFORMATION:
5355 case SMB_QUERY_FILE_ALLOCATION_INFO:
5356 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5358 SOFF_T(pdata,0,allocation_size);
5361 case SMB_FILE_END_OF_FILE_INFORMATION:
5362 case SMB_QUERY_FILE_END_OF_FILEINFO:
5363 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5365 SOFF_T(pdata,0,file_size);
5368 case SMB_QUERY_FILE_ALL_INFO:
5369 case SMB_FILE_ALL_INFORMATION:
5371 unsigned int ea_size =
5372 estimate_ea_size(conn, fsp, smb_fname);
5373 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5374 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5375 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5376 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5377 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5378 SIVAL(pdata,32,mode);
5379 SIVAL(pdata,36,0); /* padding. */
5381 SOFF_T(pdata,0,allocation_size);
5382 SOFF_T(pdata,8,file_size);
5383 SIVAL(pdata,16,nlink);
5384 SCVAL(pdata,20,delete_pending);
5385 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5388 SIVAL(pdata,0,ea_size);
5389 pdata += 4; /* EA info */
5390 status = srvstr_push(dstart, flags2,
5392 PTR_DIFF(dend, pdata+4),
5394 if (!NT_STATUS_IS_OK(status)) {
5399 data_size = PTR_DIFF(pdata,(*ppdata));
5400 *fixed_portion = 10;
5404 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5406 unsigned int ea_size =
5407 estimate_ea_size(conn, fsp, smb_fname);
5408 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5409 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5410 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5411 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5412 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5413 SIVAL(pdata, 0x20, mode);
5414 SIVAL(pdata, 0x24, 0); /* padding. */
5415 SBVAL(pdata, 0x28, allocation_size);
5416 SBVAL(pdata, 0x30, file_size);
5417 SIVAL(pdata, 0x38, nlink);
5418 SCVAL(pdata, 0x3C, delete_pending);
5419 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5420 SSVAL(pdata, 0x3E, 0); /* padding */
5421 SBVAL(pdata, 0x40, file_index);
5422 SIVAL(pdata, 0x48, ea_size);
5423 SIVAL(pdata, 0x4C, access_mask);
5424 SBVAL(pdata, 0x50, pos);
5425 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5426 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5430 status = srvstr_push(dstart, flags2,
5432 PTR_DIFF(dend, pdata+4),
5434 if (!NT_STATUS_IS_OK(status)) {
5439 data_size = PTR_DIFF(pdata,(*ppdata));
5440 *fixed_portion = 104;
5443 case SMB_FILE_INTERNAL_INFORMATION:
5445 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5446 SBVAL(pdata, 0, file_index);
5451 case SMB_FILE_ACCESS_INFORMATION:
5452 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5453 SIVAL(pdata, 0, access_mask);
5458 case SMB_FILE_NAME_INFORMATION:
5459 /* Pathname with leading '\'. */
5462 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5463 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5464 SIVAL(pdata,0,byte_len);
5465 data_size = 4 + byte_len;
5469 case SMB_FILE_DISPOSITION_INFORMATION:
5470 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5472 SCVAL(pdata,0,delete_pending);
5476 case SMB_FILE_POSITION_INFORMATION:
5477 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5479 SOFF_T(pdata,0,pos);
5483 case SMB_FILE_MODE_INFORMATION:
5484 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5485 SIVAL(pdata,0,mode);
5490 case SMB_FILE_ALIGNMENT_INFORMATION:
5491 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5492 SIVAL(pdata,0,0); /* No alignment needed. */
5498 * NT4 server just returns "invalid query" to this - if we try
5499 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5502 /* The first statement above is false - verified using Thursby
5503 * client against NT4 -- gcolley.
5505 case SMB_QUERY_FILE_STREAM_INFO:
5506 case SMB_FILE_STREAM_INFORMATION: {
5507 unsigned int num_streams = 0;
5508 struct stream_struct *streams = NULL;
5510 DEBUG(10,("smbd_do_qfilepathinfo: "
5511 "SMB_FILE_STREAM_INFORMATION\n"));
5513 if (is_ntfs_stream_smb_fname(smb_fname)) {
5514 return NT_STATUS_INVALID_PARAMETER;
5517 status = vfs_streaminfo(conn,
5524 if (!NT_STATUS_IS_OK(status)) {
5525 DEBUG(10, ("could not get stream info: %s\n",
5526 nt_errstr(status)));
5530 status = marshall_stream_info(num_streams, streams,
5531 pdata, max_data_bytes,
5534 if (!NT_STATUS_IS_OK(status)) {
5535 DEBUG(10, ("marshall_stream_info failed: %s\n",
5536 nt_errstr(status)));
5537 TALLOC_FREE(streams);
5541 TALLOC_FREE(streams);
5543 *fixed_portion = 32;
5547 case SMB_QUERY_COMPRESSION_INFO:
5548 case SMB_FILE_COMPRESSION_INFORMATION:
5549 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5550 SOFF_T(pdata,0,file_size);
5551 SIVAL(pdata,8,0); /* ??? */
5552 SIVAL(pdata,12,0); /* ??? */
5554 *fixed_portion = 16;
5557 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5558 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5559 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5560 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5561 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5562 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5563 SOFF_T(pdata,32,allocation_size);
5564 SOFF_T(pdata,40,file_size);
5565 SIVAL(pdata,48,mode);
5566 SIVAL(pdata,52,0); /* ??? */
5568 *fixed_portion = 56;
5571 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5572 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5573 SIVAL(pdata,0,mode);
5580 * CIFS UNIX Extensions.
5583 case SMB_QUERY_FILE_UNIX_BASIC:
5585 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5586 data_size = PTR_DIFF(pdata,(*ppdata));
5588 DEBUG(4,("smbd_do_qfilepathinfo: "
5589 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5590 dump_data(4, (uint8_t *)(*ppdata), data_size);
5594 case SMB_QUERY_FILE_UNIX_INFO2:
5596 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5597 data_size = PTR_DIFF(pdata,(*ppdata));
5601 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5603 for (i=0; i<100; i++)
5604 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5610 case SMB_QUERY_FILE_UNIX_LINK:
5613 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5616 return NT_STATUS_NO_MEMORY;
5619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5621 if(!S_ISLNK(psbuf->st_ex_mode)) {
5622 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5625 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5627 link_len = SMB_VFS_READLINK(conn,
5630 if (link_len == -1) {
5631 return map_nt_error_from_unix(errno);
5633 buffer[link_len] = 0;
5634 status = srvstr_push(dstart, flags2,
5636 PTR_DIFF(dend, pdata),
5637 STR_TERMINATE, &len);
5638 if (!NT_STATUS_IS_OK(status)) {
5642 data_size = PTR_DIFF(pdata,(*ppdata));
5647 #if defined(HAVE_POSIX_ACLS)
5648 case SMB_QUERY_POSIX_ACL:
5650 SMB_ACL_T file_acl = NULL;
5651 SMB_ACL_T def_acl = NULL;
5652 uint16_t num_file_acls = 0;
5653 uint16_t num_def_acls = 0;
5655 status = refuse_symlink(conn,
5658 if (!NT_STATUS_IS_OK(status)) {
5662 if (fsp && fsp->fh->fd != -1) {
5663 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5667 SMB_VFS_SYS_ACL_GET_FILE(conn,
5669 SMB_ACL_TYPE_ACCESS,
5673 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5674 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5675 "not implemented on "
5676 "filesystem containing %s\n",
5677 smb_fname->base_name));
5678 return NT_STATUS_NOT_IMPLEMENTED;
5681 if (S_ISDIR(psbuf->st_ex_mode)) {
5682 if (fsp && fsp->is_directory) {
5684 SMB_VFS_SYS_ACL_GET_FILE(
5687 SMB_ACL_TYPE_DEFAULT,
5691 SMB_VFS_SYS_ACL_GET_FILE(
5694 SMB_ACL_TYPE_DEFAULT,
5697 def_acl = free_empty_sys_acl(conn, def_acl);
5700 num_file_acls = count_acl_entries(conn, file_acl);
5701 num_def_acls = count_acl_entries(conn, def_acl);
5703 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5704 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5706 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5707 SMB_POSIX_ACL_HEADER_SIZE) ));
5709 TALLOC_FREE(file_acl);
5712 TALLOC_FREE(def_acl);
5714 return NT_STATUS_BUFFER_TOO_SMALL;
5717 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5718 SSVAL(pdata,2,num_file_acls);
5719 SSVAL(pdata,4,num_def_acls);
5720 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5722 TALLOC_FREE(file_acl);
5725 TALLOC_FREE(def_acl);
5727 return NT_STATUS_INTERNAL_ERROR;
5729 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5731 TALLOC_FREE(file_acl);
5734 TALLOC_FREE(def_acl);
5736 return NT_STATUS_INTERNAL_ERROR;
5740 TALLOC_FREE(file_acl);
5743 TALLOC_FREE(def_acl);
5745 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5751 case SMB_QUERY_POSIX_LOCK:
5756 enum brl_type lock_type;
5758 /* We need an open file with a real fd for this. */
5759 if (!fsp || fsp->fh->fd == -1) {
5760 return NT_STATUS_INVALID_LEVEL;
5763 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5764 return NT_STATUS_INVALID_PARAMETER;
5767 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5768 case POSIX_LOCK_TYPE_READ:
5769 lock_type = READ_LOCK;
5771 case POSIX_LOCK_TYPE_WRITE:
5772 lock_type = WRITE_LOCK;
5774 case POSIX_LOCK_TYPE_UNLOCK:
5776 /* There's no point in asking for an unlock... */
5777 return NT_STATUS_INVALID_PARAMETER;
5780 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5781 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5782 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5784 status = query_lock(fsp,
5791 if (ERROR_WAS_LOCK_DENIED(status)) {
5792 /* Here we need to report who has it locked... */
5793 data_size = POSIX_LOCK_DATA_SIZE;
5795 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5796 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5797 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5798 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5799 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5801 } else if (NT_STATUS_IS_OK(status)) {
5802 /* For success we just return a copy of what we sent
5803 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5804 data_size = POSIX_LOCK_DATA_SIZE;
5805 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5806 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5814 return NT_STATUS_INVALID_LEVEL;
5817 *pdata_size = data_size;
5818 return NT_STATUS_OK;
5821 /****************************************************************************
5822 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5823 file name or file id).
5824 ****************************************************************************/
5826 static void call_trans2qfilepathinfo(connection_struct *conn,
5827 struct smb_request *req,
5828 unsigned int tran_call,
5829 char **pparams, int total_params,
5830 char **ppdata, int total_data,
5831 unsigned int max_data_bytes)
5833 char *params = *pparams;
5834 char *pdata = *ppdata;
5835 uint16_t info_level;
5836 unsigned int data_size = 0;
5837 unsigned int param_size = 2;
5838 struct smb_filename *smb_fname = NULL;
5839 bool delete_pending = False;
5840 struct timespec write_time_ts;
5841 files_struct *fsp = NULL;
5842 struct file_id fileid;
5843 struct ea_list *ea_list = NULL;
5844 int lock_data_count = 0;
5845 char *lock_data = NULL;
5846 size_t fixed_portion;
5847 NTSTATUS status = NT_STATUS_OK;
5850 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5854 ZERO_STRUCT(write_time_ts);
5856 if (tran_call == TRANSACT2_QFILEINFO) {
5857 if (total_params < 4) {
5858 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5863 call_trans2qpipeinfo(conn, req, tran_call,
5864 pparams, total_params,
5870 fsp = file_fsp(req, SVAL(params,0));
5871 info_level = SVAL(params,2);
5873 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5875 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5876 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5880 /* Initial check for valid fsp ptr. */
5881 if (!check_fsp_open(conn, req, fsp)) {
5885 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5886 if (smb_fname == NULL) {
5887 reply_nterror(req, NT_STATUS_NO_MEMORY);
5891 if(fsp->fake_file_handle) {
5893 * This is actually for the QUOTA_FAKE_FILE --metze
5896 /* We know this name is ok, it's already passed the checks. */
5898 } else if(fsp->fh->fd == -1) {
5900 * This is actually a QFILEINFO on a directory
5901 * handle (returned from an NT SMB). NT5.0 seems
5902 * to do this call. JRA.
5905 if (INFO_LEVEL_IS_UNIX(info_level)) {
5906 /* Always do lstat for UNIX calls. */
5907 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5908 DEBUG(3,("call_trans2qfilepathinfo: "
5909 "SMB_VFS_LSTAT of %s failed "
5911 smb_fname_str_dbg(smb_fname),
5914 map_nt_error_from_unix(errno));
5917 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5918 DEBUG(3,("call_trans2qfilepathinfo: "
5919 "SMB_VFS_STAT of %s failed (%s)\n",
5920 smb_fname_str_dbg(smb_fname),
5923 map_nt_error_from_unix(errno));
5927 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5928 fileid = vfs_file_id_from_sbuf(
5929 conn, &smb_fname->st);
5930 get_file_infos(fileid, fsp->name_hash,
5936 * Original code - this is an open file.
5938 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5939 DEBUG(3, ("fstat of %s failed (%s)\n",
5940 fsp_fnum_dbg(fsp), strerror(errno)));
5942 map_nt_error_from_unix(errno));
5945 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5946 fileid = vfs_file_id_from_sbuf(
5947 conn, &smb_fname->st);
5948 get_file_infos(fileid, fsp->name_hash,
5957 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5960 if (total_params < 7) {
5961 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5965 info_level = SVAL(params,0);
5967 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5969 if (INFO_LEVEL_IS_UNIX(info_level)) {
5970 if (!lp_unix_extensions()) {
5971 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5974 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5975 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5976 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5977 req->posix_pathnames) {
5978 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5982 if (req->posix_pathnames) {
5983 srvstr_get_path_posix(req,
5992 srvstr_get_path(req,
6001 if (!NT_STATUS_IS_OK(status)) {
6002 reply_nterror(req, status);
6006 status = filename_convert(req,
6013 if (!NT_STATUS_IS_OK(status)) {
6014 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6015 reply_botherror(req,
6016 NT_STATUS_PATH_NOT_COVERED,
6017 ERRSRV, ERRbadpath);
6020 reply_nterror(req, status);
6024 /* If this is a stream, check if there is a delete_pending. */
6025 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6026 && is_ntfs_stream_smb_fname(smb_fname)) {
6027 struct smb_filename *smb_fname_base;
6029 /* Create an smb_filename with stream_name == NULL. */
6030 smb_fname_base = synthetic_smb_fname(
6032 smb_fname->base_name,
6036 if (smb_fname_base == NULL) {
6037 reply_nterror(req, NT_STATUS_NO_MEMORY);
6041 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6042 /* Always do lstat for UNIX calls. */
6043 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6044 DEBUG(3,("call_trans2qfilepathinfo: "
6045 "SMB_VFS_LSTAT of %s failed "
6047 smb_fname_str_dbg(smb_fname_base),
6049 TALLOC_FREE(smb_fname_base);
6051 map_nt_error_from_unix(errno));
6055 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6056 DEBUG(3,("call_trans2qfilepathinfo: "
6057 "fileinfo of %s failed "
6059 smb_fname_str_dbg(smb_fname_base),
6061 TALLOC_FREE(smb_fname_base);
6063 map_nt_error_from_unix(errno));
6068 status = file_name_hash(conn,
6069 smb_fname_str_dbg(smb_fname_base),
6071 if (!NT_STATUS_IS_OK(status)) {
6072 TALLOC_FREE(smb_fname_base);
6073 reply_nterror(req, status);
6077 fileid = vfs_file_id_from_sbuf(conn,
6078 &smb_fname_base->st);
6079 TALLOC_FREE(smb_fname_base);
6080 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6081 if (delete_pending) {
6082 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6087 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6088 /* Always do lstat for UNIX calls. */
6089 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6090 DEBUG(3,("call_trans2qfilepathinfo: "
6091 "SMB_VFS_LSTAT of %s failed (%s)\n",
6092 smb_fname_str_dbg(smb_fname),
6095 map_nt_error_from_unix(errno));
6100 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6101 DEBUG(3,("call_trans2qfilepathinfo: "
6102 "SMB_VFS_STAT of %s failed (%s)\n",
6103 smb_fname_str_dbg(smb_fname),
6106 map_nt_error_from_unix(errno));
6111 status = file_name_hash(conn,
6112 smb_fname_str_dbg(smb_fname),
6114 if (!NT_STATUS_IS_OK(status)) {
6115 reply_nterror(req, status);
6119 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6120 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6121 get_file_infos(fileid, name_hash, &delete_pending,
6125 if (delete_pending) {
6126 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6131 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6132 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6134 info_level,tran_call,total_data));
6136 /* Pull out any data sent here before we realloc. */
6137 switch (info_level) {
6138 case SMB_INFO_QUERY_EAS_FROM_LIST:
6140 /* Pull any EA list from the data portion. */
6143 if (total_data < 4) {
6145 req, NT_STATUS_INVALID_PARAMETER);
6148 ea_size = IVAL(pdata,0);
6150 if (total_data > 0 && ea_size != total_data) {
6151 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6152 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6154 req, NT_STATUS_INVALID_PARAMETER);
6158 if (!lp_ea_support(SNUM(conn))) {
6159 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6163 /* Pull out the list of names. */
6164 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6167 req, NT_STATUS_INVALID_PARAMETER);
6173 case SMB_QUERY_POSIX_LOCK:
6175 if (fsp == NULL || fsp->fh->fd == -1) {
6176 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6180 if (total_data != POSIX_LOCK_DATA_SIZE) {
6182 req, NT_STATUS_INVALID_PARAMETER);
6186 /* Copy the lock range data. */
6187 lock_data = (char *)talloc_memdup(
6188 req, pdata, total_data);
6190 reply_nterror(req, NT_STATUS_NO_MEMORY);
6193 lock_data_count = total_data;
6199 *pparams = (char *)SMB_REALLOC(*pparams,2);
6200 if (*pparams == NULL) {
6201 reply_nterror(req, NT_STATUS_NO_MEMORY);
6208 * draft-leach-cifs-v1-spec-02.txt
6209 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6212 * The requested information is placed in the Data portion of the
6213 * transaction response. For the information levels greater than 0x100,
6214 * the transaction response has 1 parameter word which should be
6215 * ignored by the client.
6217 * However Windows only follows this rule for the IS_NAME_VALID call.
6219 switch (info_level) {
6220 case SMB_INFO_IS_NAME_VALID:
6225 if ((info_level & 0xFF00) == 0xFF00) {
6227 * We use levels that start with 0xFF00
6228 * internally to represent SMB2 specific levels
6230 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6234 status = smbd_do_qfilepathinfo(conn, req, info_level,
6236 delete_pending, write_time_ts,
6238 lock_data_count, lock_data,
6239 req->flags2, max_data_bytes,
6241 ppdata, &data_size);
6242 if (!NT_STATUS_IS_OK(status)) {
6243 reply_nterror(req, status);
6246 if (fixed_portion > max_data_bytes) {
6247 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6251 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6257 /****************************************************************************
6258 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6260 ****************************************************************************/
6262 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6263 connection_struct *conn,
6264 struct smb_request *req,
6265 bool overwrite_if_exists,
6266 const struct smb_filename *smb_fname_old,
6267 struct smb_filename *smb_fname_new)
6269 NTSTATUS status = NT_STATUS_OK;
6272 /* source must already exist. */
6273 if (!VALID_STAT(smb_fname_old->st)) {
6274 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6277 if (VALID_STAT(smb_fname_new->st)) {
6278 if (overwrite_if_exists) {
6279 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6280 return NT_STATUS_FILE_IS_A_DIRECTORY;
6282 status = unlink_internals(conn,
6284 FILE_ATTRIBUTE_NORMAL,
6287 if (!NT_STATUS_IS_OK(status)) {
6291 /* Disallow if newname already exists. */
6292 return NT_STATUS_OBJECT_NAME_COLLISION;
6296 /* No links from a directory. */
6297 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6298 return NT_STATUS_FILE_IS_A_DIRECTORY;
6301 /* Setting a hardlink to/from a stream isn't currently supported. */
6302 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6304 DBG_DEBUG("Old name has streams\n");
6305 return NT_STATUS_INVALID_PARAMETER;
6307 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6309 DBG_DEBUG("New name has streams\n");
6310 return NT_STATUS_INVALID_PARAMETER;
6313 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6314 smb_fname_old->base_name, smb_fname_new->base_name));
6316 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6317 status = map_nt_error_from_unix(errno);
6318 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6319 nt_errstr(status), smb_fname_old->base_name,
6320 smb_fname_new->base_name));
6325 /****************************************************************************
6326 Deal with setting the time from any of the setfilepathinfo functions.
6327 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6328 calling this function.
6329 ****************************************************************************/
6331 NTSTATUS smb_set_file_time(connection_struct *conn,
6333 const struct smb_filename *smb_fname,
6334 struct smb_file_time *ft,
6335 bool setting_write_time)
6337 struct smb_filename smb_fname_base;
6339 FILE_NOTIFY_CHANGE_LAST_ACCESS
6340 |FILE_NOTIFY_CHANGE_LAST_WRITE
6341 |FILE_NOTIFY_CHANGE_CREATION;
6343 if (!VALID_STAT(smb_fname->st)) {
6344 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6347 /* get some defaults (no modifications) if any info is zero or -1. */
6348 if (null_timespec(ft->create_time)) {
6349 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6352 if (null_timespec(ft->atime)) {
6353 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6356 if (null_timespec(ft->mtime)) {
6357 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6360 if (!setting_write_time) {
6361 /* ft->mtime comes from change time, not write time. */
6362 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6365 /* Ensure the resolution is the correct for
6366 * what we can store on this filesystem. */
6368 round_timespec(conn->ts_res, &ft->create_time);
6369 round_timespec(conn->ts_res, &ft->ctime);
6370 round_timespec(conn->ts_res, &ft->atime);
6371 round_timespec(conn->ts_res, &ft->mtime);
6373 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6374 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6375 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6376 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6377 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6378 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6379 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6380 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6382 if (setting_write_time) {
6384 * This was a Windows setfileinfo on an open file.
6385 * NT does this a lot. We also need to
6386 * set the time here, as it can be read by
6387 * FindFirst/FindNext and with the patch for bug #2045
6388 * in smbd/fileio.c it ensures that this timestamp is
6389 * kept sticky even after a write. We save the request
6390 * away and will set it on file close and after a write. JRA.
6393 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6394 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6397 if (fsp->base_fsp) {
6398 set_sticky_write_time_fsp(fsp->base_fsp,
6401 set_sticky_write_time_fsp(fsp, ft->mtime);
6404 set_sticky_write_time_path(
6405 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6410 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6412 /* Always call ntimes on the base, even if a stream was passed in. */
6413 smb_fname_base = *smb_fname;
6414 smb_fname_base.stream_name = NULL;
6416 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6417 return map_nt_error_from_unix(errno);
6420 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6421 smb_fname->base_name);
6422 return NT_STATUS_OK;
6425 /****************************************************************************
6426 Deal with setting the dosmode from any of the setfilepathinfo functions.
6427 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6428 done before calling this function.
6429 ****************************************************************************/
6431 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6432 const struct smb_filename *smb_fname,
6435 struct smb_filename *smb_fname_base;
6438 if (!VALID_STAT(smb_fname->st)) {
6439 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6442 /* Always operate on the base_name, even if a stream was passed in. */
6443 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6444 smb_fname->base_name,
6448 if (smb_fname_base == NULL) {
6449 return NT_STATUS_NO_MEMORY;
6453 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6454 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6456 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6460 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6462 /* check the mode isn't different, before changing it */
6463 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6464 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6465 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6466 (unsigned int)dosmode));
6468 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6470 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6472 smb_fname_str_dbg(smb_fname_base),
6474 status = map_nt_error_from_unix(errno);
6478 status = NT_STATUS_OK;
6480 TALLOC_FREE(smb_fname_base);
6484 /****************************************************************************
6485 Deal with setting the size from any of the setfilepathinfo functions.
6486 ****************************************************************************/
6488 static NTSTATUS smb_set_file_size(connection_struct *conn,
6489 struct smb_request *req,
6491 const struct smb_filename *smb_fname,
6492 const SMB_STRUCT_STAT *psbuf,
6494 bool fail_after_createfile)
6496 NTSTATUS status = NT_STATUS_OK;
6497 struct smb_filename *smb_fname_tmp = NULL;
6498 files_struct *new_fsp = NULL;
6500 if (!VALID_STAT(*psbuf)) {
6501 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6504 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6506 get_file_size_stat(psbuf));
6508 if (size == get_file_size_stat(psbuf)) {
6509 return NT_STATUS_OK;
6512 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6513 smb_fname_str_dbg(smb_fname), (double)size));
6515 if (fsp && fsp->fh->fd != -1) {
6516 /* Handle based call. */
6517 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6518 return NT_STATUS_ACCESS_DENIED;
6521 if (vfs_set_filelen(fsp, size) == -1) {
6522 return map_nt_error_from_unix(errno);
6524 trigger_write_time_update_immediate(fsp);
6525 return NT_STATUS_OK;
6528 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6529 if (smb_fname_tmp == NULL) {
6530 return NT_STATUS_NO_MEMORY;
6533 smb_fname_tmp->st = *psbuf;
6535 status = SMB_VFS_CREATE_FILE(
6538 0, /* root_dir_fid */
6539 smb_fname_tmp, /* fname */
6540 FILE_WRITE_DATA, /* access_mask */
6541 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6543 FILE_OPEN, /* create_disposition*/
6544 0, /* create_options */
6545 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6546 0, /* oplock_request */
6548 0, /* allocation_size */
6549 0, /* private_flags */
6552 &new_fsp, /* result */
6554 NULL, NULL); /* create context */
6556 TALLOC_FREE(smb_fname_tmp);
6558 if (!NT_STATUS_IS_OK(status)) {
6559 /* NB. We check for open_was_deferred in the caller. */
6563 /* See RAW-SFILEINFO-END-OF-FILE */
6564 if (fail_after_createfile) {
6565 close_file(req, new_fsp,NORMAL_CLOSE);
6566 return NT_STATUS_INVALID_LEVEL;
6569 if (vfs_set_filelen(new_fsp, size) == -1) {
6570 status = map_nt_error_from_unix(errno);
6571 close_file(req, new_fsp,NORMAL_CLOSE);
6575 trigger_write_time_update_immediate(new_fsp);
6576 close_file(req, new_fsp,NORMAL_CLOSE);
6577 return NT_STATUS_OK;
6580 /****************************************************************************
6581 Deal with SMB_INFO_SET_EA.
6582 ****************************************************************************/
6584 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6588 const struct smb_filename *smb_fname)
6590 struct ea_list *ea_list = NULL;
6591 TALLOC_CTX *ctx = NULL;
6592 NTSTATUS status = NT_STATUS_OK;
6594 if (total_data < 10) {
6596 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6597 length. They seem to have no effect. Bug #3212. JRA */
6599 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6600 /* We're done. We only get EA info in this call. */
6601 return NT_STATUS_OK;
6604 return NT_STATUS_INVALID_PARAMETER;
6607 if (IVAL(pdata,0) > total_data) {
6608 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6609 IVAL(pdata,0), (unsigned int)total_data));
6610 return NT_STATUS_INVALID_PARAMETER;
6614 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6616 return NT_STATUS_INVALID_PARAMETER;
6619 status = set_ea(conn, fsp, smb_fname, ea_list);
6624 /****************************************************************************
6625 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6626 ****************************************************************************/
6628 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6633 struct ea_list *ea_list = NULL;
6637 return NT_STATUS_INVALID_HANDLE;
6640 if (!lp_ea_support(SNUM(conn))) {
6641 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6642 "EA's not supported.\n",
6643 (unsigned int)total_data));
6644 return NT_STATUS_EAS_NOT_SUPPORTED;
6647 if (total_data < 10) {
6648 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6650 (unsigned int)total_data));
6651 return NT_STATUS_INVALID_PARAMETER;
6654 ea_list = read_nttrans_ea_list(talloc_tos(),
6659 return NT_STATUS_INVALID_PARAMETER;
6662 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6664 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6665 smb_fname_str_dbg(fsp->fsp_name),
6666 nt_errstr(status) ));
6672 /****************************************************************************
6673 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6674 ****************************************************************************/
6676 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6680 struct smb_filename *smb_fname)
6682 NTSTATUS status = NT_STATUS_OK;
6683 bool delete_on_close;
6684 uint32_t dosmode = 0;
6686 if (total_data < 1) {
6687 return NT_STATUS_INVALID_PARAMETER;
6691 return NT_STATUS_INVALID_HANDLE;
6694 delete_on_close = (CVAL(pdata,0) ? True : False);
6695 dosmode = dos_mode(conn, smb_fname);
6697 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6698 "delete_on_close = %u\n",
6699 smb_fname_str_dbg(smb_fname),
6700 (unsigned int)dosmode,
6701 (unsigned int)delete_on_close ));
6703 if (delete_on_close) {
6704 status = can_set_delete_on_close(fsp, dosmode);
6705 if (!NT_STATUS_IS_OK(status)) {
6710 /* The set is across all open files on this dev/inode pair. */
6711 if (!set_delete_on_close(fsp, delete_on_close,
6712 conn->session_info->security_token,
6713 conn->session_info->unix_token)) {
6714 return NT_STATUS_ACCESS_DENIED;
6716 return NT_STATUS_OK;
6719 /****************************************************************************
6720 Deal with SMB_FILE_POSITION_INFORMATION.
6721 ****************************************************************************/
6723 static NTSTATUS smb_file_position_information(connection_struct *conn,
6728 uint64_t position_information;
6730 if (total_data < 8) {
6731 return NT_STATUS_INVALID_PARAMETER;
6735 /* Ignore on pathname based set. */
6736 return NT_STATUS_OK;
6739 position_information = (uint64_t)IVAL(pdata,0);
6740 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6742 DEBUG(10,("smb_file_position_information: Set file position "
6743 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6744 (double)position_information));
6745 fsp->fh->position_information = position_information;
6746 return NT_STATUS_OK;
6749 /****************************************************************************
6750 Deal with SMB_FILE_MODE_INFORMATION.
6751 ****************************************************************************/
6753 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6759 if (total_data < 4) {
6760 return NT_STATUS_INVALID_PARAMETER;
6762 mode = IVAL(pdata,0);
6763 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6764 return NT_STATUS_INVALID_PARAMETER;
6766 return NT_STATUS_OK;
6769 /****************************************************************************
6770 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6771 ****************************************************************************/
6773 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6774 struct smb_request *req,
6777 const struct smb_filename *new_smb_fname)
6779 char *link_target = NULL;
6780 TALLOC_CTX *ctx = talloc_tos();
6782 /* Set a symbolic link. */
6783 /* Don't allow this if follow links is false. */
6785 if (total_data == 0) {
6786 return NT_STATUS_INVALID_PARAMETER;
6789 if (!lp_follow_symlinks(SNUM(conn))) {
6790 return NT_STATUS_ACCESS_DENIED;
6793 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6794 total_data, STR_TERMINATE);
6797 return NT_STATUS_INVALID_PARAMETER;
6800 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6801 new_smb_fname->base_name, link_target ));
6803 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6804 return map_nt_error_from_unix(errno);
6807 return NT_STATUS_OK;
6810 /****************************************************************************
6811 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6812 ****************************************************************************/
6814 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6815 struct smb_request *req,
6816 const char *pdata, int total_data,
6817 struct smb_filename *smb_fname_new)
6819 char *oldname = NULL;
6820 struct smb_filename *smb_fname_old = NULL;
6821 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6822 TALLOC_CTX *ctx = talloc_tos();
6823 NTSTATUS status = NT_STATUS_OK;
6825 /* Set a hard link. */
6826 if (total_data == 0) {
6827 return NT_STATUS_INVALID_PARAMETER;
6830 if (req->posix_pathnames) {
6831 srvstr_get_path_posix(ctx,
6840 srvstr_get_path(ctx,
6849 if (!NT_STATUS_IS_OK(status)) {
6853 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6854 smb_fname_str_dbg(smb_fname_new), oldname));
6856 status = filename_convert(ctx,
6863 if (!NT_STATUS_IS_OK(status)) {
6867 return hardlink_internals(ctx, conn, req, false,
6868 smb_fname_old, smb_fname_new);
6871 /****************************************************************************
6872 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6873 ****************************************************************************/
6875 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6876 struct smb_request *req,
6880 struct smb_filename *smb_fname_src)
6884 char *newname = NULL;
6885 struct smb_filename *smb_fname_dst = NULL;
6886 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6887 ucf_flags_from_smb_request(req);
6888 NTSTATUS status = NT_STATUS_OK;
6889 TALLOC_CTX *ctx = talloc_tos();
6892 return NT_STATUS_INVALID_HANDLE;
6895 if (total_data < 20) {
6896 return NT_STATUS_INVALID_PARAMETER;
6899 overwrite = (CVAL(pdata,0) ? True : False);
6900 len = IVAL(pdata,16);
6902 if (len > (total_data - 20) || (len == 0)) {
6903 return NT_STATUS_INVALID_PARAMETER;
6906 if (req->posix_pathnames) {
6907 srvstr_get_path_posix(ctx,
6916 srvstr_get_path(ctx,
6925 if (!NT_STATUS_IS_OK(status)) {
6929 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6932 status = filename_convert(ctx,
6939 if (!NT_STATUS_IS_OK(status)) {
6943 if (fsp->base_fsp) {
6944 /* newname must be a stream name. */
6945 if (newname[0] != ':') {
6946 return NT_STATUS_NOT_SUPPORTED;
6949 /* Create an smb_fname to call rename_internals_fsp() with. */
6950 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6951 fsp->base_fsp->fsp_name->base_name,
6954 fsp->base_fsp->fsp_name->flags);
6955 if (smb_fname_dst == NULL) {
6956 status = NT_STATUS_NO_MEMORY;
6961 * Set the original last component, since
6962 * rename_internals_fsp() requires it.
6964 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6966 if (smb_fname_dst->original_lcomp == NULL) {
6967 status = NT_STATUS_NO_MEMORY;
6973 DEBUG(10,("smb2_file_rename_information: "
6974 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6975 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6976 smb_fname_str_dbg(smb_fname_dst)));
6977 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6978 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6982 TALLOC_FREE(smb_fname_dst);
6986 static NTSTATUS smb_file_link_information(connection_struct *conn,
6987 struct smb_request *req,
6991 struct smb_filename *smb_fname_src)
6995 char *newname = NULL;
6996 struct smb_filename *smb_fname_dst = NULL;
6997 NTSTATUS status = NT_STATUS_OK;
6998 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6999 ucf_flags_from_smb_request(req);
7000 TALLOC_CTX *ctx = talloc_tos();
7003 return NT_STATUS_INVALID_HANDLE;
7006 if (total_data < 20) {
7007 return NT_STATUS_INVALID_PARAMETER;
7010 overwrite = (CVAL(pdata,0) ? true : false);
7011 len = IVAL(pdata,16);
7013 if (len > (total_data - 20) || (len == 0)) {
7014 return NT_STATUS_INVALID_PARAMETER;
7017 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7018 srvstr_get_path_posix(ctx,
7026 ucf_flags |= UCF_POSIX_PATHNAMES;
7028 srvstr_get_path(ctx,
7037 if (!NT_STATUS_IS_OK(status)) {
7041 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7044 status = filename_convert(ctx,
7051 if (!NT_STATUS_IS_OK(status)) {
7055 if (fsp->base_fsp) {
7056 /* No stream names. */
7057 return NT_STATUS_NOT_SUPPORTED;
7060 DEBUG(10,("smb_file_link_information: "
7061 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7062 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7063 smb_fname_str_dbg(smb_fname_dst)));
7064 status = hardlink_internals(ctx,
7071 TALLOC_FREE(smb_fname_dst);
7075 /****************************************************************************
7076 Deal with SMB_FILE_RENAME_INFORMATION.
7077 ****************************************************************************/
7079 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7080 struct smb_request *req,
7084 struct smb_filename *smb_fname_src)
7089 char *newname = NULL;
7090 struct smb_filename *smb_fname_dst = NULL;
7091 bool dest_has_wcard = False;
7092 NTSTATUS status = NT_STATUS_OK;
7094 TALLOC_CTX *ctx = talloc_tos();
7096 if (total_data < 13) {
7097 return NT_STATUS_INVALID_PARAMETER;
7100 overwrite = (CVAL(pdata,0) ? True : False);
7101 root_fid = IVAL(pdata,4);
7102 len = IVAL(pdata,8);
7104 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7105 return NT_STATUS_INVALID_PARAMETER;
7108 if (req->posix_pathnames) {
7109 srvstr_get_path_wcard_posix(ctx,
7119 srvstr_get_path_wcard(ctx,
7129 if (!NT_STATUS_IS_OK(status)) {
7133 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7136 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7137 status = resolve_dfspath_wcard(ctx, conn,
7139 UCF_COND_ALLOW_WCARD_LCOMP,
7140 !conn->sconn->using_smb2,
7143 if (!NT_STATUS_IS_OK(status)) {
7148 /* Check the new name has no '/' characters. */
7149 if (strchr_m(newname, '/')) {
7150 return NT_STATUS_NOT_SUPPORTED;
7153 if (fsp && fsp->base_fsp) {
7154 /* newname must be a stream name. */
7155 if (newname[0] != ':') {
7156 return NT_STATUS_NOT_SUPPORTED;
7159 /* Create an smb_fname to call rename_internals_fsp() with. */
7160 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7161 fsp->base_fsp->fsp_name->base_name,
7164 fsp->base_fsp->fsp_name->flags);
7165 if (smb_fname_dst == NULL) {
7166 status = NT_STATUS_NO_MEMORY;
7171 * Set the original last component, since
7172 * rename_internals_fsp() requires it.
7174 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7176 if (smb_fname_dst->original_lcomp == NULL) {
7177 status = NT_STATUS_NO_MEMORY;
7183 * Build up an smb_fname_dst based on the filename passed in.
7184 * We basically just strip off the last component, and put on
7185 * the newname instead.
7187 char *base_name = NULL;
7188 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7189 ucf_flags_from_smb_request(req);
7191 if (dest_has_wcard) {
7192 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7195 /* newname must *not* be a stream name. */
7196 if (newname[0] == ':') {
7197 return NT_STATUS_NOT_SUPPORTED;
7201 * Strip off the last component (filename) of the path passed
7204 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7206 return NT_STATUS_NO_MEMORY;
7208 p = strrchr_m(base_name, '/');
7212 base_name = talloc_strdup(ctx, "");
7214 return NT_STATUS_NO_MEMORY;
7217 /* Append the new name. */
7218 base_name = talloc_asprintf_append(base_name,
7222 return NT_STATUS_NO_MEMORY;
7225 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7228 /* If an error we expect this to be
7229 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7231 if (!NT_STATUS_IS_OK(status)) {
7232 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7236 /* Create an smb_fname to call rename_internals_fsp() */
7237 smb_fname_dst = synthetic_smb_fname(ctx,
7241 smb_fname_src->flags);
7242 if (smb_fname_dst == NULL) {
7243 status = NT_STATUS_NO_MEMORY;
7250 DEBUG(10,("smb_file_rename_information: "
7251 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7252 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7253 smb_fname_str_dbg(smb_fname_dst)));
7254 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7257 DEBUG(10,("smb_file_rename_information: "
7258 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7259 smb_fname_str_dbg(smb_fname_src),
7260 smb_fname_str_dbg(smb_fname_dst)));
7261 status = rename_internals(ctx, conn, req, smb_fname_src,
7262 smb_fname_dst, 0, overwrite, false,
7264 FILE_WRITE_ATTRIBUTES);
7267 TALLOC_FREE(smb_fname_dst);
7271 /****************************************************************************
7272 Deal with SMB_SET_POSIX_ACL.
7273 ****************************************************************************/
7275 #if defined(HAVE_POSIX_ACLS)
7276 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7277 struct smb_request *req,
7281 const struct smb_filename *smb_fname)
7283 uint16_t posix_acl_version;
7284 uint16_t num_file_acls;
7285 uint16_t num_def_acls;
7286 bool valid_file_acls = true;
7287 bool valid_def_acls = true;
7289 unsigned int size_needed;
7290 unsigned int total_data;
7292 if (total_data_in < 0) {
7293 status = NT_STATUS_INVALID_PARAMETER;
7297 total_data = total_data_in;
7299 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7300 status = NT_STATUS_INVALID_PARAMETER;
7303 posix_acl_version = SVAL(pdata,0);
7304 num_file_acls = SVAL(pdata,2);
7305 num_def_acls = SVAL(pdata,4);
7307 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7308 valid_file_acls = false;
7312 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7313 valid_def_acls = false;
7317 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7318 status = NT_STATUS_INVALID_PARAMETER;
7323 if (num_file_acls + num_def_acls < num_file_acls) {
7324 status = NT_STATUS_INVALID_PARAMETER;
7328 size_needed = num_file_acls + num_def_acls;
7331 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7332 * than UINT_MAX, so check by division.
7334 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7335 status = NT_STATUS_INVALID_PARAMETER;
7339 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7340 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7341 status = NT_STATUS_INVALID_PARAMETER;
7344 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7346 if (total_data < size_needed) {
7347 status = NT_STATUS_INVALID_PARAMETER;
7351 status = refuse_symlink(conn, fsp, smb_fname);
7352 if (!NT_STATUS_IS_OK(status)) {
7356 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7357 "num_def_acls = %"PRIu16"\n",
7358 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7362 /* Move pdata to the start of the file ACL entries. */
7363 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7365 if (valid_file_acls) {
7366 bool ok = set_unix_posix_acl(conn,
7372 status = map_nt_error_from_unix(errno);
7377 /* Move pdata to the start of the default ACL entries. */
7378 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7380 if (valid_def_acls) {
7381 bool ok = set_unix_posix_default_acl(conn,
7386 status = map_nt_error_from_unix(errno);
7391 status = NT_STATUS_OK;
7399 /****************************************************************************
7400 Deal with SMB_SET_POSIX_LOCK.
7401 ****************************************************************************/
7403 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7405 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7406 struct smb_request *req,
7411 struct tevent_req *subreq = NULL;
7412 struct smbd_lock_element *lck = NULL;
7416 bool blocking_lock = False;
7417 enum brl_type lock_type;
7419 NTSTATUS status = NT_STATUS_OK;
7421 if (fsp == NULL || fsp->fh->fd == -1) {
7422 return NT_STATUS_INVALID_HANDLE;
7425 if (total_data != POSIX_LOCK_DATA_SIZE) {
7426 return NT_STATUS_INVALID_PARAMETER;
7429 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7430 case POSIX_LOCK_TYPE_READ:
7431 lock_type = READ_LOCK;
7433 case POSIX_LOCK_TYPE_WRITE:
7434 /* Return the right POSIX-mappable error code for files opened read-only. */
7435 if (!fsp->can_write) {
7436 return NT_STATUS_INVALID_HANDLE;
7438 lock_type = WRITE_LOCK;
7440 case POSIX_LOCK_TYPE_UNLOCK:
7441 lock_type = UNLOCK_LOCK;
7444 return NT_STATUS_INVALID_PARAMETER;
7447 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7448 case POSIX_LOCK_FLAG_NOWAIT:
7449 blocking_lock = false;
7451 case POSIX_LOCK_FLAG_WAIT:
7452 blocking_lock = true;
7455 return NT_STATUS_INVALID_PARAMETER;
7458 if (!lp_blocking_locks(SNUM(conn))) {
7459 blocking_lock = False;
7462 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7463 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7464 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7465 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7466 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7468 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7469 "count = %"PRIu64", offset = %"PRIu64"\n",
7471 (unsigned int)lock_type,
7476 if (lock_type == UNLOCK_LOCK) {
7477 struct smbd_lock_element l = {
7479 .brltype = UNLOCK_LOCK,
7483 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7487 lck = talloc(req, struct smbd_lock_element);
7489 return NT_STATUS_NO_MEMORY;
7492 *lck = (struct smbd_lock_element) {
7494 .brltype = lock_type,
7499 subreq = smbd_smb1_do_locks_send(
7502 req->sconn->msg_ctx,
7505 blocking_lock ? UINT32_MAX : 0,
7506 true, /* large_offset */
7510 if (subreq == NULL) {
7512 return NT_STATUS_NO_MEMORY;
7514 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7515 return NT_STATUS_EVENT_PENDING;
7518 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7520 struct smb_request *req = NULL;
7524 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7527 status = smbd_smb1_do_locks_recv(subreq);
7528 TALLOC_FREE(subreq);
7530 if (NT_STATUS_IS_OK(status)) {
7531 char params[2] = {0};
7532 /* Fake up max_data_bytes here - we know it fits. */
7533 send_trans2_replies(
7543 reply_nterror(req, status);
7546 (char *)req->outbuf,
7549 IS_CONN_ENCRYPTED(req->conn),
7552 exit_server_cleanly("smb_set_posix_lock_done: "
7553 "srv_send_smb failed.");
7561 /****************************************************************************
7562 Deal with SMB_SET_FILE_BASIC_INFO.
7563 ****************************************************************************/
7565 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7569 const struct smb_filename *smb_fname)
7571 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7572 struct smb_file_time ft;
7573 uint32_t dosmode = 0;
7574 NTSTATUS status = NT_STATUS_OK;
7578 if (total_data < 36) {
7579 return NT_STATUS_INVALID_PARAMETER;
7582 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7583 if (!NT_STATUS_IS_OK(status)) {
7587 /* Set the attributes */
7588 dosmode = IVAL(pdata,32);
7589 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7590 if (!NT_STATUS_IS_OK(status)) {
7595 ft.create_time = interpret_long_date(pdata);
7598 ft.atime = interpret_long_date(pdata+8);
7601 ft.mtime = interpret_long_date(pdata+16);
7604 ft.ctime = interpret_long_date(pdata+24);
7606 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7607 smb_fname_str_dbg(smb_fname)));
7609 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7613 /****************************************************************************
7614 Deal with SMB_INFO_STANDARD.
7615 ****************************************************************************/
7617 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7621 const struct smb_filename *smb_fname)
7624 struct smb_file_time ft;
7628 if (total_data < 12) {
7629 return NT_STATUS_INVALID_PARAMETER;
7633 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7635 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7637 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7639 DEBUG(10,("smb_set_info_standard: file %s\n",
7640 smb_fname_str_dbg(smb_fname)));
7642 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7643 if (!NT_STATUS_IS_OK(status)) {
7647 return smb_set_file_time(conn,
7654 /****************************************************************************
7655 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7656 ****************************************************************************/
7658 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7659 struct smb_request *req,
7663 struct smb_filename *smb_fname)
7665 uint64_t allocation_size = 0;
7666 NTSTATUS status = NT_STATUS_OK;
7667 files_struct *new_fsp = NULL;
7669 if (!VALID_STAT(smb_fname->st)) {
7670 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7673 if (total_data < 8) {
7674 return NT_STATUS_INVALID_PARAMETER;
7677 allocation_size = (uint64_t)IVAL(pdata,0);
7678 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7679 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7680 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7681 (double)allocation_size));
7683 if (allocation_size) {
7684 allocation_size = smb_roundup(conn, allocation_size);
7687 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7688 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7689 (double)allocation_size));
7691 if (fsp && fsp->fh->fd != -1) {
7692 /* Open file handle. */
7693 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7694 return NT_STATUS_ACCESS_DENIED;
7697 /* Only change if needed. */
7698 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7699 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7700 return map_nt_error_from_unix(errno);
7703 /* But always update the time. */
7705 * This is equivalent to a write. Ensure it's seen immediately
7706 * if there are no pending writes.
7708 trigger_write_time_update_immediate(fsp);
7709 return NT_STATUS_OK;
7712 /* Pathname or stat or directory file. */
7713 status = SMB_VFS_CREATE_FILE(
7716 0, /* root_dir_fid */
7717 smb_fname, /* fname */
7718 FILE_WRITE_DATA, /* access_mask */
7719 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7721 FILE_OPEN, /* create_disposition*/
7722 0, /* create_options */
7723 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7724 0, /* oplock_request */
7726 0, /* allocation_size */
7727 0, /* private_flags */
7730 &new_fsp, /* result */
7732 NULL, NULL); /* create context */
7734 if (!NT_STATUS_IS_OK(status)) {
7735 /* NB. We check for open_was_deferred in the caller. */
7739 /* Only change if needed. */
7740 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7741 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7742 status = map_nt_error_from_unix(errno);
7743 close_file(req, new_fsp, NORMAL_CLOSE);
7748 /* Changing the allocation size should set the last mod time. */
7750 * This is equivalent to a write. Ensure it's seen immediately
7751 * if there are no pending writes.
7753 trigger_write_time_update_immediate(new_fsp);
7754 close_file(req, new_fsp, NORMAL_CLOSE);
7755 return NT_STATUS_OK;
7758 /****************************************************************************
7759 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7760 ****************************************************************************/
7762 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7763 struct smb_request *req,
7767 const struct smb_filename *smb_fname,
7768 bool fail_after_createfile)
7772 if (total_data < 8) {
7773 return NT_STATUS_INVALID_PARAMETER;
7776 size = IVAL(pdata,0);
7777 size |= (((off_t)IVAL(pdata,4)) << 32);
7778 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7779 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7782 return smb_set_file_size(conn, req,
7787 fail_after_createfile);
7790 /****************************************************************************
7791 Allow a UNIX info mknod.
7792 ****************************************************************************/
7794 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7797 const struct smb_filename *smb_fname)
7799 uint32_t file_type = IVAL(pdata,56);
7800 #if defined(HAVE_MAKEDEV)
7801 uint32_t dev_major = IVAL(pdata,60);
7802 uint32_t dev_minor = IVAL(pdata,68);
7804 SMB_DEV_T dev = (SMB_DEV_T)0;
7805 uint32_t raw_unixmode = IVAL(pdata,84);
7809 if (total_data < 100) {
7810 return NT_STATUS_INVALID_PARAMETER;
7813 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7814 PERM_NEW_FILE, &unixmode);
7815 if (!NT_STATUS_IS_OK(status)) {
7819 #if defined(HAVE_MAKEDEV)
7820 dev = makedev(dev_major, dev_minor);
7823 switch (file_type) {
7824 #if defined(S_IFIFO)
7825 case UNIX_TYPE_FIFO:
7826 unixmode |= S_IFIFO;
7829 #if defined(S_IFSOCK)
7830 case UNIX_TYPE_SOCKET:
7831 unixmode |= S_IFSOCK;
7834 #if defined(S_IFCHR)
7835 case UNIX_TYPE_CHARDEV:
7836 unixmode |= S_IFCHR;
7839 #if defined(S_IFBLK)
7840 case UNIX_TYPE_BLKDEV:
7841 unixmode |= S_IFBLK;
7845 return NT_STATUS_INVALID_PARAMETER;
7848 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7849 "%.0f mode 0%o for file %s\n", (double)dev,
7850 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7852 /* Ok - do the mknod. */
7853 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7854 return map_nt_error_from_unix(errno);
7857 /* If any of the other "set" calls fail we
7858 * don't want to end up with a half-constructed mknod.
7861 if (lp_inherit_permissions(SNUM(conn))) {
7863 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7865 return NT_STATUS_NO_MEMORY;
7867 inherit_access_posix_acl(conn, parent, smb_fname,
7869 TALLOC_FREE(parent);
7872 return NT_STATUS_OK;
7875 /****************************************************************************
7876 Deal with SMB_SET_FILE_UNIX_BASIC.
7877 ****************************************************************************/
7879 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7880 struct smb_request *req,
7884 const struct smb_filename *smb_fname)
7886 struct smb_file_time ft;
7887 uint32_t raw_unixmode;
7890 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7891 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7892 NTSTATUS status = NT_STATUS_OK;
7893 bool delete_on_fail = False;
7894 enum perm_type ptype;
7895 files_struct *all_fsps = NULL;
7896 bool modify_mtime = true;
7898 struct smb_filename *smb_fname_tmp = NULL;
7899 SMB_STRUCT_STAT sbuf;
7903 if (total_data < 100) {
7904 return NT_STATUS_INVALID_PARAMETER;
7907 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7908 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7909 size=IVAL(pdata,0); /* first 8 Bytes are size */
7910 size |= (((off_t)IVAL(pdata,4)) << 32);
7913 ft.atime = interpret_long_date(pdata+24); /* access_time */
7914 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7915 set_owner = (uid_t)IVAL(pdata,40);
7916 set_grp = (gid_t)IVAL(pdata,48);
7917 raw_unixmode = IVAL(pdata,84);
7919 if (VALID_STAT(smb_fname->st)) {
7920 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7921 ptype = PERM_EXISTING_DIR;
7923 ptype = PERM_EXISTING_FILE;
7926 ptype = PERM_NEW_FILE;
7929 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7931 if (!NT_STATUS_IS_OK(status)) {
7935 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7936 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7937 smb_fname_str_dbg(smb_fname), (double)size,
7938 (unsigned int)set_owner, (unsigned int)set_grp,
7939 (int)raw_unixmode));
7941 sbuf = smb_fname->st;
7943 if (!VALID_STAT(sbuf)) {
7945 * The only valid use of this is to create character and block
7946 * devices, and named pipes. This is deprecated (IMHO) and
7947 * a new info level should be used for mknod. JRA.
7950 status = smb_unix_mknod(conn,
7954 if (!NT_STATUS_IS_OK(status)) {
7958 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7959 if (smb_fname_tmp == NULL) {
7960 return NT_STATUS_NO_MEMORY;
7963 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7964 status = map_nt_error_from_unix(errno);
7965 TALLOC_FREE(smb_fname_tmp);
7966 SMB_VFS_UNLINK(conn, smb_fname);
7970 sbuf = smb_fname_tmp->st;
7971 smb_fname = smb_fname_tmp;
7973 /* Ensure we don't try and change anything else. */
7974 raw_unixmode = SMB_MODE_NO_CHANGE;
7975 size = get_file_size_stat(&sbuf);
7976 ft.atime = sbuf.st_ex_atime;
7977 ft.mtime = sbuf.st_ex_mtime;
7979 * We continue here as we might want to change the
7982 delete_on_fail = True;
7986 /* Horrible backwards compatibility hack as an old server bug
7987 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7991 size = get_file_size_stat(&sbuf);
7996 * Deal with the UNIX specific mode set.
7999 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8002 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8003 "setting mode 0%o for file %s\n",
8004 (unsigned int)unixmode,
8005 smb_fname_str_dbg(smb_fname)));
8006 if (fsp && fsp->fh->fd != -1) {
8007 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8009 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8012 return map_nt_error_from_unix(errno);
8017 * Deal with the UNIX specific uid set.
8020 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8021 (sbuf.st_ex_uid != set_owner)) {
8024 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8025 "changing owner %u for path %s\n",
8026 (unsigned int)set_owner,
8027 smb_fname_str_dbg(smb_fname)));
8029 if (fsp && fsp->fh->fd != -1) {
8030 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8033 * UNIX extensions calls must always operate
8036 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8037 set_owner, (gid_t)-1);
8041 status = map_nt_error_from_unix(errno);
8042 if (delete_on_fail) {
8043 SMB_VFS_UNLINK(conn, smb_fname);
8050 * Deal with the UNIX specific gid set.
8053 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8054 (sbuf.st_ex_gid != set_grp)) {
8057 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8058 "changing group %u for file %s\n",
8059 (unsigned int)set_grp,
8060 smb_fname_str_dbg(smb_fname)));
8061 if (fsp && fsp->fh->fd != -1) {
8062 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8065 * UNIX extensions calls must always operate
8068 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8072 status = map_nt_error_from_unix(errno);
8073 if (delete_on_fail) {
8074 SMB_VFS_UNLINK(conn, smb_fname);
8080 /* Deal with any size changes. */
8082 status = smb_set_file_size(conn, req,
8088 if (!NT_STATUS_IS_OK(status)) {
8092 /* Deal with any time changes. */
8093 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
8094 /* No change, don't cancel anything. */
8098 id = vfs_file_id_from_sbuf(conn, &sbuf);
8099 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8100 all_fsps = file_find_di_next(all_fsps)) {
8102 * We're setting the time explicitly for UNIX.
8103 * Cancel any pending changes over all handles.
8105 all_fsps->update_write_time_on_close = false;
8106 TALLOC_FREE(all_fsps->update_write_time_event);
8110 * Override the "setting_write_time"
8111 * parameter here as it almost does what
8112 * we need. Just remember if we modified
8113 * mtime and send the notify ourselves.
8115 if (null_timespec(ft.mtime)) {
8116 modify_mtime = false;
8119 status = smb_set_file_time(conn,
8125 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8126 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8131 /****************************************************************************
8132 Deal with SMB_SET_FILE_UNIX_INFO2.
8133 ****************************************************************************/
8135 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8136 struct smb_request *req,
8140 const struct smb_filename *smb_fname)
8143 uint32_t smb_fflags;
8146 if (total_data < 116) {
8147 return NT_STATUS_INVALID_PARAMETER;
8150 /* Start by setting all the fields that are common between UNIX_BASIC
8153 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8155 if (!NT_STATUS_IS_OK(status)) {
8159 smb_fflags = IVAL(pdata, 108);
8160 smb_fmask = IVAL(pdata, 112);
8162 /* NB: We should only attempt to alter the file flags if the client
8163 * sends a non-zero mask.
8165 if (smb_fmask != 0) {
8166 int stat_fflags = 0;
8168 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8169 smb_fmask, &stat_fflags)) {
8170 /* Client asked to alter a flag we don't understand. */
8171 return NT_STATUS_INVALID_PARAMETER;
8174 if (fsp && fsp->fh->fd != -1) {
8175 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8176 return NT_STATUS_NOT_SUPPORTED;
8178 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8179 stat_fflags) != 0) {
8180 return map_nt_error_from_unix(errno);
8185 /* XXX: need to add support for changing the create_time here. You
8186 * can do this for paths on Darwin with setattrlist(2). The right way
8187 * to hook this up is probably by extending the VFS utimes interface.
8190 return NT_STATUS_OK;
8193 /****************************************************************************
8194 Create a directory with POSIX semantics.
8195 ****************************************************************************/
8197 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8198 struct smb_request *req,
8201 struct smb_filename *smb_fname,
8202 int *pdata_return_size)
8204 NTSTATUS status = NT_STATUS_OK;
8205 uint32_t raw_unixmode = 0;
8206 uint32_t mod_unixmode = 0;
8207 mode_t unixmode = (mode_t)0;
8208 files_struct *fsp = NULL;
8209 uint16_t info_level_return = 0;
8211 char *pdata = *ppdata;
8213 if (total_data < 18) {
8214 return NT_STATUS_INVALID_PARAMETER;
8217 raw_unixmode = IVAL(pdata,8);
8218 /* Next 4 bytes are not yet defined. */
8220 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8221 PERM_NEW_DIR, &unixmode);
8222 if (!NT_STATUS_IS_OK(status)) {
8226 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8228 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8229 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8231 status = SMB_VFS_CREATE_FILE(
8234 0, /* root_dir_fid */
8235 smb_fname, /* fname */
8236 FILE_READ_ATTRIBUTES, /* access_mask */
8237 FILE_SHARE_NONE, /* share_access */
8238 FILE_CREATE, /* create_disposition*/
8239 FILE_DIRECTORY_FILE, /* create_options */
8240 mod_unixmode, /* file_attributes */
8241 0, /* oplock_request */
8243 0, /* allocation_size */
8244 0, /* private_flags */
8249 NULL, NULL); /* create context */
8251 if (NT_STATUS_IS_OK(status)) {
8252 close_file(req, fsp, NORMAL_CLOSE);
8255 info_level_return = SVAL(pdata,16);
8257 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8258 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8259 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8260 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8262 *pdata_return_size = 12;
8265 /* Realloc the data size */
8266 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8267 if (*ppdata == NULL) {
8268 *pdata_return_size = 0;
8269 return NT_STATUS_NO_MEMORY;
8273 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8274 SSVAL(pdata,2,0); /* No fnum. */
8275 SIVAL(pdata,4,info); /* Was directory created. */
8277 switch (info_level_return) {
8278 case SMB_QUERY_FILE_UNIX_BASIC:
8279 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8280 SSVAL(pdata,10,0); /* Padding. */
8281 store_file_unix_basic(conn, pdata + 12, fsp,
8284 case SMB_QUERY_FILE_UNIX_INFO2:
8285 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8286 SSVAL(pdata,10,0); /* Padding. */
8287 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8291 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8292 SSVAL(pdata,10,0); /* Padding. */
8299 /****************************************************************************
8300 Open/Create a file with POSIX semantics.
8301 ****************************************************************************/
8303 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8304 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8306 static NTSTATUS smb_posix_open(connection_struct *conn,
8307 struct smb_request *req,
8310 struct smb_filename *smb_fname,
8311 int *pdata_return_size)
8313 bool extended_oplock_granted = False;
8314 char *pdata = *ppdata;
8316 uint32_t wire_open_mode = 0;
8317 uint32_t raw_unixmode = 0;
8318 uint32_t mod_unixmode = 0;
8319 uint32_t create_disp = 0;
8320 uint32_t access_mask = 0;
8321 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8322 NTSTATUS status = NT_STATUS_OK;
8323 mode_t unixmode = (mode_t)0;
8324 files_struct *fsp = NULL;
8325 int oplock_request = 0;
8327 uint16_t info_level_return = 0;
8329 if (total_data < 18) {
8330 return NT_STATUS_INVALID_PARAMETER;
8333 flags = IVAL(pdata,0);
8334 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8335 if (oplock_request) {
8336 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8339 wire_open_mode = IVAL(pdata,4);
8341 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8342 return smb_posix_mkdir(conn, req,
8349 switch (wire_open_mode & SMB_ACCMODE) {
8351 access_mask = SMB_O_RDONLY_MAPPING;
8354 access_mask = SMB_O_WRONLY_MAPPING;
8357 access_mask = (SMB_O_RDONLY_MAPPING|
8358 SMB_O_WRONLY_MAPPING);
8361 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8362 (unsigned int)wire_open_mode ));
8363 return NT_STATUS_INVALID_PARAMETER;
8366 wire_open_mode &= ~SMB_ACCMODE;
8368 /* First take care of O_CREAT|O_EXCL interactions. */
8369 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8370 case (SMB_O_CREAT | SMB_O_EXCL):
8371 /* File exists fail. File not exist create. */
8372 create_disp = FILE_CREATE;
8375 /* File exists open. File not exist create. */
8376 create_disp = FILE_OPEN_IF;
8379 /* O_EXCL on its own without O_CREAT is undefined.
8380 We deliberately ignore it as some versions of
8381 Linux CIFSFS can send a bare O_EXCL on the
8382 wire which other filesystems in the kernel
8383 ignore. See bug 9519 for details. */
8388 /* File exists open. File not exist fail. */
8389 create_disp = FILE_OPEN;
8392 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8393 (unsigned int)wire_open_mode ));
8394 return NT_STATUS_INVALID_PARAMETER;
8397 /* Next factor in the effects of O_TRUNC. */
8398 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8400 if (wire_open_mode & SMB_O_TRUNC) {
8401 switch (create_disp) {
8403 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8404 /* Leave create_disp alone as
8405 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8407 /* File exists fail. File not exist create. */
8410 /* SMB_O_CREAT | SMB_O_TRUNC */
8411 /* File exists overwrite. File not exist create. */
8412 create_disp = FILE_OVERWRITE_IF;
8416 /* File exists overwrite. File not exist fail. */
8417 create_disp = FILE_OVERWRITE;
8420 /* Cannot get here. */
8421 smb_panic("smb_posix_open: logic error");
8422 return NT_STATUS_INVALID_PARAMETER;
8426 raw_unixmode = IVAL(pdata,8);
8427 /* Next 4 bytes are not yet defined. */
8429 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8430 (VALID_STAT(smb_fname->st) ?
8431 PERM_EXISTING_FILE : PERM_NEW_FILE),
8434 if (!NT_STATUS_IS_OK(status)) {
8438 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8440 if (wire_open_mode & SMB_O_SYNC) {
8441 create_options |= FILE_WRITE_THROUGH;
8443 if (wire_open_mode & SMB_O_APPEND) {
8444 access_mask |= FILE_APPEND_DATA;
8446 if (wire_open_mode & SMB_O_DIRECT) {
8447 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8450 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8451 VALID_STAT_OF_DIR(smb_fname->st)) {
8452 if (access_mask != SMB_O_RDONLY_MAPPING) {
8453 return NT_STATUS_FILE_IS_A_DIRECTORY;
8455 create_options &= ~FILE_NON_DIRECTORY_FILE;
8456 create_options |= FILE_DIRECTORY_FILE;
8459 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8460 smb_fname_str_dbg(smb_fname),
8461 (unsigned int)wire_open_mode,
8462 (unsigned int)unixmode ));
8464 status = SMB_VFS_CREATE_FILE(
8467 0, /* root_dir_fid */
8468 smb_fname, /* fname */
8469 access_mask, /* access_mask */
8470 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8472 create_disp, /* create_disposition*/
8473 create_options, /* create_options */
8474 mod_unixmode, /* file_attributes */
8475 oplock_request, /* oplock_request */
8477 0, /* allocation_size */
8478 0, /* private_flags */
8483 NULL, NULL); /* create context */
8485 if (!NT_STATUS_IS_OK(status)) {
8489 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8490 extended_oplock_granted = True;
8493 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8494 extended_oplock_granted = True;
8497 info_level_return = SVAL(pdata,16);
8499 /* Allocate the correct return size. */
8501 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8502 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8503 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8504 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8506 *pdata_return_size = 12;
8509 /* Realloc the data size */
8510 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8511 if (*ppdata == NULL) {
8512 close_file(req, fsp, ERROR_CLOSE);
8513 *pdata_return_size = 0;
8514 return NT_STATUS_NO_MEMORY;
8518 if (extended_oplock_granted) {
8519 if (flags & REQUEST_BATCH_OPLOCK) {
8520 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8522 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8524 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8525 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8527 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8530 SSVAL(pdata,2,fsp->fnum);
8531 SIVAL(pdata,4,info); /* Was file created etc. */
8533 switch (info_level_return) {
8534 case SMB_QUERY_FILE_UNIX_BASIC:
8535 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8536 SSVAL(pdata,10,0); /* padding. */
8537 store_file_unix_basic(conn, pdata + 12, fsp,
8540 case SMB_QUERY_FILE_UNIX_INFO2:
8541 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8542 SSVAL(pdata,10,0); /* padding. */
8543 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8547 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8548 SSVAL(pdata,10,0); /* padding. */
8551 return NT_STATUS_OK;
8554 /****************************************************************************
8555 Delete a file with POSIX semantics.
8556 ****************************************************************************/
8558 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8559 struct smb_request *req,
8562 struct smb_filename *smb_fname)
8564 struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
8565 NTSTATUS status = NT_STATUS_OK;
8566 files_struct *fsp = NULL;
8570 int create_options = 0;
8571 struct share_mode_lock *lck = NULL;
8572 bool other_nonposix_opens;
8574 if (total_data < 2) {
8575 return NT_STATUS_INVALID_PARAMETER;
8578 flags = SVAL(pdata,0);
8580 if (!VALID_STAT(smb_fname->st)) {
8581 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8584 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8585 !VALID_STAT_OF_DIR(smb_fname->st)) {
8586 return NT_STATUS_NOT_A_DIRECTORY;
8589 DEBUG(10,("smb_posix_unlink: %s %s\n",
8590 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8591 smb_fname_str_dbg(smb_fname)));
8593 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8594 create_options |= FILE_DIRECTORY_FILE;
8597 status = SMB_VFS_CREATE_FILE(
8600 0, /* root_dir_fid */
8601 smb_fname, /* fname */
8602 DELETE_ACCESS, /* access_mask */
8603 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8605 FILE_OPEN, /* create_disposition*/
8606 create_options, /* create_options */
8607 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8608 0, /* oplock_request */
8610 0, /* allocation_size */
8611 0, /* private_flags */
8616 NULL, NULL); /* create context */
8618 if (!NT_STATUS_IS_OK(status)) {
8623 * Don't lie to client. If we can't really delete due to
8624 * non-POSIX opens return SHARING_VIOLATION.
8627 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8629 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8630 "lock for file %s\n", fsp_str_dbg(fsp)));
8631 close_file(req, fsp, NORMAL_CLOSE);
8632 return NT_STATUS_INVALID_PARAMETER;
8635 other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
8636 if (other_nonposix_opens) {
8637 /* Fail with sharing violation. */
8639 close_file(req, fsp, NORMAL_CLOSE);
8640 return NT_STATUS_SHARING_VIOLATION;
8644 * Set the delete on close.
8646 status = smb_set_file_disposition_info(conn,
8654 if (!NT_STATUS_IS_OK(status)) {
8655 close_file(req, fsp, NORMAL_CLOSE);
8658 return close_file(req, fsp, NORMAL_CLOSE);
8661 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8662 struct smb_request *req,
8663 TALLOC_CTX *mem_ctx,
8664 uint16_t info_level,
8666 struct smb_filename *smb_fname,
8667 char **ppdata, int total_data,
8670 char *pdata = *ppdata;
8671 NTSTATUS status = NT_STATUS_OK;
8672 int data_return_size = 0;
8676 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8677 return NT_STATUS_INVALID_LEVEL;
8680 if (!CAN_WRITE(conn)) {
8681 /* Allow POSIX opens. The open path will deny
8682 * any non-readonly opens. */
8683 if (info_level != SMB_POSIX_PATH_OPEN) {
8684 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8688 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8689 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8691 info_level, total_data));
8693 switch (info_level) {
8695 case SMB_INFO_STANDARD:
8697 status = smb_set_info_standard(conn,
8705 case SMB_INFO_SET_EA:
8707 status = smb_info_set_ea(conn,
8715 case SMB_SET_FILE_BASIC_INFO:
8716 case SMB_FILE_BASIC_INFORMATION:
8718 status = smb_set_file_basic_info(conn,
8726 case SMB_FILE_ALLOCATION_INFORMATION:
8727 case SMB_SET_FILE_ALLOCATION_INFO:
8729 status = smb_set_file_allocation_info(conn, req,
8737 case SMB_FILE_END_OF_FILE_INFORMATION:
8738 case SMB_SET_FILE_END_OF_FILE_INFO:
8741 * XP/Win7 both fail after the createfile with
8742 * SMB_SET_FILE_END_OF_FILE_INFO but not
8743 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8744 * The level is known here, so pass it down
8748 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8750 status = smb_set_file_end_of_file_info(conn, req,
8759 case SMB_FILE_DISPOSITION_INFORMATION:
8760 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8763 /* JRA - We used to just ignore this on a path ?
8764 * Shouldn't this be invalid level on a pathname
8767 if (tran_call != TRANSACT2_SETFILEINFO) {
8768 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8771 status = smb_set_file_disposition_info(conn,
8779 case SMB_FILE_POSITION_INFORMATION:
8781 status = smb_file_position_information(conn,
8788 case SMB_FILE_FULL_EA_INFORMATION:
8790 status = smb_set_file_full_ea_info(conn,
8797 /* From tridge Samba4 :
8798 * MODE_INFORMATION in setfileinfo (I have no
8799 * idea what "mode information" on a file is - it takes a value of 0,
8800 * 2, 4 or 6. What could it be?).
8803 case SMB_FILE_MODE_INFORMATION:
8805 status = smb_file_mode_information(conn,
8811 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8812 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8813 case SMB_FILE_SHORT_NAME_INFORMATION:
8814 return NT_STATUS_NOT_SUPPORTED;
8817 * CIFS UNIX extensions.
8820 case SMB_SET_FILE_UNIX_BASIC:
8822 status = smb_set_file_unix_basic(conn, req,
8830 case SMB_SET_FILE_UNIX_INFO2:
8832 status = smb_set_file_unix_info2(conn, req,
8840 case SMB_SET_FILE_UNIX_LINK:
8843 /* We must have a pathname for this. */
8844 return NT_STATUS_INVALID_LEVEL;
8846 status = smb_set_file_unix_link(conn, req, pdata,
8847 total_data, smb_fname);
8851 case SMB_SET_FILE_UNIX_HLINK:
8854 /* We must have a pathname for this. */
8855 return NT_STATUS_INVALID_LEVEL;
8857 status = smb_set_file_unix_hlink(conn, req,
8863 case SMB_FILE_RENAME_INFORMATION:
8865 status = smb_file_rename_information(conn, req,
8871 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8873 /* SMB2 rename information. */
8874 status = smb2_file_rename_information(conn, req,
8880 case SMB_FILE_LINK_INFORMATION:
8882 status = smb_file_link_information(conn, req,
8888 #if defined(HAVE_POSIX_ACLS)
8889 case SMB_SET_POSIX_ACL:
8891 status = smb_set_posix_acl(conn,
8901 case SMB_SET_POSIX_LOCK:
8904 return NT_STATUS_INVALID_LEVEL;
8906 status = smb_set_posix_lock(conn, req,
8907 pdata, total_data, fsp);
8911 case SMB_POSIX_PATH_OPEN:
8914 /* We must have a pathname for this. */
8915 return NT_STATUS_INVALID_LEVEL;
8918 status = smb_posix_open(conn, req,
8926 case SMB_POSIX_PATH_UNLINK:
8929 /* We must have a pathname for this. */
8930 return NT_STATUS_INVALID_LEVEL;
8933 status = smb_posix_unlink(conn, req,
8941 return NT_STATUS_INVALID_LEVEL;
8944 if (!NT_STATUS_IS_OK(status)) {
8948 *ret_data_size = data_return_size;
8949 return NT_STATUS_OK;
8952 /****************************************************************************
8953 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8954 ****************************************************************************/
8956 static void call_trans2setfilepathinfo(connection_struct *conn,
8957 struct smb_request *req,
8958 unsigned int tran_call,
8959 char **pparams, int total_params,
8960 char **ppdata, int total_data,
8961 unsigned int max_data_bytes)
8963 char *params = *pparams;
8964 char *pdata = *ppdata;
8965 uint16_t info_level;
8966 struct smb_filename *smb_fname = NULL;
8967 files_struct *fsp = NULL;
8968 NTSTATUS status = NT_STATUS_OK;
8969 int data_return_size = 0;
8972 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8976 if (tran_call == TRANSACT2_SETFILEINFO) {
8977 if (total_params < 4) {
8978 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8982 fsp = file_fsp(req, SVAL(params,0));
8983 /* Basic check for non-null fsp. */
8984 if (!check_fsp_open(conn, req, fsp)) {
8987 info_level = SVAL(params,2);
8989 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8990 if (smb_fname == NULL) {
8991 reply_nterror(req, NT_STATUS_NO_MEMORY);
8995 if(fsp->fh->fd == -1) {
8997 * This is actually a SETFILEINFO on a directory
8998 * handle (returned from an NT SMB). NT5.0 seems
8999 * to do this call. JRA.
9001 if (INFO_LEVEL_IS_UNIX(info_level)) {
9002 /* Always do lstat for UNIX calls. */
9003 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9004 DEBUG(3,("call_trans2setfilepathinfo: "
9005 "SMB_VFS_LSTAT of %s failed "
9007 smb_fname_str_dbg(smb_fname),
9009 reply_nterror(req, map_nt_error_from_unix(errno));
9013 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9014 DEBUG(3,("call_trans2setfilepathinfo: "
9015 "fileinfo of %s failed (%s)\n",
9016 smb_fname_str_dbg(smb_fname),
9018 reply_nterror(req, map_nt_error_from_unix(errno));
9022 } else if (fsp->print_file) {
9024 * Doing a DELETE_ON_CLOSE should cancel a print job.
9026 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9027 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9029 DEBUG(3,("call_trans2setfilepathinfo: "
9030 "Cancelling print job (%s)\n",
9034 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9040 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9045 * Original code - this is an open file.
9047 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9048 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9049 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9051 reply_nterror(req, map_nt_error_from_unix(errno));
9057 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9060 if (total_params < 7) {
9061 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9065 info_level = SVAL(params,0);
9066 if (req->posix_pathnames) {
9067 srvstr_get_path_posix(req,
9076 srvstr_get_path(req,
9085 if (!NT_STATUS_IS_OK(status)) {
9086 reply_nterror(req, status);
9090 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9091 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9092 info_level == SMB_FILE_RENAME_INFORMATION ||
9093 info_level == SMB_POSIX_PATH_OPEN ||
9094 info_level == SMB_POSIX_PATH_UNLINK) {
9095 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9098 status = filename_convert(req, conn,
9104 if (!NT_STATUS_IS_OK(status)) {
9105 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9106 reply_botherror(req,
9107 NT_STATUS_PATH_NOT_COVERED,
9108 ERRSRV, ERRbadpath);
9111 reply_nterror(req, status);
9115 if (INFO_LEVEL_IS_UNIX(info_level)) {
9117 * For CIFS UNIX extensions the target name may not exist.
9120 /* Always do lstat for UNIX calls. */
9121 SMB_VFS_LSTAT(conn, smb_fname);
9123 } else if (!VALID_STAT(smb_fname->st) &&
9124 SMB_VFS_STAT(conn, smb_fname)) {
9125 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9127 smb_fname_str_dbg(smb_fname),
9129 reply_nterror(req, map_nt_error_from_unix(errno));
9134 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9135 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9137 info_level,total_data));
9139 /* Realloc the parameter size */
9140 *pparams = (char *)SMB_REALLOC(*pparams,2);
9141 if (*pparams == NULL) {
9142 reply_nterror(req, NT_STATUS_NO_MEMORY);
9149 status = smbd_do_setfilepathinfo(conn, req, req,
9155 if (!NT_STATUS_IS_OK(status)) {
9156 if (open_was_deferred(req->xconn, req->mid)) {
9157 /* We have re-scheduled this call. */
9160 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9161 /* We have re-scheduled this call. */
9164 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9165 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9166 ERRSRV, ERRbadpath);
9169 if (info_level == SMB_POSIX_PATH_OPEN) {
9170 reply_openerror(req, status);
9175 * Invalid EA name needs to return 2 param bytes,
9176 * not a zero-length error packet.
9178 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9179 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9182 reply_nterror(req, status);
9187 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9193 /****************************************************************************
9194 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9195 ****************************************************************************/
9197 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9198 char **pparams, int total_params,
9199 char **ppdata, int total_data,
9200 unsigned int max_data_bytes)
9202 struct smb_filename *smb_dname = NULL;
9203 char *params = *pparams;
9204 char *pdata = *ppdata;
9205 char *directory = NULL;
9206 NTSTATUS status = NT_STATUS_OK;
9207 struct ea_list *ea_list = NULL;
9208 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9209 TALLOC_CTX *ctx = talloc_tos();
9211 if (!CAN_WRITE(conn)) {
9212 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9216 if (total_params < 5) {
9217 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9221 if (req->posix_pathnames) {
9222 srvstr_get_path_posix(ctx,
9231 srvstr_get_path(ctx,
9240 if (!NT_STATUS_IS_OK(status)) {
9241 reply_nterror(req, status);
9245 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9247 status = filename_convert(ctx,
9255 if (!NT_STATUS_IS_OK(status)) {
9256 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9257 reply_botherror(req,
9258 NT_STATUS_PATH_NOT_COVERED,
9259 ERRSRV, ERRbadpath);
9262 reply_nterror(req, status);
9267 * OS/2 workplace shell seems to send SET_EA requests of "null"
9268 * length (4 bytes containing IVAL 4).
9269 * They seem to have no effect. Bug #3212. JRA.
9272 if (total_data && (total_data != 4)) {
9273 /* Any data in this call is an EA list. */
9274 if (total_data < 10) {
9275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9279 if (IVAL(pdata,0) > total_data) {
9280 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9281 IVAL(pdata,0), (unsigned int)total_data));
9282 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9286 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9289 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9293 if (!lp_ea_support(SNUM(conn))) {
9294 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9298 /* If total_data == 4 Windows doesn't care what values
9299 * are placed in that field, it just ignores them.
9300 * The System i QNTC IBM SMB client puts bad values here,
9301 * so ignore them. */
9303 status = create_directory(conn, req, smb_dname);
9305 if (!NT_STATUS_IS_OK(status)) {
9306 reply_nterror(req, status);
9310 /* Try and set any given EA. */
9312 status = set_ea(conn, NULL, smb_dname, ea_list);
9313 if (!NT_STATUS_IS_OK(status)) {
9314 reply_nterror(req, status);
9319 /* Realloc the parameter and data sizes */
9320 *pparams = (char *)SMB_REALLOC(*pparams,2);
9321 if(*pparams == NULL) {
9322 reply_nterror(req, NT_STATUS_NO_MEMORY);
9329 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9332 TALLOC_FREE(smb_dname);
9336 /****************************************************************************
9337 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9338 We don't actually do this - we just send a null response.
9339 ****************************************************************************/
9341 static void call_trans2findnotifyfirst(connection_struct *conn,
9342 struct smb_request *req,
9343 char **pparams, int total_params,
9344 char **ppdata, int total_data,
9345 unsigned int max_data_bytes)
9347 char *params = *pparams;
9348 uint16_t info_level;
9350 if (total_params < 6) {
9351 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9355 info_level = SVAL(params,4);
9356 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9358 switch (info_level) {
9363 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9367 /* Realloc the parameter and data sizes */
9368 *pparams = (char *)SMB_REALLOC(*pparams,6);
9369 if (*pparams == NULL) {
9370 reply_nterror(req, NT_STATUS_NO_MEMORY);
9375 SSVAL(params,0,fnf_handle);
9376 SSVAL(params,2,0); /* No changes */
9377 SSVAL(params,4,0); /* No EA errors */
9384 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9389 /****************************************************************************
9390 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9391 changes). Currently this does nothing.
9392 ****************************************************************************/
9394 static void call_trans2findnotifynext(connection_struct *conn,
9395 struct smb_request *req,
9396 char **pparams, int total_params,
9397 char **ppdata, int total_data,
9398 unsigned int max_data_bytes)
9400 char *params = *pparams;
9402 DEBUG(3,("call_trans2findnotifynext\n"));
9404 /* Realloc the parameter and data sizes */
9405 *pparams = (char *)SMB_REALLOC(*pparams,4);
9406 if (*pparams == NULL) {
9407 reply_nterror(req, NT_STATUS_NO_MEMORY);
9412 SSVAL(params,0,0); /* No changes */
9413 SSVAL(params,2,0); /* No EA errors */
9415 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9420 /****************************************************************************
9421 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9422 ****************************************************************************/
9424 static void call_trans2getdfsreferral(connection_struct *conn,
9425 struct smb_request *req,
9426 char **pparams, int total_params,
9427 char **ppdata, int total_data,
9428 unsigned int max_data_bytes)
9430 char *params = *pparams;
9431 char *pathname = NULL;
9433 int max_referral_level;
9434 NTSTATUS status = NT_STATUS_OK;
9435 TALLOC_CTX *ctx = talloc_tos();
9437 DEBUG(10,("call_trans2getdfsreferral\n"));
9439 if (total_params < 3) {
9440 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9444 max_referral_level = SVAL(params,0);
9446 if(!lp_host_msdfs()) {
9447 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9451 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9452 total_params - 2, STR_TERMINATE);
9454 reply_nterror(req, NT_STATUS_NOT_FOUND);
9457 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9458 ppdata,&status)) < 0) {
9459 reply_nterror(req, status);
9463 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9464 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9465 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9470 #define LMCAT_SPL 0x53
9471 #define LMFUNC_GETJOBID 0x60
9473 /****************************************************************************
9474 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9475 ****************************************************************************/
9477 static void call_trans2ioctl(connection_struct *conn,
9478 struct smb_request *req,
9479 char **pparams, int total_params,
9480 char **ppdata, int total_data,
9481 unsigned int max_data_bytes)
9483 char *pdata = *ppdata;
9484 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9488 /* check for an invalid fid before proceeding */
9491 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9495 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9496 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9497 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9498 if (*ppdata == NULL) {
9499 reply_nterror(req, NT_STATUS_NO_MEMORY);
9504 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9505 CAN ACCEPT THIS IN UNICODE. JRA. */
9508 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9510 status = srvstr_push(pdata, req->flags2, pdata + 2,
9511 lp_netbios_name(), 15,
9512 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9513 if (!NT_STATUS_IS_OK(status)) {
9514 reply_nterror(req, status);
9517 status = srvstr_push(pdata, req->flags2, pdata+18,
9518 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9519 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9520 if (!NT_STATUS_IS_OK(status)) {
9521 reply_nterror(req, status);
9524 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9529 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9530 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9533 /****************************************************************************
9534 Reply to a SMBfindclose (stop trans2 directory search).
9535 ****************************************************************************/
9537 void reply_findclose(struct smb_request *req)
9540 struct smbd_server_connection *sconn = req->sconn;
9542 START_PROFILE(SMBfindclose);
9545 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9546 END_PROFILE(SMBfindclose);
9550 dptr_num = SVALS(req->vwv+0, 0);
9552 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9554 dptr_close(sconn, &dptr_num);
9556 reply_outbuf(req, 0, 0);
9558 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9560 END_PROFILE(SMBfindclose);
9564 /****************************************************************************
9565 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9566 ****************************************************************************/
9568 void reply_findnclose(struct smb_request *req)
9572 START_PROFILE(SMBfindnclose);
9575 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9576 END_PROFILE(SMBfindnclose);
9580 dptr_num = SVAL(req->vwv+0, 0);
9582 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9584 /* We never give out valid handles for a
9585 findnotifyfirst - so any dptr_num is ok here.
9588 reply_outbuf(req, 0, 0);
9590 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9592 END_PROFILE(SMBfindnclose);
9596 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9597 struct trans_state *state)
9599 if (get_Protocol() >= PROTOCOL_NT1) {
9600 req->flags2 |= 0x40; /* IS_LONG_NAME */
9601 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9604 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9605 if (state->call != TRANSACT2_QFSINFO &&
9606 state->call != TRANSACT2_SETFSINFO) {
9607 DEBUG(0,("handle_trans2: encryption required "
9609 (unsigned int)state->call));
9610 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9615 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9617 /* Now we must call the relevant TRANS2 function */
9618 switch(state->call) {
9619 case TRANSACT2_OPEN:
9621 START_PROFILE(Trans2_open);
9622 call_trans2open(conn, req,
9623 &state->param, state->total_param,
9624 &state->data, state->total_data,
9625 state->max_data_return);
9626 END_PROFILE(Trans2_open);
9630 case TRANSACT2_FINDFIRST:
9632 START_PROFILE(Trans2_findfirst);
9633 call_trans2findfirst(conn, req,
9634 &state->param, state->total_param,
9635 &state->data, state->total_data,
9636 state->max_data_return);
9637 END_PROFILE(Trans2_findfirst);
9641 case TRANSACT2_FINDNEXT:
9643 START_PROFILE(Trans2_findnext);
9644 call_trans2findnext(conn, req,
9645 &state->param, state->total_param,
9646 &state->data, state->total_data,
9647 state->max_data_return);
9648 END_PROFILE(Trans2_findnext);
9652 case TRANSACT2_QFSINFO:
9654 START_PROFILE(Trans2_qfsinfo);
9655 call_trans2qfsinfo(conn, req,
9656 &state->param, state->total_param,
9657 &state->data, state->total_data,
9658 state->max_data_return);
9659 END_PROFILE(Trans2_qfsinfo);
9663 case TRANSACT2_SETFSINFO:
9665 START_PROFILE(Trans2_setfsinfo);
9666 call_trans2setfsinfo(conn, req,
9667 &state->param, state->total_param,
9668 &state->data, state->total_data,
9669 state->max_data_return);
9670 END_PROFILE(Trans2_setfsinfo);
9674 case TRANSACT2_QPATHINFO:
9675 case TRANSACT2_QFILEINFO:
9677 START_PROFILE(Trans2_qpathinfo);
9678 call_trans2qfilepathinfo(conn, req, state->call,
9679 &state->param, state->total_param,
9680 &state->data, state->total_data,
9681 state->max_data_return);
9682 END_PROFILE(Trans2_qpathinfo);
9686 case TRANSACT2_SETPATHINFO:
9687 case TRANSACT2_SETFILEINFO:
9689 START_PROFILE(Trans2_setpathinfo);
9690 call_trans2setfilepathinfo(conn, req, state->call,
9691 &state->param, state->total_param,
9692 &state->data, state->total_data,
9693 state->max_data_return);
9694 END_PROFILE(Trans2_setpathinfo);
9698 case TRANSACT2_FINDNOTIFYFIRST:
9700 START_PROFILE(Trans2_findnotifyfirst);
9701 call_trans2findnotifyfirst(conn, req,
9702 &state->param, state->total_param,
9703 &state->data, state->total_data,
9704 state->max_data_return);
9705 END_PROFILE(Trans2_findnotifyfirst);
9709 case TRANSACT2_FINDNOTIFYNEXT:
9711 START_PROFILE(Trans2_findnotifynext);
9712 call_trans2findnotifynext(conn, req,
9713 &state->param, state->total_param,
9714 &state->data, state->total_data,
9715 state->max_data_return);
9716 END_PROFILE(Trans2_findnotifynext);
9720 case TRANSACT2_MKDIR:
9722 START_PROFILE(Trans2_mkdir);
9723 call_trans2mkdir(conn, req,
9724 &state->param, state->total_param,
9725 &state->data, state->total_data,
9726 state->max_data_return);
9727 END_PROFILE(Trans2_mkdir);
9731 case TRANSACT2_GET_DFS_REFERRAL:
9733 START_PROFILE(Trans2_get_dfs_referral);
9734 call_trans2getdfsreferral(conn, req,
9735 &state->param, state->total_param,
9736 &state->data, state->total_data,
9737 state->max_data_return);
9738 END_PROFILE(Trans2_get_dfs_referral);
9742 case TRANSACT2_IOCTL:
9744 START_PROFILE(Trans2_ioctl);
9745 call_trans2ioctl(conn, req,
9746 &state->param, state->total_param,
9747 &state->data, state->total_data,
9748 state->max_data_return);
9749 END_PROFILE(Trans2_ioctl);
9754 /* Error in request */
9755 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9756 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9760 /****************************************************************************
9761 Reply to a SMBtrans2.
9762 ****************************************************************************/
9764 void reply_trans2(struct smb_request *req)
9766 connection_struct *conn = req->conn;
9771 unsigned int tran_call;
9772 struct trans_state *state;
9775 START_PROFILE(SMBtrans2);
9777 if (req->wct < 14) {
9778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9779 END_PROFILE(SMBtrans2);
9783 dsoff = SVAL(req->vwv+12, 0);
9784 dscnt = SVAL(req->vwv+11, 0);
9785 psoff = SVAL(req->vwv+10, 0);
9786 pscnt = SVAL(req->vwv+9, 0);
9787 tran_call = SVAL(req->vwv+14, 0);
9789 result = allow_new_trans(conn->pending_trans, req->mid);
9790 if (!NT_STATUS_IS_OK(result)) {
9791 DEBUG(2, ("Got invalid trans2 request: %s\n",
9792 nt_errstr(result)));
9793 reply_nterror(req, result);
9794 END_PROFILE(SMBtrans2);
9799 switch (tran_call) {
9800 /* List the allowed trans2 calls on IPC$ */
9801 case TRANSACT2_OPEN:
9802 case TRANSACT2_GET_DFS_REFERRAL:
9803 case TRANSACT2_QFILEINFO:
9804 case TRANSACT2_QFSINFO:
9805 case TRANSACT2_SETFSINFO:
9808 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9809 END_PROFILE(SMBtrans2);
9814 if ((state = talloc(conn, struct trans_state)) == NULL) {
9815 DEBUG(0, ("talloc failed\n"));
9816 reply_nterror(req, NT_STATUS_NO_MEMORY);
9817 END_PROFILE(SMBtrans2);
9821 state->cmd = SMBtrans2;
9823 state->mid = req->mid;
9824 state->vuid = req->vuid;
9825 state->setup_count = SVAL(req->vwv+13, 0);
9826 state->setup = NULL;
9827 state->total_param = SVAL(req->vwv+0, 0);
9828 state->param = NULL;
9829 state->total_data = SVAL(req->vwv+1, 0);
9831 state->max_param_return = SVAL(req->vwv+2, 0);
9832 state->max_data_return = SVAL(req->vwv+3, 0);
9833 state->max_setup_return = SVAL(req->vwv+4, 0);
9834 state->close_on_completion = BITSETW(req->vwv+5, 0);
9835 state->one_way = BITSETW(req->vwv+5, 1);
9837 state->call = tran_call;
9839 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9840 is so as a sanity check */
9841 if (state->setup_count != 1) {
9843 * Need to have rc=0 for ioctl to get job id for OS/2.
9844 * Network printing will fail if function is not successful.
9845 * Similar function in reply.c will be used if protocol
9846 * is LANMAN1.0 instead of LM1.2X002.
9847 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9848 * outbuf doesn't have to be set(only job id is used).
9850 if ( (state->setup_count == 4)
9851 && (tran_call == TRANSACT2_IOCTL)
9852 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9853 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9854 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9856 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9857 DEBUG(2,("Transaction is %d\n",tran_call));
9859 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9860 END_PROFILE(SMBtrans2);
9865 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9868 if (state->total_data) {
9870 if (trans_oob(state->total_data, 0, dscnt)
9871 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9875 /* Can't use talloc here, the core routines do realloc on the
9876 * params and data. */
9877 state->data = (char *)SMB_MALLOC(state->total_data);
9878 if (state->data == NULL) {
9879 DEBUG(0,("reply_trans2: data malloc fail for %u "
9880 "bytes !\n", (unsigned int)state->total_data));
9882 reply_nterror(req, NT_STATUS_NO_MEMORY);
9883 END_PROFILE(SMBtrans2);
9887 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9890 if (state->total_param) {
9892 if (trans_oob(state->total_param, 0, pscnt)
9893 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9897 /* Can't use talloc here, the core routines do realloc on the
9898 * params and data. */
9899 state->param = (char *)SMB_MALLOC(state->total_param);
9900 if (state->param == NULL) {
9901 DEBUG(0,("reply_trans: param malloc fail for %u "
9902 "bytes !\n", (unsigned int)state->total_param));
9903 SAFE_FREE(state->data);
9905 reply_nterror(req, NT_STATUS_NO_MEMORY);
9906 END_PROFILE(SMBtrans2);
9910 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9913 state->received_data = dscnt;
9914 state->received_param = pscnt;
9916 if ((state->received_param == state->total_param) &&
9917 (state->received_data == state->total_data)) {
9919 handle_trans2(conn, req, state);
9921 SAFE_FREE(state->data);
9922 SAFE_FREE(state->param);
9924 END_PROFILE(SMBtrans2);
9928 DLIST_ADD(conn->pending_trans, state);
9930 /* We need to send an interim response then receive the rest
9931 of the parameter/data bytes */
9932 reply_outbuf(req, 0, 0);
9933 show_msg((char *)req->outbuf);
9934 END_PROFILE(SMBtrans2);
9939 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9940 SAFE_FREE(state->data);
9941 SAFE_FREE(state->param);
9943 END_PROFILE(SMBtrans2);
9944 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9948 /****************************************************************************
9949 Reply to a SMBtranss2
9950 ****************************************************************************/
9952 void reply_transs2(struct smb_request *req)
9954 connection_struct *conn = req->conn;
9955 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9956 struct trans_state *state;
9958 START_PROFILE(SMBtranss2);
9960 show_msg((const char *)req->inbuf);
9962 /* Windows clients expect all replies to
9963 a transact secondary (SMBtranss2 0x33)
9964 to have a command code of transact
9965 (SMBtrans2 0x32). See bug #8989
9966 and also [MS-CIFS] section 2.2.4.47.2
9969 req->cmd = SMBtrans2;
9972 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9973 END_PROFILE(SMBtranss2);
9977 for (state = conn->pending_trans; state != NULL;
9978 state = state->next) {
9979 if (state->mid == req->mid) {
9984 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9985 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9986 END_PROFILE(SMBtranss2);
9990 /* Revise state->total_param and state->total_data in case they have
9991 changed downwards */
9993 if (SVAL(req->vwv+0, 0) < state->total_param)
9994 state->total_param = SVAL(req->vwv+0, 0);
9995 if (SVAL(req->vwv+1, 0) < state->total_data)
9996 state->total_data = SVAL(req->vwv+1, 0);
9998 pcnt = SVAL(req->vwv+2, 0);
9999 poff = SVAL(req->vwv+3, 0);
10000 pdisp = SVAL(req->vwv+4, 0);
10002 dcnt = SVAL(req->vwv+5, 0);
10003 doff = SVAL(req->vwv+6, 0);
10004 ddisp = SVAL(req->vwv+7, 0);
10006 state->received_param += pcnt;
10007 state->received_data += dcnt;
10009 if ((state->received_data > state->total_data) ||
10010 (state->received_param > state->total_param))
10014 if (trans_oob(state->total_param, pdisp, pcnt)
10015 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10018 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10022 if (trans_oob(state->total_data, ddisp, dcnt)
10023 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10026 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10029 if ((state->received_param < state->total_param) ||
10030 (state->received_data < state->total_data)) {
10031 END_PROFILE(SMBtranss2);
10035 handle_trans2(conn, req, state);
10037 DLIST_REMOVE(conn->pending_trans, state);
10038 SAFE_FREE(state->data);
10039 SAFE_FREE(state->param);
10040 TALLOC_FREE(state);
10042 END_PROFILE(SMBtranss2);
10047 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10048 DLIST_REMOVE(conn->pending_trans, state);
10049 SAFE_FREE(state->data);
10050 SAFE_FREE(state->param);
10051 TALLOC_FREE(state);
10052 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10053 END_PROFILE(SMBtranss2);