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;
7291 bool close_fsp = false;
7293 if (total_data_in < 0) {
7294 status = NT_STATUS_INVALID_PARAMETER;
7298 total_data = total_data_in;
7300 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7301 status = NT_STATUS_INVALID_PARAMETER;
7304 posix_acl_version = SVAL(pdata,0);
7305 num_file_acls = SVAL(pdata,2);
7306 num_def_acls = SVAL(pdata,4);
7308 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7309 valid_file_acls = false;
7313 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7314 valid_def_acls = false;
7318 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7319 status = NT_STATUS_INVALID_PARAMETER;
7324 if (num_file_acls + num_def_acls < num_file_acls) {
7325 status = NT_STATUS_INVALID_PARAMETER;
7329 size_needed = num_file_acls + num_def_acls;
7332 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7333 * than UINT_MAX, so check by division.
7335 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7336 status = NT_STATUS_INVALID_PARAMETER;
7340 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7341 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7342 status = NT_STATUS_INVALID_PARAMETER;
7345 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7347 if (total_data < size_needed) {
7348 status = NT_STATUS_INVALID_PARAMETER;
7353 * Ensure we always operate on a file descriptor, not just
7357 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7359 SEC_STD_READ_CONTROL|
7360 FILE_READ_ATTRIBUTES|
7361 FILE_WRITE_ATTRIBUTES;
7363 status = get_posix_fsp(conn,
7369 if (!NT_STATUS_IS_OK(status)) {
7375 /* Here we know fsp != NULL */
7376 SMB_ASSERT(fsp != NULL);
7378 status = refuse_symlink(conn, fsp, smb_fname);
7379 if (!NT_STATUS_IS_OK(status)) {
7383 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7384 "num_def_acls = %"PRIu16"\n",
7385 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7389 /* Move pdata to the start of the file ACL entries. */
7390 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7392 if (valid_file_acls) {
7393 bool ok = set_unix_posix_acl(conn,
7399 status = map_nt_error_from_unix(errno);
7404 /* Move pdata to the start of the default ACL entries. */
7405 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7407 if (valid_def_acls) {
7408 bool ok = set_unix_posix_default_acl(conn,
7413 status = map_nt_error_from_unix(errno);
7418 status = NT_STATUS_OK;
7423 (void)close_file(req, fsp, NORMAL_CLOSE);
7430 /****************************************************************************
7431 Deal with SMB_SET_POSIX_LOCK.
7432 ****************************************************************************/
7434 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7436 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7437 struct smb_request *req,
7442 struct tevent_req *subreq = NULL;
7443 struct smbd_lock_element *lck = NULL;
7447 bool blocking_lock = False;
7448 enum brl_type lock_type;
7450 NTSTATUS status = NT_STATUS_OK;
7452 if (fsp == NULL || fsp->fh->fd == -1) {
7453 return NT_STATUS_INVALID_HANDLE;
7456 if (total_data != POSIX_LOCK_DATA_SIZE) {
7457 return NT_STATUS_INVALID_PARAMETER;
7460 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7461 case POSIX_LOCK_TYPE_READ:
7462 lock_type = READ_LOCK;
7464 case POSIX_LOCK_TYPE_WRITE:
7465 /* Return the right POSIX-mappable error code for files opened read-only. */
7466 if (!fsp->can_write) {
7467 return NT_STATUS_INVALID_HANDLE;
7469 lock_type = WRITE_LOCK;
7471 case POSIX_LOCK_TYPE_UNLOCK:
7472 lock_type = UNLOCK_LOCK;
7475 return NT_STATUS_INVALID_PARAMETER;
7478 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7479 case POSIX_LOCK_FLAG_NOWAIT:
7480 blocking_lock = false;
7482 case POSIX_LOCK_FLAG_WAIT:
7483 blocking_lock = true;
7486 return NT_STATUS_INVALID_PARAMETER;
7489 if (!lp_blocking_locks(SNUM(conn))) {
7490 blocking_lock = False;
7493 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7494 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7495 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7496 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7497 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7499 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7500 "count = %"PRIu64", offset = %"PRIu64"\n",
7502 (unsigned int)lock_type,
7507 if (lock_type == UNLOCK_LOCK) {
7508 struct smbd_lock_element l = {
7510 .brltype = UNLOCK_LOCK,
7514 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7518 lck = talloc(req, struct smbd_lock_element);
7520 return NT_STATUS_NO_MEMORY;
7523 *lck = (struct smbd_lock_element) {
7525 .brltype = lock_type,
7530 subreq = smbd_smb1_do_locks_send(
7533 req->sconn->msg_ctx,
7536 blocking_lock ? UINT32_MAX : 0,
7537 true, /* large_offset */
7541 if (subreq == NULL) {
7543 return NT_STATUS_NO_MEMORY;
7545 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7546 return NT_STATUS_EVENT_PENDING;
7549 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7551 struct smb_request *req = NULL;
7555 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7558 status = smbd_smb1_do_locks_recv(subreq);
7559 TALLOC_FREE(subreq);
7561 if (NT_STATUS_IS_OK(status)) {
7562 char params[2] = {0};
7563 /* Fake up max_data_bytes here - we know it fits. */
7564 send_trans2_replies(
7574 reply_nterror(req, status);
7577 (char *)req->outbuf,
7580 IS_CONN_ENCRYPTED(req->conn),
7583 exit_server_cleanly("smb_set_posix_lock_done: "
7584 "srv_send_smb failed.");
7592 /****************************************************************************
7593 Deal with SMB_SET_FILE_BASIC_INFO.
7594 ****************************************************************************/
7596 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7600 const struct smb_filename *smb_fname)
7602 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7603 struct smb_file_time ft;
7604 uint32_t dosmode = 0;
7605 NTSTATUS status = NT_STATUS_OK;
7609 if (total_data < 36) {
7610 return NT_STATUS_INVALID_PARAMETER;
7613 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7614 if (!NT_STATUS_IS_OK(status)) {
7618 /* Set the attributes */
7619 dosmode = IVAL(pdata,32);
7620 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7621 if (!NT_STATUS_IS_OK(status)) {
7626 ft.create_time = interpret_long_date(pdata);
7629 ft.atime = interpret_long_date(pdata+8);
7632 ft.mtime = interpret_long_date(pdata+16);
7635 ft.ctime = interpret_long_date(pdata+24);
7637 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7638 smb_fname_str_dbg(smb_fname)));
7640 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7644 /****************************************************************************
7645 Deal with SMB_INFO_STANDARD.
7646 ****************************************************************************/
7648 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7652 const struct smb_filename *smb_fname)
7655 struct smb_file_time ft;
7659 if (total_data < 12) {
7660 return NT_STATUS_INVALID_PARAMETER;
7664 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7666 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7668 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7670 DEBUG(10,("smb_set_info_standard: file %s\n",
7671 smb_fname_str_dbg(smb_fname)));
7673 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7674 if (!NT_STATUS_IS_OK(status)) {
7678 return smb_set_file_time(conn,
7685 /****************************************************************************
7686 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7687 ****************************************************************************/
7689 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7690 struct smb_request *req,
7694 struct smb_filename *smb_fname)
7696 uint64_t allocation_size = 0;
7697 NTSTATUS status = NT_STATUS_OK;
7698 files_struct *new_fsp = NULL;
7700 if (!VALID_STAT(smb_fname->st)) {
7701 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7704 if (total_data < 8) {
7705 return NT_STATUS_INVALID_PARAMETER;
7708 allocation_size = (uint64_t)IVAL(pdata,0);
7709 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7710 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7711 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7712 (double)allocation_size));
7714 if (allocation_size) {
7715 allocation_size = smb_roundup(conn, allocation_size);
7718 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7719 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7720 (double)allocation_size));
7722 if (fsp && fsp->fh->fd != -1) {
7723 /* Open file handle. */
7724 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7725 return NT_STATUS_ACCESS_DENIED;
7728 /* Only change if needed. */
7729 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7730 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7731 return map_nt_error_from_unix(errno);
7734 /* But always update the time. */
7736 * This is equivalent to a write. Ensure it's seen immediately
7737 * if there are no pending writes.
7739 trigger_write_time_update_immediate(fsp);
7740 return NT_STATUS_OK;
7743 /* Pathname or stat or directory file. */
7744 status = SMB_VFS_CREATE_FILE(
7747 0, /* root_dir_fid */
7748 smb_fname, /* fname */
7749 FILE_WRITE_DATA, /* access_mask */
7750 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7752 FILE_OPEN, /* create_disposition*/
7753 0, /* create_options */
7754 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7755 0, /* oplock_request */
7757 0, /* allocation_size */
7758 0, /* private_flags */
7761 &new_fsp, /* result */
7763 NULL, NULL); /* create context */
7765 if (!NT_STATUS_IS_OK(status)) {
7766 /* NB. We check for open_was_deferred in the caller. */
7770 /* Only change if needed. */
7771 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7772 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7773 status = map_nt_error_from_unix(errno);
7774 close_file(req, new_fsp, NORMAL_CLOSE);
7779 /* Changing the allocation size should set the last mod time. */
7781 * This is equivalent to a write. Ensure it's seen immediately
7782 * if there are no pending writes.
7784 trigger_write_time_update_immediate(new_fsp);
7785 close_file(req, new_fsp, NORMAL_CLOSE);
7786 return NT_STATUS_OK;
7789 /****************************************************************************
7790 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7791 ****************************************************************************/
7793 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7794 struct smb_request *req,
7798 const struct smb_filename *smb_fname,
7799 bool fail_after_createfile)
7803 if (total_data < 8) {
7804 return NT_STATUS_INVALID_PARAMETER;
7807 size = IVAL(pdata,0);
7808 size |= (((off_t)IVAL(pdata,4)) << 32);
7809 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7810 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7813 return smb_set_file_size(conn, req,
7818 fail_after_createfile);
7821 /****************************************************************************
7822 Allow a UNIX info mknod.
7823 ****************************************************************************/
7825 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7828 const struct smb_filename *smb_fname)
7830 uint32_t file_type = IVAL(pdata,56);
7831 #if defined(HAVE_MAKEDEV)
7832 uint32_t dev_major = IVAL(pdata,60);
7833 uint32_t dev_minor = IVAL(pdata,68);
7835 SMB_DEV_T dev = (SMB_DEV_T)0;
7836 uint32_t raw_unixmode = IVAL(pdata,84);
7840 if (total_data < 100) {
7841 return NT_STATUS_INVALID_PARAMETER;
7844 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7845 PERM_NEW_FILE, &unixmode);
7846 if (!NT_STATUS_IS_OK(status)) {
7850 #if defined(HAVE_MAKEDEV)
7851 dev = makedev(dev_major, dev_minor);
7854 switch (file_type) {
7855 #if defined(S_IFIFO)
7856 case UNIX_TYPE_FIFO:
7857 unixmode |= S_IFIFO;
7860 #if defined(S_IFSOCK)
7861 case UNIX_TYPE_SOCKET:
7862 unixmode |= S_IFSOCK;
7865 #if defined(S_IFCHR)
7866 case UNIX_TYPE_CHARDEV:
7867 unixmode |= S_IFCHR;
7870 #if defined(S_IFBLK)
7871 case UNIX_TYPE_BLKDEV:
7872 unixmode |= S_IFBLK;
7876 return NT_STATUS_INVALID_PARAMETER;
7879 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7880 "%.0f mode 0%o for file %s\n", (double)dev,
7881 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7883 /* Ok - do the mknod. */
7884 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7885 return map_nt_error_from_unix(errno);
7888 /* If any of the other "set" calls fail we
7889 * don't want to end up with a half-constructed mknod.
7892 if (lp_inherit_permissions(SNUM(conn))) {
7894 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7896 return NT_STATUS_NO_MEMORY;
7898 inherit_access_posix_acl(conn, parent, smb_fname,
7900 TALLOC_FREE(parent);
7903 return NT_STATUS_OK;
7906 /****************************************************************************
7907 Deal with SMB_SET_FILE_UNIX_BASIC.
7908 ****************************************************************************/
7910 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7911 struct smb_request *req,
7915 const struct smb_filename *smb_fname)
7917 struct smb_file_time ft;
7918 uint32_t raw_unixmode;
7921 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7922 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7923 NTSTATUS status = NT_STATUS_OK;
7924 bool delete_on_fail = False;
7925 enum perm_type ptype;
7926 files_struct *all_fsps = NULL;
7927 bool modify_mtime = true;
7929 struct smb_filename *smb_fname_tmp = NULL;
7930 SMB_STRUCT_STAT sbuf;
7934 if (total_data < 100) {
7935 return NT_STATUS_INVALID_PARAMETER;
7938 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7939 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7940 size=IVAL(pdata,0); /* first 8 Bytes are size */
7941 size |= (((off_t)IVAL(pdata,4)) << 32);
7944 ft.atime = interpret_long_date(pdata+24); /* access_time */
7945 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7946 set_owner = (uid_t)IVAL(pdata,40);
7947 set_grp = (gid_t)IVAL(pdata,48);
7948 raw_unixmode = IVAL(pdata,84);
7950 if (VALID_STAT(smb_fname->st)) {
7951 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7952 ptype = PERM_EXISTING_DIR;
7954 ptype = PERM_EXISTING_FILE;
7957 ptype = PERM_NEW_FILE;
7960 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7962 if (!NT_STATUS_IS_OK(status)) {
7966 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7967 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7968 smb_fname_str_dbg(smb_fname), (double)size,
7969 (unsigned int)set_owner, (unsigned int)set_grp,
7970 (int)raw_unixmode));
7972 sbuf = smb_fname->st;
7974 if (!VALID_STAT(sbuf)) {
7976 * The only valid use of this is to create character and block
7977 * devices, and named pipes. This is deprecated (IMHO) and
7978 * a new info level should be used for mknod. JRA.
7981 status = smb_unix_mknod(conn,
7985 if (!NT_STATUS_IS_OK(status)) {
7989 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7990 if (smb_fname_tmp == NULL) {
7991 return NT_STATUS_NO_MEMORY;
7994 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7995 status = map_nt_error_from_unix(errno);
7996 TALLOC_FREE(smb_fname_tmp);
7997 SMB_VFS_UNLINK(conn, smb_fname);
8001 sbuf = smb_fname_tmp->st;
8002 smb_fname = smb_fname_tmp;
8004 /* Ensure we don't try and change anything else. */
8005 raw_unixmode = SMB_MODE_NO_CHANGE;
8006 size = get_file_size_stat(&sbuf);
8007 ft.atime = sbuf.st_ex_atime;
8008 ft.mtime = sbuf.st_ex_mtime;
8010 * We continue here as we might want to change the
8013 delete_on_fail = True;
8017 /* Horrible backwards compatibility hack as an old server bug
8018 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8022 size = get_file_size_stat(&sbuf);
8027 * Deal with the UNIX specific mode set.
8030 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8033 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8034 "setting mode 0%o for file %s\n",
8035 (unsigned int)unixmode,
8036 smb_fname_str_dbg(smb_fname)));
8037 if (fsp && fsp->fh->fd != -1) {
8038 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8040 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8043 return map_nt_error_from_unix(errno);
8048 * Deal with the UNIX specific uid set.
8051 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8052 (sbuf.st_ex_uid != set_owner)) {
8055 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8056 "changing owner %u for path %s\n",
8057 (unsigned int)set_owner,
8058 smb_fname_str_dbg(smb_fname)));
8060 if (fsp && fsp->fh->fd != -1) {
8061 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8064 * UNIX extensions calls must always operate
8067 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8068 set_owner, (gid_t)-1);
8072 status = map_nt_error_from_unix(errno);
8073 if (delete_on_fail) {
8074 SMB_VFS_UNLINK(conn, smb_fname);
8081 * Deal with the UNIX specific gid set.
8084 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8085 (sbuf.st_ex_gid != set_grp)) {
8088 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8089 "changing group %u for file %s\n",
8090 (unsigned int)set_grp,
8091 smb_fname_str_dbg(smb_fname)));
8092 if (fsp && fsp->fh->fd != -1) {
8093 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8096 * UNIX extensions calls must always operate
8099 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8103 status = map_nt_error_from_unix(errno);
8104 if (delete_on_fail) {
8105 SMB_VFS_UNLINK(conn, smb_fname);
8111 /* Deal with any size changes. */
8113 status = smb_set_file_size(conn, req,
8119 if (!NT_STATUS_IS_OK(status)) {
8123 /* Deal with any time changes. */
8124 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
8125 /* No change, don't cancel anything. */
8129 id = vfs_file_id_from_sbuf(conn, &sbuf);
8130 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8131 all_fsps = file_find_di_next(all_fsps)) {
8133 * We're setting the time explicitly for UNIX.
8134 * Cancel any pending changes over all handles.
8136 all_fsps->update_write_time_on_close = false;
8137 TALLOC_FREE(all_fsps->update_write_time_event);
8141 * Override the "setting_write_time"
8142 * parameter here as it almost does what
8143 * we need. Just remember if we modified
8144 * mtime and send the notify ourselves.
8146 if (null_timespec(ft.mtime)) {
8147 modify_mtime = false;
8150 status = smb_set_file_time(conn,
8156 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8157 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8162 /****************************************************************************
8163 Deal with SMB_SET_FILE_UNIX_INFO2.
8164 ****************************************************************************/
8166 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8167 struct smb_request *req,
8171 const struct smb_filename *smb_fname)
8174 uint32_t smb_fflags;
8177 if (total_data < 116) {
8178 return NT_STATUS_INVALID_PARAMETER;
8181 /* Start by setting all the fields that are common between UNIX_BASIC
8184 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8186 if (!NT_STATUS_IS_OK(status)) {
8190 smb_fflags = IVAL(pdata, 108);
8191 smb_fmask = IVAL(pdata, 112);
8193 /* NB: We should only attempt to alter the file flags if the client
8194 * sends a non-zero mask.
8196 if (smb_fmask != 0) {
8197 int stat_fflags = 0;
8199 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8200 smb_fmask, &stat_fflags)) {
8201 /* Client asked to alter a flag we don't understand. */
8202 return NT_STATUS_INVALID_PARAMETER;
8205 if (fsp && fsp->fh->fd != -1) {
8206 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8207 return NT_STATUS_NOT_SUPPORTED;
8209 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8210 stat_fflags) != 0) {
8211 return map_nt_error_from_unix(errno);
8216 /* XXX: need to add support for changing the create_time here. You
8217 * can do this for paths on Darwin with setattrlist(2). The right way
8218 * to hook this up is probably by extending the VFS utimes interface.
8221 return NT_STATUS_OK;
8224 /****************************************************************************
8225 Create a directory with POSIX semantics.
8226 ****************************************************************************/
8228 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8229 struct smb_request *req,
8232 struct smb_filename *smb_fname,
8233 int *pdata_return_size)
8235 NTSTATUS status = NT_STATUS_OK;
8236 uint32_t raw_unixmode = 0;
8237 uint32_t mod_unixmode = 0;
8238 mode_t unixmode = (mode_t)0;
8239 files_struct *fsp = NULL;
8240 uint16_t info_level_return = 0;
8242 char *pdata = *ppdata;
8244 if (total_data < 18) {
8245 return NT_STATUS_INVALID_PARAMETER;
8248 raw_unixmode = IVAL(pdata,8);
8249 /* Next 4 bytes are not yet defined. */
8251 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8252 PERM_NEW_DIR, &unixmode);
8253 if (!NT_STATUS_IS_OK(status)) {
8257 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8259 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8260 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8262 status = SMB_VFS_CREATE_FILE(
8265 0, /* root_dir_fid */
8266 smb_fname, /* fname */
8267 FILE_READ_ATTRIBUTES, /* access_mask */
8268 FILE_SHARE_NONE, /* share_access */
8269 FILE_CREATE, /* create_disposition*/
8270 FILE_DIRECTORY_FILE, /* create_options */
8271 mod_unixmode, /* file_attributes */
8272 0, /* oplock_request */
8274 0, /* allocation_size */
8275 0, /* private_flags */
8280 NULL, NULL); /* create context */
8282 if (NT_STATUS_IS_OK(status)) {
8283 close_file(req, fsp, NORMAL_CLOSE);
8286 info_level_return = SVAL(pdata,16);
8288 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8289 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8290 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8291 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8293 *pdata_return_size = 12;
8296 /* Realloc the data size */
8297 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8298 if (*ppdata == NULL) {
8299 *pdata_return_size = 0;
8300 return NT_STATUS_NO_MEMORY;
8304 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8305 SSVAL(pdata,2,0); /* No fnum. */
8306 SIVAL(pdata,4,info); /* Was directory created. */
8308 switch (info_level_return) {
8309 case SMB_QUERY_FILE_UNIX_BASIC:
8310 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8311 SSVAL(pdata,10,0); /* Padding. */
8312 store_file_unix_basic(conn, pdata + 12, fsp,
8315 case SMB_QUERY_FILE_UNIX_INFO2:
8316 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8317 SSVAL(pdata,10,0); /* Padding. */
8318 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8322 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8323 SSVAL(pdata,10,0); /* Padding. */
8330 /****************************************************************************
8331 Open/Create a file with POSIX semantics.
8332 ****************************************************************************/
8334 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8335 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8337 static NTSTATUS smb_posix_open(connection_struct *conn,
8338 struct smb_request *req,
8341 struct smb_filename *smb_fname,
8342 int *pdata_return_size)
8344 bool extended_oplock_granted = False;
8345 char *pdata = *ppdata;
8347 uint32_t wire_open_mode = 0;
8348 uint32_t raw_unixmode = 0;
8349 uint32_t mod_unixmode = 0;
8350 uint32_t create_disp = 0;
8351 uint32_t access_mask = 0;
8352 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8353 NTSTATUS status = NT_STATUS_OK;
8354 mode_t unixmode = (mode_t)0;
8355 files_struct *fsp = NULL;
8356 int oplock_request = 0;
8358 uint16_t info_level_return = 0;
8360 if (total_data < 18) {
8361 return NT_STATUS_INVALID_PARAMETER;
8364 flags = IVAL(pdata,0);
8365 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8366 if (oplock_request) {
8367 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8370 wire_open_mode = IVAL(pdata,4);
8372 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8373 return smb_posix_mkdir(conn, req,
8380 switch (wire_open_mode & SMB_ACCMODE) {
8382 access_mask = SMB_O_RDONLY_MAPPING;
8385 access_mask = SMB_O_WRONLY_MAPPING;
8388 access_mask = (SMB_O_RDONLY_MAPPING|
8389 SMB_O_WRONLY_MAPPING);
8392 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8393 (unsigned int)wire_open_mode ));
8394 return NT_STATUS_INVALID_PARAMETER;
8397 wire_open_mode &= ~SMB_ACCMODE;
8399 /* First take care of O_CREAT|O_EXCL interactions. */
8400 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8401 case (SMB_O_CREAT | SMB_O_EXCL):
8402 /* File exists fail. File not exist create. */
8403 create_disp = FILE_CREATE;
8406 /* File exists open. File not exist create. */
8407 create_disp = FILE_OPEN_IF;
8410 /* O_EXCL on its own without O_CREAT is undefined.
8411 We deliberately ignore it as some versions of
8412 Linux CIFSFS can send a bare O_EXCL on the
8413 wire which other filesystems in the kernel
8414 ignore. See bug 9519 for details. */
8419 /* File exists open. File not exist fail. */
8420 create_disp = FILE_OPEN;
8423 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8424 (unsigned int)wire_open_mode ));
8425 return NT_STATUS_INVALID_PARAMETER;
8428 /* Next factor in the effects of O_TRUNC. */
8429 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8431 if (wire_open_mode & SMB_O_TRUNC) {
8432 switch (create_disp) {
8434 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8435 /* Leave create_disp alone as
8436 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8438 /* File exists fail. File not exist create. */
8441 /* SMB_O_CREAT | SMB_O_TRUNC */
8442 /* File exists overwrite. File not exist create. */
8443 create_disp = FILE_OVERWRITE_IF;
8447 /* File exists overwrite. File not exist fail. */
8448 create_disp = FILE_OVERWRITE;
8451 /* Cannot get here. */
8452 smb_panic("smb_posix_open: logic error");
8453 return NT_STATUS_INVALID_PARAMETER;
8457 raw_unixmode = IVAL(pdata,8);
8458 /* Next 4 bytes are not yet defined. */
8460 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8461 (VALID_STAT(smb_fname->st) ?
8462 PERM_EXISTING_FILE : PERM_NEW_FILE),
8465 if (!NT_STATUS_IS_OK(status)) {
8469 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8471 if (wire_open_mode & SMB_O_SYNC) {
8472 create_options |= FILE_WRITE_THROUGH;
8474 if (wire_open_mode & SMB_O_APPEND) {
8475 access_mask |= FILE_APPEND_DATA;
8477 if (wire_open_mode & SMB_O_DIRECT) {
8478 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8481 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8482 VALID_STAT_OF_DIR(smb_fname->st)) {
8483 if (access_mask != SMB_O_RDONLY_MAPPING) {
8484 return NT_STATUS_FILE_IS_A_DIRECTORY;
8486 create_options &= ~FILE_NON_DIRECTORY_FILE;
8487 create_options |= FILE_DIRECTORY_FILE;
8490 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8491 smb_fname_str_dbg(smb_fname),
8492 (unsigned int)wire_open_mode,
8493 (unsigned int)unixmode ));
8495 status = SMB_VFS_CREATE_FILE(
8498 0, /* root_dir_fid */
8499 smb_fname, /* fname */
8500 access_mask, /* access_mask */
8501 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8503 create_disp, /* create_disposition*/
8504 create_options, /* create_options */
8505 mod_unixmode, /* file_attributes */
8506 oplock_request, /* oplock_request */
8508 0, /* allocation_size */
8509 0, /* private_flags */
8514 NULL, NULL); /* create context */
8516 if (!NT_STATUS_IS_OK(status)) {
8520 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8521 extended_oplock_granted = True;
8524 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8525 extended_oplock_granted = True;
8528 info_level_return = SVAL(pdata,16);
8530 /* Allocate the correct return size. */
8532 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8533 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8534 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8535 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8537 *pdata_return_size = 12;
8540 /* Realloc the data size */
8541 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8542 if (*ppdata == NULL) {
8543 close_file(req, fsp, ERROR_CLOSE);
8544 *pdata_return_size = 0;
8545 return NT_STATUS_NO_MEMORY;
8549 if (extended_oplock_granted) {
8550 if (flags & REQUEST_BATCH_OPLOCK) {
8551 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8553 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8555 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8556 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8558 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8561 SSVAL(pdata,2,fsp->fnum);
8562 SIVAL(pdata,4,info); /* Was file created etc. */
8564 switch (info_level_return) {
8565 case SMB_QUERY_FILE_UNIX_BASIC:
8566 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8567 SSVAL(pdata,10,0); /* padding. */
8568 store_file_unix_basic(conn, pdata + 12, fsp,
8571 case SMB_QUERY_FILE_UNIX_INFO2:
8572 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8573 SSVAL(pdata,10,0); /* padding. */
8574 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8578 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8579 SSVAL(pdata,10,0); /* padding. */
8582 return NT_STATUS_OK;
8585 /****************************************************************************
8586 Delete a file with POSIX semantics.
8587 ****************************************************************************/
8589 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8590 struct smb_request *req,
8593 struct smb_filename *smb_fname)
8595 struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
8596 NTSTATUS status = NT_STATUS_OK;
8597 files_struct *fsp = NULL;
8601 int create_options = 0;
8602 struct share_mode_lock *lck = NULL;
8603 bool other_nonposix_opens;
8605 if (total_data < 2) {
8606 return NT_STATUS_INVALID_PARAMETER;
8609 flags = SVAL(pdata,0);
8611 if (!VALID_STAT(smb_fname->st)) {
8612 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8615 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8616 !VALID_STAT_OF_DIR(smb_fname->st)) {
8617 return NT_STATUS_NOT_A_DIRECTORY;
8620 DEBUG(10,("smb_posix_unlink: %s %s\n",
8621 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8622 smb_fname_str_dbg(smb_fname)));
8624 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8625 create_options |= FILE_DIRECTORY_FILE;
8628 status = SMB_VFS_CREATE_FILE(
8631 0, /* root_dir_fid */
8632 smb_fname, /* fname */
8633 DELETE_ACCESS, /* access_mask */
8634 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8636 FILE_OPEN, /* create_disposition*/
8637 create_options, /* create_options */
8638 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8639 0, /* oplock_request */
8641 0, /* allocation_size */
8642 0, /* private_flags */
8647 NULL, NULL); /* create context */
8649 if (!NT_STATUS_IS_OK(status)) {
8654 * Don't lie to client. If we can't really delete due to
8655 * non-POSIX opens return SHARING_VIOLATION.
8658 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8660 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8661 "lock for file %s\n", fsp_str_dbg(fsp)));
8662 close_file(req, fsp, NORMAL_CLOSE);
8663 return NT_STATUS_INVALID_PARAMETER;
8666 other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
8667 if (other_nonposix_opens) {
8668 /* Fail with sharing violation. */
8670 close_file(req, fsp, NORMAL_CLOSE);
8671 return NT_STATUS_SHARING_VIOLATION;
8675 * Set the delete on close.
8677 status = smb_set_file_disposition_info(conn,
8685 if (!NT_STATUS_IS_OK(status)) {
8686 close_file(req, fsp, NORMAL_CLOSE);
8689 return close_file(req, fsp, NORMAL_CLOSE);
8692 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8693 struct smb_request *req,
8694 TALLOC_CTX *mem_ctx,
8695 uint16_t info_level,
8697 struct smb_filename *smb_fname,
8698 char **ppdata, int total_data,
8701 char *pdata = *ppdata;
8702 NTSTATUS status = NT_STATUS_OK;
8703 int data_return_size = 0;
8707 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8708 return NT_STATUS_INVALID_LEVEL;
8711 if (!CAN_WRITE(conn)) {
8712 /* Allow POSIX opens. The open path will deny
8713 * any non-readonly opens. */
8714 if (info_level != SMB_POSIX_PATH_OPEN) {
8715 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8719 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8720 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8722 info_level, total_data));
8724 switch (info_level) {
8726 case SMB_INFO_STANDARD:
8728 status = smb_set_info_standard(conn,
8736 case SMB_INFO_SET_EA:
8738 status = smb_info_set_ea(conn,
8746 case SMB_SET_FILE_BASIC_INFO:
8747 case SMB_FILE_BASIC_INFORMATION:
8749 status = smb_set_file_basic_info(conn,
8757 case SMB_FILE_ALLOCATION_INFORMATION:
8758 case SMB_SET_FILE_ALLOCATION_INFO:
8760 status = smb_set_file_allocation_info(conn, req,
8768 case SMB_FILE_END_OF_FILE_INFORMATION:
8769 case SMB_SET_FILE_END_OF_FILE_INFO:
8772 * XP/Win7 both fail after the createfile with
8773 * SMB_SET_FILE_END_OF_FILE_INFO but not
8774 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8775 * The level is known here, so pass it down
8779 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8781 status = smb_set_file_end_of_file_info(conn, req,
8790 case SMB_FILE_DISPOSITION_INFORMATION:
8791 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8794 /* JRA - We used to just ignore this on a path ?
8795 * Shouldn't this be invalid level on a pathname
8798 if (tran_call != TRANSACT2_SETFILEINFO) {
8799 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8802 status = smb_set_file_disposition_info(conn,
8810 case SMB_FILE_POSITION_INFORMATION:
8812 status = smb_file_position_information(conn,
8819 case SMB_FILE_FULL_EA_INFORMATION:
8821 status = smb_set_file_full_ea_info(conn,
8828 /* From tridge Samba4 :
8829 * MODE_INFORMATION in setfileinfo (I have no
8830 * idea what "mode information" on a file is - it takes a value of 0,
8831 * 2, 4 or 6. What could it be?).
8834 case SMB_FILE_MODE_INFORMATION:
8836 status = smb_file_mode_information(conn,
8842 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8843 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8844 case SMB_FILE_SHORT_NAME_INFORMATION:
8845 return NT_STATUS_NOT_SUPPORTED;
8848 * CIFS UNIX extensions.
8851 case SMB_SET_FILE_UNIX_BASIC:
8853 status = smb_set_file_unix_basic(conn, req,
8861 case SMB_SET_FILE_UNIX_INFO2:
8863 status = smb_set_file_unix_info2(conn, req,
8871 case SMB_SET_FILE_UNIX_LINK:
8874 /* We must have a pathname for this. */
8875 return NT_STATUS_INVALID_LEVEL;
8877 status = smb_set_file_unix_link(conn, req, pdata,
8878 total_data, smb_fname);
8882 case SMB_SET_FILE_UNIX_HLINK:
8885 /* We must have a pathname for this. */
8886 return NT_STATUS_INVALID_LEVEL;
8888 status = smb_set_file_unix_hlink(conn, req,
8894 case SMB_FILE_RENAME_INFORMATION:
8896 status = smb_file_rename_information(conn, req,
8902 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8904 /* SMB2 rename information. */
8905 status = smb2_file_rename_information(conn, req,
8911 case SMB_FILE_LINK_INFORMATION:
8913 status = smb_file_link_information(conn, req,
8919 #if defined(HAVE_POSIX_ACLS)
8920 case SMB_SET_POSIX_ACL:
8922 status = smb_set_posix_acl(conn,
8932 case SMB_SET_POSIX_LOCK:
8935 return NT_STATUS_INVALID_LEVEL;
8937 status = smb_set_posix_lock(conn, req,
8938 pdata, total_data, fsp);
8942 case SMB_POSIX_PATH_OPEN:
8945 /* We must have a pathname for this. */
8946 return NT_STATUS_INVALID_LEVEL;
8949 status = smb_posix_open(conn, req,
8957 case SMB_POSIX_PATH_UNLINK:
8960 /* We must have a pathname for this. */
8961 return NT_STATUS_INVALID_LEVEL;
8964 status = smb_posix_unlink(conn, req,
8972 return NT_STATUS_INVALID_LEVEL;
8975 if (!NT_STATUS_IS_OK(status)) {
8979 *ret_data_size = data_return_size;
8980 return NT_STATUS_OK;
8983 /****************************************************************************
8984 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8985 ****************************************************************************/
8987 static void call_trans2setfilepathinfo(connection_struct *conn,
8988 struct smb_request *req,
8989 unsigned int tran_call,
8990 char **pparams, int total_params,
8991 char **ppdata, int total_data,
8992 unsigned int max_data_bytes)
8994 char *params = *pparams;
8995 char *pdata = *ppdata;
8996 uint16_t info_level;
8997 struct smb_filename *smb_fname = NULL;
8998 files_struct *fsp = NULL;
8999 NTSTATUS status = NT_STATUS_OK;
9000 int data_return_size = 0;
9003 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9007 if (tran_call == TRANSACT2_SETFILEINFO) {
9008 if (total_params < 4) {
9009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9013 fsp = file_fsp(req, SVAL(params,0));
9014 /* Basic check for non-null fsp. */
9015 if (!check_fsp_open(conn, req, fsp)) {
9018 info_level = SVAL(params,2);
9020 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9021 if (smb_fname == NULL) {
9022 reply_nterror(req, NT_STATUS_NO_MEMORY);
9026 if(fsp->fh->fd == -1) {
9028 * This is actually a SETFILEINFO on a directory
9029 * handle (returned from an NT SMB). NT5.0 seems
9030 * to do this call. JRA.
9032 if (INFO_LEVEL_IS_UNIX(info_level)) {
9033 /* Always do lstat for UNIX calls. */
9034 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9035 DEBUG(3,("call_trans2setfilepathinfo: "
9036 "SMB_VFS_LSTAT of %s failed "
9038 smb_fname_str_dbg(smb_fname),
9040 reply_nterror(req, map_nt_error_from_unix(errno));
9044 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9045 DEBUG(3,("call_trans2setfilepathinfo: "
9046 "fileinfo of %s failed (%s)\n",
9047 smb_fname_str_dbg(smb_fname),
9049 reply_nterror(req, map_nt_error_from_unix(errno));
9053 } else if (fsp->print_file) {
9055 * Doing a DELETE_ON_CLOSE should cancel a print job.
9057 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9058 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9060 DEBUG(3,("call_trans2setfilepathinfo: "
9061 "Cancelling print job (%s)\n",
9065 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9071 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9076 * Original code - this is an open file.
9078 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9079 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9080 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9082 reply_nterror(req, map_nt_error_from_unix(errno));
9088 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9091 if (total_params < 7) {
9092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9096 info_level = SVAL(params,0);
9097 if (req->posix_pathnames) {
9098 srvstr_get_path_posix(req,
9107 srvstr_get_path(req,
9116 if (!NT_STATUS_IS_OK(status)) {
9117 reply_nterror(req, status);
9121 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9122 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9123 info_level == SMB_FILE_RENAME_INFORMATION ||
9124 info_level == SMB_POSIX_PATH_OPEN ||
9125 info_level == SMB_POSIX_PATH_UNLINK) {
9126 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9129 status = filename_convert(req, conn,
9135 if (!NT_STATUS_IS_OK(status)) {
9136 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9137 reply_botherror(req,
9138 NT_STATUS_PATH_NOT_COVERED,
9139 ERRSRV, ERRbadpath);
9142 reply_nterror(req, status);
9146 if (INFO_LEVEL_IS_UNIX(info_level)) {
9148 * For CIFS UNIX extensions the target name may not exist.
9151 /* Always do lstat for UNIX calls. */
9152 SMB_VFS_LSTAT(conn, smb_fname);
9154 } else if (!VALID_STAT(smb_fname->st) &&
9155 SMB_VFS_STAT(conn, smb_fname)) {
9156 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9158 smb_fname_str_dbg(smb_fname),
9160 reply_nterror(req, map_nt_error_from_unix(errno));
9165 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9166 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9168 info_level,total_data));
9170 /* Realloc the parameter size */
9171 *pparams = (char *)SMB_REALLOC(*pparams,2);
9172 if (*pparams == NULL) {
9173 reply_nterror(req, NT_STATUS_NO_MEMORY);
9180 status = smbd_do_setfilepathinfo(conn, req, req,
9186 if (!NT_STATUS_IS_OK(status)) {
9187 if (open_was_deferred(req->xconn, req->mid)) {
9188 /* We have re-scheduled this call. */
9191 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9192 /* We have re-scheduled this call. */
9195 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9196 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9197 ERRSRV, ERRbadpath);
9200 if (info_level == SMB_POSIX_PATH_OPEN) {
9201 reply_openerror(req, status);
9206 * Invalid EA name needs to return 2 param bytes,
9207 * not a zero-length error packet.
9209 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9210 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9213 reply_nterror(req, status);
9218 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9224 /****************************************************************************
9225 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9226 ****************************************************************************/
9228 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9229 char **pparams, int total_params,
9230 char **ppdata, int total_data,
9231 unsigned int max_data_bytes)
9233 struct smb_filename *smb_dname = NULL;
9234 char *params = *pparams;
9235 char *pdata = *ppdata;
9236 char *directory = NULL;
9237 NTSTATUS status = NT_STATUS_OK;
9238 struct ea_list *ea_list = NULL;
9239 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9240 TALLOC_CTX *ctx = talloc_tos();
9242 if (!CAN_WRITE(conn)) {
9243 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9247 if (total_params < 5) {
9248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9252 if (req->posix_pathnames) {
9253 srvstr_get_path_posix(ctx,
9262 srvstr_get_path(ctx,
9271 if (!NT_STATUS_IS_OK(status)) {
9272 reply_nterror(req, status);
9276 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9278 status = filename_convert(ctx,
9286 if (!NT_STATUS_IS_OK(status)) {
9287 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9288 reply_botherror(req,
9289 NT_STATUS_PATH_NOT_COVERED,
9290 ERRSRV, ERRbadpath);
9293 reply_nterror(req, status);
9298 * OS/2 workplace shell seems to send SET_EA requests of "null"
9299 * length (4 bytes containing IVAL 4).
9300 * They seem to have no effect. Bug #3212. JRA.
9303 if (total_data && (total_data != 4)) {
9304 /* Any data in this call is an EA list. */
9305 if (total_data < 10) {
9306 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9310 if (IVAL(pdata,0) > total_data) {
9311 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9312 IVAL(pdata,0), (unsigned int)total_data));
9313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9317 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9320 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9324 if (!lp_ea_support(SNUM(conn))) {
9325 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9329 /* If total_data == 4 Windows doesn't care what values
9330 * are placed in that field, it just ignores them.
9331 * The System i QNTC IBM SMB client puts bad values here,
9332 * so ignore them. */
9334 status = create_directory(conn, req, smb_dname);
9336 if (!NT_STATUS_IS_OK(status)) {
9337 reply_nterror(req, status);
9341 /* Try and set any given EA. */
9343 status = set_ea(conn, NULL, smb_dname, ea_list);
9344 if (!NT_STATUS_IS_OK(status)) {
9345 reply_nterror(req, status);
9350 /* Realloc the parameter and data sizes */
9351 *pparams = (char *)SMB_REALLOC(*pparams,2);
9352 if(*pparams == NULL) {
9353 reply_nterror(req, NT_STATUS_NO_MEMORY);
9360 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9363 TALLOC_FREE(smb_dname);
9367 /****************************************************************************
9368 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9369 We don't actually do this - we just send a null response.
9370 ****************************************************************************/
9372 static void call_trans2findnotifyfirst(connection_struct *conn,
9373 struct smb_request *req,
9374 char **pparams, int total_params,
9375 char **ppdata, int total_data,
9376 unsigned int max_data_bytes)
9378 char *params = *pparams;
9379 uint16_t info_level;
9381 if (total_params < 6) {
9382 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9386 info_level = SVAL(params,4);
9387 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9389 switch (info_level) {
9394 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9398 /* Realloc the parameter and data sizes */
9399 *pparams = (char *)SMB_REALLOC(*pparams,6);
9400 if (*pparams == NULL) {
9401 reply_nterror(req, NT_STATUS_NO_MEMORY);
9406 SSVAL(params,0,fnf_handle);
9407 SSVAL(params,2,0); /* No changes */
9408 SSVAL(params,4,0); /* No EA errors */
9415 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9420 /****************************************************************************
9421 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9422 changes). Currently this does nothing.
9423 ****************************************************************************/
9425 static void call_trans2findnotifynext(connection_struct *conn,
9426 struct smb_request *req,
9427 char **pparams, int total_params,
9428 char **ppdata, int total_data,
9429 unsigned int max_data_bytes)
9431 char *params = *pparams;
9433 DEBUG(3,("call_trans2findnotifynext\n"));
9435 /* Realloc the parameter and data sizes */
9436 *pparams = (char *)SMB_REALLOC(*pparams,4);
9437 if (*pparams == NULL) {
9438 reply_nterror(req, NT_STATUS_NO_MEMORY);
9443 SSVAL(params,0,0); /* No changes */
9444 SSVAL(params,2,0); /* No EA errors */
9446 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9451 /****************************************************************************
9452 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9453 ****************************************************************************/
9455 static void call_trans2getdfsreferral(connection_struct *conn,
9456 struct smb_request *req,
9457 char **pparams, int total_params,
9458 char **ppdata, int total_data,
9459 unsigned int max_data_bytes)
9461 char *params = *pparams;
9462 char *pathname = NULL;
9464 int max_referral_level;
9465 NTSTATUS status = NT_STATUS_OK;
9466 TALLOC_CTX *ctx = talloc_tos();
9468 DEBUG(10,("call_trans2getdfsreferral\n"));
9470 if (total_params < 3) {
9471 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9475 max_referral_level = SVAL(params,0);
9477 if(!lp_host_msdfs()) {
9478 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9482 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9483 total_params - 2, STR_TERMINATE);
9485 reply_nterror(req, NT_STATUS_NOT_FOUND);
9488 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9489 ppdata,&status)) < 0) {
9490 reply_nterror(req, status);
9494 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9495 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9496 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9501 #define LMCAT_SPL 0x53
9502 #define LMFUNC_GETJOBID 0x60
9504 /****************************************************************************
9505 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9506 ****************************************************************************/
9508 static void call_trans2ioctl(connection_struct *conn,
9509 struct smb_request *req,
9510 char **pparams, int total_params,
9511 char **ppdata, int total_data,
9512 unsigned int max_data_bytes)
9514 char *pdata = *ppdata;
9515 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9519 /* check for an invalid fid before proceeding */
9522 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9526 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9527 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9528 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9529 if (*ppdata == NULL) {
9530 reply_nterror(req, NT_STATUS_NO_MEMORY);
9535 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9536 CAN ACCEPT THIS IN UNICODE. JRA. */
9539 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9541 status = srvstr_push(pdata, req->flags2, pdata + 2,
9542 lp_netbios_name(), 15,
9543 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9544 if (!NT_STATUS_IS_OK(status)) {
9545 reply_nterror(req, status);
9548 status = srvstr_push(pdata, req->flags2, pdata+18,
9549 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9550 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9551 if (!NT_STATUS_IS_OK(status)) {
9552 reply_nterror(req, status);
9555 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9560 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9561 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9564 /****************************************************************************
9565 Reply to a SMBfindclose (stop trans2 directory search).
9566 ****************************************************************************/
9568 void reply_findclose(struct smb_request *req)
9571 struct smbd_server_connection *sconn = req->sconn;
9573 START_PROFILE(SMBfindclose);
9576 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9577 END_PROFILE(SMBfindclose);
9581 dptr_num = SVALS(req->vwv+0, 0);
9583 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9585 dptr_close(sconn, &dptr_num);
9587 reply_outbuf(req, 0, 0);
9589 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9591 END_PROFILE(SMBfindclose);
9595 /****************************************************************************
9596 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9597 ****************************************************************************/
9599 void reply_findnclose(struct smb_request *req)
9603 START_PROFILE(SMBfindnclose);
9606 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9607 END_PROFILE(SMBfindnclose);
9611 dptr_num = SVAL(req->vwv+0, 0);
9613 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9615 /* We never give out valid handles for a
9616 findnotifyfirst - so any dptr_num is ok here.
9619 reply_outbuf(req, 0, 0);
9621 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9623 END_PROFILE(SMBfindnclose);
9627 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9628 struct trans_state *state)
9630 if (get_Protocol() >= PROTOCOL_NT1) {
9631 req->flags2 |= 0x40; /* IS_LONG_NAME */
9632 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9635 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9636 if (state->call != TRANSACT2_QFSINFO &&
9637 state->call != TRANSACT2_SETFSINFO) {
9638 DEBUG(0,("handle_trans2: encryption required "
9640 (unsigned int)state->call));
9641 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9646 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9648 /* Now we must call the relevant TRANS2 function */
9649 switch(state->call) {
9650 case TRANSACT2_OPEN:
9652 START_PROFILE(Trans2_open);
9653 call_trans2open(conn, req,
9654 &state->param, state->total_param,
9655 &state->data, state->total_data,
9656 state->max_data_return);
9657 END_PROFILE(Trans2_open);
9661 case TRANSACT2_FINDFIRST:
9663 START_PROFILE(Trans2_findfirst);
9664 call_trans2findfirst(conn, req,
9665 &state->param, state->total_param,
9666 &state->data, state->total_data,
9667 state->max_data_return);
9668 END_PROFILE(Trans2_findfirst);
9672 case TRANSACT2_FINDNEXT:
9674 START_PROFILE(Trans2_findnext);
9675 call_trans2findnext(conn, req,
9676 &state->param, state->total_param,
9677 &state->data, state->total_data,
9678 state->max_data_return);
9679 END_PROFILE(Trans2_findnext);
9683 case TRANSACT2_QFSINFO:
9685 START_PROFILE(Trans2_qfsinfo);
9686 call_trans2qfsinfo(conn, req,
9687 &state->param, state->total_param,
9688 &state->data, state->total_data,
9689 state->max_data_return);
9690 END_PROFILE(Trans2_qfsinfo);
9694 case TRANSACT2_SETFSINFO:
9696 START_PROFILE(Trans2_setfsinfo);
9697 call_trans2setfsinfo(conn, req,
9698 &state->param, state->total_param,
9699 &state->data, state->total_data,
9700 state->max_data_return);
9701 END_PROFILE(Trans2_setfsinfo);
9705 case TRANSACT2_QPATHINFO:
9706 case TRANSACT2_QFILEINFO:
9708 START_PROFILE(Trans2_qpathinfo);
9709 call_trans2qfilepathinfo(conn, req, state->call,
9710 &state->param, state->total_param,
9711 &state->data, state->total_data,
9712 state->max_data_return);
9713 END_PROFILE(Trans2_qpathinfo);
9717 case TRANSACT2_SETPATHINFO:
9718 case TRANSACT2_SETFILEINFO:
9720 START_PROFILE(Trans2_setpathinfo);
9721 call_trans2setfilepathinfo(conn, req, state->call,
9722 &state->param, state->total_param,
9723 &state->data, state->total_data,
9724 state->max_data_return);
9725 END_PROFILE(Trans2_setpathinfo);
9729 case TRANSACT2_FINDNOTIFYFIRST:
9731 START_PROFILE(Trans2_findnotifyfirst);
9732 call_trans2findnotifyfirst(conn, req,
9733 &state->param, state->total_param,
9734 &state->data, state->total_data,
9735 state->max_data_return);
9736 END_PROFILE(Trans2_findnotifyfirst);
9740 case TRANSACT2_FINDNOTIFYNEXT:
9742 START_PROFILE(Trans2_findnotifynext);
9743 call_trans2findnotifynext(conn, req,
9744 &state->param, state->total_param,
9745 &state->data, state->total_data,
9746 state->max_data_return);
9747 END_PROFILE(Trans2_findnotifynext);
9751 case TRANSACT2_MKDIR:
9753 START_PROFILE(Trans2_mkdir);
9754 call_trans2mkdir(conn, req,
9755 &state->param, state->total_param,
9756 &state->data, state->total_data,
9757 state->max_data_return);
9758 END_PROFILE(Trans2_mkdir);
9762 case TRANSACT2_GET_DFS_REFERRAL:
9764 START_PROFILE(Trans2_get_dfs_referral);
9765 call_trans2getdfsreferral(conn, req,
9766 &state->param, state->total_param,
9767 &state->data, state->total_data,
9768 state->max_data_return);
9769 END_PROFILE(Trans2_get_dfs_referral);
9773 case TRANSACT2_IOCTL:
9775 START_PROFILE(Trans2_ioctl);
9776 call_trans2ioctl(conn, req,
9777 &state->param, state->total_param,
9778 &state->data, state->total_data,
9779 state->max_data_return);
9780 END_PROFILE(Trans2_ioctl);
9785 /* Error in request */
9786 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9787 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9791 /****************************************************************************
9792 Reply to a SMBtrans2.
9793 ****************************************************************************/
9795 void reply_trans2(struct smb_request *req)
9797 connection_struct *conn = req->conn;
9802 unsigned int tran_call;
9803 struct trans_state *state;
9806 START_PROFILE(SMBtrans2);
9808 if (req->wct < 14) {
9809 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9810 END_PROFILE(SMBtrans2);
9814 dsoff = SVAL(req->vwv+12, 0);
9815 dscnt = SVAL(req->vwv+11, 0);
9816 psoff = SVAL(req->vwv+10, 0);
9817 pscnt = SVAL(req->vwv+9, 0);
9818 tran_call = SVAL(req->vwv+14, 0);
9820 result = allow_new_trans(conn->pending_trans, req->mid);
9821 if (!NT_STATUS_IS_OK(result)) {
9822 DEBUG(2, ("Got invalid trans2 request: %s\n",
9823 nt_errstr(result)));
9824 reply_nterror(req, result);
9825 END_PROFILE(SMBtrans2);
9830 switch (tran_call) {
9831 /* List the allowed trans2 calls on IPC$ */
9832 case TRANSACT2_OPEN:
9833 case TRANSACT2_GET_DFS_REFERRAL:
9834 case TRANSACT2_QFILEINFO:
9835 case TRANSACT2_QFSINFO:
9836 case TRANSACT2_SETFSINFO:
9839 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9840 END_PROFILE(SMBtrans2);
9845 if ((state = talloc(conn, struct trans_state)) == NULL) {
9846 DEBUG(0, ("talloc failed\n"));
9847 reply_nterror(req, NT_STATUS_NO_MEMORY);
9848 END_PROFILE(SMBtrans2);
9852 state->cmd = SMBtrans2;
9854 state->mid = req->mid;
9855 state->vuid = req->vuid;
9856 state->setup_count = SVAL(req->vwv+13, 0);
9857 state->setup = NULL;
9858 state->total_param = SVAL(req->vwv+0, 0);
9859 state->param = NULL;
9860 state->total_data = SVAL(req->vwv+1, 0);
9862 state->max_param_return = SVAL(req->vwv+2, 0);
9863 state->max_data_return = SVAL(req->vwv+3, 0);
9864 state->max_setup_return = SVAL(req->vwv+4, 0);
9865 state->close_on_completion = BITSETW(req->vwv+5, 0);
9866 state->one_way = BITSETW(req->vwv+5, 1);
9868 state->call = tran_call;
9870 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9871 is so as a sanity check */
9872 if (state->setup_count != 1) {
9874 * Need to have rc=0 for ioctl to get job id for OS/2.
9875 * Network printing will fail if function is not successful.
9876 * Similar function in reply.c will be used if protocol
9877 * is LANMAN1.0 instead of LM1.2X002.
9878 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9879 * outbuf doesn't have to be set(only job id is used).
9881 if ( (state->setup_count == 4)
9882 && (tran_call == TRANSACT2_IOCTL)
9883 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9884 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9885 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9887 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9888 DEBUG(2,("Transaction is %d\n",tran_call));
9890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9891 END_PROFILE(SMBtrans2);
9896 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9899 if (state->total_data) {
9901 if (trans_oob(state->total_data, 0, dscnt)
9902 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9906 /* Can't use talloc here, the core routines do realloc on the
9907 * params and data. */
9908 state->data = (char *)SMB_MALLOC(state->total_data);
9909 if (state->data == NULL) {
9910 DEBUG(0,("reply_trans2: data malloc fail for %u "
9911 "bytes !\n", (unsigned int)state->total_data));
9913 reply_nterror(req, NT_STATUS_NO_MEMORY);
9914 END_PROFILE(SMBtrans2);
9918 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9921 if (state->total_param) {
9923 if (trans_oob(state->total_param, 0, pscnt)
9924 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9928 /* Can't use talloc here, the core routines do realloc on the
9929 * params and data. */
9930 state->param = (char *)SMB_MALLOC(state->total_param);
9931 if (state->param == NULL) {
9932 DEBUG(0,("reply_trans: param malloc fail for %u "
9933 "bytes !\n", (unsigned int)state->total_param));
9934 SAFE_FREE(state->data);
9936 reply_nterror(req, NT_STATUS_NO_MEMORY);
9937 END_PROFILE(SMBtrans2);
9941 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9944 state->received_data = dscnt;
9945 state->received_param = pscnt;
9947 if ((state->received_param == state->total_param) &&
9948 (state->received_data == state->total_data)) {
9950 handle_trans2(conn, req, state);
9952 SAFE_FREE(state->data);
9953 SAFE_FREE(state->param);
9955 END_PROFILE(SMBtrans2);
9959 DLIST_ADD(conn->pending_trans, state);
9961 /* We need to send an interim response then receive the rest
9962 of the parameter/data bytes */
9963 reply_outbuf(req, 0, 0);
9964 show_msg((char *)req->outbuf);
9965 END_PROFILE(SMBtrans2);
9970 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9971 SAFE_FREE(state->data);
9972 SAFE_FREE(state->param);
9974 END_PROFILE(SMBtrans2);
9975 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9979 /****************************************************************************
9980 Reply to a SMBtranss2
9981 ****************************************************************************/
9983 void reply_transs2(struct smb_request *req)
9985 connection_struct *conn = req->conn;
9986 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9987 struct trans_state *state;
9989 START_PROFILE(SMBtranss2);
9991 show_msg((const char *)req->inbuf);
9993 /* Windows clients expect all replies to
9994 a transact secondary (SMBtranss2 0x33)
9995 to have a command code of transact
9996 (SMBtrans2 0x32). See bug #8989
9997 and also [MS-CIFS] section 2.2.4.47.2
10000 req->cmd = SMBtrans2;
10002 if (req->wct < 8) {
10003 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10004 END_PROFILE(SMBtranss2);
10008 for (state = conn->pending_trans; state != NULL;
10009 state = state->next) {
10010 if (state->mid == req->mid) {
10015 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10017 END_PROFILE(SMBtranss2);
10021 /* Revise state->total_param and state->total_data in case they have
10022 changed downwards */
10024 if (SVAL(req->vwv+0, 0) < state->total_param)
10025 state->total_param = SVAL(req->vwv+0, 0);
10026 if (SVAL(req->vwv+1, 0) < state->total_data)
10027 state->total_data = SVAL(req->vwv+1, 0);
10029 pcnt = SVAL(req->vwv+2, 0);
10030 poff = SVAL(req->vwv+3, 0);
10031 pdisp = SVAL(req->vwv+4, 0);
10033 dcnt = SVAL(req->vwv+5, 0);
10034 doff = SVAL(req->vwv+6, 0);
10035 ddisp = SVAL(req->vwv+7, 0);
10037 state->received_param += pcnt;
10038 state->received_data += dcnt;
10040 if ((state->received_data > state->total_data) ||
10041 (state->received_param > state->total_param))
10045 if (trans_oob(state->total_param, pdisp, pcnt)
10046 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10049 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10053 if (trans_oob(state->total_data, ddisp, dcnt)
10054 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10057 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10060 if ((state->received_param < state->total_param) ||
10061 (state->received_data < state->total_data)) {
10062 END_PROFILE(SMBtranss2);
10066 handle_trans2(conn, req, state);
10068 DLIST_REMOVE(conn->pending_trans, state);
10069 SAFE_FREE(state->data);
10070 SAFE_FREE(state->param);
10071 TALLOC_FREE(state);
10073 END_PROFILE(SMBtranss2);
10078 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10079 DLIST_REMOVE(conn->pending_trans, state);
10080 SAFE_FREE(state->data);
10081 SAFE_FREE(state->param);
10082 TALLOC_FREE(state);
10083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10084 END_PROFILE(SMBtranss2);