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 Globally (for this connection / multi-channel) disable file-ID
218 calculation. This is required to be global because it serves
219 Macs in AAPL mode, which is globally set.
220 ********************************************************************/
221 void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
223 sconn->aapl_zero_file_id = true;
226 /****************************************************************************
227 Utility functions for dealing with extended attributes.
228 ****************************************************************************/
230 /****************************************************************************
231 Refuse to allow clients to overwrite our private xattrs.
232 ****************************************************************************/
234 bool samba_private_attr_name(const char *unix_ea_name)
236 static const char * const prohibited_ea_names[] = {
237 SAMBA_POSIX_INHERITANCE_EA_NAME,
238 SAMBA_XATTR_DOS_ATTRIB,
246 for (i = 0; prohibited_ea_names[i]; i++) {
247 if (strequal( prohibited_ea_names[i], unix_ea_name))
250 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
251 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
257 /****************************************************************************
258 Get one EA value. Fill in a struct ea_struct.
259 ****************************************************************************/
261 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
262 connection_struct *conn,
264 const struct smb_filename *smb_fname,
266 struct ea_struct *pea)
268 /* Get the value of this xattr. Max size is 64k. */
269 size_t attr_size = 256;
275 val = talloc_realloc(mem_ctx, val, char, attr_size);
277 return NT_STATUS_NO_MEMORY;
280 if (fsp && fsp->fh->fd != -1) {
281 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
283 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
284 ea_name, val, attr_size);
287 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
293 return map_nt_error_from_unix(errno);
296 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
297 dump_data(10, (uint8_t *)val, sizeret);
300 if (strnequal(ea_name, "user.", 5)) {
301 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
303 pea->name = talloc_strdup(mem_ctx, ea_name);
305 if (pea->name == NULL) {
307 return NT_STATUS_NO_MEMORY;
309 pea->value.data = (unsigned char *)val;
310 pea->value.length = (size_t)sizeret;
314 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
315 connection_struct *conn,
317 const struct smb_filename *smb_fname,
322 /* Get a list of all xattrs. Max namesize is 64k. */
323 size_t ea_namelist_size = 1024;
324 char *ea_namelist = smallbuf;
325 char *to_free = NULL;
330 ssize_t sizeret = -1;
338 status = refuse_symlink(conn, fsp, smb_fname);
339 if (!NT_STATUS_IS_OK(status)) {
341 * Just return no EA's on a symlink.
346 if (fsp && fsp->fh->fd != -1) {
347 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
350 sizeret = SMB_VFS_LISTXATTR(conn,
356 if ((sizeret == -1) && (errno == ERANGE)) {
357 ea_namelist_size = 65536;
358 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
359 if (ea_namelist == NULL) {
360 return NT_STATUS_NO_MEMORY;
362 to_free = ea_namelist;
364 if (fsp && fsp->fh->fd != -1) {
365 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
368 sizeret = SMB_VFS_LISTXATTR(conn,
376 status = map_nt_error_from_unix(errno);
377 TALLOC_FREE(to_free);
381 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
384 TALLOC_FREE(to_free);
389 * Ensure the result is 0-terminated
392 if (ea_namelist[sizeret-1] != '\0') {
393 TALLOC_FREE(to_free);
394 return NT_STATUS_INTERNAL_ERROR;
402 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
406 *pnum_names = num_names;
408 if (pnames == NULL) {
409 TALLOC_FREE(to_free);
413 names = talloc_array(mem_ctx, char *, num_names);
415 DEBUG(0, ("talloc failed\n"));
416 TALLOC_FREE(to_free);
417 return NT_STATUS_NO_MEMORY;
420 if (ea_namelist == smallbuf) {
421 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
422 if (ea_namelist == NULL) {
424 return NT_STATUS_NO_MEMORY;
427 talloc_steal(names, ea_namelist);
429 ea_namelist = talloc_realloc(names, ea_namelist, char,
431 if (ea_namelist == NULL) {
433 return NT_STATUS_NO_MEMORY;
439 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
440 names[num_names++] = p;
448 /****************************************************************************
449 Return a linked list of the total EA's. Plus the total size
450 ****************************************************************************/
452 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
453 connection_struct *conn,
455 const struct smb_filename *smb_fname,
456 size_t *pea_total_len,
457 struct ea_list **ea_list)
459 /* Get a list of all xattrs. Max namesize is 64k. */
462 struct ea_list *ea_list_head = NULL;
463 bool posix_pathnames = false;
469 if (!lp_ea_support(SNUM(conn))) {
475 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
477 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
480 status = get_ea_names_from_file(talloc_tos(),
487 if (!NT_STATUS_IS_OK(status)) {
491 if (num_names == 0) {
495 for (i=0; i<num_names; i++) {
496 struct ea_list *listp;
499 if (strnequal(names[i], "system.", 7)
500 || samba_private_attr_name(names[i]))
504 * Filter out any underlying POSIX EA names
505 * that a Windows client can't handle.
507 if (!posix_pathnames &&
508 is_invalid_windows_ea_name(names[i])) {
512 listp = talloc(mem_ctx, struct ea_list);
514 return NT_STATUS_NO_MEMORY;
517 status = get_ea_value(listp,
524 if (!NT_STATUS_IS_OK(status)) {
529 if (listp->ea.value.length == 0) {
531 * We can never return a zero length EA.
532 * Windows reports the EA's as corrupted.
538 push_ascii_fstring(dos_ea_name, listp->ea.name);
541 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
543 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
544 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
545 (unsigned int)listp->ea.value.length));
547 DLIST_ADD_END(ea_list_head, listp);
551 /* Add on 4 for total length. */
552 if (*pea_total_len) {
556 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
557 (unsigned int)*pea_total_len));
559 *ea_list = ea_list_head;
563 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
564 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
569 if (!lp_ea_support(SNUM(conn))) {
573 if (is_ntfs_stream_smb_fname(smb_fname)) {
574 return NT_STATUS_INVALID_PARAMETER;
577 return get_ea_list_from_file_path(mem_ctx,
585 /****************************************************************************
586 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
588 ****************************************************************************/
590 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
591 connection_struct *conn, struct ea_list *ea_list)
593 unsigned int ret_data_size = 4;
596 SMB_ASSERT(total_data_size >= 4);
598 if (!lp_ea_support(SNUM(conn))) {
603 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
606 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
607 dos_namelen = strlen(dos_ea_name);
608 if (dos_namelen > 255 || dos_namelen == 0) {
611 if (ea_list->ea.value.length > 65535) {
614 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
618 /* We know we have room. */
619 SCVAL(p,0,ea_list->ea.flags);
620 SCVAL(p,1,dos_namelen);
621 SSVAL(p,2,ea_list->ea.value.length);
622 strlcpy(p+4, dos_ea_name, dos_namelen+1);
623 if (ea_list->ea.value.length > 0) {
624 memcpy(p + 4 + dos_namelen + 1,
625 ea_list->ea.value.data,
626 ea_list->ea.value.length);
629 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
630 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
633 ret_data_size = PTR_DIFF(p, pdata);
634 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
635 SIVAL(pdata,0,ret_data_size);
636 return ret_data_size;
639 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
641 unsigned int total_data_size,
642 unsigned int *ret_data_size,
643 connection_struct *conn,
644 struct ea_list *ea_list)
646 uint8_t *p = (uint8_t *)pdata;
647 uint8_t *last_start = NULL;
648 bool do_store_data = (pdata != NULL);
652 if (!lp_ea_support(SNUM(conn))) {
653 return NT_STATUS_NO_EAS_ON_FILE;
656 for (; ea_list; ea_list = ea_list->next) {
662 if (last_start != NULL && do_store_data) {
663 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
667 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
668 dos_namelen = strlen(dos_ea_name);
669 if (dos_namelen > 255 || dos_namelen == 0) {
670 return NT_STATUS_INTERNAL_ERROR;
672 if (ea_list->ea.value.length > 65535) {
673 return NT_STATUS_INTERNAL_ERROR;
676 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
679 pad = (4 - (this_size % 4)) % 4;
684 if (this_size > total_data_size) {
685 return NT_STATUS_INFO_LENGTH_MISMATCH;
688 /* We know we have room. */
689 SIVAL(p, 0x00, 0); /* next offset */
690 SCVAL(p, 0x04, ea_list->ea.flags);
691 SCVAL(p, 0x05, dos_namelen);
692 SSVAL(p, 0x06, ea_list->ea.value.length);
693 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
694 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
696 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
700 total_data_size -= this_size;
706 *ret_data_size = PTR_DIFF(p, pdata);
707 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
711 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
713 size_t total_ea_len = 0;
715 struct ea_list *ea_list = NULL;
717 if (!lp_ea_support(SNUM(conn))) {
720 mem_ctx = talloc_stackframe();
722 /* If this is a stream fsp, then we need to instead find the
723 * estimated ea len from the main file, not the stream
724 * (streams cannot have EAs), but the estimate isn't just 0 in
726 if (is_ntfs_stream_smb_fname(smb_fname)) {
729 (void)get_ea_list_from_file_path(mem_ctx,
735 if(conn->sconn->using_smb2) {
737 unsigned int ret_data_size;
739 * We're going to be using fill_ea_chained_buffer() to
740 * marshall EA's - this size is significantly larger
741 * than the SMB1 buffer. Re-calculate the size without
744 status = fill_ea_chained_buffer(mem_ctx,
750 if (!NT_STATUS_IS_OK(status)) {
753 total_ea_len = ret_data_size;
755 TALLOC_FREE(mem_ctx);
759 /****************************************************************************
760 Ensure the EA name is case insensitive by matching any existing EA name.
761 ****************************************************************************/
763 static void canonicalize_ea_name(connection_struct *conn,
765 const struct smb_filename *smb_fname,
766 fstring unix_ea_name)
769 TALLOC_CTX *mem_ctx = talloc_tos();
770 struct ea_list *ea_list;
771 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
777 if (!NT_STATUS_IS_OK(status)) {
781 for (; ea_list; ea_list = ea_list->next) {
782 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
783 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
784 &unix_ea_name[5], ea_list->ea.name));
785 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
791 /****************************************************************************
792 Set or delete an extended attribute.
793 ****************************************************************************/
795 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
796 const struct smb_filename *smb_fname, struct ea_list *ea_list)
799 bool posix_pathnames = false;
801 if (!lp_ea_support(SNUM(conn))) {
802 return NT_STATUS_EAS_NOT_SUPPORTED;
807 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
809 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
812 status = refuse_symlink(conn, fsp, smb_fname);
813 if (!NT_STATUS_IS_OK(status)) {
817 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
818 if (!NT_STATUS_IS_OK(status)) {
822 /* Setting EAs on streams isn't supported. */
823 if (is_ntfs_stream_smb_fname(smb_fname)) {
824 return NT_STATUS_INVALID_PARAMETER;
828 * Filter out invalid Windows EA names - before
829 * we set *any* of them.
832 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
833 return STATUS_INVALID_EA_NAME;
836 for (;ea_list; ea_list = ea_list->next) {
838 fstring unix_ea_name;
840 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
841 fstrcat(unix_ea_name, ea_list->ea.name);
843 canonicalize_ea_name(conn,
848 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
850 if (samba_private_attr_name(unix_ea_name)) {
851 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
852 return NT_STATUS_ACCESS_DENIED;
855 if (ea_list->ea.value.length == 0) {
856 /* Remove the attribute. */
857 if (fsp && (fsp->fh->fd != -1)) {
858 DEBUG(10,("set_ea: deleting ea name %s on "
859 "file %s by file descriptor.\n",
860 unix_ea_name, fsp_str_dbg(fsp)));
861 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
863 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
864 unix_ea_name, smb_fname->base_name));
865 ret = SMB_VFS_REMOVEXATTR(conn,
870 /* Removing a non existent attribute always succeeds. */
871 if (ret == -1 && errno == ENOATTR) {
872 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
878 if (fsp && (fsp->fh->fd != -1)) {
879 DEBUG(10,("set_ea: setting ea name %s on file "
880 "%s by file descriptor.\n",
881 unix_ea_name, fsp_str_dbg(fsp)));
882 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
883 ea_list->ea.value.data, ea_list->ea.value.length, 0);
885 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
886 unix_ea_name, smb_fname->base_name));
887 ret = SMB_VFS_SETXATTR(conn,
890 ea_list->ea.value.data,
891 ea_list->ea.value.length,
898 if (errno == ENOTSUP) {
899 return NT_STATUS_EAS_NOT_SUPPORTED;
902 return map_nt_error_from_unix(errno);
908 /****************************************************************************
909 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
910 ****************************************************************************/
912 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
914 struct ea_list *ea_list_head = NULL;
915 size_t converted_size, offset = 0;
917 while (offset + 2 < data_size) {
918 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
919 unsigned int namelen = CVAL(pdata,offset);
921 offset++; /* Go past the namelen byte. */
923 /* integer wrap paranioa. */
924 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
925 (offset > data_size) || (namelen > data_size) ||
926 (offset + namelen >= data_size)) {
929 /* Ensure the name is null terminated. */
930 if (pdata[offset + namelen] != '\0') {
933 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
935 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
936 "failed: %s", strerror(errno)));
942 offset += (namelen + 1); /* Go past the name + terminating zero. */
943 DLIST_ADD_END(ea_list_head, eal);
944 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
950 /****************************************************************************
951 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
952 ****************************************************************************/
954 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
956 struct ea_list *ea_list_head = NULL;
958 size_t bytes_used = 0;
960 while (offset < data_size) {
961 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
967 DLIST_ADD_END(ea_list_head, eal);
968 offset += bytes_used;
974 /****************************************************************************
975 Count the total EA size needed.
976 ****************************************************************************/
978 static size_t ea_list_size(struct ea_list *ealist)
981 struct ea_list *listp;
984 for (listp = ealist; listp; listp = listp->next) {
985 push_ascii_fstring(dos_ea_name, listp->ea.name);
986 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
988 /* Add on 4 for total length. */
996 /****************************************************************************
997 Return a union of EA's from a file list and a list of names.
998 The TALLOC context for the two lists *MUST* be identical as we steal
999 memory from one list to add to another. JRA.
1000 ****************************************************************************/
1002 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
1004 struct ea_list *nlistp, *flistp;
1006 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
1007 for (flistp = file_list; flistp; flistp = flistp->next) {
1008 if (strequal(nlistp->ea.name, flistp->ea.name)) {
1014 /* Copy the data from this entry. */
1015 nlistp->ea.flags = flistp->ea.flags;
1016 nlistp->ea.value = flistp->ea.value;
1019 nlistp->ea.flags = 0;
1020 ZERO_STRUCT(nlistp->ea.value);
1024 *total_ea_len = ea_list_size(name_list);
1028 /****************************************************************************
1029 Send the required number of replies back.
1030 We assume all fields other than the data fields are
1031 set correctly for the type of call.
1032 HACK ! Always assumes smb_setup field is zero.
1033 ****************************************************************************/
1035 void send_trans2_replies(connection_struct *conn,
1036 struct smb_request *req,
1044 /* As we are using a protocol > LANMAN1 then the max_send
1045 variable must have been set in the sessetupX call.
1046 This takes precedence over the max_xmit field in the
1047 global struct. These different max_xmit variables should
1048 be merged as this is now too confusing */
1050 int data_to_send = datasize;
1051 int params_to_send = paramsize;
1053 const char *pp = params;
1054 const char *pd = pdata;
1055 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1056 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1057 int data_alignment_offset = 0;
1058 bool overflow = False;
1059 struct smbXsrv_connection *xconn = req->xconn;
1060 int max_send = xconn->smb1.sessions.max_send;
1062 /* Modify the data_to_send and datasize and set the error if
1063 we're trying to send more than max_data_bytes. We still send
1064 the part of the packet(s) that fit. Strange, but needed
1067 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1068 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1069 max_data_bytes, datasize ));
1070 datasize = data_to_send = max_data_bytes;
1074 /* If there genuinely are no parameters or data to send just send the empty packet */
1076 if(params_to_send == 0 && data_to_send == 0) {
1077 reply_outbuf(req, 10, 0);
1078 if (NT_STATUS_V(status)) {
1081 ntstatus_to_dos(status, &eclass, &ecode);
1082 error_packet_set((char *)req->outbuf,
1083 eclass, ecode, status,
1086 show_msg((char *)req->outbuf);
1087 if (!srv_send_smb(xconn,
1088 (char *)req->outbuf,
1089 true, req->seqnum+1,
1090 IS_CONN_ENCRYPTED(conn),
1092 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1094 TALLOC_FREE(req->outbuf);
1098 /* When sending params and data ensure that both are nicely aligned */
1099 /* Only do this alignment when there is also data to send - else
1100 can cause NT redirector problems. */
1102 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1103 data_alignment_offset = 4 - (params_to_send % 4);
1105 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1106 /* The alignment_offset is to align the param bytes on an even byte
1107 boundary. NT 4.0 Beta needs this to work correctly. */
1109 useable_space = max_send - (smb_size
1112 + data_alignment_offset);
1114 if (useable_space < 0) {
1115 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1116 "= %d!!!", useable_space));
1117 exit_server_cleanly("send_trans2_replies: Not enough space");
1120 while (params_to_send || data_to_send) {
1121 /* Calculate whether we will totally or partially fill this packet */
1123 total_sent_thistime = params_to_send + data_to_send;
1125 /* We can never send more than useable_space */
1127 * Note that 'useable_space' does not include the alignment offsets,
1128 * but we must include the alignment offsets in the calculation of
1129 * the length of the data we send over the wire, as the alignment offsets
1130 * are sent here. Fix from Marc_Jacobsen@hp.com.
1133 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1135 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1136 + data_alignment_offset);
1138 /* Set total params and data to be sent */
1139 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1140 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1142 /* Calculate how many parameters and data we can fit into
1143 * this packet. Parameters get precedence
1146 params_sent_thistime = MIN(params_to_send,useable_space);
1147 data_sent_thistime = useable_space - params_sent_thistime;
1148 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1150 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1152 /* smb_proff is the offset from the start of the SMB header to the
1153 parameter bytes, however the first 4 bytes of outbuf are
1154 the Netbios over TCP header. Thus use smb_base() to subtract
1155 them from the calculation */
1157 SSVAL(req->outbuf,smb_proff,
1158 ((smb_buf(req->outbuf)+alignment_offset)
1159 - smb_base(req->outbuf)));
1161 if(params_sent_thistime == 0)
1162 SSVAL(req->outbuf,smb_prdisp,0);
1164 /* Absolute displacement of param bytes sent in this packet */
1165 SSVAL(req->outbuf,smb_prdisp,pp - params);
1167 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1168 if(data_sent_thistime == 0) {
1169 SSVAL(req->outbuf,smb_droff,0);
1170 SSVAL(req->outbuf,smb_drdisp, 0);
1172 /* The offset of the data bytes is the offset of the
1173 parameter bytes plus the number of parameters being sent this time */
1174 SSVAL(req->outbuf, smb_droff,
1175 ((smb_buf(req->outbuf)+alignment_offset)
1176 - smb_base(req->outbuf))
1177 + params_sent_thistime + data_alignment_offset);
1178 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1181 /* Initialize the padding for alignment */
1183 if (alignment_offset != 0) {
1184 memset(smb_buf(req->outbuf), 0, alignment_offset);
1187 /* Copy the param bytes into the packet */
1189 if(params_sent_thistime) {
1190 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1191 params_sent_thistime);
1194 /* Copy in the data bytes */
1195 if(data_sent_thistime) {
1196 if (data_alignment_offset != 0) {
1197 memset((smb_buf(req->outbuf)+alignment_offset+
1198 params_sent_thistime), 0,
1199 data_alignment_offset);
1201 memcpy(smb_buf(req->outbuf)+alignment_offset
1202 +params_sent_thistime+data_alignment_offset,
1203 pd,data_sent_thistime);
1206 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1207 params_sent_thistime, data_sent_thistime, useable_space));
1208 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1209 params_to_send, data_to_send, paramsize, datasize));
1212 error_packet_set((char *)req->outbuf,
1213 ERRDOS,ERRbufferoverflow,
1214 STATUS_BUFFER_OVERFLOW,
1216 } else if (NT_STATUS_V(status)) {
1219 ntstatus_to_dos(status, &eclass, &ecode);
1220 error_packet_set((char *)req->outbuf,
1221 eclass, ecode, status,
1225 /* Send the packet */
1226 show_msg((char *)req->outbuf);
1227 if (!srv_send_smb(xconn,
1228 (char *)req->outbuf,
1229 true, req->seqnum+1,
1230 IS_CONN_ENCRYPTED(conn),
1232 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1234 TALLOC_FREE(req->outbuf);
1236 pp += params_sent_thistime;
1237 pd += data_sent_thistime;
1239 params_to_send -= params_sent_thistime;
1240 data_to_send -= data_sent_thistime;
1243 if(params_to_send < 0 || data_to_send < 0) {
1244 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1245 params_to_send, data_to_send));
1253 /****************************************************************************
1254 Reply to a TRANSACT2_OPEN.
1255 ****************************************************************************/
1257 static void call_trans2open(connection_struct *conn,
1258 struct smb_request *req,
1259 char **pparams, int total_params,
1260 char **ppdata, int total_data,
1261 unsigned int max_data_bytes)
1263 struct smb_filename *smb_fname = NULL;
1264 char *params = *pparams;
1265 char *pdata = *ppdata;
1268 bool oplock_request;
1270 bool return_additional_info;
1279 int fattr=0,mtime=0;
1280 SMB_INO_T inode = 0;
1283 struct ea_list *ea_list = NULL;
1286 uint32_t access_mask;
1287 uint32_t share_mode;
1288 uint32_t create_disposition;
1289 uint32_t create_options = 0;
1290 uint32_t private_flags = 0;
1291 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1292 TALLOC_CTX *ctx = talloc_tos();
1295 * Ensure we have enough parameters to perform the operation.
1298 if (total_params < 29) {
1299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1303 flags = SVAL(params, 0);
1304 deny_mode = SVAL(params, 2);
1305 open_attr = SVAL(params,6);
1306 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1307 if (oplock_request) {
1308 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1312 return_additional_info = BITSETW(params,0);
1313 open_sattr = SVAL(params, 4);
1314 open_time = make_unix_date3(params+8);
1316 open_ofun = SVAL(params,12);
1317 open_size = IVAL(params,14);
1318 pname = ¶ms[28];
1321 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1325 if (req->posix_pathnames) {
1326 srvstr_get_path_posix(ctx,
1335 srvstr_get_path(ctx,
1344 if (!NT_STATUS_IS_OK(status)) {
1345 reply_nterror(req, status);
1349 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1350 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1351 (unsigned int)open_ofun, open_size));
1353 status = filename_convert(ctx,
1360 if (!NT_STATUS_IS_OK(status)) {
1361 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1362 reply_botherror(req,
1363 NT_STATUS_PATH_NOT_COVERED,
1364 ERRSRV, ERRbadpath);
1367 reply_nterror(req, status);
1371 if (open_ofun == 0) {
1372 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1376 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1378 &access_mask, &share_mode,
1379 &create_disposition,
1382 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1386 /* Any data in this call is an EA list. */
1387 if (total_data && (total_data != 4)) {
1388 if (total_data < 10) {
1389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1393 if (IVAL(pdata,0) > total_data) {
1394 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1395 IVAL(pdata,0), (unsigned int)total_data));
1396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1400 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1403 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1407 if (!lp_ea_support(SNUM(conn))) {
1408 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1412 if (!req->posix_pathnames &&
1413 ea_list_has_invalid_name(ea_list)) {
1415 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1416 if(*pparams == NULL ) {
1417 reply_nterror(req, NT_STATUS_NO_MEMORY);
1421 memset(params, '\0', param_len);
1422 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1423 params, param_len, NULL, 0, max_data_bytes);
1428 status = SMB_VFS_CREATE_FILE(
1431 0, /* root_dir_fid */
1432 smb_fname, /* fname */
1433 access_mask, /* access_mask */
1434 share_mode, /* share_access */
1435 create_disposition, /* create_disposition*/
1436 create_options, /* create_options */
1437 open_attr, /* file_attributes */
1438 oplock_request, /* oplock_request */
1440 open_size, /* allocation_size */
1443 ea_list, /* ea_list */
1445 &smb_action, /* psbuf */
1446 NULL, NULL); /* create context */
1448 if (!NT_STATUS_IS_OK(status)) {
1449 if (open_was_deferred(req->xconn, req->mid)) {
1450 /* We have re-scheduled this call. */
1453 reply_openerror(req, status);
1457 size = get_file_size_stat(&smb_fname->st);
1458 fattr = dos_mode(conn, smb_fname);
1459 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1460 inode = smb_fname->st.st_ex_ino;
1461 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1462 close_file(req, fsp, ERROR_CLOSE);
1463 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1467 /* Realloc the size of parameters and data we will return */
1468 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1469 if(*pparams == NULL ) {
1470 reply_nterror(req, NT_STATUS_NO_MEMORY);
1475 SSVAL(params,0,fsp->fnum);
1476 SSVAL(params,2,fattr);
1477 srv_put_dos_date2(params,4, mtime);
1478 SIVAL(params,8, (uint32_t)size);
1479 SSVAL(params,12,deny_mode);
1480 SSVAL(params,14,0); /* open_type - file or directory. */
1481 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1483 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1484 smb_action |= EXTENDED_OPLOCK_GRANTED;
1487 SSVAL(params,18,smb_action);
1490 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1492 SIVAL(params,20,inode);
1493 SSVAL(params,24,0); /* Padding. */
1495 uint32_t ea_size = estimate_ea_size(conn, fsp,
1497 SIVAL(params, 26, ea_size);
1499 SIVAL(params, 26, 0);
1502 /* Send the required number of replies */
1503 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1505 TALLOC_FREE(smb_fname);
1508 /*********************************************************
1509 Routine to check if a given string matches exactly.
1510 as a special case a mask of "." does NOT match. That
1511 is required for correct wildcard semantics
1512 Case can be significant or not.
1513 **********************************************************/
1515 static bool exact_match(bool has_wild,
1516 bool case_sensitive,
1520 if (mask[0] == '.' && mask[1] == 0) {
1528 if (case_sensitive) {
1529 return strcmp(str,mask)==0;
1531 return strcasecmp_m(str,mask) == 0;
1535 /****************************************************************************
1536 Return the filetype for UNIX extensions.
1537 ****************************************************************************/
1539 static uint32_t unix_filetype(mode_t mode)
1542 return UNIX_TYPE_FILE;
1543 else if(S_ISDIR(mode))
1544 return UNIX_TYPE_DIR;
1546 else if(S_ISLNK(mode))
1547 return UNIX_TYPE_SYMLINK;
1550 else if(S_ISCHR(mode))
1551 return UNIX_TYPE_CHARDEV;
1554 else if(S_ISBLK(mode))
1555 return UNIX_TYPE_BLKDEV;
1558 else if(S_ISFIFO(mode))
1559 return UNIX_TYPE_FIFO;
1562 else if(S_ISSOCK(mode))
1563 return UNIX_TYPE_SOCKET;
1566 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1567 return UNIX_TYPE_UNKNOWN;
1570 /****************************************************************************
1571 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1572 ****************************************************************************/
1574 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1576 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1577 const SMB_STRUCT_STAT *psbuf,
1579 enum perm_type ptype,
1584 if (perms == SMB_MODE_NO_CHANGE) {
1585 if (!VALID_STAT(*psbuf)) {
1586 return NT_STATUS_INVALID_PARAMETER;
1588 *ret_perms = psbuf->st_ex_mode;
1589 return NT_STATUS_OK;
1593 ret = wire_perms_to_unix(perms);
1595 if (ptype == PERM_NEW_FILE) {
1597 * "create mask"/"force create mode" are
1598 * only applied to new files, not existing ones.
1600 ret &= lp_create_mask(SNUM(conn));
1601 /* Add in force bits */
1602 ret |= lp_force_create_mode(SNUM(conn));
1603 } else if (ptype == PERM_NEW_DIR) {
1605 * "directory mask"/"force directory mode" are
1606 * only applied to new directories, not existing ones.
1608 ret &= lp_directory_mask(SNUM(conn));
1609 /* Add in force bits */
1610 ret |= lp_force_directory_mode(SNUM(conn));
1614 return NT_STATUS_OK;
1617 /****************************************************************************
1618 Needed to show the msdfs symlinks as directories. Modifies psbuf
1619 to be a directory if it's a msdfs link.
1620 ****************************************************************************/
1622 static bool check_msdfs_link(connection_struct *conn,
1623 struct smb_filename *smb_fname)
1625 int saved_errno = errno;
1626 if(lp_host_msdfs() &&
1627 lp_msdfs_root(SNUM(conn)) &&
1628 is_msdfs_link(conn, smb_fname)) {
1630 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1632 smb_fname->base_name));
1633 smb_fname->st.st_ex_mode =
1634 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1635 errno = saved_errno;
1638 errno = saved_errno;
1643 /****************************************************************************
1644 Get a level dependent lanman2 dir entry.
1645 ****************************************************************************/
1647 struct smbd_dirptr_lanman2_state {
1648 connection_struct *conn;
1649 uint32_t info_level;
1650 bool check_mangled_names;
1652 bool got_exact_match;
1655 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1661 struct smbd_dirptr_lanman2_state *state =
1662 (struct smbd_dirptr_lanman2_state *)private_data;
1664 char mangled_name[13]; /* mangled 8.3 name. */
1668 /* Mangle fname if it's an illegal name. */
1669 if (mangle_must_mangle(dname, state->conn->params)) {
1671 * Slow path - ensure we can push the original name as UCS2. If
1672 * not, then just don't return this name.
1676 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1677 uint8_t *tmp = talloc_array(talloc_tos(),
1681 status = srvstr_push(NULL,
1682 FLAGS2_UNICODE_STRINGS,
1691 if (!NT_STATUS_IS_OK(status)) {
1695 ok = name_to_8_3(dname, mangled_name,
1696 true, state->conn->params);
1700 fname = mangled_name;
1705 got_match = exact_match(state->has_wild,
1706 state->conn->case_sensitive,
1708 state->got_exact_match = got_match;
1710 got_match = mask_match(fname, mask,
1711 state->conn->case_sensitive);
1714 if(!got_match && state->check_mangled_names &&
1715 !mangle_is_8_3(fname, false, state->conn->params)) {
1717 * It turns out that NT matches wildcards against
1718 * both long *and* short names. This may explain some
1719 * of the wildcard wierdness from old DOS clients
1720 * that some people have been seeing.... JRA.
1722 /* Force the mangling into 8.3. */
1723 ok = name_to_8_3(fname, mangled_name,
1724 false, state->conn->params);
1729 got_match = exact_match(state->has_wild,
1730 state->conn->case_sensitive,
1731 mangled_name, mask);
1732 state->got_exact_match = got_match;
1734 got_match = mask_match(mangled_name, mask,
1735 state->conn->case_sensitive);
1743 *_fname = talloc_strdup(ctx, fname);
1744 if (*_fname == NULL) {
1751 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1753 struct smb_filename *smb_fname,
1757 struct smbd_dirptr_lanman2_state *state =
1758 (struct smbd_dirptr_lanman2_state *)private_data;
1759 bool ms_dfs_link = false;
1762 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1763 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1764 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1765 "Couldn't lstat [%s] (%s)\n",
1766 smb_fname_str_dbg(smb_fname),
1770 } else if (!VALID_STAT(smb_fname->st) &&
1771 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1772 /* Needed to show the msdfs symlinks as
1775 ms_dfs_link = check_msdfs_link(state->conn,
1778 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1779 "Couldn't stat [%s] (%s)\n",
1780 smb_fname_str_dbg(smb_fname),
1787 mode = dos_mode_msdfs(state->conn, smb_fname);
1788 } else if (get_dosmode) {
1789 mode = dos_mode(state->conn, smb_fname);
1796 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1797 connection_struct *conn,
1799 uint32_t info_level,
1800 struct ea_list *name_list,
1801 bool check_mangled_names,
1802 bool requires_resume_key,
1805 const struct smb_filename *smb_fname,
1806 int space_remaining,
1812 uint64_t *last_entry_off)
1814 char *p, *q, *pdata = *ppdata;
1816 uint64_t file_size = 0;
1817 uint64_t allocation_size = 0;
1818 uint64_t file_id = 0;
1820 struct timespec mdate_ts = {0};
1821 struct timespec adate_ts = {0};
1822 struct timespec cdate_ts = {0};
1823 struct timespec create_date_ts = {0};
1824 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1826 char *last_entry_ptr;
1831 struct readdir_attr_data *readdir_attr_data = NULL;
1833 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1834 file_size = get_file_size_stat(&smb_fname->st);
1836 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1838 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1839 if (!NT_STATUS_IS_OK(status)) {
1840 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1845 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1847 mdate_ts = smb_fname->st.st_ex_mtime;
1848 adate_ts = smb_fname->st.st_ex_atime;
1849 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1850 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1852 if (lp_dos_filetime_resolution(SNUM(conn))) {
1853 dos_filetime_timespec(&create_date_ts);
1854 dos_filetime_timespec(&mdate_ts);
1855 dos_filetime_timespec(&adate_ts);
1856 dos_filetime_timespec(&cdate_ts);
1859 create_date = convert_timespec_to_time_t(create_date_ts);
1860 mdate = convert_timespec_to_time_t(mdate_ts);
1861 adate = convert_timespec_to_time_t(adate_ts);
1863 /* align the record */
1864 SMB_ASSERT(align >= 1);
1866 off = (int)PTR_DIFF(pdata, base_data);
1867 pad = (off + (align-1)) & ~(align-1);
1870 if (pad && pad > space_remaining) {
1871 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1872 "for padding (wanted %u, had %d)\n",
1875 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1879 /* initialize padding to 0 */
1881 memset(pdata, 0, pad);
1883 space_remaining -= pad;
1885 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1895 switch (info_level) {
1896 case SMB_FIND_INFO_STANDARD:
1897 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1898 if(requires_resume_key) {
1902 srv_put_dos_date2(p,0,create_date);
1903 srv_put_dos_date2(p,4,adate);
1904 srv_put_dos_date2(p,8,mdate);
1905 SIVAL(p,12,(uint32_t)file_size);
1906 SIVAL(p,16,(uint32_t)allocation_size);
1910 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1911 p += ucs2_align(base_data, p, 0);
1913 status = srvstr_push(base_data, flags2, p,
1914 fname, PTR_DIFF(end_data, p),
1915 STR_TERMINATE, &len);
1916 if (!NT_STATUS_IS_OK(status)) {
1919 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1921 SCVAL(nameptr, -1, len - 2);
1923 SCVAL(nameptr, -1, 0);
1927 SCVAL(nameptr, -1, len - 1);
1929 SCVAL(nameptr, -1, 0);
1935 case SMB_FIND_EA_SIZE:
1936 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1937 if (requires_resume_key) {
1941 srv_put_dos_date2(p,0,create_date);
1942 srv_put_dos_date2(p,4,adate);
1943 srv_put_dos_date2(p,8,mdate);
1944 SIVAL(p,12,(uint32_t)file_size);
1945 SIVAL(p,16,(uint32_t)allocation_size);
1948 unsigned int ea_size = estimate_ea_size(conn, NULL,
1950 SIVAL(p,22,ea_size); /* Extended attributes */
1954 status = srvstr_push(base_data, flags2,
1955 p, fname, PTR_DIFF(end_data, p),
1956 STR_TERMINATE | STR_NOALIGN, &len);
1957 if (!NT_STATUS_IS_OK(status)) {
1960 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1973 SCVAL(nameptr,0,len);
1975 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1978 case SMB_FIND_EA_LIST:
1980 struct ea_list *file_list = NULL;
1983 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1985 return NT_STATUS_INVALID_PARAMETER;
1987 if (requires_resume_key) {
1991 srv_put_dos_date2(p,0,create_date);
1992 srv_put_dos_date2(p,4,adate);
1993 srv_put_dos_date2(p,8,mdate);
1994 SIVAL(p,12,(uint32_t)file_size);
1995 SIVAL(p,16,(uint32_t)allocation_size);
1997 p += 22; /* p now points to the EA area. */
1999 status = get_ea_list_from_file(ctx, conn, NULL,
2001 &ea_len, &file_list);
2002 if (!NT_STATUS_IS_OK(status)) {
2005 name_list = ea_list_union(name_list, file_list, &ea_len);
2007 /* We need to determine if this entry will fit in the space available. */
2008 /* Max string size is 255 bytes. */
2009 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2010 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2011 "(wanted %u, had %d)\n",
2012 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2014 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2017 /* Push the ea_data followed by the name. */
2018 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2020 status = srvstr_push(base_data, flags2,
2021 p + 1, fname, PTR_DIFF(end_data, p+1),
2022 STR_TERMINATE | STR_NOALIGN, &len);
2023 if (!NT_STATUS_IS_OK(status)) {
2026 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2039 SCVAL(nameptr,0,len);
2041 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2045 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2046 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2047 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2049 SIVAL(p,0,reskey); p += 4;
2050 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2051 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2052 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2053 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2054 SOFF_T(p,0,file_size); p += 8;
2055 SOFF_T(p,0,allocation_size); p += 8;
2056 SIVAL(p,0,mode); p += 4;
2057 q = p; p += 4; /* q is placeholder for name length. */
2058 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2059 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2061 unsigned int ea_size = estimate_ea_size(conn, NULL,
2063 SIVAL(p,0,ea_size); /* Extended attributes */
2066 /* Clear the short name buffer. This is
2067 * IMPORTANT as not doing so will trigger
2068 * a Win2k client bug. JRA.
2070 if (!was_8_3 && check_mangled_names) {
2071 char mangled_name[13]; /* mangled 8.3 name. */
2072 if (!name_to_8_3(fname,mangled_name,True,
2074 /* Error - mangle failed ! */
2075 memset(mangled_name,'\0',12);
2077 mangled_name[12] = 0;
2078 status = srvstr_push(base_data, flags2,
2079 p+2, mangled_name, 24,
2080 STR_UPPER|STR_UNICODE, &len);
2081 if (!NT_STATUS_IS_OK(status)) {
2085 memset(p + 2 + len,'\0',24 - len);
2092 status = srvstr_push(base_data, flags2, p,
2093 fname, PTR_DIFF(end_data, p),
2094 STR_TERMINATE_ASCII, &len);
2095 if (!NT_STATUS_IS_OK(status)) {
2101 len = PTR_DIFF(p, pdata);
2102 pad = (len + (align-1)) & ~(align-1);
2104 * offset to the next entry, the caller
2105 * will overwrite it for the last entry
2106 * that's why we always include the padding
2110 * set padding to zero
2113 memset(p, 0, pad - len);
2120 case SMB_FIND_FILE_DIRECTORY_INFO:
2121 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2123 SIVAL(p,0,reskey); p += 4;
2124 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2125 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2126 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2127 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2128 SOFF_T(p,0,file_size); p += 8;
2129 SOFF_T(p,0,allocation_size); p += 8;
2130 SIVAL(p,0,mode); p += 4;
2131 status = srvstr_push(base_data, flags2,
2132 p + 4, fname, PTR_DIFF(end_data, p+4),
2133 STR_TERMINATE_ASCII, &len);
2134 if (!NT_STATUS_IS_OK(status)) {
2140 len = PTR_DIFF(p, pdata);
2141 pad = (len + (align-1)) & ~(align-1);
2143 * offset to the next entry, the caller
2144 * will overwrite it for the last entry
2145 * that's why we always include the padding
2149 * set padding to zero
2152 memset(p, 0, pad - len);
2159 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2160 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2162 SIVAL(p,0,reskey); p += 4;
2163 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2164 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2165 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2166 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2167 SOFF_T(p,0,file_size); p += 8;
2168 SOFF_T(p,0,allocation_size); p += 8;
2169 SIVAL(p,0,mode); p += 4;
2170 q = p; p += 4; /* q is placeholder for name length. */
2171 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2172 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2174 unsigned int ea_size = estimate_ea_size(conn, NULL,
2176 SIVAL(p,0,ea_size); /* Extended attributes */
2179 status = srvstr_push(base_data, flags2, p,
2180 fname, PTR_DIFF(end_data, p),
2181 STR_TERMINATE_ASCII, &len);
2182 if (!NT_STATUS_IS_OK(status)) {
2188 len = PTR_DIFF(p, pdata);
2189 pad = (len + (align-1)) & ~(align-1);
2191 * offset to the next entry, the caller
2192 * will overwrite it for the last entry
2193 * that's why we always include the padding
2197 * set padding to zero
2200 memset(p, 0, pad - len);
2207 case SMB_FIND_FILE_NAMES_INFO:
2208 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2210 SIVAL(p,0,reskey); p += 4;
2212 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2213 acl on a dir (tridge) */
2214 status = srvstr_push(base_data, flags2, p,
2215 fname, PTR_DIFF(end_data, p),
2216 STR_TERMINATE_ASCII, &len);
2217 if (!NT_STATUS_IS_OK(status)) {
2223 len = PTR_DIFF(p, pdata);
2224 pad = (len + (align-1)) & ~(align-1);
2226 * offset to the next entry, the caller
2227 * will overwrite it for the last entry
2228 * that's why we always include the padding
2232 * set padding to zero
2235 memset(p, 0, pad - len);
2242 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2243 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2245 SIVAL(p,0,reskey); p += 4;
2246 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2247 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2248 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2249 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2250 SOFF_T(p,0,file_size); p += 8;
2251 SOFF_T(p,0,allocation_size); p += 8;
2252 SIVAL(p,0,mode); p += 4;
2253 q = p; p += 4; /* q is placeholder for name length. */
2254 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2255 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2257 unsigned int ea_size = estimate_ea_size(conn, NULL,
2259 SIVAL(p,0,ea_size); /* Extended attributes */
2262 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2263 SBVAL(p,0,file_id); p += 8;
2264 status = srvstr_push(base_data, flags2, p,
2265 fname, PTR_DIFF(end_data, p),
2266 STR_TERMINATE_ASCII, &len);
2267 if (!NT_STATUS_IS_OK(status)) {
2273 len = PTR_DIFF(p, pdata);
2274 pad = (len + (align-1)) & ~(align-1);
2276 * offset to the next entry, the caller
2277 * will overwrite it for the last entry
2278 * that's why we always include the padding
2282 * set padding to zero
2285 memset(p, 0, pad - len);
2292 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2293 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2294 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2296 SIVAL(p,0,reskey); p += 4;
2297 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2298 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2299 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2300 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2301 SOFF_T(p,0,file_size); p += 8;
2302 SOFF_T(p,0,allocation_size); p += 8;
2303 SIVAL(p,0,mode); p += 4;
2304 q = p; p += 4; /* q is placeholder for name length */
2305 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2306 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2307 } else if (readdir_attr_data &&
2308 readdir_attr_data->type == RDATTR_AAPL) {
2310 * OS X specific SMB2 extension negotiated via
2311 * AAPL create context: return max_access in
2314 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2316 unsigned int ea_size = estimate_ea_size(conn, NULL,
2318 SIVAL(p,0,ea_size); /* Extended attributes */
2322 if (readdir_attr_data &&
2323 readdir_attr_data->type == RDATTR_AAPL) {
2325 * OS X specific SMB2 extension negotiated via
2326 * AAPL create context: return resource fork
2327 * length and compressed FinderInfo in
2330 * According to documentation short_name_len
2331 * should be 0, but on the wire behaviour
2332 * shows its set to 24 by clients.
2336 /* Resourefork length */
2337 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2339 /* Compressed FinderInfo */
2340 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2341 } else if (!was_8_3 && check_mangled_names) {
2342 char mangled_name[13]; /* mangled 8.3 name. */
2343 if (!name_to_8_3(fname,mangled_name,True,
2345 /* Error - mangle failed ! */
2346 memset(mangled_name,'\0',12);
2348 mangled_name[12] = 0;
2349 status = srvstr_push(base_data, flags2,
2350 p+2, mangled_name, 24,
2351 STR_UPPER|STR_UNICODE, &len);
2352 if (!NT_STATUS_IS_OK(status)) {
2357 memset(p + 2 + len,'\0',24 - len);
2361 /* Clear the short name buffer. This is
2362 * IMPORTANT as not doing so will trigger
2363 * a Win2k client bug. JRA.
2370 if (readdir_attr_data &&
2371 readdir_attr_data->type == RDATTR_AAPL) {
2373 * OS X specific SMB2 extension negotiated via
2374 * AAPL create context: return UNIX mode in
2377 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2378 SSVAL(p, 0, aapl_mode);
2384 SBVAL(p,0,file_id); p += 8;
2385 status = srvstr_push(base_data, flags2, p,
2386 fname, PTR_DIFF(end_data, p),
2387 STR_TERMINATE_ASCII, &len);
2388 if (!NT_STATUS_IS_OK(status)) {
2394 len = PTR_DIFF(p, pdata);
2395 pad = (len + (align-1)) & ~(align-1);
2397 * offset to the next entry, the caller
2398 * will overwrite it for the last entry
2399 * that's why we always include the padding
2403 * set padding to zero
2406 memset(p, 0, pad - len);
2413 /* CIFS UNIX Extension. */
2415 case SMB_FIND_FILE_UNIX:
2416 case SMB_FIND_FILE_UNIX_INFO2:
2418 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2420 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2422 if (info_level == SMB_FIND_FILE_UNIX) {
2423 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2424 p = store_file_unix_basic(conn, p,
2425 NULL, &smb_fname->st);
2426 status = srvstr_push(base_data, flags2, p,
2427 fname, PTR_DIFF(end_data, p),
2428 STR_TERMINATE, &len);
2429 if (!NT_STATUS_IS_OK(status)) {
2433 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2434 p = store_file_unix_basic_info2(conn, p,
2435 NULL, &smb_fname->st);
2438 status = srvstr_push(base_data, flags2, p, fname,
2439 PTR_DIFF(end_data, p), 0, &len);
2440 if (!NT_STATUS_IS_OK(status)) {
2443 SIVAL(nameptr, 0, len);
2448 len = PTR_DIFF(p, pdata);
2449 pad = (len + (align-1)) & ~(align-1);
2451 * offset to the next entry, the caller
2452 * will overwrite it for the last entry
2453 * that's why we always include the padding
2457 * set padding to zero
2460 memset(p, 0, pad - len);
2465 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2470 return NT_STATUS_INVALID_LEVEL;
2473 if (PTR_DIFF(p,pdata) > space_remaining) {
2474 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2475 "(wanted %u, had %d)\n",
2476 (unsigned int)PTR_DIFF(p,pdata),
2478 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2481 /* Setup the last entry pointer, as an offset from base_data */
2482 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2483 /* Advance the data pointer to the next slot */
2486 return NT_STATUS_OK;
2489 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2490 connection_struct *conn,
2491 struct dptr_struct *dirptr,
2493 const char *path_mask,
2496 int requires_resume_key,
2505 int space_remaining,
2506 struct smb_filename **_smb_fname,
2507 bool *got_exact_match,
2508 int *_last_entry_off,
2509 struct ea_list *name_list,
2510 struct file_id *file_id)
2513 const char *mask = NULL;
2514 long prev_dirpos = 0;
2517 struct smb_filename *smb_fname = NULL;
2518 struct smbd_dirptr_lanman2_state state;
2520 uint64_t last_entry_off = 0;
2522 enum mangled_names_options mangled_names;
2523 bool marshall_with_83_names;
2525 mangled_names = lp_mangled_names(conn->params);
2529 state.info_level = info_level;
2530 if (mangled_names != MANGLED_NAMES_NO) {
2531 state.check_mangled_names = true;
2533 state.has_wild = dptr_has_wild(dirptr);
2534 state.got_exact_match = false;
2536 *got_exact_match = false;
2538 p = strrchr_m(path_mask,'/');
2549 ok = smbd_dirptr_get_entry(ctx,
2556 smbd_dirptr_lanman2_match_fn,
2557 smbd_dirptr_lanman2_mode_fn,
2564 return NT_STATUS_END_OF_FILE;
2567 *got_exact_match = state.got_exact_match;
2569 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2571 status = smbd_marshall_dir_entry(ctx,
2576 marshall_with_83_names,
2577 requires_resume_key,
2588 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2589 DEBUG(1,("Conversion error: illegal character: %s\n",
2590 smb_fname_str_dbg(smb_fname)));
2593 if (file_id != NULL) {
2594 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2597 if (!NT_STATUS_IS_OK(status) &&
2598 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2600 TALLOC_FREE(smb_fname);
2605 if (_smb_fname != NULL) {
2606 struct smb_filename *name = NULL;
2608 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2610 TALLOC_FREE(smb_fname);
2612 return NT_STATUS_NO_MEMORY;
2617 TALLOC_FREE(smb_fname);
2620 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2621 dptr_SeekDir(dirptr, prev_dirpos);
2625 *_last_entry_off = last_entry_off;
2626 return NT_STATUS_OK;
2629 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2630 connection_struct *conn,
2631 struct dptr_struct *dirptr,
2633 const char *path_mask,
2636 bool requires_resume_key,
2642 int space_remaining,
2643 bool *got_exact_match,
2644 int *last_entry_off,
2645 struct ea_list *name_list)
2648 const bool do_pad = true;
2650 if (info_level >= 1 && info_level <= 3) {
2651 /* No alignment on earlier info levels. */
2655 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2656 path_mask, dirtype, info_level,
2657 requires_resume_key, dont_descend, ask_sharemode,
2658 true, align, do_pad,
2659 ppdata, base_data, end_data,
2663 last_entry_off, name_list, NULL);
2666 /****************************************************************************
2667 Reply to a TRANS2_FINDFIRST.
2668 ****************************************************************************/
2670 static void call_trans2findfirst(connection_struct *conn,
2671 struct smb_request *req,
2672 char **pparams, int total_params,
2673 char **ppdata, int total_data,
2674 unsigned int max_data_bytes)
2676 /* We must be careful here that we don't return more than the
2677 allowed number of data bytes. If this means returning fewer than
2678 maxentries then so be it. We assume that the redirector has
2679 enough room for the fixed number of parameter bytes it has
2681 struct smb_filename *smb_dname = NULL;
2682 char *params = *pparams;
2683 char *pdata = *ppdata;
2687 uint16_t findfirst_flags;
2688 bool close_after_first;
2690 bool requires_resume_key;
2692 char *directory = NULL;
2695 int last_entry_off=0;
2699 bool finished = False;
2700 bool dont_descend = False;
2701 bool out_of_space = False;
2702 int space_remaining;
2703 bool mask_contains_wcard = False;
2704 struct ea_list *ea_list = NULL;
2705 NTSTATUS ntstatus = NT_STATUS_OK;
2706 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2707 struct dptr_struct *dirptr = NULL;
2708 struct smbd_server_connection *sconn = req->sconn;
2709 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2710 ucf_flags_from_smb_request(req);
2711 bool backup_priv = false;
2712 bool as_root = false;
2714 if (total_params < 13) {
2715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2719 dirtype = SVAL(params,0);
2720 maxentries = SVAL(params,2);
2721 findfirst_flags = SVAL(params,4);
2722 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2723 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2724 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2725 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2726 security_token_has_privilege(get_current_nttok(conn),
2729 info_level = SVAL(params,6);
2731 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2732 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2733 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2735 info_level, max_data_bytes));
2738 /* W2K3 seems to treat zero as 1. */
2742 switch (info_level) {
2743 case SMB_FIND_INFO_STANDARD:
2744 case SMB_FIND_EA_SIZE:
2745 case SMB_FIND_EA_LIST:
2746 case SMB_FIND_FILE_DIRECTORY_INFO:
2747 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2748 case SMB_FIND_FILE_NAMES_INFO:
2749 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2750 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2751 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2753 case SMB_FIND_FILE_UNIX:
2754 case SMB_FIND_FILE_UNIX_INFO2:
2755 /* Always use filesystem for UNIX mtime query. */
2756 ask_sharemode = false;
2757 if (!lp_unix_extensions()) {
2758 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2761 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2764 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2768 if (req->posix_pathnames) {
2769 srvstr_get_path_wcard_posix(talloc_tos(),
2777 &mask_contains_wcard);
2779 srvstr_get_path_wcard(talloc_tos(),
2787 &mask_contains_wcard);
2789 if (!NT_STATUS_IS_OK(ntstatus)) {
2790 reply_nterror(req, ntstatus);
2797 ntstatus = filename_convert_with_privilege(talloc_tos(),
2802 &mask_contains_wcard,
2805 ntstatus = filename_convert(talloc_tos(), conn,
2809 &mask_contains_wcard,
2813 if (!NT_STATUS_IS_OK(ntstatus)) {
2814 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2815 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2816 ERRSRV, ERRbadpath);
2819 reply_nterror(req, ntstatus);
2823 mask = smb_dname->original_lcomp;
2825 directory = smb_dname->base_name;
2827 p = strrchr_m(directory,'/');
2829 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2830 if((directory[0] == '.') && (directory[1] == '\0')) {
2831 mask = talloc_strdup(talloc_tos(),"*");
2833 reply_nterror(req, NT_STATUS_NO_MEMORY);
2836 mask_contains_wcard = True;
2842 if (p == NULL || p == directory) {
2843 /* Ensure we don't have a directory name of "". */
2844 directory = talloc_strdup(talloc_tos(), ".");
2846 reply_nterror(req, NT_STATUS_NO_MEMORY);
2849 /* Ensure smb_dname->base_name matches. */
2850 smb_dname->base_name = directory;
2853 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2855 if (info_level == SMB_FIND_EA_LIST) {
2858 if (total_data < 4) {
2859 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2863 ea_size = IVAL(pdata,0);
2864 if (ea_size != total_data) {
2865 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2866 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2867 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2871 if (!lp_ea_support(SNUM(conn))) {
2872 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2876 /* Pull out the list of names. */
2877 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2879 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2884 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2889 *ppdata = (char *)SMB_REALLOC(
2890 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2891 if(*ppdata == NULL ) {
2892 reply_nterror(req, NT_STATUS_NO_MEMORY);
2896 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2898 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2901 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2902 /* Realloc the params space */
2903 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2904 if (*pparams == NULL) {
2905 reply_nterror(req, NT_STATUS_NO_MEMORY);
2910 /* Save the wildcard match and attribs we are using on this directory -
2911 needed as lanman2 assumes these are being saved between calls */
2913 ntstatus = dptr_create(conn,
2921 mask_contains_wcard,
2925 if (!NT_STATUS_IS_OK(ntstatus)) {
2926 reply_nterror(req, ntstatus);
2931 /* Remember this in case we have
2932 to do a findnext. */
2933 dptr_set_priv(dirptr);
2936 dptr_num = dptr_dnum(dirptr);
2937 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2939 /* We don't need to check for VOL here as this is returned by
2940 a different TRANS2 call. */
2942 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2943 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2944 if (in_list(directory,
2945 lp_dont_descend(talloc_tos(), SNUM(conn)),
2946 conn->case_sensitive)) {
2947 dont_descend = True;
2951 space_remaining = max_data_bytes;
2952 out_of_space = False;
2954 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2955 bool got_exact_match = False;
2957 /* this is a heuristic to avoid seeking the dirptr except when
2958 absolutely necessary. It allows for a filename of about 40 chars */
2959 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2960 out_of_space = True;
2963 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2967 mask,dirtype,info_level,
2968 requires_resume_key,dont_descend,
2973 &last_entry_off, ea_list);
2974 if (NT_STATUS_EQUAL(ntstatus,
2975 NT_STATUS_ILLEGAL_CHARACTER)) {
2977 * Bad character conversion on name. Ignore this
2982 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2983 out_of_space = true;
2985 finished = !NT_STATUS_IS_OK(ntstatus);
2989 if (!finished && !out_of_space)
2993 * As an optimisation if we know we aren't looking
2994 * for a wildcard name (ie. the name matches the wildcard exactly)
2995 * then we can finish on any (first) match.
2996 * This speeds up large directory searches. JRA.
3002 /* Ensure space_remaining never goes -ve. */
3003 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3004 space_remaining = 0;
3005 out_of_space = true;
3007 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3011 /* Check if we can close the dirptr */
3012 if(close_after_first || (finished && close_if_end)) {
3013 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3014 dptr_close(sconn, &dptr_num);
3018 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3019 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3020 * the protocol level is less than NT1. Tested with smbclient. JRA.
3021 * This should fix the OS/2 client bug #2335.
3024 if(numentries == 0) {
3025 dptr_close(sconn, &dptr_num);
3026 if (get_Protocol() < PROTOCOL_NT1) {
3027 reply_force_doserror(req, ERRDOS, ERRnofiles);
3030 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3031 ERRDOS, ERRbadfile);
3036 /* At this point pdata points to numentries directory entries. */
3038 /* Set up the return parameter block */
3039 SSVAL(params,0,dptr_num);
3040 SSVAL(params,2,numentries);
3041 SSVAL(params,4,finished);
3042 SSVAL(params,6,0); /* Never an EA error */
3043 SSVAL(params,8,last_entry_off);
3045 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3048 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3049 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3051 reply_nterror(req, NT_STATUS_NO_MEMORY);
3055 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3056 smb_fn_name(req->cmd),
3057 mask, directory, dirtype, numentries ) );
3060 * Force a name mangle here to ensure that the
3061 * mask as an 8.3 name is top of the mangled cache.
3062 * The reasons for this are subtle. Don't remove
3063 * this code unless you know what you are doing
3064 * (see PR#13758). JRA.
3067 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3068 char mangled_name[13];
3069 name_to_8_3(mask, mangled_name, True, conn->params);
3077 TALLOC_FREE(smb_dname);
3081 /****************************************************************************
3082 Reply to a TRANS2_FINDNEXT.
3083 ****************************************************************************/
3085 static void call_trans2findnext(connection_struct *conn,
3086 struct smb_request *req,
3087 char **pparams, int total_params,
3088 char **ppdata, int total_data,
3089 unsigned int max_data_bytes)
3091 /* We must be careful here that we don't return more than the
3092 allowed number of data bytes. If this means returning fewer than
3093 maxentries then so be it. We assume that the redirector has
3094 enough room for the fixed number of parameter bytes it has
3096 char *params = *pparams;
3097 char *pdata = *ppdata;
3101 uint16_t info_level;
3102 uint32_t resume_key;
3103 uint16_t findnext_flags;
3104 bool close_after_request;
3106 bool requires_resume_key;
3108 bool mask_contains_wcard = False;
3109 char *resume_name = NULL;
3110 const char *mask = NULL;
3111 const char *directory = NULL;
3115 int i, last_entry_off=0;
3116 bool finished = False;
3117 bool dont_descend = False;
3118 bool out_of_space = False;
3119 int space_remaining;
3120 struct ea_list *ea_list = NULL;
3121 NTSTATUS ntstatus = NT_STATUS_OK;
3122 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3123 TALLOC_CTX *ctx = talloc_tos();
3124 struct dptr_struct *dirptr;
3125 struct smbd_server_connection *sconn = req->sconn;
3126 bool backup_priv = false;
3127 bool as_root = false;
3129 if (total_params < 13) {
3130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3134 dptr_num = SVAL(params,0);
3135 maxentries = SVAL(params,2);
3136 info_level = SVAL(params,4);
3137 resume_key = IVAL(params,6);
3138 findnext_flags = SVAL(params,10);
3139 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3140 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3141 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3142 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3144 if (!continue_bit) {
3145 /* We only need resume_name if continue_bit is zero. */
3146 if (req->posix_pathnames) {
3147 srvstr_get_path_wcard_posix(ctx,
3155 &mask_contains_wcard);
3157 srvstr_get_path_wcard(ctx,
3165 &mask_contains_wcard);
3167 if (!NT_STATUS_IS_OK(ntstatus)) {
3168 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3169 complain (it thinks we're asking for the directory above the shared
3170 path or an invalid name). Catch this as the resume name is only compared, never used in
3171 a file access. JRA. */
3172 srvstr_pull_talloc(ctx, params, req->flags2,
3173 &resume_name, params+12,
3177 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3178 reply_nterror(req, ntstatus);
3184 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3185 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3186 resume_key = %d resume name = %s continue=%d level = %d\n",
3187 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3188 requires_resume_key, resume_key,
3189 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3192 /* W2K3 seems to treat zero as 1. */
3196 switch (info_level) {
3197 case SMB_FIND_INFO_STANDARD:
3198 case SMB_FIND_EA_SIZE:
3199 case SMB_FIND_EA_LIST:
3200 case SMB_FIND_FILE_DIRECTORY_INFO:
3201 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3202 case SMB_FIND_FILE_NAMES_INFO:
3203 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3204 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3205 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3207 case SMB_FIND_FILE_UNIX:
3208 case SMB_FIND_FILE_UNIX_INFO2:
3209 /* Always use filesystem for UNIX mtime query. */
3210 ask_sharemode = false;
3211 if (!lp_unix_extensions()) {
3212 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3217 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3221 if (info_level == SMB_FIND_EA_LIST) {
3224 if (total_data < 4) {
3225 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3229 ea_size = IVAL(pdata,0);
3230 if (ea_size != total_data) {
3231 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3232 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3233 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3237 if (!lp_ea_support(SNUM(conn))) {
3238 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3242 /* Pull out the list of names. */
3243 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3250 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3251 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3255 *ppdata = (char *)SMB_REALLOC(
3256 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3257 if(*ppdata == NULL) {
3258 reply_nterror(req, NT_STATUS_NO_MEMORY);
3263 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3266 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3269 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3270 /* Realloc the params space */
3271 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3272 if(*pparams == NULL ) {
3273 reply_nterror(req, NT_STATUS_NO_MEMORY);
3279 /* Check that the dptr is valid */
3280 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3281 reply_nterror(req, STATUS_NO_MORE_FILES);
3285 directory = dptr_path(sconn, dptr_num);
3287 /* Get the wildcard mask from the dptr */
3288 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3289 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3290 reply_nterror(req, STATUS_NO_MORE_FILES);
3294 /* Get the attr mask from the dptr */
3295 dirtype = dptr_attr(sconn, dptr_num);
3297 backup_priv = dptr_get_priv(dirptr);
3299 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3300 "backup_priv = %d\n",
3301 dptr_num, mask, dirtype,
3303 dptr_TellDir(dirptr),
3306 /* We don't need to check for VOL here as this is returned by
3307 a different TRANS2 call. */
3309 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3310 directory,lp_dont_descend(ctx, SNUM(conn))));
3311 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3312 dont_descend = True;
3315 space_remaining = max_data_bytes;
3316 out_of_space = False;
3324 * Seek to the correct position. We no longer use the resume key but
3325 * depend on the last file name instead.
3328 if(!continue_bit && resume_name && *resume_name) {
3331 long current_pos = 0;
3333 * Remember, name_to_8_3 is called by
3334 * get_lanman2_dir_entry(), so the resume name
3335 * could be mangled. Ensure we check the unmangled name.
3338 if (mangle_is_mangled(resume_name, conn->params)) {
3339 char *new_resume_name = NULL;
3340 mangle_lookup_name_from_8_3(ctx,
3344 if (new_resume_name) {
3345 resume_name = new_resume_name;
3350 * Fix for NT redirector problem triggered by resume key indexes
3351 * changing between directory scans. We now return a resume key of 0
3352 * and instead look for the filename to continue from (also given
3353 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3354 * findfirst/findnext (as is usual) then the directory pointer
3355 * should already be at the correct place.
3358 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3359 } /* end if resume_name && !continue_bit */
3361 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3362 bool got_exact_match = False;
3364 /* this is a heuristic to avoid seeking the dirptr except when
3365 absolutely necessary. It allows for a filename of about 40 chars */
3366 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3367 out_of_space = True;
3370 ntstatus = get_lanman2_dir_entry(ctx,
3374 mask,dirtype,info_level,
3375 requires_resume_key,dont_descend,
3380 &last_entry_off, ea_list);
3381 if (NT_STATUS_EQUAL(ntstatus,
3382 NT_STATUS_ILLEGAL_CHARACTER)) {
3384 * Bad character conversion on name. Ignore this
3389 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3390 out_of_space = true;
3392 finished = !NT_STATUS_IS_OK(ntstatus);
3396 if (!finished && !out_of_space)
3400 * As an optimisation if we know we aren't looking
3401 * for a wildcard name (ie. the name matches the wildcard exactly)
3402 * then we can finish on any (first) match.
3403 * This speeds up large directory searches. JRA.
3409 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3412 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3413 smb_fn_name(req->cmd),
3414 mask, directory, dirtype, numentries ) );
3416 /* Check if we can close the dirptr */
3417 if(close_after_request || (finished && close_if_end)) {
3418 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3419 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3426 /* Set up the return parameter block */
3427 SSVAL(params,0,numentries);
3428 SSVAL(params,2,finished);
3429 SSVAL(params,4,0); /* Never an EA error */
3430 SSVAL(params,6,last_entry_off);
3432 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3438 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3440 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3444 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3446 SMB_ASSERT(extended_info != NULL);
3448 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3449 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3450 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3451 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3452 #ifdef SAMBA_VERSION_REVISION
3453 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3455 extended_info->samba_subversion = 0;
3456 #ifdef SAMBA_VERSION_RC_RELEASE
3457 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3459 #ifdef SAMBA_VERSION_PRE_RELEASE
3460 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3463 #ifdef SAMBA_VERSION_VENDOR_PATCH
3464 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3466 extended_info->samba_gitcommitdate = 0;
3467 #ifdef SAMBA_VERSION_COMMIT_TIME
3468 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3471 memset(extended_info->samba_version_string, 0,
3472 sizeof(extended_info->samba_version_string));
3474 snprintf (extended_info->samba_version_string,
3475 sizeof(extended_info->samba_version_string),
3476 "%s", samba_version_string());
3479 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3480 connection_struct *conn,
3481 TALLOC_CTX *mem_ctx,
3482 uint16_t info_level,
3484 unsigned int max_data_bytes,
3485 size_t *fixed_portion,
3486 struct smb_filename *fname,
3490 char *pdata, *end_data;
3493 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3494 int snum = SNUM(conn);
3495 const char *fstype = lp_fstype(SNUM(conn));
3496 const char *filename = NULL;
3497 const uint64_t bytes_per_sector = 512;
3498 uint32_t additional_flags = 0;
3499 struct smb_filename smb_fname;
3501 NTSTATUS status = NT_STATUS_OK;
3504 if (fname == NULL || fname->base_name == NULL) {
3507 filename = fname->base_name;
3511 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3512 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3513 "info level (0x%x) on IPC$.\n",
3514 (unsigned int)info_level));
3515 return NT_STATUS_ACCESS_DENIED;
3519 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3521 ZERO_STRUCT(smb_fname);
3522 smb_fname.base_name = discard_const_p(char, filename);
3524 if(info_level != SMB_FS_QUOTA_INFORMATION
3525 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3526 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3527 return map_nt_error_from_unix(errno);
3532 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3533 return NT_STATUS_INVALID_PARAMETER;
3536 *ppdata = (char *)SMB_REALLOC(
3537 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3538 if (*ppdata == NULL) {
3539 return NT_STATUS_NO_MEMORY;
3543 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3544 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3548 switch (info_level) {
3549 case SMB_INFO_ALLOCATION:
3551 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3553 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3555 if (df_ret == (uint64_t)-1) {
3556 return map_nt_error_from_unix(errno);
3559 block_size = lp_block_size(snum);
3560 if (bsize < block_size) {
3561 uint64_t factor = block_size/bsize;
3566 if (bsize > block_size) {
3567 uint64_t factor = bsize/block_size;
3572 sectors_per_unit = bsize/bytes_per_sector;
3574 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3575 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3576 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3579 * For large drives, return max values and not modulo.
3581 dsize = MIN(dsize, UINT32_MAX);
3582 dfree = MIN(dfree, UINT32_MAX);
3584 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3585 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3586 SIVAL(pdata,l1_cUnit,dsize);
3587 SIVAL(pdata,l1_cUnitAvail,dfree);
3588 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3592 case SMB_INFO_VOLUME:
3593 /* Return volume name */
3595 * Add volume serial number - hash of a combination of
3596 * the called hostname and the service name.
3598 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3600 * Win2k3 and previous mess this up by sending a name length
3601 * one byte short. I believe only older clients (OS/2 Win9x) use
3602 * this call so try fixing this by adding a terminating null to
3603 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3605 status = srvstr_push(
3607 pdata+l2_vol_szVolLabel, vname,
3608 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3609 STR_NOALIGN|STR_TERMINATE, &len);
3610 if (!NT_STATUS_IS_OK(status)) {
3613 SCVAL(pdata,l2_vol_cch,len);
3614 data_len = l2_vol_szVolLabel + len;
3615 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3616 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3617 (unsigned)len, vname));
3620 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3621 case SMB_FS_ATTRIBUTE_INFORMATION:
3623 additional_flags = 0;
3624 #if defined(HAVE_SYS_QUOTAS)
3625 additional_flags |= FILE_VOLUME_QUOTAS;
3628 if(lp_nt_acl_support(SNUM(conn))) {
3629 additional_flags |= FILE_PERSISTENT_ACLS;
3632 /* Capabilities are filled in at connection time through STATVFS call */
3633 additional_flags |= conn->fs_capabilities;
3634 additional_flags |= lp_parm_int(conn->params->service,
3635 "share", "fake_fscaps",
3638 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3639 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3640 additional_flags); /* FS ATTRIBUTES */
3642 SIVAL(pdata,4,255); /* Max filename component length */
3643 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3644 and will think we can't do long filenames */
3645 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3646 PTR_DIFF(end_data, pdata+12),
3648 if (!NT_STATUS_IS_OK(status)) {
3652 data_len = 12 + len;
3653 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3654 /* the client only requested a portion of the
3656 data_len = max_data_bytes;
3657 status = STATUS_BUFFER_OVERFLOW;
3659 *fixed_portion = 16;
3662 case SMB_QUERY_FS_LABEL_INFO:
3663 case SMB_FS_LABEL_INFORMATION:
3664 status = srvstr_push(pdata, flags2, pdata+4, vname,
3665 PTR_DIFF(end_data, pdata+4), 0, &len);
3666 if (!NT_STATUS_IS_OK(status)) {
3673 case SMB_QUERY_FS_VOLUME_INFO:
3674 case SMB_FS_VOLUME_INFORMATION:
3677 * Add volume serial number - hash of a combination of
3678 * the called hostname and the service name.
3680 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3681 (str_checksum(get_local_machine_name())<<16));
3683 /* Max label len is 32 characters. */
3684 status = srvstr_push(pdata, flags2, pdata+18, vname,
3685 PTR_DIFF(end_data, pdata+18),
3687 if (!NT_STATUS_IS_OK(status)) {
3690 SIVAL(pdata,12,len);
3693 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3694 (int)strlen(vname),vname,
3695 lp_servicename(talloc_tos(), snum)));
3696 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3697 /* the client only requested a portion of the
3699 data_len = max_data_bytes;
3700 status = STATUS_BUFFER_OVERFLOW;
3702 *fixed_portion = 24;
3705 case SMB_QUERY_FS_SIZE_INFO:
3706 case SMB_FS_SIZE_INFORMATION:
3708 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3710 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3712 if (df_ret == (uint64_t)-1) {
3713 return map_nt_error_from_unix(errno);
3715 block_size = lp_block_size(snum);
3716 if (bsize < block_size) {
3717 uint64_t factor = block_size/bsize;
3722 if (bsize > block_size) {
3723 uint64_t factor = bsize/block_size;
3728 sectors_per_unit = bsize/bytes_per_sector;
3729 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3730 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3731 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3732 SBIG_UINT(pdata,0,dsize);
3733 SBIG_UINT(pdata,8,dfree);
3734 SIVAL(pdata,16,sectors_per_unit);
3735 SIVAL(pdata,20,bytes_per_sector);
3736 *fixed_portion = 24;
3740 case SMB_FS_FULL_SIZE_INFORMATION:
3742 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3744 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3746 if (df_ret == (uint64_t)-1) {
3747 return map_nt_error_from_unix(errno);
3749 block_size = lp_block_size(snum);
3750 if (bsize < block_size) {
3751 uint64_t factor = block_size/bsize;
3756 if (bsize > block_size) {
3757 uint64_t factor = bsize/block_size;
3762 sectors_per_unit = bsize/bytes_per_sector;
3763 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3764 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3765 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3766 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3767 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3768 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3769 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3770 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3771 *fixed_portion = 32;
3775 case SMB_QUERY_FS_DEVICE_INFO:
3776 case SMB_FS_DEVICE_INFORMATION:
3778 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3780 if (!CAN_WRITE(conn)) {
3781 characteristics |= FILE_READ_ONLY_DEVICE;
3784 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3785 SIVAL(pdata,4,characteristics);
3790 #ifdef HAVE_SYS_QUOTAS
3791 case SMB_FS_QUOTA_INFORMATION:
3793 * what we have to send --metze:
3795 * Unknown1: 24 NULL bytes
3796 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3797 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3798 * Quota Flags: 2 byte :
3799 * Unknown3: 6 NULL bytes
3803 * details for Quota Flags:
3805 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3806 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3807 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3808 * 0x0001 Enable Quotas: enable quota for this fs
3812 /* we need to fake up a fsp here,
3813 * because its not send in this call
3816 SMB_NTQUOTA_STRUCT quotas;
3819 ZERO_STRUCT(quotas);
3822 fsp.fnum = FNUM_FIELD_INVALID;
3825 if (get_current_uid(conn) != 0) {
3826 DEBUG(0,("get_user_quota: access_denied "
3827 "service [%s] user [%s]\n",
3828 lp_servicename(talloc_tos(), SNUM(conn)),
3829 conn->session_info->unix_info->unix_name));
3830 return NT_STATUS_ACCESS_DENIED;
3833 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3835 if (!NT_STATUS_IS_OK(status)) {
3836 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3842 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3843 lp_servicename(talloc_tos(), SNUM(conn))));
3845 /* Unknown1 24 NULL bytes*/
3846 SBIG_UINT(pdata,0,(uint64_t)0);
3847 SBIG_UINT(pdata,8,(uint64_t)0);
3848 SBIG_UINT(pdata,16,(uint64_t)0);
3850 /* Default Soft Quota 8 bytes */
3851 SBIG_UINT(pdata,24,quotas.softlim);
3853 /* Default Hard Quota 8 bytes */
3854 SBIG_UINT(pdata,32,quotas.hardlim);
3856 /* Quota flag 2 bytes */
3857 SSVAL(pdata,40,quotas.qflags);
3859 /* Unknown3 6 NULL bytes */
3865 #endif /* HAVE_SYS_QUOTAS */
3866 case SMB_FS_OBJECTID_INFORMATION:
3868 unsigned char objid[16];
3869 struct smb_extended_info extended_info;
3870 memcpy(pdata,create_volume_objectid(conn, objid),16);
3871 samba_extended_info_version (&extended_info);
3872 SIVAL(pdata,16,extended_info.samba_magic);
3873 SIVAL(pdata,20,extended_info.samba_version);
3874 SIVAL(pdata,24,extended_info.samba_subversion);
3875 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3876 memcpy(pdata+36,extended_info.samba_version_string,28);
3881 case SMB_FS_SECTOR_SIZE_INFORMATION:
3885 * These values match a physical Windows Server 2012
3886 * share backed by NTFS atop spinning rust.
3888 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3889 /* logical_bytes_per_sector */
3890 SIVAL(pdata, 0, bytes_per_sector);
3891 /* phys_bytes_per_sector_atomic */
3892 SIVAL(pdata, 4, bytes_per_sector);
3893 /* phys_bytes_per_sector_perf */
3894 SIVAL(pdata, 8, bytes_per_sector);
3895 /* fs_effective_phys_bytes_per_sector_atomic */
3896 SIVAL(pdata, 12, bytes_per_sector);
3898 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3899 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3900 /* byte_off_sector_align */
3901 SIVAL(pdata, 20, 0);
3902 /* byte_off_partition_align */
3903 SIVAL(pdata, 24, 0);
3904 *fixed_portion = 28;
3910 * Query the version and capabilities of the CIFS UNIX extensions
3914 case SMB_QUERY_CIFS_UNIX_INFO:
3916 bool large_write = lp_min_receive_file_size() &&
3917 !srv_is_signing_active(xconn);
3918 bool large_read = !srv_is_signing_active(xconn);
3919 int encrypt_caps = 0;
3921 if (!lp_unix_extensions()) {
3922 return NT_STATUS_INVALID_LEVEL;
3925 switch (conn->encrypt_level) {
3926 case SMB_SIGNING_OFF:
3929 case SMB_SIGNING_DESIRED:
3930 case SMB_SIGNING_IF_REQUIRED:
3931 case SMB_SIGNING_DEFAULT:
3932 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3934 case SMB_SIGNING_REQUIRED:
3935 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3936 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3937 large_write = false;
3943 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3944 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3946 /* We have POSIX ACLs, pathname, encryption,
3947 * large read/write, and locking capability. */
3949 SBIG_UINT(pdata,4,((uint64_t)(
3950 CIFS_UNIX_POSIX_ACLS_CAP|
3951 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3952 CIFS_UNIX_FCNTL_LOCKS_CAP|
3953 CIFS_UNIX_EXTATTR_CAP|
3954 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3956 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3958 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3962 case SMB_QUERY_POSIX_FS_INFO:
3965 vfs_statvfs_struct svfs;
3967 if (!lp_unix_extensions()) {
3968 return NT_STATUS_INVALID_LEVEL;
3971 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3975 SIVAL(pdata,0,svfs.OptimalTransferSize);
3976 SIVAL(pdata,4,svfs.BlockSize);
3977 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3978 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3979 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3980 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3981 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3982 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3983 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3985 } else if (rc == EOPNOTSUPP) {
3986 return NT_STATUS_INVALID_LEVEL;
3987 #endif /* EOPNOTSUPP */
3989 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3990 return NT_STATUS_DOS(ERRSRV, ERRerror);
3995 case SMB_QUERY_POSIX_WHOAMI:
4001 if (!lp_unix_extensions()) {
4002 return NT_STATUS_INVALID_LEVEL;
4005 if (max_data_bytes < 40) {
4006 return NT_STATUS_BUFFER_TOO_SMALL;
4009 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4010 flags |= SMB_WHOAMI_GUEST;
4013 /* NOTE: 8 bytes for UID/GID, irrespective of native
4014 * platform size. This matches
4015 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4017 data_len = 4 /* flags */
4024 + 4 /* pad/reserved */
4025 + (conn->session_info->unix_token->ngroups * 8)
4027 + (conn->session_info->security_token->num_sids *
4031 SIVAL(pdata, 0, flags);
4032 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4034 (uint64_t)conn->session_info->unix_token->uid);
4035 SBIG_UINT(pdata, 16,
4036 (uint64_t)conn->session_info->unix_token->gid);
4039 if (data_len >= max_data_bytes) {
4040 /* Potential overflow, skip the GIDs and SIDs. */
4042 SIVAL(pdata, 24, 0); /* num_groups */
4043 SIVAL(pdata, 28, 0); /* num_sids */
4044 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4045 SIVAL(pdata, 36, 0); /* reserved */
4051 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4052 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4054 /* We walk the SID list twice, but this call is fairly
4055 * infrequent, and I don't expect that it's performance
4056 * sensitive -- jpeach
4058 for (i = 0, sid_bytes = 0;
4059 i < conn->session_info->security_token->num_sids; ++i) {
4060 sid_bytes += ndr_size_dom_sid(
4061 &conn->session_info->security_token->sids[i],
4065 /* SID list byte count */
4066 SIVAL(pdata, 32, sid_bytes);
4068 /* 4 bytes pad/reserved - must be zero */
4069 SIVAL(pdata, 36, 0);
4073 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4074 SBIG_UINT(pdata, data_len,
4075 (uint64_t)conn->session_info->unix_token->groups[i]);
4081 i < conn->session_info->security_token->num_sids; ++i) {
4082 int sid_len = ndr_size_dom_sid(
4083 &conn->session_info->security_token->sids[i],
4086 sid_linearize((uint8_t *)(pdata + data_len),
4088 &conn->session_info->security_token->sids[i]);
4089 data_len += sid_len;
4095 case SMB_MAC_QUERY_FS_INFO:
4097 * Thursby MAC extension... ONLY on NTFS filesystems
4098 * once we do streams then we don't need this
4100 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4102 SIVAL(pdata,84,0x100); /* Don't support mac... */
4108 return NT_STATUS_INVALID_LEVEL;
4111 *ret_data_len = data_len;
4115 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4116 struct smb_request *req,
4118 const DATA_BLOB *qdata)
4121 SMB_NTQUOTA_STRUCT quotas;
4123 ZERO_STRUCT(quotas);
4126 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4127 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4128 lp_servicename(talloc_tos(), SNUM(conn)),
4129 conn->session_info->unix_info->unix_name));
4130 return NT_STATUS_ACCESS_DENIED;
4133 if (!check_fsp_ntquota_handle(conn, req,
4135 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4136 return NT_STATUS_INVALID_HANDLE;
4139 /* note: normally there're 48 bytes,
4140 * but we didn't use the last 6 bytes for now
4143 if (qdata->length < 42) {
4144 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4145 (unsigned int)qdata->length));
4146 return NT_STATUS_INVALID_PARAMETER;
4149 /* unknown_1 24 NULL bytes in pdata*/
4151 /* the soft quotas 8 bytes (uint64_t)*/
4152 quotas.softlim = BVAL(qdata->data,24);
4154 /* the hard quotas 8 bytes (uint64_t)*/
4155 quotas.hardlim = BVAL(qdata->data,32);
4157 /* quota_flags 2 bytes **/
4158 quotas.qflags = SVAL(qdata->data,40);
4160 /* unknown_2 6 NULL bytes follow*/
4162 /* now set the quotas */
4163 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4164 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4165 lp_servicename(talloc_tos(), SNUM(conn))));
4166 status = map_nt_error_from_unix(errno);
4168 status = NT_STATUS_OK;
4173 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4174 struct smb_request *req,
4175 TALLOC_CTX *mem_ctx,
4176 uint16_t info_level,
4178 const DATA_BLOB *pdata)
4180 switch (info_level) {
4181 case SMB_FS_QUOTA_INFORMATION:
4183 return smb_set_fsquota(conn,
4192 return NT_STATUS_INVALID_LEVEL;
4195 /****************************************************************************
4196 Reply to a TRANS2_QFSINFO (query filesystem info).
4197 ****************************************************************************/
4199 static void call_trans2qfsinfo(connection_struct *conn,
4200 struct smb_request *req,
4201 char **pparams, int total_params,
4202 char **ppdata, int total_data,
4203 unsigned int max_data_bytes)
4205 char *params = *pparams;
4206 uint16_t info_level;
4208 size_t fixed_portion;
4211 if (total_params < 2) {
4212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4216 info_level = SVAL(params,0);
4218 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4219 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4220 DEBUG(0,("call_trans2qfsinfo: encryption required "
4221 "and info level 0x%x sent.\n",
4222 (unsigned int)info_level));
4223 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4228 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4230 status = smbd_do_qfsinfo(req->xconn, conn, req,
4237 if (!NT_STATUS_IS_OK(status)) {
4238 reply_nterror(req, status);
4242 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4245 DEBUG( 4, ( "%s info_level = %d\n",
4246 smb_fn_name(req->cmd), info_level) );
4251 /****************************************************************************
4252 Reply to a TRANS2_SETFSINFO (set filesystem info).
4253 ****************************************************************************/
4255 static void call_trans2setfsinfo(connection_struct *conn,
4256 struct smb_request *req,
4257 char **pparams, int total_params,
4258 char **ppdata, int total_data,
4259 unsigned int max_data_bytes)
4261 struct smbXsrv_connection *xconn = req->xconn;
4262 char *pdata = *ppdata;
4263 char *params = *pparams;
4264 uint16_t info_level;
4266 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4267 lp_servicename(talloc_tos(), SNUM(conn))));
4270 if (total_params < 4) {
4271 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4277 info_level = SVAL(params,2);
4280 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4281 info_level != SMB_SET_CIFS_UNIX_INFO) {
4282 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4283 "info level (0x%x) on IPC$.\n",
4284 (unsigned int)info_level));
4285 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4290 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4291 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4292 DEBUG(0,("call_trans2setfsinfo: encryption required "
4293 "and info level 0x%x sent.\n",
4294 (unsigned int)info_level));
4295 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4300 switch(info_level) {
4301 case SMB_SET_CIFS_UNIX_INFO:
4302 if (!lp_unix_extensions()) {
4303 DEBUG(2,("call_trans2setfsinfo: "
4304 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4305 "unix extensions off\n"));
4307 NT_STATUS_INVALID_LEVEL);
4311 /* There should be 12 bytes of capabilities set. */
4312 if (total_data < 12) {
4315 NT_STATUS_INVALID_PARAMETER);
4318 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4319 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4320 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4321 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4322 /* Just print these values for now. */
4323 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4324 "major = %u, minor = %u cap_low = 0x%x, "
4326 (unsigned int)xconn->
4327 smb1.unix_info.client_major,
4328 (unsigned int)xconn->
4329 smb1.unix_info.client_minor,
4330 (unsigned int)xconn->
4331 smb1.unix_info.client_cap_low,
4332 (unsigned int)xconn->
4333 smb1.unix_info.client_cap_high));
4335 /* Here is where we must switch to posix pathname processing... */
4336 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4337 lp_set_posix_pathnames();
4338 mangle_change_to_posix();
4341 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4342 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4343 /* Client that knows how to do posix locks,
4344 * but not posix open/mkdir operations. Set a
4345 * default type for read/write checks. */
4347 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4352 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4355 size_t param_len = 0;
4356 size_t data_len = total_data;
4358 if (!lp_unix_extensions()) {
4361 NT_STATUS_INVALID_LEVEL);
4365 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4368 NT_STATUS_NOT_SUPPORTED);
4372 if (xconn->smb1.echo_handler.trusted_fde) {
4373 DEBUG( 2,("call_trans2setfsinfo: "
4374 "request transport encryption disabled"
4375 "with 'fork echo handler = yes'\n"));
4378 NT_STATUS_NOT_SUPPORTED);
4382 DEBUG( 4,("call_trans2setfsinfo: "
4383 "request transport encryption.\n"));
4385 status = srv_request_encryption_setup(conn,
4386 (unsigned char **)ppdata,
4388 (unsigned char **)pparams,
4391 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4392 !NT_STATUS_IS_OK(status)) {
4393 reply_nterror(req, status);
4397 send_trans2_replies(conn, req,
4405 if (NT_STATUS_IS_OK(status)) {
4406 /* Server-side transport
4407 * encryption is now *on*. */
4408 status = srv_encryption_start(conn);
4409 if (!NT_STATUS_IS_OK(status)) {
4410 char *reason = talloc_asprintf(talloc_tos(),
4411 "Failure in setting "
4412 "up encrypted transport: %s",
4414 exit_server_cleanly(reason);
4420 case SMB_FS_QUOTA_INFORMATION:
4424 .data = (uint8_t *)pdata,
4425 .length = total_data
4427 files_struct *fsp = NULL;
4428 fsp = file_fsp(req, SVAL(params,0));
4430 status = smb_set_fsquota(conn,
4434 if (!NT_STATUS_IS_OK(status)) {
4435 reply_nterror(req, status);
4441 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4443 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4449 * sending this reply works fine,
4450 * but I'm not sure it's the same
4451 * like windows do...
4454 reply_outbuf(req, 10, 0);
4457 #if defined(HAVE_POSIX_ACLS)
4458 /****************************************************************************
4459 Utility function to count the number of entries in a POSIX acl.
4460 ****************************************************************************/
4462 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4464 unsigned int ace_count = 0;
4465 int entry_id = SMB_ACL_FIRST_ENTRY;
4466 SMB_ACL_ENTRY_T entry;
4468 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4470 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4471 entry_id = SMB_ACL_NEXT_ENTRY;
4478 /****************************************************************************
4479 Utility function to marshall a POSIX acl into wire format.
4480 ****************************************************************************/
4482 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4484 int entry_id = SMB_ACL_FIRST_ENTRY;
4485 SMB_ACL_ENTRY_T entry;
4487 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4488 SMB_ACL_TAG_T tagtype;
4489 SMB_ACL_PERMSET_T permset;
4490 unsigned char perms = 0;
4491 unsigned int own_grp;
4494 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4495 entry_id = SMB_ACL_NEXT_ENTRY;
4498 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4499 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4503 if (sys_acl_get_permset(entry, &permset) == -1) {
4504 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4508 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4509 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4510 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4512 SCVAL(pdata,1,perms);
4515 case SMB_ACL_USER_OBJ:
4516 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4517 own_grp = (unsigned int)pst->st_ex_uid;
4518 SIVAL(pdata,2,own_grp);
4523 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4525 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4528 own_grp = (unsigned int)*puid;
4529 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4530 SIVAL(pdata,2,own_grp);
4534 case SMB_ACL_GROUP_OBJ:
4535 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4536 own_grp = (unsigned int)pst->st_ex_gid;
4537 SIVAL(pdata,2,own_grp);
4542 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4544 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4547 own_grp = (unsigned int)*pgid;
4548 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4549 SIVAL(pdata,2,own_grp);
4554 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4555 SIVAL(pdata,2,0xFFFFFFFF);
4556 SIVAL(pdata,6,0xFFFFFFFF);
4559 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4560 SIVAL(pdata,2,0xFFFFFFFF);
4561 SIVAL(pdata,6,0xFFFFFFFF);
4564 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4567 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4574 /****************************************************************************
4575 Store the FILE_UNIX_BASIC info.
4576 ****************************************************************************/
4578 static char *store_file_unix_basic(connection_struct *conn,
4581 const SMB_STRUCT_STAT *psbuf)
4585 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4586 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4588 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4591 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4594 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4595 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4596 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4599 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4603 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4607 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4610 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4611 devno = psbuf->st_ex_rdev;
4613 devno = psbuf->st_ex_dev;
4616 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4620 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4624 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4627 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4631 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4638 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4639 * the chflags(2) (or equivalent) flags.
4641 * XXX: this really should be behind the VFS interface. To do this, we would
4642 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4643 * Each VFS module could then implement its own mapping as appropriate for the
4644 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4646 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4650 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4654 { UF_IMMUTABLE, EXT_IMMUTABLE },
4658 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4662 { UF_HIDDEN, EXT_HIDDEN },
4665 /* Do not remove. We need to guarantee that this array has at least one
4666 * entry to build on HP-UX.
4672 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4673 uint32_t *smb_fflags, uint32_t *smb_fmask)
4677 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4678 *smb_fmask |= info2_flags_map[i].smb_fflag;
4679 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4680 *smb_fflags |= info2_flags_map[i].smb_fflag;
4685 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4686 const uint32_t smb_fflags,
4687 const uint32_t smb_fmask,
4690 uint32_t max_fmask = 0;
4693 *stat_fflags = psbuf->st_ex_flags;
4695 /* For each flags requested in smb_fmask, check the state of the
4696 * corresponding flag in smb_fflags and set or clear the matching
4700 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4701 max_fmask |= info2_flags_map[i].smb_fflag;
4702 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4703 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4704 *stat_fflags |= info2_flags_map[i].stat_fflag;
4706 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4711 /* If smb_fmask is asking to set any bits that are not supported by
4712 * our flag mappings, we should fail.
4714 if ((smb_fmask & max_fmask) != smb_fmask) {
4722 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4723 * of file flags and birth (create) time.
4725 static char *store_file_unix_basic_info2(connection_struct *conn,
4728 const SMB_STRUCT_STAT *psbuf)
4730 uint32_t file_flags = 0;
4731 uint32_t flags_mask = 0;
4733 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4735 /* Create (birth) time 64 bit */
4736 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4739 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4740 SIVAL(pdata, 0, file_flags); /* flags */
4741 SIVAL(pdata, 4, flags_mask); /* mask */
4747 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4748 const struct stream_struct *streams,
4750 unsigned int max_data_bytes,
4751 unsigned int *data_size)
4754 unsigned int ofs = 0;
4756 if (max_data_bytes < 32) {
4757 return NT_STATUS_INFO_LENGTH_MISMATCH;
4760 for (i = 0; i < num_streams; i++) {
4761 unsigned int next_offset;
4763 smb_ucs2_t *namebuf;
4765 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4766 streams[i].name, &namelen) ||
4769 return NT_STATUS_INVALID_PARAMETER;
4773 * name_buf is now null-terminated, we need to marshall as not
4780 * We cannot overflow ...
4782 if ((ofs + 24 + namelen) > max_data_bytes) {
4783 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4785 TALLOC_FREE(namebuf);
4786 return STATUS_BUFFER_OVERFLOW;
4789 SIVAL(data, ofs+4, namelen);
4790 SOFF_T(data, ofs+8, streams[i].size);
4791 SOFF_T(data, ofs+16, streams[i].alloc_size);
4792 memcpy(data+ofs+24, namebuf, namelen);
4793 TALLOC_FREE(namebuf);
4795 next_offset = ofs + 24 + namelen;
4797 if (i == num_streams-1) {
4798 SIVAL(data, ofs, 0);
4801 unsigned int align = ndr_align_size(next_offset, 8);
4803 if ((next_offset + align) > max_data_bytes) {
4804 DEBUG(10, ("refusing to overflow align "
4805 "reply at stream %u\n",
4807 TALLOC_FREE(namebuf);
4808 return STATUS_BUFFER_OVERFLOW;
4811 memset(data+next_offset, 0, align);
4812 next_offset += align;
4814 SIVAL(data, ofs, next_offset - ofs);
4821 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4825 return NT_STATUS_OK;
4828 #if defined(HAVE_POSIX_ACLS)
4829 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4830 struct smb_request *req,
4832 struct smb_filename *smb_fname,
4834 unsigned int data_size_in,
4835 unsigned int *pdata_size_out)
4837 SMB_ACL_T file_acl = NULL;
4838 SMB_ACL_T def_acl = NULL;
4839 uint16_t num_file_acls = 0;
4840 uint16_t num_def_acls = 0;
4841 unsigned int size_needed = 0;
4847 * Ensure we always operate on a file descriptor, not just
4851 uint32_t access_mask = SEC_STD_READ_CONTROL|
4852 FILE_READ_ATTRIBUTES|
4853 FILE_WRITE_ATTRIBUTES;
4855 status = get_posix_fsp(conn,
4861 if (!NT_STATUS_IS_OK(status)) {
4867 SMB_ASSERT(fsp != NULL);
4869 status = refuse_symlink(conn,
4872 if (!NT_STATUS_IS_OK(status)) {
4876 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4879 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4880 DBG_INFO("ACLs not implemented on "
4881 "filesystem containing %s\n",
4883 status = NT_STATUS_NOT_IMPLEMENTED;
4887 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4889 * We can only have default POSIX ACLs on
4892 if (!fsp->is_directory) {
4893 DBG_INFO("Non-directory open %s\n",
4895 status = NT_STATUS_INVALID_HANDLE;
4898 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
4900 SMB_ACL_TYPE_DEFAULT,
4902 def_acl = free_empty_sys_acl(conn, def_acl);
4905 num_file_acls = count_acl_entries(conn, file_acl);
4906 num_def_acls = count_acl_entries(conn, def_acl);
4909 if (num_file_acls + num_def_acls < num_file_acls) {
4910 status = NT_STATUS_INVALID_PARAMETER;
4914 size_needed = num_file_acls + num_def_acls;
4917 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4918 * than UINT_MAX, so check by division.
4920 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4921 status = NT_STATUS_INVALID_PARAMETER;
4925 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
4926 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
4927 status = NT_STATUS_INVALID_PARAMETER;
4930 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
4932 if ( data_size_in < size_needed) {
4933 DBG_INFO("data_size too small (%u) need %u\n",
4936 status = NT_STATUS_BUFFER_TOO_SMALL;
4940 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4941 SSVAL(pdata,2,num_file_acls);
4942 SSVAL(pdata,4,num_def_acls);
4943 pdata += SMB_POSIX_ACL_HEADER_SIZE;
4945 ok = marshall_posix_acl(conn,
4950 status = NT_STATUS_INTERNAL_ERROR;
4953 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
4955 ok = marshall_posix_acl(conn,
4960 status = NT_STATUS_INTERNAL_ERROR;
4964 *pdata_size_out = size_needed;
4965 status = NT_STATUS_OK;
4971 * Ensure the stat struct in smb_fname is up to
4972 * date. Structure copy.
4974 smb_fname->st = fsp->fsp_name->st;
4975 (void)close_file(req, fsp, NORMAL_CLOSE);
4979 TALLOC_FREE(file_acl);
4980 TALLOC_FREE(def_acl);
4985 /****************************************************************************
4986 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4987 ****************************************************************************/
4989 static void call_trans2qpipeinfo(connection_struct *conn,
4990 struct smb_request *req,
4991 unsigned int tran_call,
4992 char **pparams, int total_params,
4993 char **ppdata, int total_data,
4994 unsigned int max_data_bytes)
4996 char *params = *pparams;
4997 char *pdata = *ppdata;
4998 unsigned int data_size = 0;
4999 unsigned int param_size = 2;
5000 uint16_t info_level;
5004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5008 if (total_params < 4) {
5009 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5013 fsp = file_fsp(req, SVAL(params,0));
5014 if (!fsp_is_np(fsp)) {
5015 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5019 info_level = SVAL(params,2);
5021 *pparams = (char *)SMB_REALLOC(*pparams,2);
5022 if (*pparams == NULL) {
5023 reply_nterror(req, NT_STATUS_NO_MEMORY);
5028 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5029 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5032 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5033 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5034 if (*ppdata == NULL ) {
5035 reply_nterror(req, NT_STATUS_NO_MEMORY);
5040 switch (info_level) {
5041 case SMB_FILE_STANDARD_INFORMATION:
5043 SOFF_T(pdata,0,4096LL);
5050 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5054 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5060 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5061 TALLOC_CTX *mem_ctx,
5062 struct smb_request *req,
5063 uint16_t info_level,
5065 struct smb_filename *smb_fname,
5066 bool delete_pending,
5067 struct timespec write_time_ts,
5068 struct ea_list *ea_list,
5069 int lock_data_count,
5072 unsigned int max_data_bytes,
5073 size_t *fixed_portion,
5075 unsigned int *pdata_size)
5077 char *pdata = *ppdata;
5078 char *dstart, *dend;
5079 unsigned int data_size;
5080 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5081 time_t create_time, mtime, atime, c_time;
5082 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5089 uint64_t file_size = 0;
5091 uint64_t allocation_size = 0;
5092 uint64_t file_id = 0;
5093 uint32_t access_mask = 0;
5096 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5097 return NT_STATUS_INVALID_LEVEL;
5100 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5101 smb_fname_str_dbg(smb_fname),
5103 info_level, max_data_bytes));
5105 mode = dos_mode(conn, smb_fname);
5106 nlink = psbuf->st_ex_nlink;
5108 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5112 if ((nlink > 0) && delete_pending) {
5116 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5117 return NT_STATUS_INVALID_PARAMETER;
5120 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5121 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5122 if (*ppdata == NULL) {
5123 return NT_STATUS_NO_MEMORY;
5127 dend = dstart + data_size - 1;
5129 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
5130 update_stat_ex_mtime(psbuf, write_time_ts);
5133 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5134 mtime_ts = psbuf->st_ex_mtime;
5135 atime_ts = psbuf->st_ex_atime;
5136 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5138 if (lp_dos_filetime_resolution(SNUM(conn))) {
5139 dos_filetime_timespec(&create_time_ts);
5140 dos_filetime_timespec(&mtime_ts);
5141 dos_filetime_timespec(&atime_ts);
5142 dos_filetime_timespec(&ctime_ts);
5145 create_time = convert_timespec_to_time_t(create_time_ts);
5146 mtime = convert_timespec_to_time_t(mtime_ts);
5147 atime = convert_timespec_to_time_t(atime_ts);
5148 c_time = convert_timespec_to_time_t(ctime_ts);
5150 p = strrchr_m(smb_fname->base_name,'/');
5152 base_name = smb_fname->base_name;
5156 /* NT expects the name to be in an exact form of the *full*
5157 filename. See the trans2 torture test */
5158 if (ISDOT(base_name)) {
5159 dos_fname = talloc_strdup(mem_ctx, "\\");
5161 return NT_STATUS_NO_MEMORY;
5164 dos_fname = talloc_asprintf(mem_ctx,
5166 smb_fname->base_name);
5168 return NT_STATUS_NO_MEMORY;
5170 if (is_ntfs_stream_smb_fname(smb_fname)) {
5171 dos_fname = talloc_asprintf(dos_fname, "%s",
5172 smb_fname->stream_name);
5174 return NT_STATUS_NO_MEMORY;
5178 string_replace(dos_fname, '/', '\\');
5181 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5184 /* Do we have this path open ? */
5186 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5187 fsp1 = file_find_di_first(conn->sconn, fileid);
5188 if (fsp1 && fsp1->initial_allocation_size) {
5189 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5193 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5194 file_size = get_file_size_stat(psbuf);
5198 pos = fsp->fh->position_information;
5202 access_mask = fsp->access_mask;
5204 /* GENERIC_EXECUTE mapping from Windows */
5205 access_mask = 0x12019F;
5208 /* This should be an index number - looks like
5211 I think this causes us to fail the IFSKIT
5212 BasicFileInformationTest. -tpot */
5213 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5217 switch (info_level) {
5218 case SMB_INFO_STANDARD:
5219 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5221 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5222 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5223 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5224 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5225 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5226 SSVAL(pdata,l1_attrFile,mode);
5229 case SMB_INFO_QUERY_EA_SIZE:
5231 unsigned int ea_size =
5232 estimate_ea_size(conn, fsp,
5234 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5236 srv_put_dos_date2(pdata,0,create_time);
5237 srv_put_dos_date2(pdata,4,atime);
5238 srv_put_dos_date2(pdata,8,mtime); /* write time */
5239 SIVAL(pdata,12,(uint32_t)file_size);
5240 SIVAL(pdata,16,(uint32_t)allocation_size);
5241 SSVAL(pdata,20,mode);
5242 SIVAL(pdata,22,ea_size);
5246 case SMB_INFO_IS_NAME_VALID:
5247 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5249 /* os/2 needs this ? really ?*/
5250 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5252 /* This is only reached for qpathinfo */
5256 case SMB_INFO_QUERY_EAS_FROM_LIST:
5258 size_t total_ea_len = 0;
5259 struct ea_list *ea_file_list = NULL;
5260 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5263 get_ea_list_from_file(mem_ctx, conn, fsp,
5265 &total_ea_len, &ea_file_list);
5266 if (!NT_STATUS_IS_OK(status)) {
5270 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5272 if (!ea_list || (total_ea_len > data_size)) {
5274 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5278 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5282 case SMB_INFO_QUERY_ALL_EAS:
5284 /* We have data_size bytes to put EA's into. */
5285 size_t total_ea_len = 0;
5286 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5288 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5290 &total_ea_len, &ea_list);
5291 if (!NT_STATUS_IS_OK(status)) {
5295 if (!ea_list || (total_ea_len > data_size)) {
5297 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5301 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5305 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5307 /* This is FileFullEaInformation - 0xF which maps to
5308 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5310 /* We have data_size bytes to put EA's into. */
5311 size_t total_ea_len = 0;
5312 struct ea_list *ea_file_list = NULL;
5314 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5316 /*TODO: add filtering and index handling */
5319 get_ea_list_from_file(mem_ctx, conn, fsp,
5321 &total_ea_len, &ea_file_list);
5322 if (!NT_STATUS_IS_OK(status)) {
5325 if (!ea_file_list) {
5326 return NT_STATUS_NO_EAS_ON_FILE;
5329 status = fill_ea_chained_buffer(mem_ctx,
5333 conn, ea_file_list);
5334 if (!NT_STATUS_IS_OK(status)) {
5340 case SMB_FILE_BASIC_INFORMATION:
5341 case SMB_QUERY_FILE_BASIC_INFO:
5343 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5344 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5345 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5347 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5351 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5352 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5353 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5354 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5355 SIVAL(pdata,32,mode);
5357 DEBUG(5,("SMB_QFBI - "));
5358 DEBUG(5,("create: %s ", ctime(&create_time)));
5359 DEBUG(5,("access: %s ", ctime(&atime)));
5360 DEBUG(5,("write: %s ", ctime(&mtime)));
5361 DEBUG(5,("change: %s ", ctime(&c_time)));
5362 DEBUG(5,("mode: %x\n", mode));
5363 *fixed_portion = data_size;
5366 case SMB_FILE_STANDARD_INFORMATION:
5367 case SMB_QUERY_FILE_STANDARD_INFO:
5369 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5371 SOFF_T(pdata,0,allocation_size);
5372 SOFF_T(pdata,8,file_size);
5373 SIVAL(pdata,16,nlink);
5374 SCVAL(pdata,20,delete_pending?1:0);
5375 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5376 SSVAL(pdata,22,0); /* Padding. */
5377 *fixed_portion = 24;
5380 case SMB_FILE_EA_INFORMATION:
5381 case SMB_QUERY_FILE_EA_INFO:
5383 unsigned int ea_size =
5384 estimate_ea_size(conn, fsp, smb_fname);
5385 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5388 SIVAL(pdata,0,ea_size);
5392 /* Get the 8.3 name - used if NT SMB was negotiated. */
5393 case SMB_QUERY_FILE_ALT_NAME_INFO:
5394 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5396 char mangled_name[13];
5397 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5398 if (!name_to_8_3(base_name,mangled_name,
5399 True,conn->params)) {
5400 return NT_STATUS_NO_MEMORY;
5402 status = srvstr_push(dstart, flags2,
5403 pdata+4, mangled_name,
5404 PTR_DIFF(dend, pdata+4),
5406 if (!NT_STATUS_IS_OK(status)) {
5409 data_size = 4 + len;
5415 case SMB_QUERY_FILE_NAME_INFO:
5418 this must be *exactly* right for ACLs on mapped drives to work
5420 status = srvstr_push(dstart, flags2,
5422 PTR_DIFF(dend, pdata+4),
5424 if (!NT_STATUS_IS_OK(status)) {
5427 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5428 data_size = 4 + len;
5433 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5435 char *nfname = NULL;
5437 if (!fsp->conn->sconn->using_smb2) {
5438 return NT_STATUS_INVALID_LEVEL;
5441 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5442 if (nfname == NULL) {
5443 return NT_STATUS_NO_MEMORY;
5446 if (ISDOT(nfname)) {
5449 string_replace(nfname, '/', '\\');
5451 if (smb_fname->stream_name != NULL) {
5452 const char *s = smb_fname->stream_name;
5453 const char *e = NULL;
5456 SMB_ASSERT(s[0] != '\0');
5459 * smb_fname->stream_name is in form
5460 * of ':StrEam:$DATA', but we should only
5461 * append ':StrEam' here.
5464 e = strchr(&s[1], ':');
5470 nfname = talloc_strndup_append(nfname, s, n);
5471 if (nfname == NULL) {
5472 return NT_STATUS_NO_MEMORY;
5476 status = srvstr_push(dstart, flags2,
5478 PTR_DIFF(dend, pdata+4),
5480 if (!NT_STATUS_IS_OK(status)) {
5483 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5484 data_size = 4 + len;
5490 case SMB_FILE_ALLOCATION_INFORMATION:
5491 case SMB_QUERY_FILE_ALLOCATION_INFO:
5492 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5494 SOFF_T(pdata,0,allocation_size);
5497 case SMB_FILE_END_OF_FILE_INFORMATION:
5498 case SMB_QUERY_FILE_END_OF_FILEINFO:
5499 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5501 SOFF_T(pdata,0,file_size);
5504 case SMB_QUERY_FILE_ALL_INFO:
5505 case SMB_FILE_ALL_INFORMATION:
5507 unsigned int ea_size =
5508 estimate_ea_size(conn, fsp, smb_fname);
5509 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5510 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5511 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5512 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5513 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5514 SIVAL(pdata,32,mode);
5515 SIVAL(pdata,36,0); /* padding. */
5517 SOFF_T(pdata,0,allocation_size);
5518 SOFF_T(pdata,8,file_size);
5519 SIVAL(pdata,16,nlink);
5520 SCVAL(pdata,20,delete_pending);
5521 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5524 SIVAL(pdata,0,ea_size);
5525 pdata += 4; /* EA info */
5526 status = srvstr_push(dstart, flags2,
5528 PTR_DIFF(dend, pdata+4),
5530 if (!NT_STATUS_IS_OK(status)) {
5535 data_size = PTR_DIFF(pdata,(*ppdata));
5536 *fixed_portion = 10;
5540 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5542 unsigned int ea_size =
5543 estimate_ea_size(conn, fsp, smb_fname);
5544 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5545 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5546 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5547 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5548 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5549 SIVAL(pdata, 0x20, mode);
5550 SIVAL(pdata, 0x24, 0); /* padding. */
5551 SBVAL(pdata, 0x28, allocation_size);
5552 SBVAL(pdata, 0x30, file_size);
5553 SIVAL(pdata, 0x38, nlink);
5554 SCVAL(pdata, 0x3C, delete_pending);
5555 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5556 SSVAL(pdata, 0x3E, 0); /* padding */
5557 SBVAL(pdata, 0x40, file_id);
5558 SIVAL(pdata, 0x48, ea_size);
5559 SIVAL(pdata, 0x4C, access_mask);
5560 SBVAL(pdata, 0x50, pos);
5561 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5562 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5566 status = srvstr_push(dstart, flags2,
5568 PTR_DIFF(dend, pdata+4),
5570 if (!NT_STATUS_IS_OK(status)) {
5575 data_size = PTR_DIFF(pdata,(*ppdata));
5576 *fixed_portion = 104;
5579 case SMB_FILE_INTERNAL_INFORMATION:
5581 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5582 SBVAL(pdata, 0, file_id);
5587 case SMB_FILE_ACCESS_INFORMATION:
5588 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5589 SIVAL(pdata, 0, access_mask);
5594 case SMB_FILE_NAME_INFORMATION:
5595 /* Pathname with leading '\'. */
5598 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5600 SIVAL(pdata,0,byte_len);
5601 data_size = 4 + byte_len;
5605 case SMB_FILE_DISPOSITION_INFORMATION:
5606 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5608 SCVAL(pdata,0,delete_pending);
5612 case SMB_FILE_POSITION_INFORMATION:
5613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5615 SOFF_T(pdata,0,pos);
5619 case SMB_FILE_MODE_INFORMATION:
5620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5621 SIVAL(pdata,0,mode);
5626 case SMB_FILE_ALIGNMENT_INFORMATION:
5627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5628 SIVAL(pdata,0,0); /* No alignment needed. */
5634 * NT4 server just returns "invalid query" to this - if we try
5635 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5638 /* The first statement above is false - verified using Thursby
5639 * client against NT4 -- gcolley.
5641 case SMB_QUERY_FILE_STREAM_INFO:
5642 case SMB_FILE_STREAM_INFORMATION: {
5643 unsigned int num_streams = 0;
5644 struct stream_struct *streams = NULL;
5646 DEBUG(10,("smbd_do_qfilepathinfo: "
5647 "SMB_FILE_STREAM_INFORMATION\n"));
5649 if (is_ntfs_stream_smb_fname(smb_fname)) {
5650 return NT_STATUS_INVALID_PARAMETER;
5653 status = vfs_streaminfo(conn,
5660 if (!NT_STATUS_IS_OK(status)) {
5661 DEBUG(10, ("could not get stream info: %s\n",
5662 nt_errstr(status)));
5666 status = marshall_stream_info(num_streams, streams,
5667 pdata, max_data_bytes,
5670 if (!NT_STATUS_IS_OK(status)) {
5671 DEBUG(10, ("marshall_stream_info failed: %s\n",
5672 nt_errstr(status)));
5673 TALLOC_FREE(streams);
5677 TALLOC_FREE(streams);
5679 *fixed_portion = 32;
5683 case SMB_QUERY_COMPRESSION_INFO:
5684 case SMB_FILE_COMPRESSION_INFORMATION:
5685 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5686 SOFF_T(pdata,0,file_size);
5687 SIVAL(pdata,8,0); /* ??? */
5688 SIVAL(pdata,12,0); /* ??? */
5690 *fixed_portion = 16;
5693 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5694 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5695 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5696 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5697 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5698 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5699 SOFF_T(pdata,32,allocation_size);
5700 SOFF_T(pdata,40,file_size);
5701 SIVAL(pdata,48,mode);
5702 SIVAL(pdata,52,0); /* ??? */
5704 *fixed_portion = 56;
5707 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5708 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5709 SIVAL(pdata,0,mode);
5716 * CIFS UNIX Extensions.
5719 case SMB_QUERY_FILE_UNIX_BASIC:
5721 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5722 data_size = PTR_DIFF(pdata,(*ppdata));
5724 DEBUG(4,("smbd_do_qfilepathinfo: "
5725 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5726 dump_data(4, (uint8_t *)(*ppdata), data_size);
5730 case SMB_QUERY_FILE_UNIX_INFO2:
5732 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5733 data_size = PTR_DIFF(pdata,(*ppdata));
5737 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5739 for (i=0; i<100; i++)
5740 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5746 case SMB_QUERY_FILE_UNIX_LINK:
5749 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5752 return NT_STATUS_NO_MEMORY;
5755 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5757 if(!S_ISLNK(psbuf->st_ex_mode)) {
5758 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5761 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5763 link_len = SMB_VFS_READLINK(conn,
5766 if (link_len == -1) {
5767 return map_nt_error_from_unix(errno);
5769 buffer[link_len] = 0;
5770 status = srvstr_push(dstart, flags2,
5772 PTR_DIFF(dend, pdata),
5773 STR_TERMINATE, &len);
5774 if (!NT_STATUS_IS_OK(status)) {
5778 data_size = PTR_DIFF(pdata,(*ppdata));
5783 #if defined(HAVE_POSIX_ACLS)
5784 case SMB_QUERY_POSIX_ACL:
5786 status = smb_query_posix_acl(conn,
5793 if (!NT_STATUS_IS_OK(status)) {
5801 case SMB_QUERY_POSIX_LOCK:
5806 enum brl_type lock_type;
5808 /* We need an open file with a real fd for this. */
5809 if (!fsp || fsp->fh->fd == -1) {
5810 return NT_STATUS_INVALID_LEVEL;
5813 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5814 return NT_STATUS_INVALID_PARAMETER;
5817 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5818 case POSIX_LOCK_TYPE_READ:
5819 lock_type = READ_LOCK;
5821 case POSIX_LOCK_TYPE_WRITE:
5822 lock_type = WRITE_LOCK;
5824 case POSIX_LOCK_TYPE_UNLOCK:
5826 /* There's no point in asking for an unlock... */
5827 return NT_STATUS_INVALID_PARAMETER;
5830 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5831 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5832 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5834 status = query_lock(fsp,
5841 if (ERROR_WAS_LOCK_DENIED(status)) {
5842 /* Here we need to report who has it locked... */
5843 data_size = POSIX_LOCK_DATA_SIZE;
5845 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5846 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5847 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5848 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5849 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5851 } else if (NT_STATUS_IS_OK(status)) {
5852 /* For success we just return a copy of what we sent
5853 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5854 data_size = POSIX_LOCK_DATA_SIZE;
5855 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5856 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5864 return NT_STATUS_INVALID_LEVEL;
5867 *pdata_size = data_size;
5868 return NT_STATUS_OK;
5871 /****************************************************************************
5872 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5873 file name or file id).
5874 ****************************************************************************/
5876 static void call_trans2qfilepathinfo(connection_struct *conn,
5877 struct smb_request *req,
5878 unsigned int tran_call,
5879 char **pparams, int total_params,
5880 char **ppdata, int total_data,
5881 unsigned int max_data_bytes)
5883 char *params = *pparams;
5884 char *pdata = *ppdata;
5885 uint16_t info_level;
5886 unsigned int data_size = 0;
5887 unsigned int param_size = 2;
5888 struct smb_filename *smb_fname = NULL;
5889 bool delete_pending = False;
5890 struct timespec write_time_ts;
5891 files_struct *fsp = NULL;
5892 struct file_id fileid;
5893 struct ea_list *ea_list = NULL;
5894 int lock_data_count = 0;
5895 char *lock_data = NULL;
5896 size_t fixed_portion;
5897 NTSTATUS status = NT_STATUS_OK;
5900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5904 ZERO_STRUCT(write_time_ts);
5906 if (tran_call == TRANSACT2_QFILEINFO) {
5907 if (total_params < 4) {
5908 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5913 call_trans2qpipeinfo(conn, req, tran_call,
5914 pparams, total_params,
5920 fsp = file_fsp(req, SVAL(params,0));
5921 info_level = SVAL(params,2);
5923 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5925 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5926 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5930 /* Initial check for valid fsp ptr. */
5931 if (!check_fsp_open(conn, req, fsp)) {
5935 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5936 if (smb_fname == NULL) {
5937 reply_nterror(req, NT_STATUS_NO_MEMORY);
5941 if(fsp->fake_file_handle) {
5943 * This is actually for the QUOTA_FAKE_FILE --metze
5946 /* We know this name is ok, it's already passed the checks. */
5948 } else if(fsp->fh->fd == -1) {
5950 * This is actually a QFILEINFO on a directory
5951 * handle (returned from an NT SMB). NT5.0 seems
5952 * to do this call. JRA.
5955 if (INFO_LEVEL_IS_UNIX(info_level)) {
5956 /* Always do lstat for UNIX calls. */
5957 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5958 DEBUG(3,("call_trans2qfilepathinfo: "
5959 "SMB_VFS_LSTAT of %s failed "
5961 smb_fname_str_dbg(smb_fname),
5964 map_nt_error_from_unix(errno));
5967 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5968 DEBUG(3,("call_trans2qfilepathinfo: "
5969 "SMB_VFS_STAT of %s failed (%s)\n",
5970 smb_fname_str_dbg(smb_fname),
5973 map_nt_error_from_unix(errno));
5977 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5978 fileid = vfs_file_id_from_sbuf(
5979 conn, &smb_fname->st);
5980 get_file_infos(fileid, fsp->name_hash,
5986 * Original code - this is an open file.
5988 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5989 DEBUG(3, ("fstat of %s failed (%s)\n",
5990 fsp_fnum_dbg(fsp), strerror(errno)));
5992 map_nt_error_from_unix(errno));
5995 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5996 fileid = vfs_file_id_from_sbuf(
5997 conn, &smb_fname->st);
5998 get_file_infos(fileid, fsp->name_hash,
6007 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6010 if (total_params < 7) {
6011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6015 info_level = SVAL(params,0);
6017 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6019 if (INFO_LEVEL_IS_UNIX(info_level)) {
6020 if (!lp_unix_extensions()) {
6021 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6024 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6025 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6026 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6027 req->posix_pathnames) {
6028 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6032 if (req->posix_pathnames) {
6033 srvstr_get_path_posix(req,
6042 srvstr_get_path(req,
6051 if (!NT_STATUS_IS_OK(status)) {
6052 reply_nterror(req, status);
6056 status = filename_convert(req,
6063 if (!NT_STATUS_IS_OK(status)) {
6064 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6065 reply_botherror(req,
6066 NT_STATUS_PATH_NOT_COVERED,
6067 ERRSRV, ERRbadpath);
6070 reply_nterror(req, status);
6074 /* If this is a stream, check if there is a delete_pending. */
6075 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6076 && is_ntfs_stream_smb_fname(smb_fname)) {
6077 struct smb_filename *smb_fname_base;
6079 /* Create an smb_filename with stream_name == NULL. */
6080 smb_fname_base = synthetic_smb_fname(
6082 smb_fname->base_name,
6086 if (smb_fname_base == NULL) {
6087 reply_nterror(req, NT_STATUS_NO_MEMORY);
6091 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6092 /* Always do lstat for UNIX calls. */
6093 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6094 DEBUG(3,("call_trans2qfilepathinfo: "
6095 "SMB_VFS_LSTAT of %s failed "
6097 smb_fname_str_dbg(smb_fname_base),
6099 TALLOC_FREE(smb_fname_base);
6101 map_nt_error_from_unix(errno));
6105 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6106 DEBUG(3,("call_trans2qfilepathinfo: "
6107 "fileinfo of %s failed "
6109 smb_fname_str_dbg(smb_fname_base),
6111 TALLOC_FREE(smb_fname_base);
6113 map_nt_error_from_unix(errno));
6118 status = file_name_hash(conn,
6119 smb_fname_str_dbg(smb_fname_base),
6121 if (!NT_STATUS_IS_OK(status)) {
6122 TALLOC_FREE(smb_fname_base);
6123 reply_nterror(req, status);
6127 fileid = vfs_file_id_from_sbuf(conn,
6128 &smb_fname_base->st);
6129 TALLOC_FREE(smb_fname_base);
6130 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6131 if (delete_pending) {
6132 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6137 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6138 /* Always do lstat for UNIX calls. */
6139 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6140 DEBUG(3,("call_trans2qfilepathinfo: "
6141 "SMB_VFS_LSTAT of %s failed (%s)\n",
6142 smb_fname_str_dbg(smb_fname),
6145 map_nt_error_from_unix(errno));
6150 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6151 DEBUG(3,("call_trans2qfilepathinfo: "
6152 "SMB_VFS_STAT of %s failed (%s)\n",
6153 smb_fname_str_dbg(smb_fname),
6156 map_nt_error_from_unix(errno));
6161 status = file_name_hash(conn,
6162 smb_fname_str_dbg(smb_fname),
6164 if (!NT_STATUS_IS_OK(status)) {
6165 reply_nterror(req, status);
6169 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6170 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6171 get_file_infos(fileid, name_hash, &delete_pending,
6175 if (delete_pending) {
6176 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6181 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6182 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6184 info_level,tran_call,total_data));
6186 /* Pull out any data sent here before we realloc. */
6187 switch (info_level) {
6188 case SMB_INFO_QUERY_EAS_FROM_LIST:
6190 /* Pull any EA list from the data portion. */
6193 if (total_data < 4) {
6195 req, NT_STATUS_INVALID_PARAMETER);
6198 ea_size = IVAL(pdata,0);
6200 if (total_data > 0 && ea_size != total_data) {
6201 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6202 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6204 req, NT_STATUS_INVALID_PARAMETER);
6208 if (!lp_ea_support(SNUM(conn))) {
6209 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6213 /* Pull out the list of names. */
6214 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6217 req, NT_STATUS_INVALID_PARAMETER);
6223 case SMB_QUERY_POSIX_LOCK:
6225 if (fsp == NULL || fsp->fh->fd == -1) {
6226 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6230 if (total_data != POSIX_LOCK_DATA_SIZE) {
6232 req, NT_STATUS_INVALID_PARAMETER);
6236 /* Copy the lock range data. */
6237 lock_data = (char *)talloc_memdup(
6238 req, pdata, total_data);
6240 reply_nterror(req, NT_STATUS_NO_MEMORY);
6243 lock_data_count = total_data;
6249 *pparams = (char *)SMB_REALLOC(*pparams,2);
6250 if (*pparams == NULL) {
6251 reply_nterror(req, NT_STATUS_NO_MEMORY);
6258 * draft-leach-cifs-v1-spec-02.txt
6259 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6262 * The requested information is placed in the Data portion of the
6263 * transaction response. For the information levels greater than 0x100,
6264 * the transaction response has 1 parameter word which should be
6265 * ignored by the client.
6267 * However Windows only follows this rule for the IS_NAME_VALID call.
6269 switch (info_level) {
6270 case SMB_INFO_IS_NAME_VALID:
6275 if ((info_level & 0xFF00) == 0xFF00) {
6277 * We use levels that start with 0xFF00
6278 * internally to represent SMB2 specific levels
6280 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6284 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6286 delete_pending, write_time_ts,
6288 lock_data_count, lock_data,
6289 req->flags2, max_data_bytes,
6291 ppdata, &data_size);
6292 if (!NT_STATUS_IS_OK(status)) {
6293 if (open_was_deferred(req->xconn, req->mid)) {
6294 /* We have re-scheduled this call. */
6297 reply_nterror(req, status);
6300 if (fixed_portion > max_data_bytes) {
6301 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6305 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6311 /****************************************************************************
6312 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6314 ****************************************************************************/
6316 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6317 connection_struct *conn,
6318 struct smb_request *req,
6319 bool overwrite_if_exists,
6320 const struct smb_filename *smb_fname_old,
6321 struct smb_filename *smb_fname_new)
6323 NTSTATUS status = NT_STATUS_OK;
6326 /* source must already exist. */
6327 if (!VALID_STAT(smb_fname_old->st)) {
6328 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6331 if (VALID_STAT(smb_fname_new->st)) {
6332 if (overwrite_if_exists) {
6333 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6334 return NT_STATUS_FILE_IS_A_DIRECTORY;
6336 status = unlink_internals(conn,
6338 FILE_ATTRIBUTE_NORMAL,
6341 if (!NT_STATUS_IS_OK(status)) {
6345 /* Disallow if newname already exists. */
6346 return NT_STATUS_OBJECT_NAME_COLLISION;
6350 /* No links from a directory. */
6351 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6352 return NT_STATUS_FILE_IS_A_DIRECTORY;
6355 /* Setting a hardlink to/from a stream isn't currently supported. */
6356 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6358 DBG_DEBUG("Old name has streams\n");
6359 return NT_STATUS_INVALID_PARAMETER;
6361 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6363 DBG_DEBUG("New name has streams\n");
6364 return NT_STATUS_INVALID_PARAMETER;
6367 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6368 smb_fname_old->base_name, smb_fname_new->base_name));
6370 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6371 status = map_nt_error_from_unix(errno);
6372 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6373 nt_errstr(status), smb_fname_old->base_name,
6374 smb_fname_new->base_name));
6379 /****************************************************************************
6380 Deal with setting the time from any of the setfilepathinfo functions.
6381 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6382 calling this function.
6383 ****************************************************************************/
6385 NTSTATUS smb_set_file_time(connection_struct *conn,
6387 const struct smb_filename *smb_fname,
6388 struct smb_file_time *ft,
6389 bool setting_write_time)
6391 struct smb_filename smb_fname_base;
6393 FILE_NOTIFY_CHANGE_LAST_ACCESS
6394 |FILE_NOTIFY_CHANGE_LAST_WRITE
6395 |FILE_NOTIFY_CHANGE_CREATION;
6397 if (!VALID_STAT(smb_fname->st)) {
6398 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6401 /* get some defaults (no modifications) if any info is zero or -1. */
6402 if (null_timespec(ft->create_time)) {
6403 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6406 if (null_timespec(ft->atime)) {
6407 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6410 if (null_timespec(ft->mtime)) {
6411 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6414 if (!setting_write_time) {
6415 /* ft->mtime comes from change time, not write time. */
6416 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6419 /* Ensure the resolution is the correct for
6420 * what we can store on this filesystem. */
6422 round_timespec(conn->ts_res, &ft->create_time);
6423 round_timespec(conn->ts_res, &ft->ctime);
6424 round_timespec(conn->ts_res, &ft->atime);
6425 round_timespec(conn->ts_res, &ft->mtime);
6427 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6428 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6429 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6430 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6431 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6432 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6433 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6434 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6436 if (setting_write_time) {
6438 * This was a Windows setfileinfo on an open file.
6439 * NT does this a lot. We also need to
6440 * set the time here, as it can be read by
6441 * FindFirst/FindNext and with the patch for bug #2045
6442 * in smbd/fileio.c it ensures that this timestamp is
6443 * kept sticky even after a write. We save the request
6444 * away and will set it on file close and after a write. JRA.
6447 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6448 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6451 if (fsp->base_fsp) {
6452 set_sticky_write_time_fsp(fsp->base_fsp,
6455 set_sticky_write_time_fsp(fsp, ft->mtime);
6458 set_sticky_write_time_path(
6459 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6464 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6466 /* Always call ntimes on the base, even if a stream was passed in. */
6467 smb_fname_base = *smb_fname;
6468 smb_fname_base.stream_name = NULL;
6470 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6471 return map_nt_error_from_unix(errno);
6474 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6475 smb_fname->base_name);
6476 return NT_STATUS_OK;
6479 /****************************************************************************
6480 Deal with setting the dosmode from any of the setfilepathinfo functions.
6481 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6482 done before calling this function.
6483 ****************************************************************************/
6485 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6486 const struct smb_filename *smb_fname,
6489 struct smb_filename *smb_fname_base;
6492 if (!VALID_STAT(smb_fname->st)) {
6493 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6496 /* Always operate on the base_name, even if a stream was passed in. */
6497 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6498 smb_fname->base_name,
6502 if (smb_fname_base == NULL) {
6503 return NT_STATUS_NO_MEMORY;
6507 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6508 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6510 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6514 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6516 /* check the mode isn't different, before changing it */
6517 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6518 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6519 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6520 (unsigned int)dosmode));
6522 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6524 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6526 smb_fname_str_dbg(smb_fname_base),
6528 status = map_nt_error_from_unix(errno);
6532 status = NT_STATUS_OK;
6534 TALLOC_FREE(smb_fname_base);
6538 /****************************************************************************
6539 Deal with setting the size from any of the setfilepathinfo functions.
6540 ****************************************************************************/
6542 static NTSTATUS smb_set_file_size(connection_struct *conn,
6543 struct smb_request *req,
6545 const struct smb_filename *smb_fname,
6546 const SMB_STRUCT_STAT *psbuf,
6548 bool fail_after_createfile)
6550 NTSTATUS status = NT_STATUS_OK;
6551 struct smb_filename *smb_fname_tmp = NULL;
6552 files_struct *new_fsp = NULL;
6554 if (!VALID_STAT(*psbuf)) {
6555 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6558 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6560 get_file_size_stat(psbuf));
6562 if (size == get_file_size_stat(psbuf)) {
6563 return NT_STATUS_OK;
6566 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6567 smb_fname_str_dbg(smb_fname), (double)size));
6569 if (fsp && fsp->fh->fd != -1) {
6570 /* Handle based call. */
6571 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6572 return NT_STATUS_ACCESS_DENIED;
6575 if (vfs_set_filelen(fsp, size) == -1) {
6576 return map_nt_error_from_unix(errno);
6578 trigger_write_time_update_immediate(fsp);
6579 return NT_STATUS_OK;
6582 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6583 if (smb_fname_tmp == NULL) {
6584 return NT_STATUS_NO_MEMORY;
6587 smb_fname_tmp->st = *psbuf;
6589 status = SMB_VFS_CREATE_FILE(
6592 0, /* root_dir_fid */
6593 smb_fname_tmp, /* fname */
6594 FILE_WRITE_DATA, /* access_mask */
6595 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6597 FILE_OPEN, /* create_disposition*/
6598 0, /* create_options */
6599 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6600 0, /* oplock_request */
6602 0, /* allocation_size */
6603 0, /* private_flags */
6606 &new_fsp, /* result */
6608 NULL, NULL); /* create context */
6610 TALLOC_FREE(smb_fname_tmp);
6612 if (!NT_STATUS_IS_OK(status)) {
6613 /* NB. We check for open_was_deferred in the caller. */
6617 /* See RAW-SFILEINFO-END-OF-FILE */
6618 if (fail_after_createfile) {
6619 close_file(req, new_fsp,NORMAL_CLOSE);
6620 return NT_STATUS_INVALID_LEVEL;
6623 if (vfs_set_filelen(new_fsp, size) == -1) {
6624 status = map_nt_error_from_unix(errno);
6625 close_file(req, new_fsp,NORMAL_CLOSE);
6629 trigger_write_time_update_immediate(new_fsp);
6630 close_file(req, new_fsp,NORMAL_CLOSE);
6631 return NT_STATUS_OK;
6634 /****************************************************************************
6635 Deal with SMB_INFO_SET_EA.
6636 ****************************************************************************/
6638 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6642 const struct smb_filename *smb_fname)
6644 struct ea_list *ea_list = NULL;
6645 TALLOC_CTX *ctx = NULL;
6646 NTSTATUS status = NT_STATUS_OK;
6648 if (total_data < 10) {
6650 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6651 length. They seem to have no effect. Bug #3212. JRA */
6653 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6654 /* We're done. We only get EA info in this call. */
6655 return NT_STATUS_OK;
6658 return NT_STATUS_INVALID_PARAMETER;
6661 if (IVAL(pdata,0) > total_data) {
6662 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6663 IVAL(pdata,0), (unsigned int)total_data));
6664 return NT_STATUS_INVALID_PARAMETER;
6668 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6670 return NT_STATUS_INVALID_PARAMETER;
6673 status = set_ea(conn, fsp, smb_fname, ea_list);
6678 /****************************************************************************
6679 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6680 ****************************************************************************/
6682 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6687 struct ea_list *ea_list = NULL;
6691 return NT_STATUS_INVALID_HANDLE;
6694 if (!lp_ea_support(SNUM(conn))) {
6695 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6696 "EA's not supported.\n",
6697 (unsigned int)total_data));
6698 return NT_STATUS_EAS_NOT_SUPPORTED;
6701 if (total_data < 10) {
6702 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6704 (unsigned int)total_data));
6705 return NT_STATUS_INVALID_PARAMETER;
6708 ea_list = read_nttrans_ea_list(talloc_tos(),
6713 return NT_STATUS_INVALID_PARAMETER;
6716 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6718 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6719 smb_fname_str_dbg(fsp->fsp_name),
6720 nt_errstr(status) ));
6726 /****************************************************************************
6727 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6728 ****************************************************************************/
6730 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6734 struct smb_filename *smb_fname)
6736 NTSTATUS status = NT_STATUS_OK;
6737 bool delete_on_close;
6738 uint32_t dosmode = 0;
6740 if (total_data < 1) {
6741 return NT_STATUS_INVALID_PARAMETER;
6745 return NT_STATUS_INVALID_HANDLE;
6748 delete_on_close = (CVAL(pdata,0) ? True : False);
6749 dosmode = dos_mode(conn, smb_fname);
6751 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6752 "delete_on_close = %u\n",
6753 smb_fname_str_dbg(smb_fname),
6754 (unsigned int)dosmode,
6755 (unsigned int)delete_on_close ));
6757 if (delete_on_close) {
6758 status = can_set_delete_on_close(fsp, dosmode);
6759 if (!NT_STATUS_IS_OK(status)) {
6764 /* The set is across all open files on this dev/inode pair. */
6765 if (!set_delete_on_close(fsp, delete_on_close,
6766 conn->session_info->security_token,
6767 conn->session_info->unix_token)) {
6768 return NT_STATUS_ACCESS_DENIED;
6770 return NT_STATUS_OK;
6773 /****************************************************************************
6774 Deal with SMB_FILE_POSITION_INFORMATION.
6775 ****************************************************************************/
6777 static NTSTATUS smb_file_position_information(connection_struct *conn,
6782 uint64_t position_information;
6784 if (total_data < 8) {
6785 return NT_STATUS_INVALID_PARAMETER;
6789 /* Ignore on pathname based set. */
6790 return NT_STATUS_OK;
6793 position_information = (uint64_t)IVAL(pdata,0);
6794 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6796 DEBUG(10,("smb_file_position_information: Set file position "
6797 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6798 (double)position_information));
6799 fsp->fh->position_information = position_information;
6800 return NT_STATUS_OK;
6803 /****************************************************************************
6804 Deal with SMB_FILE_MODE_INFORMATION.
6805 ****************************************************************************/
6807 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6813 if (total_data < 4) {
6814 return NT_STATUS_INVALID_PARAMETER;
6816 mode = IVAL(pdata,0);
6817 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6818 return NT_STATUS_INVALID_PARAMETER;
6820 return NT_STATUS_OK;
6823 /****************************************************************************
6824 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6825 ****************************************************************************/
6827 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6828 struct smb_request *req,
6831 const struct smb_filename *new_smb_fname)
6833 char *link_target = NULL;
6834 TALLOC_CTX *ctx = talloc_tos();
6836 /* Set a symbolic link. */
6837 /* Don't allow this if follow links is false. */
6839 if (total_data == 0) {
6840 return NT_STATUS_INVALID_PARAMETER;
6843 if (!lp_follow_symlinks(SNUM(conn))) {
6844 return NT_STATUS_ACCESS_DENIED;
6847 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6848 total_data, STR_TERMINATE);
6851 return NT_STATUS_INVALID_PARAMETER;
6854 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6855 new_smb_fname->base_name, link_target ));
6857 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6858 return map_nt_error_from_unix(errno);
6861 return NT_STATUS_OK;
6864 /****************************************************************************
6865 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6866 ****************************************************************************/
6868 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6869 struct smb_request *req,
6870 const char *pdata, int total_data,
6871 struct smb_filename *smb_fname_new)
6873 char *oldname = NULL;
6874 struct smb_filename *smb_fname_old = NULL;
6875 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6876 TALLOC_CTX *ctx = talloc_tos();
6877 NTSTATUS status = NT_STATUS_OK;
6879 /* Set a hard link. */
6880 if (total_data == 0) {
6881 return NT_STATUS_INVALID_PARAMETER;
6884 if (req->posix_pathnames) {
6885 srvstr_get_path_posix(ctx,
6894 srvstr_get_path(ctx,
6903 if (!NT_STATUS_IS_OK(status)) {
6907 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6908 smb_fname_str_dbg(smb_fname_new), oldname));
6910 status = filename_convert(ctx,
6917 if (!NT_STATUS_IS_OK(status)) {
6921 return hardlink_internals(ctx, conn, req, false,
6922 smb_fname_old, smb_fname_new);
6925 /****************************************************************************
6926 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6927 ****************************************************************************/
6929 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6930 struct smb_request *req,
6934 struct smb_filename *smb_fname_src)
6938 char *newname = NULL;
6939 struct smb_filename *smb_fname_dst = NULL;
6940 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6941 ucf_flags_from_smb_request(req);
6942 NTSTATUS status = NT_STATUS_OK;
6943 TALLOC_CTX *ctx = talloc_tos();
6946 return NT_STATUS_INVALID_HANDLE;
6949 if (total_data < 20) {
6950 return NT_STATUS_INVALID_PARAMETER;
6953 overwrite = (CVAL(pdata,0) ? True : False);
6954 len = IVAL(pdata,16);
6956 if (len > (total_data - 20) || (len == 0)) {
6957 return NT_STATUS_INVALID_PARAMETER;
6960 if (req->posix_pathnames) {
6961 srvstr_get_path_posix(ctx,
6970 srvstr_get_path(ctx,
6979 if (!NT_STATUS_IS_OK(status)) {
6983 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6986 status = filename_convert(ctx,
6993 if (!NT_STATUS_IS_OK(status)) {
6997 if (fsp->base_fsp) {
6998 /* newname must be a stream name. */
6999 if (newname[0] != ':') {
7000 return NT_STATUS_NOT_SUPPORTED;
7003 /* Create an smb_fname to call rename_internals_fsp() with. */
7004 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7005 fsp->base_fsp->fsp_name->base_name,
7008 fsp->base_fsp->fsp_name->flags);
7009 if (smb_fname_dst == NULL) {
7010 status = NT_STATUS_NO_MEMORY;
7015 * Set the original last component, since
7016 * rename_internals_fsp() requires it.
7018 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7020 if (smb_fname_dst->original_lcomp == NULL) {
7021 status = NT_STATUS_NO_MEMORY;
7027 DEBUG(10,("smb2_file_rename_information: "
7028 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7029 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7030 smb_fname_str_dbg(smb_fname_dst)));
7031 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7032 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7036 TALLOC_FREE(smb_fname_dst);
7040 static NTSTATUS smb_file_link_information(connection_struct *conn,
7041 struct smb_request *req,
7045 struct smb_filename *smb_fname_src)
7049 char *newname = NULL;
7050 struct smb_filename *smb_fname_dst = NULL;
7051 NTSTATUS status = NT_STATUS_OK;
7052 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7053 ucf_flags_from_smb_request(req);
7054 TALLOC_CTX *ctx = talloc_tos();
7057 return NT_STATUS_INVALID_HANDLE;
7060 if (total_data < 20) {
7061 return NT_STATUS_INVALID_PARAMETER;
7064 overwrite = (CVAL(pdata,0) ? true : false);
7065 len = IVAL(pdata,16);
7067 if (len > (total_data - 20) || (len == 0)) {
7068 return NT_STATUS_INVALID_PARAMETER;
7071 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7072 srvstr_get_path_posix(ctx,
7080 ucf_flags |= UCF_POSIX_PATHNAMES;
7082 srvstr_get_path(ctx,
7091 if (!NT_STATUS_IS_OK(status)) {
7095 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7098 status = filename_convert(ctx,
7105 if (!NT_STATUS_IS_OK(status)) {
7109 if (fsp->base_fsp) {
7110 /* No stream names. */
7111 return NT_STATUS_NOT_SUPPORTED;
7114 DEBUG(10,("smb_file_link_information: "
7115 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7116 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7117 smb_fname_str_dbg(smb_fname_dst)));
7118 status = hardlink_internals(ctx,
7125 TALLOC_FREE(smb_fname_dst);
7129 /****************************************************************************
7130 Deal with SMB_FILE_RENAME_INFORMATION.
7131 ****************************************************************************/
7133 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7134 struct smb_request *req,
7138 struct smb_filename *smb_fname_src)
7143 char *newname = NULL;
7144 struct smb_filename *smb_fname_dst = NULL;
7145 bool dest_has_wcard = False;
7146 NTSTATUS status = NT_STATUS_OK;
7148 TALLOC_CTX *ctx = talloc_tos();
7150 if (total_data < 13) {
7151 return NT_STATUS_INVALID_PARAMETER;
7154 overwrite = (CVAL(pdata,0) ? True : False);
7155 root_fid = IVAL(pdata,4);
7156 len = IVAL(pdata,8);
7158 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7159 return NT_STATUS_INVALID_PARAMETER;
7162 if (req->posix_pathnames) {
7163 srvstr_get_path_wcard_posix(ctx,
7173 srvstr_get_path_wcard(ctx,
7183 if (!NT_STATUS_IS_OK(status)) {
7187 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7190 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7191 status = resolve_dfspath_wcard(ctx, conn,
7193 UCF_COND_ALLOW_WCARD_LCOMP,
7194 !conn->sconn->using_smb2,
7197 if (!NT_STATUS_IS_OK(status)) {
7202 /* Check the new name has no '/' characters. */
7203 if (strchr_m(newname, '/')) {
7204 return NT_STATUS_NOT_SUPPORTED;
7207 if (fsp && fsp->base_fsp) {
7208 /* newname must be a stream name. */
7209 if (newname[0] != ':') {
7210 return NT_STATUS_NOT_SUPPORTED;
7213 /* Create an smb_fname to call rename_internals_fsp() with. */
7214 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7215 fsp->base_fsp->fsp_name->base_name,
7218 fsp->base_fsp->fsp_name->flags);
7219 if (smb_fname_dst == NULL) {
7220 status = NT_STATUS_NO_MEMORY;
7225 * Set the original last component, since
7226 * rename_internals_fsp() requires it.
7228 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7230 if (smb_fname_dst->original_lcomp == NULL) {
7231 status = NT_STATUS_NO_MEMORY;
7237 * Build up an smb_fname_dst based on the filename passed in.
7238 * We basically just strip off the last component, and put on
7239 * the newname instead.
7241 char *base_name = NULL;
7242 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7243 ucf_flags_from_smb_request(req);
7245 if (dest_has_wcard) {
7246 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7249 /* newname must *not* be a stream name. */
7250 if (newname[0] == ':') {
7251 return NT_STATUS_NOT_SUPPORTED;
7255 * Strip off the last component (filename) of the path passed
7258 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7260 return NT_STATUS_NO_MEMORY;
7262 p = strrchr_m(base_name, '/');
7266 base_name = talloc_strdup(ctx, "");
7268 return NT_STATUS_NO_MEMORY;
7271 /* Append the new name. */
7272 base_name = talloc_asprintf_append(base_name,
7276 return NT_STATUS_NO_MEMORY;
7279 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7282 /* If an error we expect this to be
7283 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7285 if (!NT_STATUS_IS_OK(status)) {
7286 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7290 /* Create an smb_fname to call rename_internals_fsp() */
7291 smb_fname_dst = synthetic_smb_fname(ctx,
7295 smb_fname_src->flags);
7296 if (smb_fname_dst == NULL) {
7297 status = NT_STATUS_NO_MEMORY;
7304 DEBUG(10,("smb_file_rename_information: "
7305 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7306 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7307 smb_fname_str_dbg(smb_fname_dst)));
7308 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7311 DEBUG(10,("smb_file_rename_information: "
7312 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7313 smb_fname_str_dbg(smb_fname_src),
7314 smb_fname_str_dbg(smb_fname_dst)));
7315 status = rename_internals(ctx, conn, req, smb_fname_src,
7316 smb_fname_dst, 0, overwrite, false,
7318 FILE_WRITE_ATTRIBUTES);
7321 TALLOC_FREE(smb_fname_dst);
7325 /****************************************************************************
7326 Deal with SMB_SET_POSIX_ACL.
7327 ****************************************************************************/
7329 #if defined(HAVE_POSIX_ACLS)
7330 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7331 struct smb_request *req,
7335 const struct smb_filename *smb_fname)
7337 uint16_t posix_acl_version;
7338 uint16_t num_file_acls;
7339 uint16_t num_def_acls;
7340 bool valid_file_acls = true;
7341 bool valid_def_acls = true;
7343 unsigned int size_needed;
7344 unsigned int total_data;
7345 bool close_fsp = false;
7347 if (total_data_in < 0) {
7348 status = NT_STATUS_INVALID_PARAMETER;
7352 total_data = total_data_in;
7354 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7355 status = NT_STATUS_INVALID_PARAMETER;
7358 posix_acl_version = SVAL(pdata,0);
7359 num_file_acls = SVAL(pdata,2);
7360 num_def_acls = SVAL(pdata,4);
7362 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7363 valid_file_acls = false;
7367 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7368 valid_def_acls = false;
7372 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7373 status = NT_STATUS_INVALID_PARAMETER;
7378 if (num_file_acls + num_def_acls < num_file_acls) {
7379 status = NT_STATUS_INVALID_PARAMETER;
7383 size_needed = num_file_acls + num_def_acls;
7386 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7387 * than UINT_MAX, so check by division.
7389 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7390 status = NT_STATUS_INVALID_PARAMETER;
7394 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7395 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7396 status = NT_STATUS_INVALID_PARAMETER;
7399 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7401 if (total_data < size_needed) {
7402 status = NT_STATUS_INVALID_PARAMETER;
7407 * Ensure we always operate on a file descriptor, not just
7411 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7413 SEC_STD_READ_CONTROL|
7414 FILE_READ_ATTRIBUTES|
7415 FILE_WRITE_ATTRIBUTES;
7417 status = get_posix_fsp(conn,
7423 if (!NT_STATUS_IS_OK(status)) {
7429 /* Here we know fsp != NULL */
7430 SMB_ASSERT(fsp != NULL);
7432 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7433 if (!NT_STATUS_IS_OK(status)) {
7437 /* If we have a default acl, this *must* be a directory. */
7438 if (valid_def_acls && !fsp->is_directory) {
7439 DBG_INFO("Can't set default acls on "
7440 "non-directory %s\n",
7442 return NT_STATUS_INVALID_HANDLE;
7445 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7446 "num_def_acls = %"PRIu16"\n",
7451 /* Move pdata to the start of the file ACL entries. */
7452 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7454 if (valid_file_acls) {
7455 status = set_unix_posix_acl(conn,
7459 if (!NT_STATUS_IS_OK(status)) {
7464 /* Move pdata to the start of the default ACL entries. */
7465 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7467 if (valid_def_acls) {
7468 status = set_unix_posix_default_acl(conn,
7472 if (!NT_STATUS_IS_OK(status)) {
7477 status = NT_STATUS_OK;
7482 (void)close_file(req, fsp, NORMAL_CLOSE);
7489 /****************************************************************************
7490 Deal with SMB_SET_POSIX_LOCK.
7491 ****************************************************************************/
7493 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7495 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7496 struct smb_request *req,
7501 struct tevent_req *subreq = NULL;
7502 struct smbd_lock_element *lck = NULL;
7506 bool blocking_lock = False;
7507 enum brl_type lock_type;
7509 NTSTATUS status = NT_STATUS_OK;
7511 if (fsp == NULL || fsp->fh->fd == -1) {
7512 return NT_STATUS_INVALID_HANDLE;
7515 if (total_data != POSIX_LOCK_DATA_SIZE) {
7516 return NT_STATUS_INVALID_PARAMETER;
7519 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7520 case POSIX_LOCK_TYPE_READ:
7521 lock_type = READ_LOCK;
7523 case POSIX_LOCK_TYPE_WRITE:
7524 /* Return the right POSIX-mappable error code for files opened read-only. */
7525 if (!fsp->can_write) {
7526 return NT_STATUS_INVALID_HANDLE;
7528 lock_type = WRITE_LOCK;
7530 case POSIX_LOCK_TYPE_UNLOCK:
7531 lock_type = UNLOCK_LOCK;
7534 return NT_STATUS_INVALID_PARAMETER;
7537 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7538 case POSIX_LOCK_FLAG_NOWAIT:
7539 blocking_lock = false;
7541 case POSIX_LOCK_FLAG_WAIT:
7542 blocking_lock = true;
7545 return NT_STATUS_INVALID_PARAMETER;
7548 if (!lp_blocking_locks(SNUM(conn))) {
7549 blocking_lock = False;
7552 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7553 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7554 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7555 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7556 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7558 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7559 "count = %"PRIu64", offset = %"PRIu64"\n",
7561 (unsigned int)lock_type,
7566 if (lock_type == UNLOCK_LOCK) {
7567 struct smbd_lock_element l = {
7569 .brltype = UNLOCK_LOCK,
7573 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7577 lck = talloc(req, struct smbd_lock_element);
7579 return NT_STATUS_NO_MEMORY;
7582 *lck = (struct smbd_lock_element) {
7584 .brltype = lock_type,
7589 subreq = smbd_smb1_do_locks_send(
7592 req->sconn->msg_ctx,
7595 blocking_lock ? UINT32_MAX : 0,
7596 true, /* large_offset */
7600 if (subreq == NULL) {
7602 return NT_STATUS_NO_MEMORY;
7604 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7605 return NT_STATUS_EVENT_PENDING;
7608 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7610 struct smb_request *req = NULL;
7614 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7617 status = smbd_smb1_do_locks_recv(subreq);
7618 TALLOC_FREE(subreq);
7620 if (NT_STATUS_IS_OK(status)) {
7621 char params[2] = {0};
7622 /* Fake up max_data_bytes here - we know it fits. */
7623 send_trans2_replies(
7633 reply_nterror(req, status);
7636 (char *)req->outbuf,
7639 IS_CONN_ENCRYPTED(req->conn),
7642 exit_server_cleanly("smb_set_posix_lock_done: "
7643 "srv_send_smb failed.");
7651 /****************************************************************************
7652 Deal with SMB_SET_FILE_BASIC_INFO.
7653 ****************************************************************************/
7655 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7659 const struct smb_filename *smb_fname)
7661 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7662 struct smb_file_time ft;
7663 uint32_t dosmode = 0;
7664 NTSTATUS status = NT_STATUS_OK;
7668 if (total_data < 36) {
7669 return NT_STATUS_INVALID_PARAMETER;
7672 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7673 if (!NT_STATUS_IS_OK(status)) {
7677 /* Set the attributes */
7678 dosmode = IVAL(pdata,32);
7679 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7680 if (!NT_STATUS_IS_OK(status)) {
7685 ft.create_time = interpret_long_date(pdata);
7688 ft.atime = interpret_long_date(pdata+8);
7691 ft.mtime = interpret_long_date(pdata+16);
7694 ft.ctime = interpret_long_date(pdata+24);
7696 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7697 smb_fname_str_dbg(smb_fname)));
7699 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7703 /****************************************************************************
7704 Deal with SMB_INFO_STANDARD.
7705 ****************************************************************************/
7707 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7711 const struct smb_filename *smb_fname)
7714 struct smb_file_time ft;
7718 if (total_data < 12) {
7719 return NT_STATUS_INVALID_PARAMETER;
7723 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7725 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7727 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7729 DEBUG(10,("smb_set_info_standard: file %s\n",
7730 smb_fname_str_dbg(smb_fname)));
7732 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7733 if (!NT_STATUS_IS_OK(status)) {
7737 return smb_set_file_time(conn,
7744 /****************************************************************************
7745 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7746 ****************************************************************************/
7748 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7749 struct smb_request *req,
7753 struct smb_filename *smb_fname)
7755 uint64_t allocation_size = 0;
7756 NTSTATUS status = NT_STATUS_OK;
7757 files_struct *new_fsp = NULL;
7759 if (!VALID_STAT(smb_fname->st)) {
7760 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7763 if (total_data < 8) {
7764 return NT_STATUS_INVALID_PARAMETER;
7767 allocation_size = (uint64_t)IVAL(pdata,0);
7768 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7769 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7770 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7771 (double)allocation_size));
7773 if (allocation_size) {
7774 allocation_size = smb_roundup(conn, allocation_size);
7777 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7778 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7779 (double)allocation_size));
7781 if (fsp && fsp->fh->fd != -1) {
7782 /* Open file handle. */
7783 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7784 return NT_STATUS_ACCESS_DENIED;
7787 /* Only change if needed. */
7788 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7789 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7790 return map_nt_error_from_unix(errno);
7793 /* But always update the time. */
7795 * This is equivalent to a write. Ensure it's seen immediately
7796 * if there are no pending writes.
7798 trigger_write_time_update_immediate(fsp);
7799 return NT_STATUS_OK;
7802 /* Pathname or stat or directory file. */
7803 status = SMB_VFS_CREATE_FILE(
7806 0, /* root_dir_fid */
7807 smb_fname, /* fname */
7808 FILE_WRITE_DATA, /* access_mask */
7809 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7811 FILE_OPEN, /* create_disposition*/
7812 0, /* create_options */
7813 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7814 0, /* oplock_request */
7816 0, /* allocation_size */
7817 0, /* private_flags */
7820 &new_fsp, /* result */
7822 NULL, NULL); /* create context */
7824 if (!NT_STATUS_IS_OK(status)) {
7825 /* NB. We check for open_was_deferred in the caller. */
7829 /* Only change if needed. */
7830 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7831 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7832 status = map_nt_error_from_unix(errno);
7833 close_file(req, new_fsp, NORMAL_CLOSE);
7838 /* Changing the allocation size should set the last mod time. */
7840 * This is equivalent to a write. Ensure it's seen immediately
7841 * if there are no pending writes.
7843 trigger_write_time_update_immediate(new_fsp);
7844 close_file(req, new_fsp, NORMAL_CLOSE);
7845 return NT_STATUS_OK;
7848 /****************************************************************************
7849 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7850 ****************************************************************************/
7852 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7853 struct smb_request *req,
7857 const struct smb_filename *smb_fname,
7858 bool fail_after_createfile)
7862 if (total_data < 8) {
7863 return NT_STATUS_INVALID_PARAMETER;
7866 size = IVAL(pdata,0);
7867 size |= (((off_t)IVAL(pdata,4)) << 32);
7868 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7869 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7872 return smb_set_file_size(conn, req,
7877 fail_after_createfile);
7880 /****************************************************************************
7881 Allow a UNIX info mknod.
7882 ****************************************************************************/
7884 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7887 const struct smb_filename *smb_fname)
7889 uint32_t file_type = IVAL(pdata,56);
7890 #if defined(HAVE_MAKEDEV)
7891 uint32_t dev_major = IVAL(pdata,60);
7892 uint32_t dev_minor = IVAL(pdata,68);
7894 SMB_DEV_T dev = (SMB_DEV_T)0;
7895 uint32_t raw_unixmode = IVAL(pdata,84);
7899 if (total_data < 100) {
7900 return NT_STATUS_INVALID_PARAMETER;
7903 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7904 PERM_NEW_FILE, &unixmode);
7905 if (!NT_STATUS_IS_OK(status)) {
7909 #if defined(HAVE_MAKEDEV)
7910 dev = makedev(dev_major, dev_minor);
7913 switch (file_type) {
7914 #if defined(S_IFIFO)
7915 case UNIX_TYPE_FIFO:
7916 unixmode |= S_IFIFO;
7919 #if defined(S_IFSOCK)
7920 case UNIX_TYPE_SOCKET:
7921 unixmode |= S_IFSOCK;
7924 #if defined(S_IFCHR)
7925 case UNIX_TYPE_CHARDEV:
7926 unixmode |= S_IFCHR;
7929 #if defined(S_IFBLK)
7930 case UNIX_TYPE_BLKDEV:
7931 unixmode |= S_IFBLK;
7935 return NT_STATUS_INVALID_PARAMETER;
7938 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7939 "%.0f mode 0%o for file %s\n", (double)dev,
7940 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7942 /* Ok - do the mknod. */
7943 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7944 return map_nt_error_from_unix(errno);
7947 /* If any of the other "set" calls fail we
7948 * don't want to end up with a half-constructed mknod.
7951 if (lp_inherit_permissions(SNUM(conn))) {
7953 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7955 return NT_STATUS_NO_MEMORY;
7957 inherit_access_posix_acl(conn, parent, smb_fname,
7959 TALLOC_FREE(parent);
7962 return NT_STATUS_OK;
7965 /****************************************************************************
7966 Deal with SMB_SET_FILE_UNIX_BASIC.
7967 ****************************************************************************/
7969 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7970 struct smb_request *req,
7974 const struct smb_filename *smb_fname)
7976 struct smb_file_time ft;
7977 uint32_t raw_unixmode;
7980 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7981 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7982 NTSTATUS status = NT_STATUS_OK;
7983 bool delete_on_fail = False;
7984 enum perm_type ptype;
7985 files_struct *all_fsps = NULL;
7986 bool modify_mtime = true;
7988 struct smb_filename *smb_fname_tmp = NULL;
7989 SMB_STRUCT_STAT sbuf;
7993 if (total_data < 100) {
7994 return NT_STATUS_INVALID_PARAMETER;
7997 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7998 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7999 size=IVAL(pdata,0); /* first 8 Bytes are size */
8000 size |= (((off_t)IVAL(pdata,4)) << 32);
8003 ft.atime = interpret_long_date(pdata+24); /* access_time */
8004 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
8005 set_owner = (uid_t)IVAL(pdata,40);
8006 set_grp = (gid_t)IVAL(pdata,48);
8007 raw_unixmode = IVAL(pdata,84);
8009 if (VALID_STAT(smb_fname->st)) {
8010 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8011 ptype = PERM_EXISTING_DIR;
8013 ptype = PERM_EXISTING_FILE;
8016 ptype = PERM_NEW_FILE;
8019 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8021 if (!NT_STATUS_IS_OK(status)) {
8025 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8026 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8027 smb_fname_str_dbg(smb_fname), (double)size,
8028 (unsigned int)set_owner, (unsigned int)set_grp,
8029 (int)raw_unixmode));
8031 sbuf = smb_fname->st;
8033 if (!VALID_STAT(sbuf)) {
8035 * The only valid use of this is to create character and block
8036 * devices, and named pipes. This is deprecated (IMHO) and
8037 * a new info level should be used for mknod. JRA.
8040 status = smb_unix_mknod(conn,
8044 if (!NT_STATUS_IS_OK(status)) {
8048 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
8049 if (smb_fname_tmp == NULL) {
8050 return NT_STATUS_NO_MEMORY;
8053 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
8054 status = map_nt_error_from_unix(errno);
8055 TALLOC_FREE(smb_fname_tmp);
8056 SMB_VFS_UNLINK(conn, smb_fname);
8060 sbuf = smb_fname_tmp->st;
8061 smb_fname = smb_fname_tmp;
8063 /* Ensure we don't try and change anything else. */
8064 raw_unixmode = SMB_MODE_NO_CHANGE;
8065 size = get_file_size_stat(&sbuf);
8066 ft.atime = sbuf.st_ex_atime;
8067 ft.mtime = sbuf.st_ex_mtime;
8069 * We continue here as we might want to change the
8072 delete_on_fail = True;
8076 /* Horrible backwards compatibility hack as an old server bug
8077 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8081 size = get_file_size_stat(&sbuf);
8086 * Deal with the UNIX specific mode set.
8089 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8092 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8093 "setting mode 0%o for file %s\n",
8094 (unsigned int)unixmode,
8095 smb_fname_str_dbg(smb_fname)));
8096 if (fsp && fsp->fh->fd != -1) {
8097 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8099 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8102 return map_nt_error_from_unix(errno);
8107 * Deal with the UNIX specific uid set.
8110 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8111 (sbuf.st_ex_uid != set_owner)) {
8114 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8115 "changing owner %u for path %s\n",
8116 (unsigned int)set_owner,
8117 smb_fname_str_dbg(smb_fname)));
8119 if (fsp && fsp->fh->fd != -1) {
8120 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8123 * UNIX extensions calls must always operate
8126 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8127 set_owner, (gid_t)-1);
8131 status = map_nt_error_from_unix(errno);
8132 if (delete_on_fail) {
8133 SMB_VFS_UNLINK(conn, smb_fname);
8140 * Deal with the UNIX specific gid set.
8143 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8144 (sbuf.st_ex_gid != set_grp)) {
8147 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8148 "changing group %u for file %s\n",
8149 (unsigned int)set_grp,
8150 smb_fname_str_dbg(smb_fname)));
8151 if (fsp && fsp->fh->fd != -1) {
8152 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8155 * UNIX extensions calls must always operate
8158 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8162 status = map_nt_error_from_unix(errno);
8163 if (delete_on_fail) {
8164 SMB_VFS_UNLINK(conn, smb_fname);
8170 /* Deal with any size changes. */
8172 status = smb_set_file_size(conn, req,
8178 if (!NT_STATUS_IS_OK(status)) {
8182 /* Deal with any time changes. */
8183 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
8184 /* No change, don't cancel anything. */
8188 id = vfs_file_id_from_sbuf(conn, &sbuf);
8189 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8190 all_fsps = file_find_di_next(all_fsps)) {
8192 * We're setting the time explicitly for UNIX.
8193 * Cancel any pending changes over all handles.
8195 all_fsps->update_write_time_on_close = false;
8196 TALLOC_FREE(all_fsps->update_write_time_event);
8200 * Override the "setting_write_time"
8201 * parameter here as it almost does what
8202 * we need. Just remember if we modified
8203 * mtime and send the notify ourselves.
8205 if (null_timespec(ft.mtime)) {
8206 modify_mtime = false;
8209 status = smb_set_file_time(conn,
8215 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8216 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8221 /****************************************************************************
8222 Deal with SMB_SET_FILE_UNIX_INFO2.
8223 ****************************************************************************/
8225 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8226 struct smb_request *req,
8230 const struct smb_filename *smb_fname)
8233 uint32_t smb_fflags;
8236 if (total_data < 116) {
8237 return NT_STATUS_INVALID_PARAMETER;
8240 /* Start by setting all the fields that are common between UNIX_BASIC
8243 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8245 if (!NT_STATUS_IS_OK(status)) {
8249 smb_fflags = IVAL(pdata, 108);
8250 smb_fmask = IVAL(pdata, 112);
8252 /* NB: We should only attempt to alter the file flags if the client
8253 * sends a non-zero mask.
8255 if (smb_fmask != 0) {
8256 int stat_fflags = 0;
8258 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8259 smb_fmask, &stat_fflags)) {
8260 /* Client asked to alter a flag we don't understand. */
8261 return NT_STATUS_INVALID_PARAMETER;
8264 if (fsp && fsp->fh->fd != -1) {
8265 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8266 return NT_STATUS_NOT_SUPPORTED;
8268 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8269 stat_fflags) != 0) {
8270 return map_nt_error_from_unix(errno);
8275 /* XXX: need to add support for changing the create_time here. You
8276 * can do this for paths on Darwin with setattrlist(2). The right way
8277 * to hook this up is probably by extending the VFS utimes interface.
8280 return NT_STATUS_OK;
8283 /****************************************************************************
8284 Create a directory with POSIX semantics.
8285 ****************************************************************************/
8287 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8288 struct smb_request *req,
8291 struct smb_filename *smb_fname,
8292 int *pdata_return_size)
8294 NTSTATUS status = NT_STATUS_OK;
8295 uint32_t raw_unixmode = 0;
8296 uint32_t mod_unixmode = 0;
8297 mode_t unixmode = (mode_t)0;
8298 files_struct *fsp = NULL;
8299 uint16_t info_level_return = 0;
8301 char *pdata = *ppdata;
8303 if (total_data < 18) {
8304 return NT_STATUS_INVALID_PARAMETER;
8307 raw_unixmode = IVAL(pdata,8);
8308 /* Next 4 bytes are not yet defined. */
8310 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8311 PERM_NEW_DIR, &unixmode);
8312 if (!NT_STATUS_IS_OK(status)) {
8316 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8318 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8319 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8321 status = SMB_VFS_CREATE_FILE(
8324 0, /* root_dir_fid */
8325 smb_fname, /* fname */
8326 FILE_READ_ATTRIBUTES, /* access_mask */
8327 FILE_SHARE_NONE, /* share_access */
8328 FILE_CREATE, /* create_disposition*/
8329 FILE_DIRECTORY_FILE, /* create_options */
8330 mod_unixmode, /* file_attributes */
8331 0, /* oplock_request */
8333 0, /* allocation_size */
8334 0, /* private_flags */
8339 NULL, NULL); /* create context */
8341 if (NT_STATUS_IS_OK(status)) {
8342 close_file(req, fsp, NORMAL_CLOSE);
8345 info_level_return = SVAL(pdata,16);
8347 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8348 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8349 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8350 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8352 *pdata_return_size = 12;
8355 /* Realloc the data size */
8356 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8357 if (*ppdata == NULL) {
8358 *pdata_return_size = 0;
8359 return NT_STATUS_NO_MEMORY;
8363 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8364 SSVAL(pdata,2,0); /* No fnum. */
8365 SIVAL(pdata,4,info); /* Was directory created. */
8367 switch (info_level_return) {
8368 case SMB_QUERY_FILE_UNIX_BASIC:
8369 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8370 SSVAL(pdata,10,0); /* Padding. */
8371 store_file_unix_basic(conn, pdata + 12, fsp,
8374 case SMB_QUERY_FILE_UNIX_INFO2:
8375 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8376 SSVAL(pdata,10,0); /* Padding. */
8377 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8381 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8382 SSVAL(pdata,10,0); /* Padding. */
8389 /****************************************************************************
8390 Open/Create a file with POSIX semantics.
8391 ****************************************************************************/
8393 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8394 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8396 static NTSTATUS smb_posix_open(connection_struct *conn,
8397 struct smb_request *req,
8400 struct smb_filename *smb_fname,
8401 int *pdata_return_size)
8403 bool extended_oplock_granted = False;
8404 char *pdata = *ppdata;
8406 uint32_t wire_open_mode = 0;
8407 uint32_t raw_unixmode = 0;
8408 uint32_t mod_unixmode = 0;
8409 uint32_t create_disp = 0;
8410 uint32_t access_mask = 0;
8411 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8412 NTSTATUS status = NT_STATUS_OK;
8413 mode_t unixmode = (mode_t)0;
8414 files_struct *fsp = NULL;
8415 int oplock_request = 0;
8417 uint16_t info_level_return = 0;
8419 if (total_data < 18) {
8420 return NT_STATUS_INVALID_PARAMETER;
8423 flags = IVAL(pdata,0);
8424 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8425 if (oplock_request) {
8426 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8429 wire_open_mode = IVAL(pdata,4);
8431 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8432 return smb_posix_mkdir(conn, req,
8439 switch (wire_open_mode & SMB_ACCMODE) {
8441 access_mask = SMB_O_RDONLY_MAPPING;
8444 access_mask = SMB_O_WRONLY_MAPPING;
8447 access_mask = (SMB_O_RDONLY_MAPPING|
8448 SMB_O_WRONLY_MAPPING);
8451 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8452 (unsigned int)wire_open_mode ));
8453 return NT_STATUS_INVALID_PARAMETER;
8456 wire_open_mode &= ~SMB_ACCMODE;
8458 /* First take care of O_CREAT|O_EXCL interactions. */
8459 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8460 case (SMB_O_CREAT | SMB_O_EXCL):
8461 /* File exists fail. File not exist create. */
8462 create_disp = FILE_CREATE;
8465 /* File exists open. File not exist create. */
8466 create_disp = FILE_OPEN_IF;
8469 /* O_EXCL on its own without O_CREAT is undefined.
8470 We deliberately ignore it as some versions of
8471 Linux CIFSFS can send a bare O_EXCL on the
8472 wire which other filesystems in the kernel
8473 ignore. See bug 9519 for details. */
8478 /* File exists open. File not exist fail. */
8479 create_disp = FILE_OPEN;
8482 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8483 (unsigned int)wire_open_mode ));
8484 return NT_STATUS_INVALID_PARAMETER;
8487 /* Next factor in the effects of O_TRUNC. */
8488 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8490 if (wire_open_mode & SMB_O_TRUNC) {
8491 switch (create_disp) {
8493 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8494 /* Leave create_disp alone as
8495 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8497 /* File exists fail. File not exist create. */
8500 /* SMB_O_CREAT | SMB_O_TRUNC */
8501 /* File exists overwrite. File not exist create. */
8502 create_disp = FILE_OVERWRITE_IF;
8506 /* File exists overwrite. File not exist fail. */
8507 create_disp = FILE_OVERWRITE;
8510 /* Cannot get here. */
8511 smb_panic("smb_posix_open: logic error");
8512 return NT_STATUS_INVALID_PARAMETER;
8516 raw_unixmode = IVAL(pdata,8);
8517 /* Next 4 bytes are not yet defined. */
8519 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8520 (VALID_STAT(smb_fname->st) ?
8521 PERM_EXISTING_FILE : PERM_NEW_FILE),
8524 if (!NT_STATUS_IS_OK(status)) {
8528 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8530 if (wire_open_mode & SMB_O_SYNC) {
8531 create_options |= FILE_WRITE_THROUGH;
8533 if (wire_open_mode & SMB_O_APPEND) {
8534 access_mask |= FILE_APPEND_DATA;
8536 if (wire_open_mode & SMB_O_DIRECT) {
8537 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8540 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8541 VALID_STAT_OF_DIR(smb_fname->st)) {
8542 if (access_mask != SMB_O_RDONLY_MAPPING) {
8543 return NT_STATUS_FILE_IS_A_DIRECTORY;
8545 create_options &= ~FILE_NON_DIRECTORY_FILE;
8546 create_options |= FILE_DIRECTORY_FILE;
8549 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8550 smb_fname_str_dbg(smb_fname),
8551 (unsigned int)wire_open_mode,
8552 (unsigned int)unixmode ));
8554 status = SMB_VFS_CREATE_FILE(
8557 0, /* root_dir_fid */
8558 smb_fname, /* fname */
8559 access_mask, /* access_mask */
8560 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8562 create_disp, /* create_disposition*/
8563 create_options, /* create_options */
8564 mod_unixmode, /* file_attributes */
8565 oplock_request, /* oplock_request */
8567 0, /* allocation_size */
8568 0, /* private_flags */
8573 NULL, NULL); /* create context */
8575 if (!NT_STATUS_IS_OK(status)) {
8579 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8580 extended_oplock_granted = True;
8583 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8584 extended_oplock_granted = True;
8587 info_level_return = SVAL(pdata,16);
8589 /* Allocate the correct return size. */
8591 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8592 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8593 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8594 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8596 *pdata_return_size = 12;
8599 /* Realloc the data size */
8600 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8601 if (*ppdata == NULL) {
8602 close_file(req, fsp, ERROR_CLOSE);
8603 *pdata_return_size = 0;
8604 return NT_STATUS_NO_MEMORY;
8608 if (extended_oplock_granted) {
8609 if (flags & REQUEST_BATCH_OPLOCK) {
8610 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8612 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8614 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8615 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8617 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8620 SSVAL(pdata,2,fsp->fnum);
8621 SIVAL(pdata,4,info); /* Was file created etc. */
8623 switch (info_level_return) {
8624 case SMB_QUERY_FILE_UNIX_BASIC:
8625 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8626 SSVAL(pdata,10,0); /* padding. */
8627 store_file_unix_basic(conn, pdata + 12, fsp,
8630 case SMB_QUERY_FILE_UNIX_INFO2:
8631 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8632 SSVAL(pdata,10,0); /* padding. */
8633 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8637 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8638 SSVAL(pdata,10,0); /* padding. */
8641 return NT_STATUS_OK;
8644 /****************************************************************************
8645 Delete a file with POSIX semantics.
8646 ****************************************************************************/
8648 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8649 struct smb_request *req,
8652 struct smb_filename *smb_fname)
8654 struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
8655 NTSTATUS status = NT_STATUS_OK;
8656 files_struct *fsp = NULL;
8660 int create_options = 0;
8661 struct share_mode_lock *lck = NULL;
8662 bool other_nonposix_opens;
8664 if (total_data < 2) {
8665 return NT_STATUS_INVALID_PARAMETER;
8668 flags = SVAL(pdata,0);
8670 if (!VALID_STAT(smb_fname->st)) {
8671 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8674 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8675 !VALID_STAT_OF_DIR(smb_fname->st)) {
8676 return NT_STATUS_NOT_A_DIRECTORY;
8679 DEBUG(10,("smb_posix_unlink: %s %s\n",
8680 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8681 smb_fname_str_dbg(smb_fname)));
8683 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8684 create_options |= FILE_DIRECTORY_FILE;
8687 status = SMB_VFS_CREATE_FILE(
8690 0, /* root_dir_fid */
8691 smb_fname, /* fname */
8692 DELETE_ACCESS, /* access_mask */
8693 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8695 FILE_OPEN, /* create_disposition*/
8696 create_options, /* create_options */
8697 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8698 0, /* oplock_request */
8700 0, /* allocation_size */
8701 0, /* private_flags */
8706 NULL, NULL); /* create context */
8708 if (!NT_STATUS_IS_OK(status)) {
8713 * Don't lie to client. If we can't really delete due to
8714 * non-POSIX opens return SHARING_VIOLATION.
8717 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8719 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8720 "lock for file %s\n", fsp_str_dbg(fsp)));
8721 close_file(req, fsp, NORMAL_CLOSE);
8722 return NT_STATUS_INVALID_PARAMETER;
8725 other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
8726 if (other_nonposix_opens) {
8727 /* Fail with sharing violation. */
8729 close_file(req, fsp, NORMAL_CLOSE);
8730 return NT_STATUS_SHARING_VIOLATION;
8734 * Set the delete on close.
8736 status = smb_set_file_disposition_info(conn,
8744 if (!NT_STATUS_IS_OK(status)) {
8745 close_file(req, fsp, NORMAL_CLOSE);
8748 return close_file(req, fsp, NORMAL_CLOSE);
8751 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8752 struct smb_request *req,
8753 TALLOC_CTX *mem_ctx,
8754 uint16_t info_level,
8756 struct smb_filename *smb_fname,
8757 char **ppdata, int total_data,
8760 char *pdata = *ppdata;
8761 NTSTATUS status = NT_STATUS_OK;
8762 int data_return_size = 0;
8766 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8767 return NT_STATUS_INVALID_LEVEL;
8770 if (!CAN_WRITE(conn)) {
8771 /* Allow POSIX opens. The open path will deny
8772 * any non-readonly opens. */
8773 if (info_level != SMB_POSIX_PATH_OPEN) {
8774 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8778 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8779 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8781 info_level, total_data));
8783 switch (info_level) {
8785 case SMB_INFO_STANDARD:
8787 status = smb_set_info_standard(conn,
8795 case SMB_INFO_SET_EA:
8797 status = smb_info_set_ea(conn,
8805 case SMB_SET_FILE_BASIC_INFO:
8806 case SMB_FILE_BASIC_INFORMATION:
8808 status = smb_set_file_basic_info(conn,
8816 case SMB_FILE_ALLOCATION_INFORMATION:
8817 case SMB_SET_FILE_ALLOCATION_INFO:
8819 status = smb_set_file_allocation_info(conn, req,
8827 case SMB_FILE_END_OF_FILE_INFORMATION:
8828 case SMB_SET_FILE_END_OF_FILE_INFO:
8831 * XP/Win7 both fail after the createfile with
8832 * SMB_SET_FILE_END_OF_FILE_INFO but not
8833 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8834 * The level is known here, so pass it down
8838 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8840 status = smb_set_file_end_of_file_info(conn, req,
8849 case SMB_FILE_DISPOSITION_INFORMATION:
8850 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8853 /* JRA - We used to just ignore this on a path ?
8854 * Shouldn't this be invalid level on a pathname
8857 if (tran_call != TRANSACT2_SETFILEINFO) {
8858 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8861 status = smb_set_file_disposition_info(conn,
8869 case SMB_FILE_POSITION_INFORMATION:
8871 status = smb_file_position_information(conn,
8878 case SMB_FILE_FULL_EA_INFORMATION:
8880 status = smb_set_file_full_ea_info(conn,
8887 /* From tridge Samba4 :
8888 * MODE_INFORMATION in setfileinfo (I have no
8889 * idea what "mode information" on a file is - it takes a value of 0,
8890 * 2, 4 or 6. What could it be?).
8893 case SMB_FILE_MODE_INFORMATION:
8895 status = smb_file_mode_information(conn,
8901 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8902 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8903 case SMB_FILE_SHORT_NAME_INFORMATION:
8904 return NT_STATUS_NOT_SUPPORTED;
8907 * CIFS UNIX extensions.
8910 case SMB_SET_FILE_UNIX_BASIC:
8912 status = smb_set_file_unix_basic(conn, req,
8920 case SMB_SET_FILE_UNIX_INFO2:
8922 status = smb_set_file_unix_info2(conn, req,
8930 case SMB_SET_FILE_UNIX_LINK:
8933 /* We must have a pathname for this. */
8934 return NT_STATUS_INVALID_LEVEL;
8936 status = smb_set_file_unix_link(conn, req, pdata,
8937 total_data, smb_fname);
8941 case SMB_SET_FILE_UNIX_HLINK:
8944 /* We must have a pathname for this. */
8945 return NT_STATUS_INVALID_LEVEL;
8947 status = smb_set_file_unix_hlink(conn, req,
8953 case SMB_FILE_RENAME_INFORMATION:
8955 status = smb_file_rename_information(conn, req,
8961 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8963 /* SMB2 rename information. */
8964 status = smb2_file_rename_information(conn, req,
8970 case SMB_FILE_LINK_INFORMATION:
8972 status = smb_file_link_information(conn, req,
8978 #if defined(HAVE_POSIX_ACLS)
8979 case SMB_SET_POSIX_ACL:
8981 status = smb_set_posix_acl(conn,
8991 case SMB_SET_POSIX_LOCK:
8994 return NT_STATUS_INVALID_LEVEL;
8996 status = smb_set_posix_lock(conn, req,
8997 pdata, total_data, fsp);
9001 case SMB_POSIX_PATH_OPEN:
9004 /* We must have a pathname for this. */
9005 return NT_STATUS_INVALID_LEVEL;
9008 status = smb_posix_open(conn, req,
9016 case SMB_POSIX_PATH_UNLINK:
9019 /* We must have a pathname for this. */
9020 return NT_STATUS_INVALID_LEVEL;
9023 status = smb_posix_unlink(conn, req,
9031 return NT_STATUS_INVALID_LEVEL;
9034 if (!NT_STATUS_IS_OK(status)) {
9038 *ret_data_size = data_return_size;
9039 return NT_STATUS_OK;
9042 /****************************************************************************
9043 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9044 ****************************************************************************/
9046 static void call_trans2setfilepathinfo(connection_struct *conn,
9047 struct smb_request *req,
9048 unsigned int tran_call,
9049 char **pparams, int total_params,
9050 char **ppdata, int total_data,
9051 unsigned int max_data_bytes)
9053 char *params = *pparams;
9054 char *pdata = *ppdata;
9055 uint16_t info_level;
9056 struct smb_filename *smb_fname = NULL;
9057 files_struct *fsp = NULL;
9058 NTSTATUS status = NT_STATUS_OK;
9059 int data_return_size = 0;
9062 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9066 if (tran_call == TRANSACT2_SETFILEINFO) {
9067 if (total_params < 4) {
9068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9072 fsp = file_fsp(req, SVAL(params,0));
9073 /* Basic check for non-null fsp. */
9074 if (!check_fsp_open(conn, req, fsp)) {
9077 info_level = SVAL(params,2);
9079 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9080 if (smb_fname == NULL) {
9081 reply_nterror(req, NT_STATUS_NO_MEMORY);
9085 if(fsp->fh->fd == -1) {
9087 * This is actually a SETFILEINFO on a directory
9088 * handle (returned from an NT SMB). NT5.0 seems
9089 * to do this call. JRA.
9091 if (INFO_LEVEL_IS_UNIX(info_level)) {
9092 /* Always do lstat for UNIX calls. */
9093 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9094 DEBUG(3,("call_trans2setfilepathinfo: "
9095 "SMB_VFS_LSTAT of %s failed "
9097 smb_fname_str_dbg(smb_fname),
9099 reply_nterror(req, map_nt_error_from_unix(errno));
9103 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9104 DEBUG(3,("call_trans2setfilepathinfo: "
9105 "fileinfo of %s failed (%s)\n",
9106 smb_fname_str_dbg(smb_fname),
9108 reply_nterror(req, map_nt_error_from_unix(errno));
9112 } else if (fsp->print_file) {
9114 * Doing a DELETE_ON_CLOSE should cancel a print job.
9116 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9117 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9119 DEBUG(3,("call_trans2setfilepathinfo: "
9120 "Cancelling print job (%s)\n",
9124 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9130 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9135 * Original code - this is an open file.
9137 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9138 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9139 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9141 reply_nterror(req, map_nt_error_from_unix(errno));
9147 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9150 if (total_params < 7) {
9151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9155 info_level = SVAL(params,0);
9156 if (req->posix_pathnames) {
9157 srvstr_get_path_posix(req,
9166 srvstr_get_path(req,
9175 if (!NT_STATUS_IS_OK(status)) {
9176 reply_nterror(req, status);
9180 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9181 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9182 info_level == SMB_FILE_RENAME_INFORMATION ||
9183 info_level == SMB_POSIX_PATH_OPEN ||
9184 info_level == SMB_POSIX_PATH_UNLINK) {
9185 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9188 status = filename_convert(req, conn,
9194 if (!NT_STATUS_IS_OK(status)) {
9195 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9196 reply_botherror(req,
9197 NT_STATUS_PATH_NOT_COVERED,
9198 ERRSRV, ERRbadpath);
9201 reply_nterror(req, status);
9205 if (INFO_LEVEL_IS_UNIX(info_level)) {
9207 * For CIFS UNIX extensions the target name may not exist.
9210 /* Always do lstat for UNIX calls. */
9211 SMB_VFS_LSTAT(conn, smb_fname);
9213 } else if (!VALID_STAT(smb_fname->st) &&
9214 SMB_VFS_STAT(conn, smb_fname)) {
9215 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9217 smb_fname_str_dbg(smb_fname),
9219 reply_nterror(req, map_nt_error_from_unix(errno));
9224 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9225 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9227 info_level,total_data));
9229 /* Realloc the parameter size */
9230 *pparams = (char *)SMB_REALLOC(*pparams,2);
9231 if (*pparams == NULL) {
9232 reply_nterror(req, NT_STATUS_NO_MEMORY);
9239 status = smbd_do_setfilepathinfo(conn, req, req,
9245 if (!NT_STATUS_IS_OK(status)) {
9246 if (open_was_deferred(req->xconn, req->mid)) {
9247 /* We have re-scheduled this call. */
9250 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9251 /* We have re-scheduled this call. */
9254 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9255 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9256 ERRSRV, ERRbadpath);
9259 if (info_level == SMB_POSIX_PATH_OPEN) {
9260 reply_openerror(req, status);
9265 * Invalid EA name needs to return 2 param bytes,
9266 * not a zero-length error packet.
9268 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9269 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9272 reply_nterror(req, status);
9277 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9283 /****************************************************************************
9284 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9285 ****************************************************************************/
9287 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9288 char **pparams, int total_params,
9289 char **ppdata, int total_data,
9290 unsigned int max_data_bytes)
9292 struct smb_filename *smb_dname = NULL;
9293 char *params = *pparams;
9294 char *pdata = *ppdata;
9295 char *directory = NULL;
9296 NTSTATUS status = NT_STATUS_OK;
9297 struct ea_list *ea_list = NULL;
9298 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9299 TALLOC_CTX *ctx = talloc_tos();
9301 if (!CAN_WRITE(conn)) {
9302 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9306 if (total_params < 5) {
9307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9311 if (req->posix_pathnames) {
9312 srvstr_get_path_posix(ctx,
9321 srvstr_get_path(ctx,
9330 if (!NT_STATUS_IS_OK(status)) {
9331 reply_nterror(req, status);
9335 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9337 status = filename_convert(ctx,
9345 if (!NT_STATUS_IS_OK(status)) {
9346 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9347 reply_botherror(req,
9348 NT_STATUS_PATH_NOT_COVERED,
9349 ERRSRV, ERRbadpath);
9352 reply_nterror(req, status);
9357 * OS/2 workplace shell seems to send SET_EA requests of "null"
9358 * length (4 bytes containing IVAL 4).
9359 * They seem to have no effect. Bug #3212. JRA.
9362 if (total_data && (total_data != 4)) {
9363 /* Any data in this call is an EA list. */
9364 if (total_data < 10) {
9365 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9369 if (IVAL(pdata,0) > total_data) {
9370 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9371 IVAL(pdata,0), (unsigned int)total_data));
9372 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9376 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9379 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9383 if (!lp_ea_support(SNUM(conn))) {
9384 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9388 /* If total_data == 4 Windows doesn't care what values
9389 * are placed in that field, it just ignores them.
9390 * The System i QNTC IBM SMB client puts bad values here,
9391 * so ignore them. */
9393 status = create_directory(conn, req, smb_dname);
9395 if (!NT_STATUS_IS_OK(status)) {
9396 reply_nterror(req, status);
9400 /* Try and set any given EA. */
9402 status = set_ea(conn, NULL, smb_dname, ea_list);
9403 if (!NT_STATUS_IS_OK(status)) {
9404 reply_nterror(req, status);
9409 /* Realloc the parameter and data sizes */
9410 *pparams = (char *)SMB_REALLOC(*pparams,2);
9411 if(*pparams == NULL) {
9412 reply_nterror(req, NT_STATUS_NO_MEMORY);
9419 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9422 TALLOC_FREE(smb_dname);
9426 /****************************************************************************
9427 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9428 We don't actually do this - we just send a null response.
9429 ****************************************************************************/
9431 static void call_trans2findnotifyfirst(connection_struct *conn,
9432 struct smb_request *req,
9433 char **pparams, int total_params,
9434 char **ppdata, int total_data,
9435 unsigned int max_data_bytes)
9437 char *params = *pparams;
9438 uint16_t info_level;
9440 if (total_params < 6) {
9441 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9445 info_level = SVAL(params,4);
9446 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9448 switch (info_level) {
9453 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9457 /* Realloc the parameter and data sizes */
9458 *pparams = (char *)SMB_REALLOC(*pparams,6);
9459 if (*pparams == NULL) {
9460 reply_nterror(req, NT_STATUS_NO_MEMORY);
9465 SSVAL(params,0,fnf_handle);
9466 SSVAL(params,2,0); /* No changes */
9467 SSVAL(params,4,0); /* No EA errors */
9474 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9479 /****************************************************************************
9480 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9481 changes). Currently this does nothing.
9482 ****************************************************************************/
9484 static void call_trans2findnotifynext(connection_struct *conn,
9485 struct smb_request *req,
9486 char **pparams, int total_params,
9487 char **ppdata, int total_data,
9488 unsigned int max_data_bytes)
9490 char *params = *pparams;
9492 DEBUG(3,("call_trans2findnotifynext\n"));
9494 /* Realloc the parameter and data sizes */
9495 *pparams = (char *)SMB_REALLOC(*pparams,4);
9496 if (*pparams == NULL) {
9497 reply_nterror(req, NT_STATUS_NO_MEMORY);
9502 SSVAL(params,0,0); /* No changes */
9503 SSVAL(params,2,0); /* No EA errors */
9505 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9510 /****************************************************************************
9511 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9512 ****************************************************************************/
9514 static void call_trans2getdfsreferral(connection_struct *conn,
9515 struct smb_request *req,
9516 char **pparams, int total_params,
9517 char **ppdata, int total_data,
9518 unsigned int max_data_bytes)
9520 char *params = *pparams;
9521 char *pathname = NULL;
9523 int max_referral_level;
9524 NTSTATUS status = NT_STATUS_OK;
9525 TALLOC_CTX *ctx = talloc_tos();
9527 DEBUG(10,("call_trans2getdfsreferral\n"));
9529 if (total_params < 3) {
9530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9534 max_referral_level = SVAL(params,0);
9536 if(!lp_host_msdfs()) {
9537 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9541 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9542 total_params - 2, STR_TERMINATE);
9544 reply_nterror(req, NT_STATUS_NOT_FOUND);
9547 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9548 ppdata,&status)) < 0) {
9549 reply_nterror(req, status);
9553 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9554 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9555 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9560 #define LMCAT_SPL 0x53
9561 #define LMFUNC_GETJOBID 0x60
9563 /****************************************************************************
9564 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9565 ****************************************************************************/
9567 static void call_trans2ioctl(connection_struct *conn,
9568 struct smb_request *req,
9569 char **pparams, int total_params,
9570 char **ppdata, int total_data,
9571 unsigned int max_data_bytes)
9573 char *pdata = *ppdata;
9574 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9578 /* check for an invalid fid before proceeding */
9581 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9585 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9586 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9587 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9588 if (*ppdata == NULL) {
9589 reply_nterror(req, NT_STATUS_NO_MEMORY);
9594 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9595 CAN ACCEPT THIS IN UNICODE. JRA. */
9598 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9600 status = srvstr_push(pdata, req->flags2, pdata + 2,
9601 lp_netbios_name(), 15,
9602 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9603 if (!NT_STATUS_IS_OK(status)) {
9604 reply_nterror(req, status);
9607 status = srvstr_push(pdata, req->flags2, pdata+18,
9608 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9609 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9610 if (!NT_STATUS_IS_OK(status)) {
9611 reply_nterror(req, status);
9614 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9619 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9620 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9623 /****************************************************************************
9624 Reply to a SMBfindclose (stop trans2 directory search).
9625 ****************************************************************************/
9627 void reply_findclose(struct smb_request *req)
9630 struct smbd_server_connection *sconn = req->sconn;
9632 START_PROFILE(SMBfindclose);
9635 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9636 END_PROFILE(SMBfindclose);
9640 dptr_num = SVALS(req->vwv+0, 0);
9642 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9644 dptr_close(sconn, &dptr_num);
9646 reply_outbuf(req, 0, 0);
9648 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9650 END_PROFILE(SMBfindclose);
9654 /****************************************************************************
9655 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9656 ****************************************************************************/
9658 void reply_findnclose(struct smb_request *req)
9662 START_PROFILE(SMBfindnclose);
9665 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9666 END_PROFILE(SMBfindnclose);
9670 dptr_num = SVAL(req->vwv+0, 0);
9672 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9674 /* We never give out valid handles for a
9675 findnotifyfirst - so any dptr_num is ok here.
9678 reply_outbuf(req, 0, 0);
9680 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9682 END_PROFILE(SMBfindnclose);
9686 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9687 struct trans_state *state)
9689 if (get_Protocol() >= PROTOCOL_NT1) {
9690 req->flags2 |= 0x40; /* IS_LONG_NAME */
9691 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9694 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9695 if (state->call != TRANSACT2_QFSINFO &&
9696 state->call != TRANSACT2_SETFSINFO) {
9697 DEBUG(0,("handle_trans2: encryption required "
9699 (unsigned int)state->call));
9700 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9705 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9707 /* Now we must call the relevant TRANS2 function */
9708 switch(state->call) {
9709 case TRANSACT2_OPEN:
9711 START_PROFILE(Trans2_open);
9712 call_trans2open(conn, req,
9713 &state->param, state->total_param,
9714 &state->data, state->total_data,
9715 state->max_data_return);
9716 END_PROFILE(Trans2_open);
9720 case TRANSACT2_FINDFIRST:
9722 START_PROFILE(Trans2_findfirst);
9723 call_trans2findfirst(conn, req,
9724 &state->param, state->total_param,
9725 &state->data, state->total_data,
9726 state->max_data_return);
9727 END_PROFILE(Trans2_findfirst);
9731 case TRANSACT2_FINDNEXT:
9733 START_PROFILE(Trans2_findnext);
9734 call_trans2findnext(conn, req,
9735 &state->param, state->total_param,
9736 &state->data, state->total_data,
9737 state->max_data_return);
9738 END_PROFILE(Trans2_findnext);
9742 case TRANSACT2_QFSINFO:
9744 START_PROFILE(Trans2_qfsinfo);
9745 call_trans2qfsinfo(conn, req,
9746 &state->param, state->total_param,
9747 &state->data, state->total_data,
9748 state->max_data_return);
9749 END_PROFILE(Trans2_qfsinfo);
9753 case TRANSACT2_SETFSINFO:
9755 START_PROFILE(Trans2_setfsinfo);
9756 call_trans2setfsinfo(conn, req,
9757 &state->param, state->total_param,
9758 &state->data, state->total_data,
9759 state->max_data_return);
9760 END_PROFILE(Trans2_setfsinfo);
9764 case TRANSACT2_QPATHINFO:
9765 case TRANSACT2_QFILEINFO:
9767 START_PROFILE(Trans2_qpathinfo);
9768 call_trans2qfilepathinfo(conn, req, state->call,
9769 &state->param, state->total_param,
9770 &state->data, state->total_data,
9771 state->max_data_return);
9772 END_PROFILE(Trans2_qpathinfo);
9776 case TRANSACT2_SETPATHINFO:
9777 case TRANSACT2_SETFILEINFO:
9779 START_PROFILE(Trans2_setpathinfo);
9780 call_trans2setfilepathinfo(conn, req, state->call,
9781 &state->param, state->total_param,
9782 &state->data, state->total_data,
9783 state->max_data_return);
9784 END_PROFILE(Trans2_setpathinfo);
9788 case TRANSACT2_FINDNOTIFYFIRST:
9790 START_PROFILE(Trans2_findnotifyfirst);
9791 call_trans2findnotifyfirst(conn, req,
9792 &state->param, state->total_param,
9793 &state->data, state->total_data,
9794 state->max_data_return);
9795 END_PROFILE(Trans2_findnotifyfirst);
9799 case TRANSACT2_FINDNOTIFYNEXT:
9801 START_PROFILE(Trans2_findnotifynext);
9802 call_trans2findnotifynext(conn, req,
9803 &state->param, state->total_param,
9804 &state->data, state->total_data,
9805 state->max_data_return);
9806 END_PROFILE(Trans2_findnotifynext);
9810 case TRANSACT2_MKDIR:
9812 START_PROFILE(Trans2_mkdir);
9813 call_trans2mkdir(conn, req,
9814 &state->param, state->total_param,
9815 &state->data, state->total_data,
9816 state->max_data_return);
9817 END_PROFILE(Trans2_mkdir);
9821 case TRANSACT2_GET_DFS_REFERRAL:
9823 START_PROFILE(Trans2_get_dfs_referral);
9824 call_trans2getdfsreferral(conn, req,
9825 &state->param, state->total_param,
9826 &state->data, state->total_data,
9827 state->max_data_return);
9828 END_PROFILE(Trans2_get_dfs_referral);
9832 case TRANSACT2_IOCTL:
9834 START_PROFILE(Trans2_ioctl);
9835 call_trans2ioctl(conn, req,
9836 &state->param, state->total_param,
9837 &state->data, state->total_data,
9838 state->max_data_return);
9839 END_PROFILE(Trans2_ioctl);
9844 /* Error in request */
9845 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9846 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9850 /****************************************************************************
9851 Reply to a SMBtrans2.
9852 ****************************************************************************/
9854 void reply_trans2(struct smb_request *req)
9856 connection_struct *conn = req->conn;
9861 unsigned int tran_call;
9862 struct trans_state *state;
9865 START_PROFILE(SMBtrans2);
9867 if (req->wct < 14) {
9868 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9869 END_PROFILE(SMBtrans2);
9873 dsoff = SVAL(req->vwv+12, 0);
9874 dscnt = SVAL(req->vwv+11, 0);
9875 psoff = SVAL(req->vwv+10, 0);
9876 pscnt = SVAL(req->vwv+9, 0);
9877 tran_call = SVAL(req->vwv+14, 0);
9879 result = allow_new_trans(conn->pending_trans, req->mid);
9880 if (!NT_STATUS_IS_OK(result)) {
9881 DEBUG(2, ("Got invalid trans2 request: %s\n",
9882 nt_errstr(result)));
9883 reply_nterror(req, result);
9884 END_PROFILE(SMBtrans2);
9889 switch (tran_call) {
9890 /* List the allowed trans2 calls on IPC$ */
9891 case TRANSACT2_OPEN:
9892 case TRANSACT2_GET_DFS_REFERRAL:
9893 case TRANSACT2_QFILEINFO:
9894 case TRANSACT2_QFSINFO:
9895 case TRANSACT2_SETFSINFO:
9898 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9899 END_PROFILE(SMBtrans2);
9904 if ((state = talloc(conn, struct trans_state)) == NULL) {
9905 DEBUG(0, ("talloc failed\n"));
9906 reply_nterror(req, NT_STATUS_NO_MEMORY);
9907 END_PROFILE(SMBtrans2);
9911 state->cmd = SMBtrans2;
9913 state->mid = req->mid;
9914 state->vuid = req->vuid;
9915 state->setup_count = SVAL(req->vwv+13, 0);
9916 state->setup = NULL;
9917 state->total_param = SVAL(req->vwv+0, 0);
9918 state->param = NULL;
9919 state->total_data = SVAL(req->vwv+1, 0);
9921 state->max_param_return = SVAL(req->vwv+2, 0);
9922 state->max_data_return = SVAL(req->vwv+3, 0);
9923 state->max_setup_return = SVAL(req->vwv+4, 0);
9924 state->close_on_completion = BITSETW(req->vwv+5, 0);
9925 state->one_way = BITSETW(req->vwv+5, 1);
9927 state->call = tran_call;
9929 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9930 is so as a sanity check */
9931 if (state->setup_count != 1) {
9933 * Need to have rc=0 for ioctl to get job id for OS/2.
9934 * Network printing will fail if function is not successful.
9935 * Similar function in reply.c will be used if protocol
9936 * is LANMAN1.0 instead of LM1.2X002.
9937 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9938 * outbuf doesn't have to be set(only job id is used).
9940 if ( (state->setup_count == 4)
9941 && (tran_call == TRANSACT2_IOCTL)
9942 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9943 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9944 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9946 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9947 DEBUG(2,("Transaction is %d\n",tran_call));
9949 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9950 END_PROFILE(SMBtrans2);
9955 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9958 if (state->total_data) {
9960 if (trans_oob(state->total_data, 0, dscnt)
9961 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9965 /* Can't use talloc here, the core routines do realloc on the
9966 * params and data. */
9967 state->data = (char *)SMB_MALLOC(state->total_data);
9968 if (state->data == NULL) {
9969 DEBUG(0,("reply_trans2: data malloc fail for %u "
9970 "bytes !\n", (unsigned int)state->total_data));
9972 reply_nterror(req, NT_STATUS_NO_MEMORY);
9973 END_PROFILE(SMBtrans2);
9977 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9980 if (state->total_param) {
9982 if (trans_oob(state->total_param, 0, pscnt)
9983 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9987 /* Can't use talloc here, the core routines do realloc on the
9988 * params and data. */
9989 state->param = (char *)SMB_MALLOC(state->total_param);
9990 if (state->param == NULL) {
9991 DEBUG(0,("reply_trans: param malloc fail for %u "
9992 "bytes !\n", (unsigned int)state->total_param));
9993 SAFE_FREE(state->data);
9995 reply_nterror(req, NT_STATUS_NO_MEMORY);
9996 END_PROFILE(SMBtrans2);
10000 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10003 state->received_data = dscnt;
10004 state->received_param = pscnt;
10006 if ((state->received_param == state->total_param) &&
10007 (state->received_data == state->total_data)) {
10009 handle_trans2(conn, req, state);
10011 SAFE_FREE(state->data);
10012 SAFE_FREE(state->param);
10013 TALLOC_FREE(state);
10014 END_PROFILE(SMBtrans2);
10018 DLIST_ADD(conn->pending_trans, state);
10020 /* We need to send an interim response then receive the rest
10021 of the parameter/data bytes */
10022 reply_outbuf(req, 0, 0);
10023 show_msg((char *)req->outbuf);
10024 END_PROFILE(SMBtrans2);
10029 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10030 SAFE_FREE(state->data);
10031 SAFE_FREE(state->param);
10032 TALLOC_FREE(state);
10033 END_PROFILE(SMBtrans2);
10034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10038 /****************************************************************************
10039 Reply to a SMBtranss2
10040 ****************************************************************************/
10042 void reply_transs2(struct smb_request *req)
10044 connection_struct *conn = req->conn;
10045 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10046 struct trans_state *state;
10048 START_PROFILE(SMBtranss2);
10050 show_msg((const char *)req->inbuf);
10052 /* Windows clients expect all replies to
10053 a transact secondary (SMBtranss2 0x33)
10054 to have a command code of transact
10055 (SMBtrans2 0x32). See bug #8989
10056 and also [MS-CIFS] section 2.2.4.47.2
10059 req->cmd = SMBtrans2;
10061 if (req->wct < 8) {
10062 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10063 END_PROFILE(SMBtranss2);
10067 for (state = conn->pending_trans; state != NULL;
10068 state = state->next) {
10069 if (state->mid == req->mid) {
10074 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10076 END_PROFILE(SMBtranss2);
10080 /* Revise state->total_param and state->total_data in case they have
10081 changed downwards */
10083 if (SVAL(req->vwv+0, 0) < state->total_param)
10084 state->total_param = SVAL(req->vwv+0, 0);
10085 if (SVAL(req->vwv+1, 0) < state->total_data)
10086 state->total_data = SVAL(req->vwv+1, 0);
10088 pcnt = SVAL(req->vwv+2, 0);
10089 poff = SVAL(req->vwv+3, 0);
10090 pdisp = SVAL(req->vwv+4, 0);
10092 dcnt = SVAL(req->vwv+5, 0);
10093 doff = SVAL(req->vwv+6, 0);
10094 ddisp = SVAL(req->vwv+7, 0);
10096 state->received_param += pcnt;
10097 state->received_data += dcnt;
10099 if ((state->received_data > state->total_data) ||
10100 (state->received_param > state->total_param))
10104 if (trans_oob(state->total_param, pdisp, pcnt)
10105 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10108 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10112 if (trans_oob(state->total_data, ddisp, dcnt)
10113 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10116 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10119 if ((state->received_param < state->total_param) ||
10120 (state->received_data < state->total_data)) {
10121 END_PROFILE(SMBtranss2);
10125 handle_trans2(conn, req, state);
10127 DLIST_REMOVE(conn->pending_trans, state);
10128 SAFE_FREE(state->data);
10129 SAFE_FREE(state->param);
10130 TALLOC_FREE(state);
10132 END_PROFILE(SMBtranss2);
10137 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10138 DLIST_REMOVE(conn->pending_trans, state);
10139 SAFE_FREE(state->data);
10140 SAFE_FREE(state->param);
10141 TALLOC_FREE(state);
10142 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10143 END_PROFILE(SMBtranss2);