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 /********************************************************************
103 The canonical "check access" based on object handle or path function.
104 ********************************************************************/
106 NTSTATUS check_access(connection_struct *conn,
108 const struct smb_filename *smb_fname,
109 uint32_t access_mask)
114 status = check_access_fsp(fsp, access_mask);
116 status = smbd_check_access_rights(conn, smb_fname,
123 /********************************************************************
124 Roundup a value to the nearest allocation roundup size boundary.
125 Only do this for Windows clients.
126 ********************************************************************/
128 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
130 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
132 /* Only roundup for Windows clients. */
133 enum remote_arch_types ra_type = get_remote_arch();
134 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
135 val = SMB_ROUNDUP(val,rval);
140 /********************************************************************
141 Create a 64 bit FileIndex. If the file is on the same device as
142 the root of the share, just return the 64-bit inode. If it isn't,
143 mangle as we used to do.
144 ********************************************************************/
146 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
149 if (conn->sconn->aapl_zero_file_id) {
152 if (conn->base_share_dev == psbuf->st_ex_dev) {
153 return (uint64_t)psbuf->st_ex_ino;
155 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
156 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
161 /********************************************************************
162 Globally (for this connection / multi-channel) disable file-ID
163 calculation. This is required to be global because it serves
164 Macs in AAPL mode, which is globally set.
165 ********************************************************************/
166 void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
168 sconn->aapl_zero_file_id = true;
171 /****************************************************************************
172 Utility functions for dealing with extended attributes.
173 ****************************************************************************/
175 /****************************************************************************
176 Refuse to allow clients to overwrite our private xattrs.
177 ****************************************************************************/
179 bool samba_private_attr_name(const char *unix_ea_name)
181 static const char * const prohibited_ea_names[] = {
182 SAMBA_POSIX_INHERITANCE_EA_NAME,
183 SAMBA_XATTR_DOS_ATTRIB,
191 for (i = 0; prohibited_ea_names[i]; i++) {
192 if (strequal( prohibited_ea_names[i], unix_ea_name))
195 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
196 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
202 /****************************************************************************
203 Get one EA value. Fill in a struct ea_struct.
204 ****************************************************************************/
206 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
207 connection_struct *conn,
209 const struct smb_filename *smb_fname,
211 struct ea_struct *pea)
213 /* Get the value of this xattr. Max size is 64k. */
214 size_t attr_size = 256;
220 val = talloc_realloc(mem_ctx, val, char, attr_size);
222 return NT_STATUS_NO_MEMORY;
225 if (fsp && fsp->fh->fd != -1) {
226 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
228 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
229 ea_name, val, attr_size);
232 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
238 return map_nt_error_from_unix(errno);
241 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
242 dump_data(10, (uint8_t *)val, sizeret);
245 if (strnequal(ea_name, "user.", 5)) {
246 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
248 pea->name = talloc_strdup(mem_ctx, ea_name);
250 if (pea->name == NULL) {
252 return NT_STATUS_NO_MEMORY;
254 pea->value.data = (unsigned char *)val;
255 pea->value.length = (size_t)sizeret;
259 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
260 connection_struct *conn,
262 const struct smb_filename *smb_fname,
267 /* Get a list of all xattrs. Max namesize is 64k. */
268 size_t ea_namelist_size = 1024;
269 char *ea_namelist = smallbuf;
270 char *to_free = NULL;
275 ssize_t sizeret = -1;
283 status = refuse_symlink(conn, fsp, smb_fname);
284 if (!NT_STATUS_IS_OK(status)) {
286 * Just return no EA's on a symlink.
291 if (fsp && fsp->fh->fd != -1) {
292 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
295 sizeret = SMB_VFS_LISTXATTR(conn,
301 if ((sizeret == -1) && (errno == ERANGE)) {
302 ea_namelist_size = 65536;
303 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
304 if (ea_namelist == NULL) {
305 return NT_STATUS_NO_MEMORY;
307 to_free = ea_namelist;
309 if (fsp && fsp->fh->fd != -1) {
310 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
313 sizeret = SMB_VFS_LISTXATTR(conn,
321 status = map_nt_error_from_unix(errno);
322 TALLOC_FREE(to_free);
326 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
329 TALLOC_FREE(to_free);
334 * Ensure the result is 0-terminated
337 if (ea_namelist[sizeret-1] != '\0') {
338 TALLOC_FREE(to_free);
339 return NT_STATUS_INTERNAL_ERROR;
347 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
351 *pnum_names = num_names;
353 if (pnames == NULL) {
354 TALLOC_FREE(to_free);
358 names = talloc_array(mem_ctx, char *, num_names);
360 DEBUG(0, ("talloc failed\n"));
361 TALLOC_FREE(to_free);
362 return NT_STATUS_NO_MEMORY;
365 if (ea_namelist == smallbuf) {
366 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
367 if (ea_namelist == NULL) {
369 return NT_STATUS_NO_MEMORY;
372 talloc_steal(names, ea_namelist);
374 ea_namelist = talloc_realloc(names, ea_namelist, char,
376 if (ea_namelist == NULL) {
378 return NT_STATUS_NO_MEMORY;
384 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
385 names[num_names++] = p;
393 /****************************************************************************
394 Return a linked list of the total EA's. Plus the total size
395 ****************************************************************************/
397 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
398 connection_struct *conn,
400 const struct smb_filename *smb_fname,
401 size_t *pea_total_len,
402 struct ea_list **ea_list)
404 /* Get a list of all xattrs. Max namesize is 64k. */
407 struct ea_list *ea_list_head = NULL;
408 bool posix_pathnames = false;
414 if (!lp_ea_support(SNUM(conn))) {
420 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
422 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
425 status = get_ea_names_from_file(talloc_tos(),
432 if (!NT_STATUS_IS_OK(status)) {
436 if (num_names == 0) {
440 for (i=0; i<num_names; i++) {
441 struct ea_list *listp;
444 if (strnequal(names[i], "system.", 7)
445 || samba_private_attr_name(names[i]))
449 * Filter out any underlying POSIX EA names
450 * that a Windows client can't handle.
452 if (!posix_pathnames &&
453 is_invalid_windows_ea_name(names[i])) {
457 listp = talloc(mem_ctx, struct ea_list);
459 return NT_STATUS_NO_MEMORY;
462 status = get_ea_value(listp,
469 if (!NT_STATUS_IS_OK(status)) {
474 if (listp->ea.value.length == 0) {
476 * We can never return a zero length EA.
477 * Windows reports the EA's as corrupted.
483 push_ascii_fstring(dos_ea_name, listp->ea.name);
486 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
488 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
489 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
490 (unsigned int)listp->ea.value.length));
492 DLIST_ADD_END(ea_list_head, listp);
496 /* Add on 4 for total length. */
497 if (*pea_total_len) {
501 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
502 (unsigned int)*pea_total_len));
504 *ea_list = ea_list_head;
508 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
509 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
514 if (!lp_ea_support(SNUM(conn))) {
518 if (is_ntfs_stream_smb_fname(smb_fname)) {
519 return NT_STATUS_INVALID_PARAMETER;
522 return get_ea_list_from_file_path(mem_ctx,
530 /****************************************************************************
531 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
533 ****************************************************************************/
535 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
536 connection_struct *conn, struct ea_list *ea_list)
538 unsigned int ret_data_size = 4;
541 SMB_ASSERT(total_data_size >= 4);
543 if (!lp_ea_support(SNUM(conn))) {
548 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
551 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
552 dos_namelen = strlen(dos_ea_name);
553 if (dos_namelen > 255 || dos_namelen == 0) {
556 if (ea_list->ea.value.length > 65535) {
559 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
563 /* We know we have room. */
564 SCVAL(p,0,ea_list->ea.flags);
565 SCVAL(p,1,dos_namelen);
566 SSVAL(p,2,ea_list->ea.value.length);
567 strlcpy(p+4, dos_ea_name, dos_namelen+1);
568 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
570 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
571 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
574 ret_data_size = PTR_DIFF(p, pdata);
575 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
576 SIVAL(pdata,0,ret_data_size);
577 return ret_data_size;
580 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
582 unsigned int total_data_size,
583 unsigned int *ret_data_size,
584 connection_struct *conn,
585 struct ea_list *ea_list)
587 uint8_t *p = (uint8_t *)pdata;
588 uint8_t *last_start = NULL;
589 bool do_store_data = (pdata != NULL);
593 if (!lp_ea_support(SNUM(conn))) {
594 return NT_STATUS_NO_EAS_ON_FILE;
597 for (; ea_list; ea_list = ea_list->next) {
603 if (last_start != NULL && do_store_data) {
604 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
608 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
609 dos_namelen = strlen(dos_ea_name);
610 if (dos_namelen > 255 || dos_namelen == 0) {
611 return NT_STATUS_INTERNAL_ERROR;
613 if (ea_list->ea.value.length > 65535) {
614 return NT_STATUS_INTERNAL_ERROR;
617 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
620 pad = (4 - (this_size % 4)) % 4;
625 if (this_size > total_data_size) {
626 return NT_STATUS_INFO_LENGTH_MISMATCH;
629 /* We know we have room. */
630 SIVAL(p, 0x00, 0); /* next offset */
631 SCVAL(p, 0x04, ea_list->ea.flags);
632 SCVAL(p, 0x05, dos_namelen);
633 SSVAL(p, 0x06, ea_list->ea.value.length);
634 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
635 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
637 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
641 total_data_size -= this_size;
647 *ret_data_size = PTR_DIFF(p, pdata);
648 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
652 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
654 size_t total_ea_len = 0;
656 struct ea_list *ea_list = NULL;
658 if (!lp_ea_support(SNUM(conn))) {
661 mem_ctx = talloc_stackframe();
663 /* If this is a stream fsp, then we need to instead find the
664 * estimated ea len from the main file, not the stream
665 * (streams cannot have EAs), but the estimate isn't just 0 in
667 if (is_ntfs_stream_smb_fname(smb_fname)) {
670 (void)get_ea_list_from_file_path(mem_ctx,
676 if(conn->sconn->using_smb2) {
678 unsigned int ret_data_size;
680 * We're going to be using fill_ea_chained_buffer() to
681 * marshall EA's - this size is significantly larger
682 * than the SMB1 buffer. Re-calculate the size without
685 status = fill_ea_chained_buffer(mem_ctx,
691 if (!NT_STATUS_IS_OK(status)) {
694 total_ea_len = ret_data_size;
696 TALLOC_FREE(mem_ctx);
700 /****************************************************************************
701 Ensure the EA name is case insensitive by matching any existing EA name.
702 ****************************************************************************/
704 static void canonicalize_ea_name(connection_struct *conn,
706 const struct smb_filename *smb_fname,
707 fstring unix_ea_name)
710 TALLOC_CTX *mem_ctx = talloc_tos();
711 struct ea_list *ea_list;
712 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
718 if (!NT_STATUS_IS_OK(status)) {
722 for (; ea_list; ea_list = ea_list->next) {
723 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
724 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
725 &unix_ea_name[5], ea_list->ea.name));
726 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
732 /****************************************************************************
733 Set or delete an extended attribute.
734 ****************************************************************************/
736 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
737 const struct smb_filename *smb_fname, struct ea_list *ea_list)
740 bool posix_pathnames = false;
742 if (!lp_ea_support(SNUM(conn))) {
743 return NT_STATUS_EAS_NOT_SUPPORTED;
748 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
750 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
753 status = refuse_symlink(conn, fsp, smb_fname);
754 if (!NT_STATUS_IS_OK(status)) {
758 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
759 if (!NT_STATUS_IS_OK(status)) {
763 /* Setting EAs on streams isn't supported. */
764 if (is_ntfs_stream_smb_fname(smb_fname)) {
765 return NT_STATUS_INVALID_PARAMETER;
769 * Filter out invalid Windows EA names - before
770 * we set *any* of them.
773 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
774 return STATUS_INVALID_EA_NAME;
777 for (;ea_list; ea_list = ea_list->next) {
779 fstring unix_ea_name;
781 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
782 fstrcat(unix_ea_name, ea_list->ea.name);
784 canonicalize_ea_name(conn,
789 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
791 if (samba_private_attr_name(unix_ea_name)) {
792 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
793 return NT_STATUS_ACCESS_DENIED;
796 if (ea_list->ea.value.length == 0) {
797 /* Remove the attribute. */
798 if (fsp && (fsp->fh->fd != -1)) {
799 DEBUG(10,("set_ea: deleting ea name %s on "
800 "file %s by file descriptor.\n",
801 unix_ea_name, fsp_str_dbg(fsp)));
802 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
804 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
805 unix_ea_name, smb_fname->base_name));
806 ret = SMB_VFS_REMOVEXATTR(conn,
811 /* Removing a non existent attribute always succeeds. */
812 if (ret == -1 && errno == ENOATTR) {
813 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
819 if (fsp && (fsp->fh->fd != -1)) {
820 DEBUG(10,("set_ea: setting ea name %s on file "
821 "%s by file descriptor.\n",
822 unix_ea_name, fsp_str_dbg(fsp)));
823 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
824 ea_list->ea.value.data, ea_list->ea.value.length, 0);
826 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
827 unix_ea_name, smb_fname->base_name));
828 ret = SMB_VFS_SETXATTR(conn,
831 ea_list->ea.value.data,
832 ea_list->ea.value.length,
839 if (errno == ENOTSUP) {
840 return NT_STATUS_EAS_NOT_SUPPORTED;
843 return map_nt_error_from_unix(errno);
849 /****************************************************************************
850 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
851 ****************************************************************************/
853 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
855 struct ea_list *ea_list_head = NULL;
856 size_t converted_size, offset = 0;
858 while (offset + 2 < data_size) {
859 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
860 unsigned int namelen = CVAL(pdata,offset);
862 offset++; /* Go past the namelen byte. */
864 /* integer wrap paranioa. */
865 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
866 (offset > data_size) || (namelen > data_size) ||
867 (offset + namelen >= data_size)) {
870 /* Ensure the name is null terminated. */
871 if (pdata[offset + namelen] != '\0') {
874 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
876 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
877 "failed: %s", strerror(errno)));
883 offset += (namelen + 1); /* Go past the name + terminating zero. */
884 DLIST_ADD_END(ea_list_head, eal);
885 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
891 /****************************************************************************
892 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
893 ****************************************************************************/
895 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
897 struct ea_list *ea_list_head = NULL;
899 size_t bytes_used = 0;
901 while (offset < data_size) {
902 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
908 DLIST_ADD_END(ea_list_head, eal);
909 offset += bytes_used;
915 /****************************************************************************
916 Count the total EA size needed.
917 ****************************************************************************/
919 static size_t ea_list_size(struct ea_list *ealist)
922 struct ea_list *listp;
925 for (listp = ealist; listp; listp = listp->next) {
926 push_ascii_fstring(dos_ea_name, listp->ea.name);
927 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
929 /* Add on 4 for total length. */
937 /****************************************************************************
938 Return a union of EA's from a file list and a list of names.
939 The TALLOC context for the two lists *MUST* be identical as we steal
940 memory from one list to add to another. JRA.
941 ****************************************************************************/
943 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
945 struct ea_list *nlistp, *flistp;
947 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
948 for (flistp = file_list; flistp; flistp = flistp->next) {
949 if (strequal(nlistp->ea.name, flistp->ea.name)) {
955 /* Copy the data from this entry. */
956 nlistp->ea.flags = flistp->ea.flags;
957 nlistp->ea.value = flistp->ea.value;
960 nlistp->ea.flags = 0;
961 ZERO_STRUCT(nlistp->ea.value);
965 *total_ea_len = ea_list_size(name_list);
969 /****************************************************************************
970 Send the required number of replies back.
971 We assume all fields other than the data fields are
972 set correctly for the type of call.
973 HACK ! Always assumes smb_setup field is zero.
974 ****************************************************************************/
976 void send_trans2_replies(connection_struct *conn,
977 struct smb_request *req,
985 /* As we are using a protocol > LANMAN1 then the max_send
986 variable must have been set in the sessetupX call.
987 This takes precedence over the max_xmit field in the
988 global struct. These different max_xmit variables should
989 be merged as this is now too confusing */
991 int data_to_send = datasize;
992 int params_to_send = paramsize;
994 const char *pp = params;
995 const char *pd = pdata;
996 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
997 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
998 int data_alignment_offset = 0;
999 bool overflow = False;
1000 struct smbXsrv_connection *xconn = req->xconn;
1001 int max_send = xconn->smb1.sessions.max_send;
1003 /* Modify the data_to_send and datasize and set the error if
1004 we're trying to send more than max_data_bytes. We still send
1005 the part of the packet(s) that fit. Strange, but needed
1008 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1009 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1010 max_data_bytes, datasize ));
1011 datasize = data_to_send = max_data_bytes;
1015 /* If there genuinely are no parameters or data to send just send the empty packet */
1017 if(params_to_send == 0 && data_to_send == 0) {
1018 reply_outbuf(req, 10, 0);
1019 if (NT_STATUS_V(status)) {
1022 ntstatus_to_dos(status, &eclass, &ecode);
1023 error_packet_set((char *)req->outbuf,
1024 eclass, ecode, status,
1027 show_msg((char *)req->outbuf);
1028 if (!srv_send_smb(xconn,
1029 (char *)req->outbuf,
1030 true, req->seqnum+1,
1031 IS_CONN_ENCRYPTED(conn),
1033 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1035 TALLOC_FREE(req->outbuf);
1039 /* When sending params and data ensure that both are nicely aligned */
1040 /* Only do this alignment when there is also data to send - else
1041 can cause NT redirector problems. */
1043 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1044 data_alignment_offset = 4 - (params_to_send % 4);
1046 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1047 /* The alignment_offset is to align the param bytes on an even byte
1048 boundary. NT 4.0 Beta needs this to work correctly. */
1050 useable_space = max_send - (smb_size
1053 + data_alignment_offset);
1055 if (useable_space < 0) {
1056 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1057 "= %d!!!", useable_space));
1058 exit_server_cleanly("send_trans2_replies: Not enough space");
1061 while (params_to_send || data_to_send) {
1062 /* Calculate whether we will totally or partially fill this packet */
1064 total_sent_thistime = params_to_send + data_to_send;
1066 /* We can never send more than useable_space */
1068 * Note that 'useable_space' does not include the alignment offsets,
1069 * but we must include the alignment offsets in the calculation of
1070 * the length of the data we send over the wire, as the alignment offsets
1071 * are sent here. Fix from Marc_Jacobsen@hp.com.
1074 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1076 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1077 + data_alignment_offset);
1079 /* Set total params and data to be sent */
1080 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1081 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1083 /* Calculate how many parameters and data we can fit into
1084 * this packet. Parameters get precedence
1087 params_sent_thistime = MIN(params_to_send,useable_space);
1088 data_sent_thistime = useable_space - params_sent_thistime;
1089 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1091 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1093 /* smb_proff is the offset from the start of the SMB header to the
1094 parameter bytes, however the first 4 bytes of outbuf are
1095 the Netbios over TCP header. Thus use smb_base() to subtract
1096 them from the calculation */
1098 SSVAL(req->outbuf,smb_proff,
1099 ((smb_buf(req->outbuf)+alignment_offset)
1100 - smb_base(req->outbuf)));
1102 if(params_sent_thistime == 0)
1103 SSVAL(req->outbuf,smb_prdisp,0);
1105 /* Absolute displacement of param bytes sent in this packet */
1106 SSVAL(req->outbuf,smb_prdisp,pp - params);
1108 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1109 if(data_sent_thistime == 0) {
1110 SSVAL(req->outbuf,smb_droff,0);
1111 SSVAL(req->outbuf,smb_drdisp, 0);
1113 /* The offset of the data bytes is the offset of the
1114 parameter bytes plus the number of parameters being sent this time */
1115 SSVAL(req->outbuf, smb_droff,
1116 ((smb_buf(req->outbuf)+alignment_offset)
1117 - smb_base(req->outbuf))
1118 + params_sent_thistime + data_alignment_offset);
1119 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1122 /* Initialize the padding for alignment */
1124 if (alignment_offset != 0) {
1125 memset(smb_buf(req->outbuf), 0, alignment_offset);
1128 /* Copy the param bytes into the packet */
1130 if(params_sent_thistime) {
1131 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1132 params_sent_thistime);
1135 /* Copy in the data bytes */
1136 if(data_sent_thistime) {
1137 if (data_alignment_offset != 0) {
1138 memset((smb_buf(req->outbuf)+alignment_offset+
1139 params_sent_thistime), 0,
1140 data_alignment_offset);
1142 memcpy(smb_buf(req->outbuf)+alignment_offset
1143 +params_sent_thistime+data_alignment_offset,
1144 pd,data_sent_thistime);
1147 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1148 params_sent_thistime, data_sent_thistime, useable_space));
1149 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1150 params_to_send, data_to_send, paramsize, datasize));
1153 error_packet_set((char *)req->outbuf,
1154 ERRDOS,ERRbufferoverflow,
1155 STATUS_BUFFER_OVERFLOW,
1157 } else if (NT_STATUS_V(status)) {
1160 ntstatus_to_dos(status, &eclass, &ecode);
1161 error_packet_set((char *)req->outbuf,
1162 eclass, ecode, status,
1166 /* Send the packet */
1167 show_msg((char *)req->outbuf);
1168 if (!srv_send_smb(xconn,
1169 (char *)req->outbuf,
1170 true, req->seqnum+1,
1171 IS_CONN_ENCRYPTED(conn),
1173 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1175 TALLOC_FREE(req->outbuf);
1177 pp += params_sent_thistime;
1178 pd += data_sent_thistime;
1180 params_to_send -= params_sent_thistime;
1181 data_to_send -= data_sent_thistime;
1184 if(params_to_send < 0 || data_to_send < 0) {
1185 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1186 params_to_send, data_to_send));
1194 /****************************************************************************
1195 Reply to a TRANSACT2_OPEN.
1196 ****************************************************************************/
1198 static void call_trans2open(connection_struct *conn,
1199 struct smb_request *req,
1200 char **pparams, int total_params,
1201 char **ppdata, int total_data,
1202 unsigned int max_data_bytes)
1204 struct smb_filename *smb_fname = NULL;
1205 char *params = *pparams;
1206 char *pdata = *ppdata;
1209 bool oplock_request;
1211 bool return_additional_info;
1220 int fattr=0,mtime=0;
1221 SMB_INO_T inode = 0;
1224 struct ea_list *ea_list = NULL;
1227 uint32_t access_mask;
1228 uint32_t share_mode;
1229 uint32_t create_disposition;
1230 uint32_t create_options = 0;
1231 uint32_t private_flags = 0;
1232 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1233 TALLOC_CTX *ctx = talloc_tos();
1236 * Ensure we have enough parameters to perform the operation.
1239 if (total_params < 29) {
1240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1244 flags = SVAL(params, 0);
1245 deny_mode = SVAL(params, 2);
1246 open_attr = SVAL(params,6);
1247 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1248 if (oplock_request) {
1249 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1253 return_additional_info = BITSETW(params,0);
1254 open_sattr = SVAL(params, 4);
1255 open_time = make_unix_date3(params+8);
1257 open_ofun = SVAL(params,12);
1258 open_size = IVAL(params,14);
1259 pname = ¶ms[28];
1262 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1266 if (req->posix_pathnames) {
1267 srvstr_get_path_posix(ctx,
1276 srvstr_get_path(ctx,
1285 if (!NT_STATUS_IS_OK(status)) {
1286 reply_nterror(req, status);
1290 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1291 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1292 (unsigned int)open_ofun, open_size));
1294 status = filename_convert(ctx,
1300 if (!NT_STATUS_IS_OK(status)) {
1301 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1302 reply_botherror(req,
1303 NT_STATUS_PATH_NOT_COVERED,
1304 ERRSRV, ERRbadpath);
1307 reply_nterror(req, status);
1311 if (open_ofun == 0) {
1312 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1316 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1318 &access_mask, &share_mode,
1319 &create_disposition,
1322 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1326 /* Any data in this call is an EA list. */
1327 if (total_data && (total_data != 4)) {
1328 if (total_data < 10) {
1329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1333 if (IVAL(pdata,0) > total_data) {
1334 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1335 IVAL(pdata,0), (unsigned int)total_data));
1336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1340 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1347 if (!lp_ea_support(SNUM(conn))) {
1348 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1352 if (!req->posix_pathnames &&
1353 ea_list_has_invalid_name(ea_list)) {
1355 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1356 if(*pparams == NULL ) {
1357 reply_nterror(req, NT_STATUS_NO_MEMORY);
1361 memset(params, '\0', param_len);
1362 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1363 params, param_len, NULL, 0, max_data_bytes);
1368 status = SMB_VFS_CREATE_FILE(
1371 0, /* root_dir_fid */
1372 smb_fname, /* fname */
1373 access_mask, /* access_mask */
1374 share_mode, /* share_access */
1375 create_disposition, /* create_disposition*/
1376 create_options, /* create_options */
1377 open_attr, /* file_attributes */
1378 oplock_request, /* oplock_request */
1380 open_size, /* allocation_size */
1383 ea_list, /* ea_list */
1385 &smb_action, /* psbuf */
1386 NULL, NULL); /* create context */
1388 if (!NT_STATUS_IS_OK(status)) {
1389 if (open_was_deferred(req->xconn, req->mid)) {
1390 /* We have re-scheduled this call. */
1393 reply_openerror(req, status);
1397 size = get_file_size_stat(&smb_fname->st);
1398 fattr = dos_mode(conn, smb_fname);
1399 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1400 inode = smb_fname->st.st_ex_ino;
1401 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1402 close_file(req, fsp, ERROR_CLOSE);
1403 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1407 /* Realloc the size of parameters and data we will return */
1408 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1409 if(*pparams == NULL ) {
1410 reply_nterror(req, NT_STATUS_NO_MEMORY);
1415 SSVAL(params,0,fsp->fnum);
1416 SSVAL(params,2,fattr);
1417 srv_put_dos_date2(params,4, mtime);
1418 SIVAL(params,8, (uint32_t)size);
1419 SSVAL(params,12,deny_mode);
1420 SSVAL(params,14,0); /* open_type - file or directory. */
1421 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1423 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1424 smb_action |= EXTENDED_OPLOCK_GRANTED;
1427 SSVAL(params,18,smb_action);
1430 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1432 SIVAL(params,20,inode);
1433 SSVAL(params,24,0); /* Padding. */
1435 uint32_t ea_size = estimate_ea_size(conn, fsp,
1437 SIVAL(params, 26, ea_size);
1439 SIVAL(params, 26, 0);
1442 /* Send the required number of replies */
1443 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1445 TALLOC_FREE(smb_fname);
1448 /*********************************************************
1449 Routine to check if a given string matches exactly.
1450 as a special case a mask of "." does NOT match. That
1451 is required for correct wildcard semantics
1452 Case can be significant or not.
1453 **********************************************************/
1455 static bool exact_match(bool has_wild,
1456 bool case_sensitive,
1460 if (mask[0] == '.' && mask[1] == 0) {
1468 if (case_sensitive) {
1469 return strcmp(str,mask)==0;
1471 return strcasecmp_m(str,mask) == 0;
1475 /****************************************************************************
1476 Return the filetype for UNIX extensions.
1477 ****************************************************************************/
1479 static uint32_t unix_filetype(mode_t mode)
1482 return UNIX_TYPE_FILE;
1483 else if(S_ISDIR(mode))
1484 return UNIX_TYPE_DIR;
1486 else if(S_ISLNK(mode))
1487 return UNIX_TYPE_SYMLINK;
1490 else if(S_ISCHR(mode))
1491 return UNIX_TYPE_CHARDEV;
1494 else if(S_ISBLK(mode))
1495 return UNIX_TYPE_BLKDEV;
1498 else if(S_ISFIFO(mode))
1499 return UNIX_TYPE_FIFO;
1502 else if(S_ISSOCK(mode))
1503 return UNIX_TYPE_SOCKET;
1506 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1507 return UNIX_TYPE_UNKNOWN;
1510 /****************************************************************************
1511 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1512 ****************************************************************************/
1514 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1516 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1517 const SMB_STRUCT_STAT *psbuf,
1519 enum perm_type ptype,
1524 if (perms == SMB_MODE_NO_CHANGE) {
1525 if (!VALID_STAT(*psbuf)) {
1526 return NT_STATUS_INVALID_PARAMETER;
1528 *ret_perms = psbuf->st_ex_mode;
1529 return NT_STATUS_OK;
1533 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1534 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1535 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1536 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1537 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1538 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1539 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1540 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1541 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1543 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1546 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1549 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1552 if (ptype == PERM_NEW_FILE) {
1554 * "create mask"/"force create mode" are
1555 * only applied to new files, not existing ones.
1557 ret &= lp_create_mask(SNUM(conn));
1558 /* Add in force bits */
1559 ret |= lp_force_create_mode(SNUM(conn));
1560 } else if (ptype == PERM_NEW_DIR) {
1562 * "directory mask"/"force directory mode" are
1563 * only applied to new directories, not existing ones.
1565 ret &= lp_directory_mask(SNUM(conn));
1566 /* Add in force bits */
1567 ret |= lp_force_directory_mode(SNUM(conn));
1571 return NT_STATUS_OK;
1574 /****************************************************************************
1575 Needed to show the msdfs symlinks as directories. Modifies psbuf
1576 to be a directory if it's a msdfs link.
1577 ****************************************************************************/
1579 static bool check_msdfs_link(connection_struct *conn,
1580 struct smb_filename *smb_fname)
1582 int saved_errno = errno;
1583 if(lp_host_msdfs() &&
1584 lp_msdfs_root(SNUM(conn)) &&
1585 is_msdfs_link(conn, smb_fname)) {
1587 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1589 smb_fname->base_name));
1590 smb_fname->st.st_ex_mode =
1591 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1592 errno = saved_errno;
1595 errno = saved_errno;
1600 /****************************************************************************
1601 Get a level dependent lanman2 dir entry.
1602 ****************************************************************************/
1604 struct smbd_dirptr_lanman2_state {
1605 connection_struct *conn;
1606 uint32_t info_level;
1607 bool check_mangled_names;
1609 bool got_exact_match;
1612 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1618 struct smbd_dirptr_lanman2_state *state =
1619 (struct smbd_dirptr_lanman2_state *)private_data;
1621 char mangled_name[13]; /* mangled 8.3 name. */
1625 /* Mangle fname if it's an illegal name. */
1626 if (mangle_must_mangle(dname, state->conn->params)) {
1628 * Slow path - ensure we can push the original name as UCS2. If
1629 * not, then just don't return this name.
1633 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1634 uint8_t *tmp = talloc_array(talloc_tos(),
1638 status = srvstr_push(NULL,
1639 FLAGS2_UNICODE_STRINGS,
1648 if (!NT_STATUS_IS_OK(status)) {
1652 ok = name_to_8_3(dname, mangled_name,
1653 true, state->conn->params);
1657 fname = mangled_name;
1662 got_match = exact_match(state->has_wild,
1663 state->conn->case_sensitive,
1665 state->got_exact_match = got_match;
1667 got_match = mask_match(fname, mask,
1668 state->conn->case_sensitive);
1671 if(!got_match && state->check_mangled_names &&
1672 !mangle_is_8_3(fname, false, state->conn->params)) {
1674 * It turns out that NT matches wildcards against
1675 * both long *and* short names. This may explain some
1676 * of the wildcard wierdness from old DOS clients
1677 * that some people have been seeing.... JRA.
1679 /* Force the mangling into 8.3. */
1680 ok = name_to_8_3(fname, mangled_name,
1681 false, state->conn->params);
1686 got_match = exact_match(state->has_wild,
1687 state->conn->case_sensitive,
1688 mangled_name, mask);
1689 state->got_exact_match = got_match;
1691 got_match = mask_match(mangled_name, mask,
1692 state->conn->case_sensitive);
1700 *_fname = talloc_strdup(ctx, fname);
1701 if (*_fname == NULL) {
1708 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1710 struct smb_filename *smb_fname,
1714 struct smbd_dirptr_lanman2_state *state =
1715 (struct smbd_dirptr_lanman2_state *)private_data;
1716 bool ms_dfs_link = false;
1719 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1720 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1721 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1722 "Couldn't lstat [%s] (%s)\n",
1723 smb_fname_str_dbg(smb_fname),
1727 } else if (!VALID_STAT(smb_fname->st) &&
1728 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1729 /* Needed to show the msdfs symlinks as
1732 ms_dfs_link = check_msdfs_link(state->conn,
1735 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1736 "Couldn't stat [%s] (%s)\n",
1737 smb_fname_str_dbg(smb_fname),
1744 mode = dos_mode_msdfs(state->conn, smb_fname);
1745 } else if (get_dosmode) {
1746 mode = dos_mode(state->conn, smb_fname);
1753 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1754 connection_struct *conn,
1756 uint32_t info_level,
1757 struct ea_list *name_list,
1758 bool check_mangled_names,
1759 bool requires_resume_key,
1762 const struct smb_filename *smb_fname,
1763 int space_remaining,
1769 uint64_t *last_entry_off)
1771 char *p, *q, *pdata = *ppdata;
1773 uint64_t file_size = 0;
1774 uint64_t allocation_size = 0;
1775 uint64_t file_index = 0;
1777 struct timespec mdate_ts = {0};
1778 struct timespec adate_ts = {0};
1779 struct timespec cdate_ts = {0};
1780 struct timespec create_date_ts = {0};
1781 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1783 char *last_entry_ptr;
1788 struct readdir_attr_data *readdir_attr_data = NULL;
1790 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1791 file_size = get_file_size_stat(&smb_fname->st);
1793 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1795 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1796 if (!NT_STATUS_IS_OK(status)) {
1797 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1802 file_index = get_FileIndex(conn, &smb_fname->st);
1804 mdate_ts = smb_fname->st.st_ex_mtime;
1805 adate_ts = smb_fname->st.st_ex_atime;
1806 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1807 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1809 if (lp_dos_filetime_resolution(SNUM(conn))) {
1810 dos_filetime_timespec(&create_date_ts);
1811 dos_filetime_timespec(&mdate_ts);
1812 dos_filetime_timespec(&adate_ts);
1813 dos_filetime_timespec(&cdate_ts);
1816 create_date = convert_timespec_to_time_t(create_date_ts);
1817 mdate = convert_timespec_to_time_t(mdate_ts);
1818 adate = convert_timespec_to_time_t(adate_ts);
1820 /* align the record */
1821 SMB_ASSERT(align >= 1);
1823 off = (int)PTR_DIFF(pdata, base_data);
1824 pad = (off + (align-1)) & ~(align-1);
1827 if (pad && pad > space_remaining) {
1828 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1829 "for padding (wanted %u, had %d)\n",
1832 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1836 /* initialize padding to 0 */
1838 memset(pdata, 0, pad);
1840 space_remaining -= pad;
1842 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1852 switch (info_level) {
1853 case SMB_FIND_INFO_STANDARD:
1854 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1855 if(requires_resume_key) {
1859 srv_put_dos_date2(p,0,create_date);
1860 srv_put_dos_date2(p,4,adate);
1861 srv_put_dos_date2(p,8,mdate);
1862 SIVAL(p,12,(uint32_t)file_size);
1863 SIVAL(p,16,(uint32_t)allocation_size);
1867 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1868 p += ucs2_align(base_data, p, 0);
1870 status = srvstr_push(base_data, flags2, p,
1871 fname, PTR_DIFF(end_data, p),
1872 STR_TERMINATE, &len);
1873 if (!NT_STATUS_IS_OK(status)) {
1876 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1878 SCVAL(nameptr, -1, len - 2);
1880 SCVAL(nameptr, -1, 0);
1884 SCVAL(nameptr, -1, len - 1);
1886 SCVAL(nameptr, -1, 0);
1892 case SMB_FIND_EA_SIZE:
1893 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1894 if (requires_resume_key) {
1898 srv_put_dos_date2(p,0,create_date);
1899 srv_put_dos_date2(p,4,adate);
1900 srv_put_dos_date2(p,8,mdate);
1901 SIVAL(p,12,(uint32_t)file_size);
1902 SIVAL(p,16,(uint32_t)allocation_size);
1905 unsigned int ea_size = estimate_ea_size(conn, NULL,
1907 SIVAL(p,22,ea_size); /* Extended attributes */
1911 status = srvstr_push(base_data, flags2,
1912 p, fname, PTR_DIFF(end_data, p),
1913 STR_TERMINATE | STR_NOALIGN, &len);
1914 if (!NT_STATUS_IS_OK(status)) {
1917 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1930 SCVAL(nameptr,0,len);
1932 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1935 case SMB_FIND_EA_LIST:
1937 struct ea_list *file_list = NULL;
1940 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1942 return NT_STATUS_INVALID_PARAMETER;
1944 if (requires_resume_key) {
1948 srv_put_dos_date2(p,0,create_date);
1949 srv_put_dos_date2(p,4,adate);
1950 srv_put_dos_date2(p,8,mdate);
1951 SIVAL(p,12,(uint32_t)file_size);
1952 SIVAL(p,16,(uint32_t)allocation_size);
1954 p += 22; /* p now points to the EA area. */
1956 status = get_ea_list_from_file(ctx, conn, NULL,
1958 &ea_len, &file_list);
1959 if (!NT_STATUS_IS_OK(status)) {
1962 name_list = ea_list_union(name_list, file_list, &ea_len);
1964 /* We need to determine if this entry will fit in the space available. */
1965 /* Max string size is 255 bytes. */
1966 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1967 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1968 "(wanted %u, had %d)\n",
1969 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1971 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1974 /* Push the ea_data followed by the name. */
1975 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1977 status = srvstr_push(base_data, flags2,
1978 p + 1, fname, PTR_DIFF(end_data, p+1),
1979 STR_TERMINATE | STR_NOALIGN, &len);
1980 if (!NT_STATUS_IS_OK(status)) {
1983 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1996 SCVAL(nameptr,0,len);
1998 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2002 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2003 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2004 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2006 SIVAL(p,0,reskey); p += 4;
2007 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2008 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2009 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2010 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2011 SOFF_T(p,0,file_size); p += 8;
2012 SOFF_T(p,0,allocation_size); p += 8;
2013 SIVAL(p,0,mode); p += 4;
2014 q = p; p += 4; /* q is placeholder for name length. */
2015 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2016 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2018 unsigned int ea_size = estimate_ea_size(conn, NULL,
2020 SIVAL(p,0,ea_size); /* Extended attributes */
2023 /* Clear the short name buffer. This is
2024 * IMPORTANT as not doing so will trigger
2025 * a Win2k client bug. JRA.
2027 if (!was_8_3 && check_mangled_names) {
2028 char mangled_name[13]; /* mangled 8.3 name. */
2029 if (!name_to_8_3(fname,mangled_name,True,
2031 /* Error - mangle failed ! */
2032 memset(mangled_name,'\0',12);
2034 mangled_name[12] = 0;
2035 status = srvstr_push(base_data, flags2,
2036 p+2, mangled_name, 24,
2037 STR_UPPER|STR_UNICODE, &len);
2038 if (!NT_STATUS_IS_OK(status)) {
2042 memset(p + 2 + len,'\0',24 - len);
2049 status = srvstr_push(base_data, flags2, p,
2050 fname, PTR_DIFF(end_data, p),
2051 STR_TERMINATE_ASCII, &len);
2052 if (!NT_STATUS_IS_OK(status)) {
2058 len = PTR_DIFF(p, pdata);
2059 pad = (len + (align-1)) & ~(align-1);
2061 * offset to the next entry, the caller
2062 * will overwrite it for the last entry
2063 * that's why we always include the padding
2067 * set padding to zero
2070 memset(p, 0, pad - len);
2077 case SMB_FIND_FILE_DIRECTORY_INFO:
2078 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2080 SIVAL(p,0,reskey); p += 4;
2081 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2082 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2083 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2084 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2085 SOFF_T(p,0,file_size); p += 8;
2086 SOFF_T(p,0,allocation_size); p += 8;
2087 SIVAL(p,0,mode); p += 4;
2088 status = srvstr_push(base_data, flags2,
2089 p + 4, fname, PTR_DIFF(end_data, p+4),
2090 STR_TERMINATE_ASCII, &len);
2091 if (!NT_STATUS_IS_OK(status)) {
2097 len = PTR_DIFF(p, pdata);
2098 pad = (len + (align-1)) & ~(align-1);
2100 * offset to the next entry, the caller
2101 * will overwrite it for the last entry
2102 * that's why we always include the padding
2106 * set padding to zero
2109 memset(p, 0, pad - len);
2116 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2117 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2119 SIVAL(p,0,reskey); p += 4;
2120 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2121 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2122 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2123 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2124 SOFF_T(p,0,file_size); p += 8;
2125 SOFF_T(p,0,allocation_size); p += 8;
2126 SIVAL(p,0,mode); p += 4;
2127 q = p; p += 4; /* q is placeholder for name length. */
2129 unsigned int ea_size = estimate_ea_size(conn, NULL,
2131 SIVAL(p,0,ea_size); /* Extended attributes */
2134 status = srvstr_push(base_data, flags2, p,
2135 fname, PTR_DIFF(end_data, p),
2136 STR_TERMINATE_ASCII, &len);
2137 if (!NT_STATUS_IS_OK(status)) {
2143 len = PTR_DIFF(p, pdata);
2144 pad = (len + (align-1)) & ~(align-1);
2146 * offset to the next entry, the caller
2147 * will overwrite it for the last entry
2148 * that's why we always include the padding
2152 * set padding to zero
2155 memset(p, 0, pad - len);
2162 case SMB_FIND_FILE_NAMES_INFO:
2163 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2165 SIVAL(p,0,reskey); p += 4;
2167 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2168 acl on a dir (tridge) */
2169 status = srvstr_push(base_data, flags2, p,
2170 fname, PTR_DIFF(end_data, p),
2171 STR_TERMINATE_ASCII, &len);
2172 if (!NT_STATUS_IS_OK(status)) {
2178 len = PTR_DIFF(p, pdata);
2179 pad = (len + (align-1)) & ~(align-1);
2181 * offset to the next entry, the caller
2182 * will overwrite it for the last entry
2183 * that's why we always include the padding
2187 * set padding to zero
2190 memset(p, 0, pad - len);
2197 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2198 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2200 SIVAL(p,0,reskey); p += 4;
2201 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2202 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2203 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2204 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2205 SOFF_T(p,0,file_size); p += 8;
2206 SOFF_T(p,0,allocation_size); p += 8;
2207 SIVAL(p,0,mode); p += 4;
2208 q = p; p += 4; /* q is placeholder for name length. */
2209 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2210 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2212 unsigned int ea_size = estimate_ea_size(conn, NULL,
2214 SIVAL(p,0,ea_size); /* Extended attributes */
2217 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2218 SBVAL(p,0,file_index); p += 8;
2219 status = srvstr_push(base_data, flags2, p,
2220 fname, PTR_DIFF(end_data, p),
2221 STR_TERMINATE_ASCII, &len);
2222 if (!NT_STATUS_IS_OK(status)) {
2228 len = PTR_DIFF(p, pdata);
2229 pad = (len + (align-1)) & ~(align-1);
2231 * offset to the next entry, the caller
2232 * will overwrite it for the last entry
2233 * that's why we always include the padding
2237 * set padding to zero
2240 memset(p, 0, pad - len);
2247 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2248 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2249 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2251 SIVAL(p,0,reskey); p += 4;
2252 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2253 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2254 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2255 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2256 SOFF_T(p,0,file_size); p += 8;
2257 SOFF_T(p,0,allocation_size); p += 8;
2258 SIVAL(p,0,mode); p += 4;
2259 q = p; p += 4; /* q is placeholder for name length */
2260 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2261 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2262 } else if (readdir_attr_data &&
2263 readdir_attr_data->type == RDATTR_AAPL) {
2265 * OS X specific SMB2 extension negotiated via
2266 * AAPL create context: return max_access in
2269 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2271 unsigned int ea_size = estimate_ea_size(conn, NULL,
2273 SIVAL(p,0,ea_size); /* Extended attributes */
2277 if (readdir_attr_data &&
2278 readdir_attr_data->type == RDATTR_AAPL) {
2280 * OS X specific SMB2 extension negotiated via
2281 * AAPL create context: return resource fork
2282 * length and compressed FinderInfo in
2285 * According to documentation short_name_len
2286 * should be 0, but on the wire behaviour
2287 * shows its set to 24 by clients.
2291 /* Resourefork length */
2292 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2294 /* Compressed FinderInfo */
2295 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2296 } else if (!was_8_3 && check_mangled_names) {
2297 char mangled_name[13]; /* mangled 8.3 name. */
2298 if (!name_to_8_3(fname,mangled_name,True,
2300 /* Error - mangle failed ! */
2301 memset(mangled_name,'\0',12);
2303 mangled_name[12] = 0;
2304 status = srvstr_push(base_data, flags2,
2305 p+2, mangled_name, 24,
2306 STR_UPPER|STR_UNICODE, &len);
2307 if (!NT_STATUS_IS_OK(status)) {
2312 memset(p + 2 + len,'\0',24 - len);
2316 /* Clear the short name buffer. This is
2317 * IMPORTANT as not doing so will trigger
2318 * a Win2k client bug. JRA.
2325 if (readdir_attr_data &&
2326 readdir_attr_data->type == RDATTR_AAPL) {
2328 * OS X specific SMB2 extension negotiated via
2329 * AAPL create context: return UNIX mode in
2332 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2333 SSVAL(p, 0, aapl_mode);
2339 SBVAL(p,0,file_index); p += 8;
2340 status = srvstr_push(base_data, flags2, p,
2341 fname, PTR_DIFF(end_data, p),
2342 STR_TERMINATE_ASCII, &len);
2343 if (!NT_STATUS_IS_OK(status)) {
2349 len = PTR_DIFF(p, pdata);
2350 pad = (len + (align-1)) & ~(align-1);
2352 * offset to the next entry, the caller
2353 * will overwrite it for the last entry
2354 * that's why we always include the padding
2358 * set padding to zero
2361 memset(p, 0, pad - len);
2368 /* CIFS UNIX Extension. */
2370 case SMB_FIND_FILE_UNIX:
2371 case SMB_FIND_FILE_UNIX_INFO2:
2373 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2375 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2377 if (info_level == SMB_FIND_FILE_UNIX) {
2378 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2379 p = store_file_unix_basic(conn, p,
2380 NULL, &smb_fname->st);
2381 status = srvstr_push(base_data, flags2, p,
2382 fname, PTR_DIFF(end_data, p),
2383 STR_TERMINATE, &len);
2384 if (!NT_STATUS_IS_OK(status)) {
2388 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2389 p = store_file_unix_basic_info2(conn, p,
2390 NULL, &smb_fname->st);
2393 status = srvstr_push(base_data, flags2, p, fname,
2394 PTR_DIFF(end_data, p), 0, &len);
2395 if (!NT_STATUS_IS_OK(status)) {
2398 SIVAL(nameptr, 0, len);
2403 len = PTR_DIFF(p, pdata);
2404 pad = (len + (align-1)) & ~(align-1);
2406 * offset to the next entry, the caller
2407 * will overwrite it for the last entry
2408 * that's why we always include the padding
2412 * set padding to zero
2415 memset(p, 0, pad - len);
2420 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2425 return NT_STATUS_INVALID_LEVEL;
2428 if (PTR_DIFF(p,pdata) > space_remaining) {
2429 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2430 "(wanted %u, had %d)\n",
2431 (unsigned int)PTR_DIFF(p,pdata),
2433 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2436 /* Setup the last entry pointer, as an offset from base_data */
2437 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2438 /* Advance the data pointer to the next slot */
2441 return NT_STATUS_OK;
2444 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2445 connection_struct *conn,
2446 struct dptr_struct *dirptr,
2448 const char *path_mask,
2451 int requires_resume_key,
2460 int space_remaining,
2461 struct smb_filename **_smb_fname,
2462 bool *got_exact_match,
2463 int *_last_entry_off,
2464 struct ea_list *name_list,
2465 struct file_id *file_id)
2468 const char *mask = NULL;
2469 long prev_dirpos = 0;
2472 struct smb_filename *smb_fname = NULL;
2473 struct smbd_dirptr_lanman2_state state;
2475 uint64_t last_entry_off = 0;
2477 enum mangled_names_options mangled_names;
2478 bool marshall_with_83_names;
2480 mangled_names = lp_mangled_names(conn->params);
2484 state.info_level = info_level;
2485 if (mangled_names != MANGLED_NAMES_NO) {
2486 state.check_mangled_names = true;
2488 state.has_wild = dptr_has_wild(dirptr);
2489 state.got_exact_match = false;
2491 *got_exact_match = false;
2493 p = strrchr_m(path_mask,'/');
2504 ok = smbd_dirptr_get_entry(ctx,
2511 smbd_dirptr_lanman2_match_fn,
2512 smbd_dirptr_lanman2_mode_fn,
2519 return NT_STATUS_END_OF_FILE;
2522 *got_exact_match = state.got_exact_match;
2524 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2526 status = smbd_marshall_dir_entry(ctx,
2531 marshall_with_83_names,
2532 requires_resume_key,
2543 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2544 DEBUG(1,("Conversion error: illegal character: %s\n",
2545 smb_fname_str_dbg(smb_fname)));
2548 if (file_id != NULL) {
2549 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2552 if (!NT_STATUS_IS_OK(status) &&
2553 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2555 TALLOC_FREE(smb_fname);
2560 if (_smb_fname != NULL) {
2561 struct smb_filename *name = NULL;
2563 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2565 TALLOC_FREE(smb_fname);
2567 return NT_STATUS_NO_MEMORY;
2572 TALLOC_FREE(smb_fname);
2575 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2576 dptr_SeekDir(dirptr, prev_dirpos);
2580 *_last_entry_off = last_entry_off;
2581 return NT_STATUS_OK;
2584 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2585 connection_struct *conn,
2586 struct dptr_struct *dirptr,
2588 const char *path_mask,
2591 bool requires_resume_key,
2597 int space_remaining,
2598 bool *got_exact_match,
2599 int *last_entry_off,
2600 struct ea_list *name_list)
2603 const bool do_pad = true;
2605 if (info_level >= 1 && info_level <= 3) {
2606 /* No alignment on earlier info levels. */
2610 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2611 path_mask, dirtype, info_level,
2612 requires_resume_key, dont_descend, ask_sharemode,
2613 true, align, do_pad,
2614 ppdata, base_data, end_data,
2618 last_entry_off, name_list, NULL);
2621 /****************************************************************************
2622 Reply to a TRANS2_FINDFIRST.
2623 ****************************************************************************/
2625 static void call_trans2findfirst(connection_struct *conn,
2626 struct smb_request *req,
2627 char **pparams, int total_params,
2628 char **ppdata, int total_data,
2629 unsigned int max_data_bytes)
2631 /* We must be careful here that we don't return more than the
2632 allowed number of data bytes. If this means returning fewer than
2633 maxentries then so be it. We assume that the redirector has
2634 enough room for the fixed number of parameter bytes it has
2636 struct smb_filename *smb_dname = NULL;
2637 char *params = *pparams;
2638 char *pdata = *ppdata;
2642 uint16_t findfirst_flags;
2643 bool close_after_first;
2645 bool requires_resume_key;
2647 char *directory = NULL;
2650 int last_entry_off=0;
2654 bool finished = False;
2655 bool dont_descend = False;
2656 bool out_of_space = False;
2657 int space_remaining;
2658 bool mask_contains_wcard = False;
2659 struct ea_list *ea_list = NULL;
2660 NTSTATUS ntstatus = NT_STATUS_OK;
2661 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2662 struct dptr_struct *dirptr = NULL;
2663 struct smbd_server_connection *sconn = req->sconn;
2664 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2665 ucf_flags_from_smb_request(req);
2666 bool backup_priv = false;
2667 bool as_root = false;
2669 if (total_params < 13) {
2670 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2674 dirtype = SVAL(params,0);
2675 maxentries = SVAL(params,2);
2676 findfirst_flags = SVAL(params,4);
2677 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2678 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2679 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2680 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2681 security_token_has_privilege(get_current_nttok(conn),
2684 info_level = SVAL(params,6);
2686 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2687 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2688 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2690 info_level, max_data_bytes));
2693 /* W2K3 seems to treat zero as 1. */
2697 switch (info_level) {
2698 case SMB_FIND_INFO_STANDARD:
2699 case SMB_FIND_EA_SIZE:
2700 case SMB_FIND_EA_LIST:
2701 case SMB_FIND_FILE_DIRECTORY_INFO:
2702 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2703 case SMB_FIND_FILE_NAMES_INFO:
2704 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2705 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2706 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2708 case SMB_FIND_FILE_UNIX:
2709 case SMB_FIND_FILE_UNIX_INFO2:
2710 /* Always use filesystem for UNIX mtime query. */
2711 ask_sharemode = false;
2712 if (!lp_unix_extensions()) {
2713 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2716 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2719 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2723 if (req->posix_pathnames) {
2724 srvstr_get_path_wcard_posix(talloc_tos(),
2732 &mask_contains_wcard);
2734 srvstr_get_path_wcard(talloc_tos(),
2742 &mask_contains_wcard);
2744 if (!NT_STATUS_IS_OK(ntstatus)) {
2745 reply_nterror(req, ntstatus);
2752 ntstatus = filename_convert_with_privilege(talloc_tos(),
2757 &mask_contains_wcard,
2760 ntstatus = filename_convert(talloc_tos(), conn,
2763 &mask_contains_wcard,
2767 if (!NT_STATUS_IS_OK(ntstatus)) {
2768 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2769 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2770 ERRSRV, ERRbadpath);
2773 reply_nterror(req, ntstatus);
2777 mask = smb_dname->original_lcomp;
2779 directory = smb_dname->base_name;
2781 p = strrchr_m(directory,'/');
2783 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2784 if((directory[0] == '.') && (directory[1] == '\0')) {
2785 mask = talloc_strdup(talloc_tos(),"*");
2787 reply_nterror(req, NT_STATUS_NO_MEMORY);
2790 mask_contains_wcard = True;
2796 if (p == NULL || p == directory) {
2797 /* Ensure we don't have a directory name of "". */
2798 directory = talloc_strdup(talloc_tos(), ".");
2800 reply_nterror(req, NT_STATUS_NO_MEMORY);
2803 /* Ensure smb_dname->base_name matches. */
2804 smb_dname->base_name = directory;
2807 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2809 if (info_level == SMB_FIND_EA_LIST) {
2812 if (total_data < 4) {
2813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2817 ea_size = IVAL(pdata,0);
2818 if (ea_size != total_data) {
2819 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2820 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2825 if (!lp_ea_support(SNUM(conn))) {
2826 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2830 /* Pull out the list of names. */
2831 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2833 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2838 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2839 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2843 *ppdata = (char *)SMB_REALLOC(
2844 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2845 if(*ppdata == NULL ) {
2846 reply_nterror(req, NT_STATUS_NO_MEMORY);
2850 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2852 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2855 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2856 /* Realloc the params space */
2857 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2858 if (*pparams == NULL) {
2859 reply_nterror(req, NT_STATUS_NO_MEMORY);
2864 /* Save the wildcard match and attribs we are using on this directory -
2865 needed as lanman2 assumes these are being saved between calls */
2867 ntstatus = dptr_create(conn,
2875 mask_contains_wcard,
2879 if (!NT_STATUS_IS_OK(ntstatus)) {
2880 reply_nterror(req, ntstatus);
2885 /* Remember this in case we have
2886 to do a findnext. */
2887 dptr_set_priv(dirptr);
2890 dptr_num = dptr_dnum(dirptr);
2891 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2893 /* We don't need to check for VOL here as this is returned by
2894 a different TRANS2 call. */
2896 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2897 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2898 if (in_list(directory,
2899 lp_dont_descend(talloc_tos(), SNUM(conn)),
2900 conn->case_sensitive)) {
2901 dont_descend = True;
2905 space_remaining = max_data_bytes;
2906 out_of_space = False;
2908 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2909 bool got_exact_match = False;
2911 /* this is a heuristic to avoid seeking the dirptr except when
2912 absolutely necessary. It allows for a filename of about 40 chars */
2913 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2914 out_of_space = True;
2917 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2921 mask,dirtype,info_level,
2922 requires_resume_key,dont_descend,
2927 &last_entry_off, ea_list);
2928 if (NT_STATUS_EQUAL(ntstatus,
2929 NT_STATUS_ILLEGAL_CHARACTER)) {
2931 * Bad character conversion on name. Ignore this
2936 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2937 out_of_space = true;
2939 finished = !NT_STATUS_IS_OK(ntstatus);
2943 if (!finished && !out_of_space)
2947 * As an optimisation if we know we aren't looking
2948 * for a wildcard name (ie. the name matches the wildcard exactly)
2949 * then we can finish on any (first) match.
2950 * This speeds up large directory searches. JRA.
2956 /* Ensure space_remaining never goes -ve. */
2957 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2958 space_remaining = 0;
2959 out_of_space = true;
2961 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2965 /* Check if we can close the dirptr */
2966 if(close_after_first || (finished && close_if_end)) {
2967 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2968 dptr_close(sconn, &dptr_num);
2972 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2973 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2974 * the protocol level is less than NT1. Tested with smbclient. JRA.
2975 * This should fix the OS/2 client bug #2335.
2978 if(numentries == 0) {
2979 dptr_close(sconn, &dptr_num);
2980 if (get_Protocol() < PROTOCOL_NT1) {
2981 reply_force_doserror(req, ERRDOS, ERRnofiles);
2984 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2985 ERRDOS, ERRbadfile);
2990 /* At this point pdata points to numentries directory entries. */
2992 /* Set up the return parameter block */
2993 SSVAL(params,0,dptr_num);
2994 SSVAL(params,2,numentries);
2995 SSVAL(params,4,finished);
2996 SSVAL(params,6,0); /* Never an EA error */
2997 SSVAL(params,8,last_entry_off);
2999 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3002 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3003 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3005 reply_nterror(req, NT_STATUS_NO_MEMORY);
3009 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3010 smb_fn_name(req->cmd),
3011 mask, directory, dirtype, numentries ) );
3014 * Force a name mangle here to ensure that the
3015 * mask as an 8.3 name is top of the mangled cache.
3016 * The reasons for this are subtle. Don't remove
3017 * this code unless you know what you are doing
3018 * (see PR#13758). JRA.
3021 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3022 char mangled_name[13];
3023 name_to_8_3(mask, mangled_name, True, conn->params);
3031 TALLOC_FREE(smb_dname);
3035 /****************************************************************************
3036 Reply to a TRANS2_FINDNEXT.
3037 ****************************************************************************/
3039 static void call_trans2findnext(connection_struct *conn,
3040 struct smb_request *req,
3041 char **pparams, int total_params,
3042 char **ppdata, int total_data,
3043 unsigned int max_data_bytes)
3045 /* We must be careful here that we don't return more than the
3046 allowed number of data bytes. If this means returning fewer than
3047 maxentries then so be it. We assume that the redirector has
3048 enough room for the fixed number of parameter bytes it has
3050 char *params = *pparams;
3051 char *pdata = *ppdata;
3055 uint16_t info_level;
3056 uint32_t resume_key;
3057 uint16_t findnext_flags;
3058 bool close_after_request;
3060 bool requires_resume_key;
3062 bool mask_contains_wcard = False;
3063 char *resume_name = NULL;
3064 const char *mask = NULL;
3065 const char *directory = NULL;
3069 int i, last_entry_off=0;
3070 bool finished = False;
3071 bool dont_descend = False;
3072 bool out_of_space = False;
3073 int space_remaining;
3074 struct ea_list *ea_list = NULL;
3075 NTSTATUS ntstatus = NT_STATUS_OK;
3076 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3077 TALLOC_CTX *ctx = talloc_tos();
3078 struct dptr_struct *dirptr;
3079 struct smbd_server_connection *sconn = req->sconn;
3080 bool backup_priv = false;
3081 bool as_root = false;
3083 if (total_params < 13) {
3084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3088 dptr_num = SVAL(params,0);
3089 maxentries = SVAL(params,2);
3090 info_level = SVAL(params,4);
3091 resume_key = IVAL(params,6);
3092 findnext_flags = SVAL(params,10);
3093 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3094 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3095 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3096 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3098 if (!continue_bit) {
3099 /* We only need resume_name if continue_bit is zero. */
3100 if (req->posix_pathnames) {
3101 srvstr_get_path_wcard_posix(ctx,
3109 &mask_contains_wcard);
3111 srvstr_get_path_wcard(ctx,
3119 &mask_contains_wcard);
3121 if (!NT_STATUS_IS_OK(ntstatus)) {
3122 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3123 complain (it thinks we're asking for the directory above the shared
3124 path or an invalid name). Catch this as the resume name is only compared, never used in
3125 a file access. JRA. */
3126 srvstr_pull_talloc(ctx, params, req->flags2,
3127 &resume_name, params+12,
3131 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3132 reply_nterror(req, ntstatus);
3138 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3139 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3140 resume_key = %d resume name = %s continue=%d level = %d\n",
3141 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3142 requires_resume_key, resume_key,
3143 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3146 /* W2K3 seems to treat zero as 1. */
3150 switch (info_level) {
3151 case SMB_FIND_INFO_STANDARD:
3152 case SMB_FIND_EA_SIZE:
3153 case SMB_FIND_EA_LIST:
3154 case SMB_FIND_FILE_DIRECTORY_INFO:
3155 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3156 case SMB_FIND_FILE_NAMES_INFO:
3157 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3158 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3159 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3161 case SMB_FIND_FILE_UNIX:
3162 case SMB_FIND_FILE_UNIX_INFO2:
3163 /* Always use filesystem for UNIX mtime query. */
3164 ask_sharemode = false;
3165 if (!lp_unix_extensions()) {
3166 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3171 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3175 if (info_level == SMB_FIND_EA_LIST) {
3178 if (total_data < 4) {
3179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3183 ea_size = IVAL(pdata,0);
3184 if (ea_size != total_data) {
3185 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3186 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3191 if (!lp_ea_support(SNUM(conn))) {
3192 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3196 /* Pull out the list of names. */
3197 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3204 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3205 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3209 *ppdata = (char *)SMB_REALLOC(
3210 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3211 if(*ppdata == NULL) {
3212 reply_nterror(req, NT_STATUS_NO_MEMORY);
3217 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3220 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3223 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3224 /* Realloc the params space */
3225 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3226 if(*pparams == NULL ) {
3227 reply_nterror(req, NT_STATUS_NO_MEMORY);
3233 /* Check that the dptr is valid */
3234 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3235 reply_nterror(req, STATUS_NO_MORE_FILES);
3239 directory = dptr_path(sconn, dptr_num);
3241 /* Get the wildcard mask from the dptr */
3242 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3243 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3244 reply_nterror(req, STATUS_NO_MORE_FILES);
3248 /* Get the attr mask from the dptr */
3249 dirtype = dptr_attr(sconn, dptr_num);
3251 backup_priv = dptr_get_priv(dirptr);
3253 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3254 "backup_priv = %d\n",
3255 dptr_num, mask, dirtype,
3257 dptr_TellDir(dirptr),
3260 /* We don't need to check for VOL here as this is returned by
3261 a different TRANS2 call. */
3263 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3264 directory,lp_dont_descend(ctx, SNUM(conn))));
3265 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3266 dont_descend = True;
3269 space_remaining = max_data_bytes;
3270 out_of_space = False;
3278 * Seek to the correct position. We no longer use the resume key but
3279 * depend on the last file name instead.
3282 if(!continue_bit && resume_name && *resume_name) {
3285 long current_pos = 0;
3287 * Remember, name_to_8_3 is called by
3288 * get_lanman2_dir_entry(), so the resume name
3289 * could be mangled. Ensure we check the unmangled name.
3292 if (mangle_is_mangled(resume_name, conn->params)) {
3293 char *new_resume_name = NULL;
3294 mangle_lookup_name_from_8_3(ctx,
3298 if (new_resume_name) {
3299 resume_name = new_resume_name;
3304 * Fix for NT redirector problem triggered by resume key indexes
3305 * changing between directory scans. We now return a resume key of 0
3306 * and instead look for the filename to continue from (also given
3307 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3308 * findfirst/findnext (as is usual) then the directory pointer
3309 * should already be at the correct place.
3312 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3313 } /* end if resume_name && !continue_bit */
3315 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3316 bool got_exact_match = False;
3318 /* this is a heuristic to avoid seeking the dirptr except when
3319 absolutely necessary. It allows for a filename of about 40 chars */
3320 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3321 out_of_space = True;
3324 ntstatus = get_lanman2_dir_entry(ctx,
3328 mask,dirtype,info_level,
3329 requires_resume_key,dont_descend,
3334 &last_entry_off, ea_list);
3335 if (NT_STATUS_EQUAL(ntstatus,
3336 NT_STATUS_ILLEGAL_CHARACTER)) {
3338 * Bad character conversion on name. Ignore this
3343 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3344 out_of_space = true;
3346 finished = !NT_STATUS_IS_OK(ntstatus);
3350 if (!finished && !out_of_space)
3354 * As an optimisation if we know we aren't looking
3355 * for a wildcard name (ie. the name matches the wildcard exactly)
3356 * then we can finish on any (first) match.
3357 * This speeds up large directory searches. JRA.
3363 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3366 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3367 smb_fn_name(req->cmd),
3368 mask, directory, dirtype, numentries ) );
3370 /* Check if we can close the dirptr */
3371 if(close_after_request || (finished && close_if_end)) {
3372 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3373 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3380 /* Set up the return parameter block */
3381 SSVAL(params,0,numentries);
3382 SSVAL(params,2,finished);
3383 SSVAL(params,4,0); /* Never an EA error */
3384 SSVAL(params,6,last_entry_off);
3386 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3392 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3394 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3398 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3400 SMB_ASSERT(extended_info != NULL);
3402 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3403 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3404 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3405 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3406 #ifdef SAMBA_VERSION_REVISION
3407 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3409 extended_info->samba_subversion = 0;
3410 #ifdef SAMBA_VERSION_RC_RELEASE
3411 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3413 #ifdef SAMBA_VERSION_PRE_RELEASE
3414 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3417 #ifdef SAMBA_VERSION_VENDOR_PATCH
3418 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3420 extended_info->samba_gitcommitdate = 0;
3421 #ifdef SAMBA_VERSION_COMMIT_TIME
3422 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3425 memset(extended_info->samba_version_string, 0,
3426 sizeof(extended_info->samba_version_string));
3428 snprintf (extended_info->samba_version_string,
3429 sizeof(extended_info->samba_version_string),
3430 "%s", samba_version_string());
3433 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3434 connection_struct *conn,
3435 TALLOC_CTX *mem_ctx,
3436 uint16_t info_level,
3438 unsigned int max_data_bytes,
3439 size_t *fixed_portion,
3440 struct smb_filename *fname,
3444 char *pdata, *end_data;
3447 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3448 int snum = SNUM(conn);
3449 const char *fstype = lp_fstype(SNUM(conn));
3450 const char *filename = NULL;
3451 const uint64_t bytes_per_sector = 512;
3452 uint32_t additional_flags = 0;
3453 struct smb_filename smb_fname;
3455 NTSTATUS status = NT_STATUS_OK;
3458 if (fname == NULL || fname->base_name == NULL) {
3461 filename = fname->base_name;
3465 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3466 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3467 "info level (0x%x) on IPC$.\n",
3468 (unsigned int)info_level));
3469 return NT_STATUS_ACCESS_DENIED;
3473 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3475 ZERO_STRUCT(smb_fname);
3476 smb_fname.base_name = discard_const_p(char, filename);
3478 if(info_level != SMB_FS_QUOTA_INFORMATION
3479 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3480 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3481 return map_nt_error_from_unix(errno);
3486 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3487 return NT_STATUS_INVALID_PARAMETER;
3490 *ppdata = (char *)SMB_REALLOC(
3491 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3492 if (*ppdata == NULL) {
3493 return NT_STATUS_NO_MEMORY;
3497 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3498 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3502 switch (info_level) {
3503 case SMB_INFO_ALLOCATION:
3505 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3507 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3509 if (df_ret == (uint64_t)-1) {
3510 return map_nt_error_from_unix(errno);
3513 block_size = lp_block_size(snum);
3514 if (bsize < block_size) {
3515 uint64_t factor = block_size/bsize;
3520 if (bsize > block_size) {
3521 uint64_t factor = bsize/block_size;
3526 sectors_per_unit = bsize/bytes_per_sector;
3528 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3529 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3530 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3533 * For large drives, return max values and not modulo.
3535 dsize = MIN(dsize, UINT32_MAX);
3536 dfree = MIN(dfree, UINT32_MAX);
3538 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3539 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3540 SIVAL(pdata,l1_cUnit,dsize);
3541 SIVAL(pdata,l1_cUnitAvail,dfree);
3542 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3546 case SMB_INFO_VOLUME:
3547 /* Return volume name */
3549 * Add volume serial number - hash of a combination of
3550 * the called hostname and the service name.
3552 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3554 * Win2k3 and previous mess this up by sending a name length
3555 * one byte short. I believe only older clients (OS/2 Win9x) use
3556 * this call so try fixing this by adding a terminating null to
3557 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3559 status = srvstr_push(
3561 pdata+l2_vol_szVolLabel, vname,
3562 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3563 STR_NOALIGN|STR_TERMINATE, &len);
3564 if (!NT_STATUS_IS_OK(status)) {
3567 SCVAL(pdata,l2_vol_cch,len);
3568 data_len = l2_vol_szVolLabel + len;
3569 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3570 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3571 (unsigned)len, vname));
3574 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3575 case SMB_FS_ATTRIBUTE_INFORMATION:
3577 additional_flags = 0;
3578 #if defined(HAVE_SYS_QUOTAS)
3579 additional_flags |= FILE_VOLUME_QUOTAS;
3582 if(lp_nt_acl_support(SNUM(conn))) {
3583 additional_flags |= FILE_PERSISTENT_ACLS;
3586 /* Capabilities are filled in at connection time through STATVFS call */
3587 additional_flags |= conn->fs_capabilities;
3588 additional_flags |= lp_parm_int(conn->params->service,
3589 "share", "fake_fscaps",
3592 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3593 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3594 additional_flags); /* FS ATTRIBUTES */
3596 SIVAL(pdata,4,255); /* Max filename component length */
3597 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3598 and will think we can't do long filenames */
3599 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3600 PTR_DIFF(end_data, pdata+12),
3602 if (!NT_STATUS_IS_OK(status)) {
3606 data_len = 12 + len;
3607 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3608 /* the client only requested a portion of the
3610 data_len = max_data_bytes;
3611 status = STATUS_BUFFER_OVERFLOW;
3613 *fixed_portion = 16;
3616 case SMB_QUERY_FS_LABEL_INFO:
3617 case SMB_FS_LABEL_INFORMATION:
3618 status = srvstr_push(pdata, flags2, pdata+4, vname,
3619 PTR_DIFF(end_data, pdata+4), 0, &len);
3620 if (!NT_STATUS_IS_OK(status)) {
3627 case SMB_QUERY_FS_VOLUME_INFO:
3628 case SMB_FS_VOLUME_INFORMATION:
3631 * Add volume serial number - hash of a combination of
3632 * the called hostname and the service name.
3634 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3635 (str_checksum(get_local_machine_name())<<16));
3637 /* Max label len is 32 characters. */
3638 status = srvstr_push(pdata, flags2, pdata+18, vname,
3639 PTR_DIFF(end_data, pdata+18),
3641 if (!NT_STATUS_IS_OK(status)) {
3644 SIVAL(pdata,12,len);
3647 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3648 (int)strlen(vname),vname,
3649 lp_servicename(talloc_tos(), snum)));
3650 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3651 /* the client only requested a portion of the
3653 data_len = max_data_bytes;
3654 status = STATUS_BUFFER_OVERFLOW;
3656 *fixed_portion = 24;
3659 case SMB_QUERY_FS_SIZE_INFO:
3660 case SMB_FS_SIZE_INFORMATION:
3662 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3664 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3666 if (df_ret == (uint64_t)-1) {
3667 return map_nt_error_from_unix(errno);
3669 block_size = lp_block_size(snum);
3670 if (bsize < block_size) {
3671 uint64_t factor = block_size/bsize;
3676 if (bsize > block_size) {
3677 uint64_t factor = bsize/block_size;
3682 sectors_per_unit = bsize/bytes_per_sector;
3683 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3684 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3685 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3686 SBIG_UINT(pdata,0,dsize);
3687 SBIG_UINT(pdata,8,dfree);
3688 SIVAL(pdata,16,sectors_per_unit);
3689 SIVAL(pdata,20,bytes_per_sector);
3690 *fixed_portion = 24;
3694 case SMB_FS_FULL_SIZE_INFORMATION:
3696 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3698 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3700 if (df_ret == (uint64_t)-1) {
3701 return map_nt_error_from_unix(errno);
3703 block_size = lp_block_size(snum);
3704 if (bsize < block_size) {
3705 uint64_t factor = block_size/bsize;
3710 if (bsize > block_size) {
3711 uint64_t factor = bsize/block_size;
3716 sectors_per_unit = bsize/bytes_per_sector;
3717 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3718 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3719 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3720 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3721 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3722 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3723 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3724 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3725 *fixed_portion = 32;
3729 case SMB_QUERY_FS_DEVICE_INFO:
3730 case SMB_FS_DEVICE_INFORMATION:
3732 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3734 if (!CAN_WRITE(conn)) {
3735 characteristics |= FILE_READ_ONLY_DEVICE;
3738 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3739 SIVAL(pdata,4,characteristics);
3744 #ifdef HAVE_SYS_QUOTAS
3745 case SMB_FS_QUOTA_INFORMATION:
3747 * what we have to send --metze:
3749 * Unknown1: 24 NULL bytes
3750 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3751 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3752 * Quota Flags: 2 byte :
3753 * Unknown3: 6 NULL bytes
3757 * details for Quota Flags:
3759 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3760 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3761 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3762 * 0x0001 Enable Quotas: enable quota for this fs
3766 /* we need to fake up a fsp here,
3767 * because its not send in this call
3770 SMB_NTQUOTA_STRUCT quotas;
3773 ZERO_STRUCT(quotas);
3776 fsp.fnum = FNUM_FIELD_INVALID;
3779 if (get_current_uid(conn) != 0) {
3780 DEBUG(0,("get_user_quota: access_denied "
3781 "service [%s] user [%s]\n",
3782 lp_servicename(talloc_tos(), SNUM(conn)),
3783 conn->session_info->unix_info->unix_name));
3784 return NT_STATUS_ACCESS_DENIED;
3787 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3789 if (!NT_STATUS_IS_OK(status)) {
3790 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3796 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3797 lp_servicename(talloc_tos(), SNUM(conn))));
3799 /* Unknown1 24 NULL bytes*/
3800 SBIG_UINT(pdata,0,(uint64_t)0);
3801 SBIG_UINT(pdata,8,(uint64_t)0);
3802 SBIG_UINT(pdata,16,(uint64_t)0);
3804 /* Default Soft Quota 8 bytes */
3805 SBIG_UINT(pdata,24,quotas.softlim);
3807 /* Default Hard Quota 8 bytes */
3808 SBIG_UINT(pdata,32,quotas.hardlim);
3810 /* Quota flag 2 bytes */
3811 SSVAL(pdata,40,quotas.qflags);
3813 /* Unknown3 6 NULL bytes */
3819 #endif /* HAVE_SYS_QUOTAS */
3820 case SMB_FS_OBJECTID_INFORMATION:
3822 unsigned char objid[16];
3823 struct smb_extended_info extended_info;
3824 memcpy(pdata,create_volume_objectid(conn, objid),16);
3825 samba_extended_info_version (&extended_info);
3826 SIVAL(pdata,16,extended_info.samba_magic);
3827 SIVAL(pdata,20,extended_info.samba_version);
3828 SIVAL(pdata,24,extended_info.samba_subversion);
3829 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3830 memcpy(pdata+36,extended_info.samba_version_string,28);
3835 case SMB_FS_SECTOR_SIZE_INFORMATION:
3839 * These values match a physical Windows Server 2012
3840 * share backed by NTFS atop spinning rust.
3842 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3843 /* logical_bytes_per_sector */
3844 SIVAL(pdata, 0, bytes_per_sector);
3845 /* phys_bytes_per_sector_atomic */
3846 SIVAL(pdata, 4, bytes_per_sector);
3847 /* phys_bytes_per_sector_perf */
3848 SIVAL(pdata, 8, bytes_per_sector);
3849 /* fs_effective_phys_bytes_per_sector_atomic */
3850 SIVAL(pdata, 12, bytes_per_sector);
3852 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3853 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3854 /* byte_off_sector_align */
3855 SIVAL(pdata, 20, 0);
3856 /* byte_off_partition_align */
3857 SIVAL(pdata, 24, 0);
3858 *fixed_portion = 28;
3864 * Query the version and capabilities of the CIFS UNIX extensions
3868 case SMB_QUERY_CIFS_UNIX_INFO:
3870 bool large_write = lp_min_receive_file_size() &&
3871 !srv_is_signing_active(xconn);
3872 bool large_read = !srv_is_signing_active(xconn);
3873 int encrypt_caps = 0;
3875 if (!lp_unix_extensions()) {
3876 return NT_STATUS_INVALID_LEVEL;
3879 switch (conn->encrypt_level) {
3880 case SMB_SIGNING_OFF:
3883 case SMB_SIGNING_DESIRED:
3884 case SMB_SIGNING_IF_REQUIRED:
3885 case SMB_SIGNING_DEFAULT:
3886 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3888 case SMB_SIGNING_REQUIRED:
3889 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3890 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3891 large_write = false;
3897 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3898 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3900 /* We have POSIX ACLs, pathname, encryption,
3901 * large read/write, and locking capability. */
3903 SBIG_UINT(pdata,4,((uint64_t)(
3904 CIFS_UNIX_POSIX_ACLS_CAP|
3905 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3906 CIFS_UNIX_FCNTL_LOCKS_CAP|
3907 CIFS_UNIX_EXTATTR_CAP|
3908 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3910 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3912 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3916 case SMB_QUERY_POSIX_FS_INFO:
3919 vfs_statvfs_struct svfs;
3921 if (!lp_unix_extensions()) {
3922 return NT_STATUS_INVALID_LEVEL;
3925 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3929 SIVAL(pdata,0,svfs.OptimalTransferSize);
3930 SIVAL(pdata,4,svfs.BlockSize);
3931 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3932 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3933 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3934 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3935 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3936 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3937 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3939 } else if (rc == EOPNOTSUPP) {
3940 return NT_STATUS_INVALID_LEVEL;
3941 #endif /* EOPNOTSUPP */
3943 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3944 return NT_STATUS_DOS(ERRSRV, ERRerror);
3949 case SMB_QUERY_POSIX_WHOAMI:
3955 if (!lp_unix_extensions()) {
3956 return NT_STATUS_INVALID_LEVEL;
3959 if (max_data_bytes < 40) {
3960 return NT_STATUS_BUFFER_TOO_SMALL;
3963 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3964 flags |= SMB_WHOAMI_GUEST;
3967 /* NOTE: 8 bytes for UID/GID, irrespective of native
3968 * platform size. This matches
3969 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3971 data_len = 4 /* flags */
3978 + 4 /* pad/reserved */
3979 + (conn->session_info->unix_token->ngroups * 8)
3981 + (conn->session_info->security_token->num_sids *
3985 SIVAL(pdata, 0, flags);
3986 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3988 (uint64_t)conn->session_info->unix_token->uid);
3989 SBIG_UINT(pdata, 16,
3990 (uint64_t)conn->session_info->unix_token->gid);
3993 if (data_len >= max_data_bytes) {
3994 /* Potential overflow, skip the GIDs and SIDs. */
3996 SIVAL(pdata, 24, 0); /* num_groups */
3997 SIVAL(pdata, 28, 0); /* num_sids */
3998 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3999 SIVAL(pdata, 36, 0); /* reserved */
4005 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4006 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4008 /* We walk the SID list twice, but this call is fairly
4009 * infrequent, and I don't expect that it's performance
4010 * sensitive -- jpeach
4012 for (i = 0, sid_bytes = 0;
4013 i < conn->session_info->security_token->num_sids; ++i) {
4014 sid_bytes += ndr_size_dom_sid(
4015 &conn->session_info->security_token->sids[i],
4019 /* SID list byte count */
4020 SIVAL(pdata, 32, sid_bytes);
4022 /* 4 bytes pad/reserved - must be zero */
4023 SIVAL(pdata, 36, 0);
4027 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4028 SBIG_UINT(pdata, data_len,
4029 (uint64_t)conn->session_info->unix_token->groups[i]);
4035 i < conn->session_info->security_token->num_sids; ++i) {
4036 int sid_len = ndr_size_dom_sid(
4037 &conn->session_info->security_token->sids[i],
4040 sid_linearize((uint8_t *)(pdata + data_len),
4042 &conn->session_info->security_token->sids[i]);
4043 data_len += sid_len;
4049 case SMB_MAC_QUERY_FS_INFO:
4051 * Thursby MAC extension... ONLY on NTFS filesystems
4052 * once we do streams then we don't need this
4054 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4056 SIVAL(pdata,84,0x100); /* Don't support mac... */
4062 return NT_STATUS_INVALID_LEVEL;
4065 *ret_data_len = data_len;
4069 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4070 struct smb_request *req,
4072 const DATA_BLOB *qdata)
4075 SMB_NTQUOTA_STRUCT quotas;
4077 ZERO_STRUCT(quotas);
4080 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4081 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4082 lp_servicename(talloc_tos(), SNUM(conn)),
4083 conn->session_info->unix_info->unix_name));
4084 return NT_STATUS_ACCESS_DENIED;
4087 if (!check_fsp_ntquota_handle(conn, req,
4089 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4090 return NT_STATUS_INVALID_HANDLE;
4093 /* note: normally there're 48 bytes,
4094 * but we didn't use the last 6 bytes for now
4097 if (qdata->length < 42) {
4098 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4099 (unsigned int)qdata->length));
4100 return NT_STATUS_INVALID_PARAMETER;
4103 /* unknown_1 24 NULL bytes in pdata*/
4105 /* the soft quotas 8 bytes (uint64_t)*/
4106 quotas.softlim = BVAL(qdata->data,24);
4108 /* the hard quotas 8 bytes (uint64_t)*/
4109 quotas.hardlim = BVAL(qdata->data,32);
4111 /* quota_flags 2 bytes **/
4112 quotas.qflags = SVAL(qdata->data,40);
4114 /* unknown_2 6 NULL bytes follow*/
4116 /* now set the quotas */
4117 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4118 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4119 lp_servicename(talloc_tos(), SNUM(conn))));
4120 status = map_nt_error_from_unix(errno);
4122 status = NT_STATUS_OK;
4127 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4128 struct smb_request *req,
4129 TALLOC_CTX *mem_ctx,
4130 uint16_t info_level,
4132 const DATA_BLOB *pdata)
4134 switch (info_level) {
4135 case SMB_FS_QUOTA_INFORMATION:
4137 return smb_set_fsquota(conn,
4146 return NT_STATUS_INVALID_LEVEL;
4149 /****************************************************************************
4150 Reply to a TRANS2_QFSINFO (query filesystem info).
4151 ****************************************************************************/
4153 static void call_trans2qfsinfo(connection_struct *conn,
4154 struct smb_request *req,
4155 char **pparams, int total_params,
4156 char **ppdata, int total_data,
4157 unsigned int max_data_bytes)
4159 char *params = *pparams;
4160 uint16_t info_level;
4162 size_t fixed_portion;
4165 if (total_params < 2) {
4166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4170 info_level = SVAL(params,0);
4172 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4173 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4174 DEBUG(0,("call_trans2qfsinfo: encryption required "
4175 "and info level 0x%x sent.\n",
4176 (unsigned int)info_level));
4177 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4182 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4184 status = smbd_do_qfsinfo(req->xconn, conn, req,
4191 if (!NT_STATUS_IS_OK(status)) {
4192 reply_nterror(req, status);
4196 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4199 DEBUG( 4, ( "%s info_level = %d\n",
4200 smb_fn_name(req->cmd), info_level) );
4205 /****************************************************************************
4206 Reply to a TRANS2_SETFSINFO (set filesystem info).
4207 ****************************************************************************/
4209 static void call_trans2setfsinfo(connection_struct *conn,
4210 struct smb_request *req,
4211 char **pparams, int total_params,
4212 char **ppdata, int total_data,
4213 unsigned int max_data_bytes)
4215 struct smbXsrv_connection *xconn = req->xconn;
4216 char *pdata = *ppdata;
4217 char *params = *pparams;
4218 uint16_t info_level;
4220 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4221 lp_servicename(talloc_tos(), SNUM(conn))));
4224 if (total_params < 4) {
4225 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4227 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4231 info_level = SVAL(params,2);
4234 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4235 info_level != SMB_SET_CIFS_UNIX_INFO) {
4236 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4237 "info level (0x%x) on IPC$.\n",
4238 (unsigned int)info_level));
4239 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4244 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4245 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4246 DEBUG(0,("call_trans2setfsinfo: encryption required "
4247 "and info level 0x%x sent.\n",
4248 (unsigned int)info_level));
4249 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4254 switch(info_level) {
4255 case SMB_SET_CIFS_UNIX_INFO:
4256 if (!lp_unix_extensions()) {
4257 DEBUG(2,("call_trans2setfsinfo: "
4258 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4259 "unix extensions off\n"));
4261 NT_STATUS_INVALID_LEVEL);
4265 /* There should be 12 bytes of capabilities set. */
4266 if (total_data < 12) {
4269 NT_STATUS_INVALID_PARAMETER);
4272 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4273 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4274 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4275 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4276 /* Just print these values for now. */
4277 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4278 "major = %u, minor = %u cap_low = 0x%x, "
4280 (unsigned int)xconn->
4281 smb1.unix_info.client_major,
4282 (unsigned int)xconn->
4283 smb1.unix_info.client_minor,
4284 (unsigned int)xconn->
4285 smb1.unix_info.client_cap_low,
4286 (unsigned int)xconn->
4287 smb1.unix_info.client_cap_high));
4289 /* Here is where we must switch to posix pathname processing... */
4290 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4291 lp_set_posix_pathnames();
4292 mangle_change_to_posix();
4295 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4296 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4297 /* Client that knows how to do posix locks,
4298 * but not posix open/mkdir operations. Set a
4299 * default type for read/write checks. */
4301 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4306 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4309 size_t param_len = 0;
4310 size_t data_len = total_data;
4312 if (!lp_unix_extensions()) {
4315 NT_STATUS_INVALID_LEVEL);
4319 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4322 NT_STATUS_NOT_SUPPORTED);
4326 if (xconn->smb1.echo_handler.trusted_fde) {
4327 DEBUG( 2,("call_trans2setfsinfo: "
4328 "request transport encryption disabled"
4329 "with 'fork echo handler = yes'\n"));
4332 NT_STATUS_NOT_SUPPORTED);
4336 DEBUG( 4,("call_trans2setfsinfo: "
4337 "request transport encryption.\n"));
4339 status = srv_request_encryption_setup(conn,
4340 (unsigned char **)ppdata,
4342 (unsigned char **)pparams,
4345 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4346 !NT_STATUS_IS_OK(status)) {
4347 reply_nterror(req, status);
4351 send_trans2_replies(conn, req,
4359 if (NT_STATUS_IS_OK(status)) {
4360 /* Server-side transport
4361 * encryption is now *on*. */
4362 status = srv_encryption_start(conn);
4363 if (!NT_STATUS_IS_OK(status)) {
4364 char *reason = talloc_asprintf(talloc_tos(),
4365 "Failure in setting "
4366 "up encrypted transport: %s",
4368 exit_server_cleanly(reason);
4374 case SMB_FS_QUOTA_INFORMATION:
4378 .data = (uint8_t *)pdata,
4379 .length = total_data
4381 files_struct *fsp = NULL;
4382 fsp = file_fsp(req, SVAL(params,0));
4384 status = smb_set_fsquota(conn,
4388 if (!NT_STATUS_IS_OK(status)) {
4389 reply_nterror(req, status);
4395 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4397 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4403 * sending this reply works fine,
4404 * but I'm not sure it's the same
4405 * like windows do...
4408 reply_outbuf(req, 10, 0);
4411 #if defined(HAVE_POSIX_ACLS)
4412 /****************************************************************************
4413 Utility function to count the number of entries in a POSIX acl.
4414 ****************************************************************************/
4416 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4418 unsigned int ace_count = 0;
4419 int entry_id = SMB_ACL_FIRST_ENTRY;
4420 SMB_ACL_ENTRY_T entry;
4422 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4424 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4425 entry_id = SMB_ACL_NEXT_ENTRY;
4432 /****************************************************************************
4433 Utility function to marshall a POSIX acl into wire format.
4434 ****************************************************************************/
4436 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4438 int entry_id = SMB_ACL_FIRST_ENTRY;
4439 SMB_ACL_ENTRY_T entry;
4441 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4442 SMB_ACL_TAG_T tagtype;
4443 SMB_ACL_PERMSET_T permset;
4444 unsigned char perms = 0;
4445 unsigned int own_grp;
4448 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4449 entry_id = SMB_ACL_NEXT_ENTRY;
4452 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4453 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4457 if (sys_acl_get_permset(entry, &permset) == -1) {
4458 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4462 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4463 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4464 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4466 SCVAL(pdata,1,perms);
4469 case SMB_ACL_USER_OBJ:
4470 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4471 own_grp = (unsigned int)pst->st_ex_uid;
4472 SIVAL(pdata,2,own_grp);
4477 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4479 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4482 own_grp = (unsigned int)*puid;
4483 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4484 SIVAL(pdata,2,own_grp);
4488 case SMB_ACL_GROUP_OBJ:
4489 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4490 own_grp = (unsigned int)pst->st_ex_gid;
4491 SIVAL(pdata,2,own_grp);
4496 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4498 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4501 own_grp = (unsigned int)*pgid;
4502 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4503 SIVAL(pdata,2,own_grp);
4508 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4509 SIVAL(pdata,2,0xFFFFFFFF);
4510 SIVAL(pdata,6,0xFFFFFFFF);
4513 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4514 SIVAL(pdata,2,0xFFFFFFFF);
4515 SIVAL(pdata,6,0xFFFFFFFF);
4518 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4521 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4528 /****************************************************************************
4529 Store the FILE_UNIX_BASIC info.
4530 ****************************************************************************/
4532 static char *store_file_unix_basic(connection_struct *conn,
4535 const SMB_STRUCT_STAT *psbuf)
4537 uint64_t file_index = get_FileIndex(conn, psbuf);
4540 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4541 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4543 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4546 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4549 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4550 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4551 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4554 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4558 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4562 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4565 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4566 devno = psbuf->st_ex_rdev;
4568 devno = psbuf->st_ex_dev;
4571 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4575 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4579 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4582 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4586 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4593 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4594 * the chflags(2) (or equivalent) flags.
4596 * XXX: this really should be behind the VFS interface. To do this, we would
4597 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4598 * Each VFS module could then implement its own mapping as appropriate for the
4599 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4601 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4605 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4609 { UF_IMMUTABLE, EXT_IMMUTABLE },
4613 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4617 { UF_HIDDEN, EXT_HIDDEN },
4620 /* Do not remove. We need to guarantee that this array has at least one
4621 * entry to build on HP-UX.
4627 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4628 uint32_t *smb_fflags, uint32_t *smb_fmask)
4632 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4633 *smb_fmask |= info2_flags_map[i].smb_fflag;
4634 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4635 *smb_fflags |= info2_flags_map[i].smb_fflag;
4640 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4641 const uint32_t smb_fflags,
4642 const uint32_t smb_fmask,
4645 uint32_t max_fmask = 0;
4648 *stat_fflags = psbuf->st_ex_flags;
4650 /* For each flags requested in smb_fmask, check the state of the
4651 * corresponding flag in smb_fflags and set or clear the matching
4655 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4656 max_fmask |= info2_flags_map[i].smb_fflag;
4657 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4658 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4659 *stat_fflags |= info2_flags_map[i].stat_fflag;
4661 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4666 /* If smb_fmask is asking to set any bits that are not supported by
4667 * our flag mappings, we should fail.
4669 if ((smb_fmask & max_fmask) != smb_fmask) {
4677 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4678 * of file flags and birth (create) time.
4680 static char *store_file_unix_basic_info2(connection_struct *conn,
4683 const SMB_STRUCT_STAT *psbuf)
4685 uint32_t file_flags = 0;
4686 uint32_t flags_mask = 0;
4688 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4690 /* Create (birth) time 64 bit */
4691 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4694 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4695 SIVAL(pdata, 0, file_flags); /* flags */
4696 SIVAL(pdata, 4, flags_mask); /* mask */
4702 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4703 const struct stream_struct *streams,
4705 unsigned int max_data_bytes,
4706 unsigned int *data_size)
4709 unsigned int ofs = 0;
4711 if (max_data_bytes < 32) {
4712 return NT_STATUS_INFO_LENGTH_MISMATCH;
4715 for (i = 0; i < num_streams; i++) {
4716 unsigned int next_offset;
4718 smb_ucs2_t *namebuf;
4720 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4721 streams[i].name, &namelen) ||
4724 return NT_STATUS_INVALID_PARAMETER;
4728 * name_buf is now null-terminated, we need to marshall as not
4735 * We cannot overflow ...
4737 if ((ofs + 24 + namelen) > max_data_bytes) {
4738 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4740 TALLOC_FREE(namebuf);
4741 return STATUS_BUFFER_OVERFLOW;
4744 SIVAL(data, ofs+4, namelen);
4745 SOFF_T(data, ofs+8, streams[i].size);
4746 SOFF_T(data, ofs+16, streams[i].alloc_size);
4747 memcpy(data+ofs+24, namebuf, namelen);
4748 TALLOC_FREE(namebuf);
4750 next_offset = ofs + 24 + namelen;
4752 if (i == num_streams-1) {
4753 SIVAL(data, ofs, 0);
4756 unsigned int align = ndr_align_size(next_offset, 8);
4758 if ((next_offset + align) > max_data_bytes) {
4759 DEBUG(10, ("refusing to overflow align "
4760 "reply at stream %u\n",
4762 TALLOC_FREE(namebuf);
4763 return STATUS_BUFFER_OVERFLOW;
4766 memset(data+next_offset, 0, align);
4767 next_offset += align;
4769 SIVAL(data, ofs, next_offset - ofs);
4776 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4780 return NT_STATUS_OK;
4783 /****************************************************************************
4784 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4785 ****************************************************************************/
4787 static void call_trans2qpipeinfo(connection_struct *conn,
4788 struct smb_request *req,
4789 unsigned int tran_call,
4790 char **pparams, int total_params,
4791 char **ppdata, int total_data,
4792 unsigned int max_data_bytes)
4794 char *params = *pparams;
4795 char *pdata = *ppdata;
4796 unsigned int data_size = 0;
4797 unsigned int param_size = 2;
4798 uint16_t info_level;
4802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4806 if (total_params < 4) {
4807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4811 fsp = file_fsp(req, SVAL(params,0));
4812 if (!fsp_is_np(fsp)) {
4813 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4817 info_level = SVAL(params,2);
4819 *pparams = (char *)SMB_REALLOC(*pparams,2);
4820 if (*pparams == NULL) {
4821 reply_nterror(req, NT_STATUS_NO_MEMORY);
4826 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4830 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4831 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4832 if (*ppdata == NULL ) {
4833 reply_nterror(req, NT_STATUS_NO_MEMORY);
4838 switch (info_level) {
4839 case SMB_FILE_STANDARD_INFORMATION:
4841 SOFF_T(pdata,0,4096LL);
4848 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4852 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4858 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4859 TALLOC_CTX *mem_ctx,
4860 uint16_t info_level,
4862 struct smb_filename *smb_fname,
4863 bool delete_pending,
4864 struct timespec write_time_ts,
4865 struct ea_list *ea_list,
4866 int lock_data_count,
4869 unsigned int max_data_bytes,
4870 size_t *fixed_portion,
4872 unsigned int *pdata_size)
4874 char *pdata = *ppdata;
4875 char *dstart, *dend;
4876 unsigned int data_size;
4877 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4878 time_t create_time, mtime, atime, c_time;
4879 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4886 uint64_t file_size = 0;
4888 uint64_t allocation_size = 0;
4889 uint64_t file_index = 0;
4890 uint32_t access_mask = 0;
4893 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4894 return NT_STATUS_INVALID_LEVEL;
4897 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4898 smb_fname_str_dbg(smb_fname),
4900 info_level, max_data_bytes));
4902 mode = dos_mode(conn, smb_fname);
4903 nlink = psbuf->st_ex_nlink;
4905 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4909 if ((nlink > 0) && delete_pending) {
4913 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4914 return NT_STATUS_INVALID_PARAMETER;
4917 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4918 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4919 if (*ppdata == NULL) {
4920 return NT_STATUS_NO_MEMORY;
4924 dend = dstart + data_size - 1;
4926 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4927 update_stat_ex_mtime(psbuf, write_time_ts);
4930 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4931 mtime_ts = psbuf->st_ex_mtime;
4932 atime_ts = psbuf->st_ex_atime;
4933 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4935 if (lp_dos_filetime_resolution(SNUM(conn))) {
4936 dos_filetime_timespec(&create_time_ts);
4937 dos_filetime_timespec(&mtime_ts);
4938 dos_filetime_timespec(&atime_ts);
4939 dos_filetime_timespec(&ctime_ts);
4942 create_time = convert_timespec_to_time_t(create_time_ts);
4943 mtime = convert_timespec_to_time_t(mtime_ts);
4944 atime = convert_timespec_to_time_t(atime_ts);
4945 c_time = convert_timespec_to_time_t(ctime_ts);
4947 p = strrchr_m(smb_fname->base_name,'/');
4949 base_name = smb_fname->base_name;
4953 /* NT expects the name to be in an exact form of the *full*
4954 filename. See the trans2 torture test */
4955 if (ISDOT(base_name)) {
4956 dos_fname = talloc_strdup(mem_ctx, "\\");
4958 return NT_STATUS_NO_MEMORY;
4961 dos_fname = talloc_asprintf(mem_ctx,
4963 smb_fname->base_name);
4965 return NT_STATUS_NO_MEMORY;
4967 if (is_ntfs_stream_smb_fname(smb_fname)) {
4968 dos_fname = talloc_asprintf(dos_fname, "%s",
4969 smb_fname->stream_name);
4971 return NT_STATUS_NO_MEMORY;
4975 string_replace(dos_fname, '/', '\\');
4978 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4981 /* Do we have this path open ? */
4983 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4984 fsp1 = file_find_di_first(conn->sconn, fileid);
4985 if (fsp1 && fsp1->initial_allocation_size) {
4986 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4990 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4991 file_size = get_file_size_stat(psbuf);
4995 pos = fsp->fh->position_information;
4999 access_mask = fsp->access_mask;
5001 /* GENERIC_EXECUTE mapping from Windows */
5002 access_mask = 0x12019F;
5005 /* This should be an index number - looks like
5008 I think this causes us to fail the IFSKIT
5009 BasicFileInformationTest. -tpot */
5010 file_index = get_FileIndex(conn, psbuf);
5014 switch (info_level) {
5015 case SMB_INFO_STANDARD:
5016 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5018 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5019 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5020 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5021 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5022 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5023 SSVAL(pdata,l1_attrFile,mode);
5026 case SMB_INFO_QUERY_EA_SIZE:
5028 unsigned int ea_size =
5029 estimate_ea_size(conn, fsp,
5031 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5033 srv_put_dos_date2(pdata,0,create_time);
5034 srv_put_dos_date2(pdata,4,atime);
5035 srv_put_dos_date2(pdata,8,mtime); /* write time */
5036 SIVAL(pdata,12,(uint32_t)file_size);
5037 SIVAL(pdata,16,(uint32_t)allocation_size);
5038 SSVAL(pdata,20,mode);
5039 SIVAL(pdata,22,ea_size);
5043 case SMB_INFO_IS_NAME_VALID:
5044 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5046 /* os/2 needs this ? really ?*/
5047 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5049 /* This is only reached for qpathinfo */
5053 case SMB_INFO_QUERY_EAS_FROM_LIST:
5055 size_t total_ea_len = 0;
5056 struct ea_list *ea_file_list = NULL;
5057 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5060 get_ea_list_from_file(mem_ctx, conn, fsp,
5062 &total_ea_len, &ea_file_list);
5063 if (!NT_STATUS_IS_OK(status)) {
5067 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5069 if (!ea_list || (total_ea_len > data_size)) {
5071 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5075 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5079 case SMB_INFO_QUERY_ALL_EAS:
5081 /* We have data_size bytes to put EA's into. */
5082 size_t total_ea_len = 0;
5083 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5085 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5087 &total_ea_len, &ea_list);
5088 if (!NT_STATUS_IS_OK(status)) {
5092 if (!ea_list || (total_ea_len > data_size)) {
5094 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5098 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5102 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5104 /* This is FileFullEaInformation - 0xF which maps to
5105 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5107 /* We have data_size bytes to put EA's into. */
5108 size_t total_ea_len = 0;
5109 struct ea_list *ea_file_list = NULL;
5111 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5113 /*TODO: add filtering and index handling */
5116 get_ea_list_from_file(mem_ctx, conn, fsp,
5118 &total_ea_len, &ea_file_list);
5119 if (!NT_STATUS_IS_OK(status)) {
5122 if (!ea_file_list) {
5123 return NT_STATUS_NO_EAS_ON_FILE;
5126 status = fill_ea_chained_buffer(mem_ctx,
5130 conn, ea_file_list);
5131 if (!NT_STATUS_IS_OK(status)) {
5137 case SMB_FILE_BASIC_INFORMATION:
5138 case SMB_QUERY_FILE_BASIC_INFO:
5140 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5141 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5142 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5144 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5148 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5149 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5150 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5151 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5152 SIVAL(pdata,32,mode);
5154 DEBUG(5,("SMB_QFBI - "));
5155 DEBUG(5,("create: %s ", ctime(&create_time)));
5156 DEBUG(5,("access: %s ", ctime(&atime)));
5157 DEBUG(5,("write: %s ", ctime(&mtime)));
5158 DEBUG(5,("change: %s ", ctime(&c_time)));
5159 DEBUG(5,("mode: %x\n", mode));
5160 *fixed_portion = data_size;
5163 case SMB_FILE_STANDARD_INFORMATION:
5164 case SMB_QUERY_FILE_STANDARD_INFO:
5166 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5168 SOFF_T(pdata,0,allocation_size);
5169 SOFF_T(pdata,8,file_size);
5170 SIVAL(pdata,16,nlink);
5171 SCVAL(pdata,20,delete_pending?1:0);
5172 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5173 SSVAL(pdata,22,0); /* Padding. */
5174 *fixed_portion = 24;
5177 case SMB_FILE_EA_INFORMATION:
5178 case SMB_QUERY_FILE_EA_INFO:
5180 unsigned int ea_size =
5181 estimate_ea_size(conn, fsp, smb_fname);
5182 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5185 SIVAL(pdata,0,ea_size);
5189 /* Get the 8.3 name - used if NT SMB was negotiated. */
5190 case SMB_QUERY_FILE_ALT_NAME_INFO:
5191 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5193 char mangled_name[13];
5194 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5195 if (!name_to_8_3(base_name,mangled_name,
5196 True,conn->params)) {
5197 return NT_STATUS_NO_MEMORY;
5199 status = srvstr_push(dstart, flags2,
5200 pdata+4, mangled_name,
5201 PTR_DIFF(dend, pdata+4),
5203 if (!NT_STATUS_IS_OK(status)) {
5206 data_size = 4 + len;
5212 case SMB_QUERY_FILE_NAME_INFO:
5215 this must be *exactly* right for ACLs on mapped drives to work
5217 status = srvstr_push(dstart, flags2,
5219 PTR_DIFF(dend, pdata+4),
5221 if (!NT_STATUS_IS_OK(status)) {
5224 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5225 data_size = 4 + len;
5230 case SMB_FILE_ALLOCATION_INFORMATION:
5231 case SMB_QUERY_FILE_ALLOCATION_INFO:
5232 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5234 SOFF_T(pdata,0,allocation_size);
5237 case SMB_FILE_END_OF_FILE_INFORMATION:
5238 case SMB_QUERY_FILE_END_OF_FILEINFO:
5239 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5241 SOFF_T(pdata,0,file_size);
5244 case SMB_QUERY_FILE_ALL_INFO:
5245 case SMB_FILE_ALL_INFORMATION:
5247 unsigned int ea_size =
5248 estimate_ea_size(conn, fsp, smb_fname);
5249 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5250 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5251 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5252 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5253 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5254 SIVAL(pdata,32,mode);
5255 SIVAL(pdata,36,0); /* padding. */
5257 SOFF_T(pdata,0,allocation_size);
5258 SOFF_T(pdata,8,file_size);
5259 SIVAL(pdata,16,nlink);
5260 SCVAL(pdata,20,delete_pending);
5261 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5264 SIVAL(pdata,0,ea_size);
5265 pdata += 4; /* EA info */
5266 status = srvstr_push(dstart, flags2,
5268 PTR_DIFF(dend, pdata+4),
5270 if (!NT_STATUS_IS_OK(status)) {
5275 data_size = PTR_DIFF(pdata,(*ppdata));
5276 *fixed_portion = 10;
5280 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5282 unsigned int ea_size =
5283 estimate_ea_size(conn, fsp, smb_fname);
5284 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5285 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5286 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5287 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5288 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5289 SIVAL(pdata, 0x20, mode);
5290 SIVAL(pdata, 0x24, 0); /* padding. */
5291 SBVAL(pdata, 0x28, allocation_size);
5292 SBVAL(pdata, 0x30, file_size);
5293 SIVAL(pdata, 0x38, nlink);
5294 SCVAL(pdata, 0x3C, delete_pending);
5295 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5296 SSVAL(pdata, 0x3E, 0); /* padding */
5297 SBVAL(pdata, 0x40, file_index);
5298 SIVAL(pdata, 0x48, ea_size);
5299 SIVAL(pdata, 0x4C, access_mask);
5300 SBVAL(pdata, 0x50, pos);
5301 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5302 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5306 status = srvstr_push(dstart, flags2,
5308 PTR_DIFF(dend, pdata+4),
5310 if (!NT_STATUS_IS_OK(status)) {
5315 data_size = PTR_DIFF(pdata,(*ppdata));
5316 *fixed_portion = 104;
5319 case SMB_FILE_INTERNAL_INFORMATION:
5321 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5322 SBVAL(pdata, 0, file_index);
5327 case SMB_FILE_ACCESS_INFORMATION:
5328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5329 SIVAL(pdata, 0, access_mask);
5334 case SMB_FILE_NAME_INFORMATION:
5335 /* Pathname with leading '\'. */
5338 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5339 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5340 SIVAL(pdata,0,byte_len);
5341 data_size = 4 + byte_len;
5345 case SMB_FILE_DISPOSITION_INFORMATION:
5346 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5348 SCVAL(pdata,0,delete_pending);
5352 case SMB_FILE_POSITION_INFORMATION:
5353 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5355 SOFF_T(pdata,0,pos);
5359 case SMB_FILE_MODE_INFORMATION:
5360 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5361 SIVAL(pdata,0,mode);
5366 case SMB_FILE_ALIGNMENT_INFORMATION:
5367 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5368 SIVAL(pdata,0,0); /* No alignment needed. */
5374 * NT4 server just returns "invalid query" to this - if we try
5375 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5378 /* The first statement above is false - verified using Thursby
5379 * client against NT4 -- gcolley.
5381 case SMB_QUERY_FILE_STREAM_INFO:
5382 case SMB_FILE_STREAM_INFORMATION: {
5383 unsigned int num_streams = 0;
5384 struct stream_struct *streams = NULL;
5386 DEBUG(10,("smbd_do_qfilepathinfo: "
5387 "SMB_FILE_STREAM_INFORMATION\n"));
5389 if (is_ntfs_stream_smb_fname(smb_fname)) {
5390 return NT_STATUS_INVALID_PARAMETER;
5393 status = vfs_streaminfo(conn,
5400 if (!NT_STATUS_IS_OK(status)) {
5401 DEBUG(10, ("could not get stream info: %s\n",
5402 nt_errstr(status)));
5406 status = marshall_stream_info(num_streams, streams,
5407 pdata, max_data_bytes,
5410 if (!NT_STATUS_IS_OK(status)) {
5411 DEBUG(10, ("marshall_stream_info failed: %s\n",
5412 nt_errstr(status)));
5413 TALLOC_FREE(streams);
5417 TALLOC_FREE(streams);
5419 *fixed_portion = 32;
5423 case SMB_QUERY_COMPRESSION_INFO:
5424 case SMB_FILE_COMPRESSION_INFORMATION:
5425 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5426 SOFF_T(pdata,0,file_size);
5427 SIVAL(pdata,8,0); /* ??? */
5428 SIVAL(pdata,12,0); /* ??? */
5430 *fixed_portion = 16;
5433 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5434 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5435 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5436 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5437 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5438 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5439 SOFF_T(pdata,32,allocation_size);
5440 SOFF_T(pdata,40,file_size);
5441 SIVAL(pdata,48,mode);
5442 SIVAL(pdata,52,0); /* ??? */
5444 *fixed_portion = 56;
5447 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5448 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5449 SIVAL(pdata,0,mode);
5456 * CIFS UNIX Extensions.
5459 case SMB_QUERY_FILE_UNIX_BASIC:
5461 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5462 data_size = PTR_DIFF(pdata,(*ppdata));
5464 DEBUG(4,("smbd_do_qfilepathinfo: "
5465 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5466 dump_data(4, (uint8_t *)(*ppdata), data_size);
5470 case SMB_QUERY_FILE_UNIX_INFO2:
5472 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5473 data_size = PTR_DIFF(pdata,(*ppdata));
5477 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5479 for (i=0; i<100; i++)
5480 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5486 case SMB_QUERY_FILE_UNIX_LINK:
5489 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5492 return NT_STATUS_NO_MEMORY;
5495 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5497 if(!S_ISLNK(psbuf->st_ex_mode)) {
5498 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5501 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5503 link_len = SMB_VFS_READLINK(conn,
5506 if (link_len == -1) {
5507 return map_nt_error_from_unix(errno);
5509 buffer[link_len] = 0;
5510 status = srvstr_push(dstart, flags2,
5512 PTR_DIFF(dend, pdata),
5513 STR_TERMINATE, &len);
5514 if (!NT_STATUS_IS_OK(status)) {
5518 data_size = PTR_DIFF(pdata,(*ppdata));
5523 #if defined(HAVE_POSIX_ACLS)
5524 case SMB_QUERY_POSIX_ACL:
5526 SMB_ACL_T file_acl = NULL;
5527 SMB_ACL_T def_acl = NULL;
5528 uint16_t num_file_acls = 0;
5529 uint16_t num_def_acls = 0;
5531 status = refuse_symlink(conn,
5534 if (!NT_STATUS_IS_OK(status)) {
5538 if (fsp && fsp->fh->fd != -1) {
5539 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5543 SMB_VFS_SYS_ACL_GET_FILE(conn,
5545 SMB_ACL_TYPE_ACCESS,
5549 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5550 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5551 "not implemented on "
5552 "filesystem containing %s\n",
5553 smb_fname->base_name));
5554 return NT_STATUS_NOT_IMPLEMENTED;
5557 if (S_ISDIR(psbuf->st_ex_mode)) {
5558 if (fsp && fsp->is_directory) {
5560 SMB_VFS_SYS_ACL_GET_FILE(
5563 SMB_ACL_TYPE_DEFAULT,
5567 SMB_VFS_SYS_ACL_GET_FILE(
5570 SMB_ACL_TYPE_DEFAULT,
5573 def_acl = free_empty_sys_acl(conn, def_acl);
5576 num_file_acls = count_acl_entries(conn, file_acl);
5577 num_def_acls = count_acl_entries(conn, def_acl);
5579 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5580 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5582 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5583 SMB_POSIX_ACL_HEADER_SIZE) ));
5585 TALLOC_FREE(file_acl);
5588 TALLOC_FREE(def_acl);
5590 return NT_STATUS_BUFFER_TOO_SMALL;
5593 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5594 SSVAL(pdata,2,num_file_acls);
5595 SSVAL(pdata,4,num_def_acls);
5596 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5598 TALLOC_FREE(file_acl);
5601 TALLOC_FREE(def_acl);
5603 return NT_STATUS_INTERNAL_ERROR;
5605 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5607 TALLOC_FREE(file_acl);
5610 TALLOC_FREE(def_acl);
5612 return NT_STATUS_INTERNAL_ERROR;
5616 TALLOC_FREE(file_acl);
5619 TALLOC_FREE(def_acl);
5621 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5627 case SMB_QUERY_POSIX_LOCK:
5632 enum brl_type lock_type;
5634 /* We need an open file with a real fd for this. */
5635 if (!fsp || fsp->fh->fd == -1) {
5636 return NT_STATUS_INVALID_LEVEL;
5639 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5640 return NT_STATUS_INVALID_PARAMETER;
5643 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5644 case POSIX_LOCK_TYPE_READ:
5645 lock_type = READ_LOCK;
5647 case POSIX_LOCK_TYPE_WRITE:
5648 lock_type = WRITE_LOCK;
5650 case POSIX_LOCK_TYPE_UNLOCK:
5652 /* There's no point in asking for an unlock... */
5653 return NT_STATUS_INVALID_PARAMETER;
5656 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5657 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5658 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5660 status = query_lock(fsp,
5667 if (ERROR_WAS_LOCK_DENIED(status)) {
5668 /* Here we need to report who has it locked... */
5669 data_size = POSIX_LOCK_DATA_SIZE;
5671 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5672 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5673 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5674 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5675 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5677 } else if (NT_STATUS_IS_OK(status)) {
5678 /* For success we just return a copy of what we sent
5679 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5680 data_size = POSIX_LOCK_DATA_SIZE;
5681 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5682 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5690 return NT_STATUS_INVALID_LEVEL;
5693 *pdata_size = data_size;
5694 return NT_STATUS_OK;
5697 /****************************************************************************
5698 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5699 file name or file id).
5700 ****************************************************************************/
5702 static void call_trans2qfilepathinfo(connection_struct *conn,
5703 struct smb_request *req,
5704 unsigned int tran_call,
5705 char **pparams, int total_params,
5706 char **ppdata, int total_data,
5707 unsigned int max_data_bytes)
5709 char *params = *pparams;
5710 char *pdata = *ppdata;
5711 uint16_t info_level;
5712 unsigned int data_size = 0;
5713 unsigned int param_size = 2;
5714 struct smb_filename *smb_fname = NULL;
5715 bool delete_pending = False;
5716 struct timespec write_time_ts;
5717 files_struct *fsp = NULL;
5718 struct file_id fileid;
5719 struct ea_list *ea_list = NULL;
5720 int lock_data_count = 0;
5721 char *lock_data = NULL;
5722 size_t fixed_portion;
5723 NTSTATUS status = NT_STATUS_OK;
5726 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5730 ZERO_STRUCT(write_time_ts);
5732 if (tran_call == TRANSACT2_QFILEINFO) {
5733 if (total_params < 4) {
5734 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5739 call_trans2qpipeinfo(conn, req, tran_call,
5740 pparams, total_params,
5746 fsp = file_fsp(req, SVAL(params,0));
5747 info_level = SVAL(params,2);
5749 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5751 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5752 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5756 /* Initial check for valid fsp ptr. */
5757 if (!check_fsp_open(conn, req, fsp)) {
5761 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5762 if (smb_fname == NULL) {
5763 reply_nterror(req, NT_STATUS_NO_MEMORY);
5767 if(fsp->fake_file_handle) {
5769 * This is actually for the QUOTA_FAKE_FILE --metze
5772 /* We know this name is ok, it's already passed the checks. */
5774 } else if(fsp->fh->fd == -1) {
5776 * This is actually a QFILEINFO on a directory
5777 * handle (returned from an NT SMB). NT5.0 seems
5778 * to do this call. JRA.
5781 if (INFO_LEVEL_IS_UNIX(info_level)) {
5782 /* Always do lstat for UNIX calls. */
5783 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5784 DEBUG(3,("call_trans2qfilepathinfo: "
5785 "SMB_VFS_LSTAT of %s failed "
5787 smb_fname_str_dbg(smb_fname),
5790 map_nt_error_from_unix(errno));
5793 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5794 DEBUG(3,("call_trans2qfilepathinfo: "
5795 "SMB_VFS_STAT of %s failed (%s)\n",
5796 smb_fname_str_dbg(smb_fname),
5799 map_nt_error_from_unix(errno));
5803 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5804 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5807 * Original code - this is an open file.
5809 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5810 DEBUG(3, ("fstat of %s failed (%s)\n",
5811 fsp_fnum_dbg(fsp), strerror(errno)));
5813 map_nt_error_from_unix(errno));
5816 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5817 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5823 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5826 if (total_params < 7) {
5827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5831 info_level = SVAL(params,0);
5833 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5835 if (INFO_LEVEL_IS_UNIX(info_level)) {
5836 if (!lp_unix_extensions()) {
5837 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5840 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5841 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5842 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5843 req->posix_pathnames) {
5844 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5848 if (req->posix_pathnames) {
5849 srvstr_get_path_posix(req,
5858 srvstr_get_path(req,
5867 if (!NT_STATUS_IS_OK(status)) {
5868 reply_nterror(req, status);
5872 status = filename_convert(req,
5878 if (!NT_STATUS_IS_OK(status)) {
5879 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5880 reply_botherror(req,
5881 NT_STATUS_PATH_NOT_COVERED,
5882 ERRSRV, ERRbadpath);
5885 reply_nterror(req, status);
5889 /* If this is a stream, check if there is a delete_pending. */
5890 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5891 && is_ntfs_stream_smb_fname(smb_fname)) {
5892 struct smb_filename *smb_fname_base;
5894 /* Create an smb_filename with stream_name == NULL. */
5895 smb_fname_base = synthetic_smb_fname(
5897 smb_fname->base_name,
5901 if (smb_fname_base == NULL) {
5902 reply_nterror(req, NT_STATUS_NO_MEMORY);
5906 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5907 /* Always do lstat for UNIX calls. */
5908 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5909 DEBUG(3,("call_trans2qfilepathinfo: "
5910 "SMB_VFS_LSTAT of %s failed "
5912 smb_fname_str_dbg(smb_fname_base),
5914 TALLOC_FREE(smb_fname_base);
5916 map_nt_error_from_unix(errno));
5920 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5921 DEBUG(3,("call_trans2qfilepathinfo: "
5922 "fileinfo of %s failed "
5924 smb_fname_str_dbg(smb_fname_base),
5926 TALLOC_FREE(smb_fname_base);
5928 map_nt_error_from_unix(errno));
5933 status = file_name_hash(conn,
5934 smb_fname_str_dbg(smb_fname_base),
5936 if (!NT_STATUS_IS_OK(status)) {
5937 TALLOC_FREE(smb_fname_base);
5938 reply_nterror(req, status);
5942 fileid = vfs_file_id_from_sbuf(conn,
5943 &smb_fname_base->st);
5944 TALLOC_FREE(smb_fname_base);
5945 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5946 if (delete_pending) {
5947 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5952 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5953 /* Always do lstat for UNIX calls. */
5954 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5955 DEBUG(3,("call_trans2qfilepathinfo: "
5956 "SMB_VFS_LSTAT of %s failed (%s)\n",
5957 smb_fname_str_dbg(smb_fname),
5960 map_nt_error_from_unix(errno));
5965 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5966 DEBUG(3,("call_trans2qfilepathinfo: "
5967 "SMB_VFS_STAT of %s failed (%s)\n",
5968 smb_fname_str_dbg(smb_fname),
5971 map_nt_error_from_unix(errno));
5976 status = file_name_hash(conn,
5977 smb_fname_str_dbg(smb_fname),
5979 if (!NT_STATUS_IS_OK(status)) {
5980 reply_nterror(req, status);
5984 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5985 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5986 if (delete_pending) {
5987 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5992 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5993 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5995 info_level,tran_call,total_data));
5997 /* Pull out any data sent here before we realloc. */
5998 switch (info_level) {
5999 case SMB_INFO_QUERY_EAS_FROM_LIST:
6001 /* Pull any EA list from the data portion. */
6004 if (total_data < 4) {
6006 req, NT_STATUS_INVALID_PARAMETER);
6009 ea_size = IVAL(pdata,0);
6011 if (total_data > 0 && ea_size != total_data) {
6012 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6013 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6015 req, NT_STATUS_INVALID_PARAMETER);
6019 if (!lp_ea_support(SNUM(conn))) {
6020 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6024 /* Pull out the list of names. */
6025 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6028 req, NT_STATUS_INVALID_PARAMETER);
6034 case SMB_QUERY_POSIX_LOCK:
6036 if (fsp == NULL || fsp->fh->fd == -1) {
6037 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6041 if (total_data != POSIX_LOCK_DATA_SIZE) {
6043 req, NT_STATUS_INVALID_PARAMETER);
6047 /* Copy the lock range data. */
6048 lock_data = (char *)talloc_memdup(
6049 req, pdata, total_data);
6051 reply_nterror(req, NT_STATUS_NO_MEMORY);
6054 lock_data_count = total_data;
6060 *pparams = (char *)SMB_REALLOC(*pparams,2);
6061 if (*pparams == NULL) {
6062 reply_nterror(req, NT_STATUS_NO_MEMORY);
6069 * draft-leach-cifs-v1-spec-02.txt
6070 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6073 * The requested information is placed in the Data portion of the
6074 * transaction response. For the information levels greater than 0x100,
6075 * the transaction response has 1 parameter word which should be
6076 * ignored by the client.
6078 * However Windows only follows this rule for the IS_NAME_VALID call.
6080 switch (info_level) {
6081 case SMB_INFO_IS_NAME_VALID:
6086 if ((info_level & 0xFF00) == 0xFF00) {
6088 * We use levels that start with 0xFF00
6089 * internally to represent SMB2 specific levels
6091 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6095 status = smbd_do_qfilepathinfo(conn, req, info_level,
6097 delete_pending, write_time_ts,
6099 lock_data_count, lock_data,
6100 req->flags2, max_data_bytes,
6102 ppdata, &data_size);
6103 if (!NT_STATUS_IS_OK(status)) {
6104 reply_nterror(req, status);
6107 if (fixed_portion > max_data_bytes) {
6108 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6112 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6118 /****************************************************************************
6119 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6121 ****************************************************************************/
6123 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6124 connection_struct *conn,
6125 struct smb_request *req,
6126 bool overwrite_if_exists,
6127 const struct smb_filename *smb_fname_old,
6128 struct smb_filename *smb_fname_new)
6130 NTSTATUS status = NT_STATUS_OK;
6132 /* source must already exist. */
6133 if (!VALID_STAT(smb_fname_old->st)) {
6134 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6137 if (VALID_STAT(smb_fname_new->st)) {
6138 if (overwrite_if_exists) {
6139 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6140 return NT_STATUS_FILE_IS_A_DIRECTORY;
6142 status = unlink_internals(conn,
6144 FILE_ATTRIBUTE_NORMAL,
6147 if (!NT_STATUS_IS_OK(status)) {
6151 /* Disallow if newname already exists. */
6152 return NT_STATUS_OBJECT_NAME_COLLISION;
6156 /* No links from a directory. */
6157 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6158 return NT_STATUS_FILE_IS_A_DIRECTORY;
6161 /* Setting a hardlink to/from a stream isn't currently supported. */
6162 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6163 is_ntfs_stream_smb_fname(smb_fname_new)) {
6164 return NT_STATUS_INVALID_PARAMETER;
6167 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6168 smb_fname_old->base_name, smb_fname_new->base_name));
6170 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6171 status = map_nt_error_from_unix(errno);
6172 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6173 nt_errstr(status), smb_fname_old->base_name,
6174 smb_fname_new->base_name));
6179 /****************************************************************************
6180 Deal with setting the time from any of the setfilepathinfo functions.
6181 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6182 calling this function.
6183 ****************************************************************************/
6185 NTSTATUS smb_set_file_time(connection_struct *conn,
6187 const struct smb_filename *smb_fname,
6188 struct smb_file_time *ft,
6189 bool setting_write_time)
6191 struct smb_filename smb_fname_base;
6193 FILE_NOTIFY_CHANGE_LAST_ACCESS
6194 |FILE_NOTIFY_CHANGE_LAST_WRITE
6195 |FILE_NOTIFY_CHANGE_CREATION;
6197 if (!VALID_STAT(smb_fname->st)) {
6198 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6201 /* get some defaults (no modifications) if any info is zero or -1. */
6202 if (null_timespec(ft->create_time)) {
6203 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6206 if (null_timespec(ft->atime)) {
6207 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6210 if (null_timespec(ft->mtime)) {
6211 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6214 if (!setting_write_time) {
6215 /* ft->mtime comes from change time, not write time. */
6216 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6219 /* Ensure the resolution is the correct for
6220 * what we can store on this filesystem. */
6222 round_timespec(conn->ts_res, &ft->create_time);
6223 round_timespec(conn->ts_res, &ft->ctime);
6224 round_timespec(conn->ts_res, &ft->atime);
6225 round_timespec(conn->ts_res, &ft->mtime);
6227 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6228 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6229 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6230 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6231 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6232 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6233 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6234 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6236 if (setting_write_time) {
6238 * This was a Windows setfileinfo on an open file.
6239 * NT does this a lot. We also need to
6240 * set the time here, as it can be read by
6241 * FindFirst/FindNext and with the patch for bug #2045
6242 * in smbd/fileio.c it ensures that this timestamp is
6243 * kept sticky even after a write. We save the request
6244 * away and will set it on file close and after a write. JRA.
6247 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6248 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6251 if (fsp->base_fsp) {
6252 set_sticky_write_time_fsp(fsp->base_fsp,
6255 set_sticky_write_time_fsp(fsp, ft->mtime);
6258 set_sticky_write_time_path(
6259 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6264 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6266 /* Always call ntimes on the base, even if a stream was passed in. */
6267 smb_fname_base = *smb_fname;
6268 smb_fname_base.stream_name = NULL;
6270 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6271 return map_nt_error_from_unix(errno);
6274 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6275 smb_fname->base_name);
6276 return NT_STATUS_OK;
6279 /****************************************************************************
6280 Deal with setting the dosmode from any of the setfilepathinfo functions.
6281 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6282 done before calling this function.
6283 ****************************************************************************/
6285 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6286 const struct smb_filename *smb_fname,
6289 struct smb_filename *smb_fname_base;
6292 if (!VALID_STAT(smb_fname->st)) {
6293 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6296 /* Always operate on the base_name, even if a stream was passed in. */
6297 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6298 smb_fname->base_name,
6302 if (smb_fname_base == NULL) {
6303 return NT_STATUS_NO_MEMORY;
6307 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6308 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6310 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6314 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6316 /* check the mode isn't different, before changing it */
6317 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6318 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6319 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6320 (unsigned int)dosmode));
6322 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6324 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6326 smb_fname_str_dbg(smb_fname_base),
6328 status = map_nt_error_from_unix(errno);
6332 status = NT_STATUS_OK;
6334 TALLOC_FREE(smb_fname_base);
6338 /****************************************************************************
6339 Deal with setting the size from any of the setfilepathinfo functions.
6340 ****************************************************************************/
6342 static NTSTATUS smb_set_file_size(connection_struct *conn,
6343 struct smb_request *req,
6345 const struct smb_filename *smb_fname,
6346 const SMB_STRUCT_STAT *psbuf,
6348 bool fail_after_createfile)
6350 NTSTATUS status = NT_STATUS_OK;
6351 struct smb_filename *smb_fname_tmp = NULL;
6352 files_struct *new_fsp = NULL;
6354 if (!VALID_STAT(*psbuf)) {
6355 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6358 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6360 get_file_size_stat(psbuf));
6362 if (size == get_file_size_stat(psbuf)) {
6363 return NT_STATUS_OK;
6366 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6367 smb_fname_str_dbg(smb_fname), (double)size));
6369 if (fsp && fsp->fh->fd != -1) {
6370 /* Handle based call. */
6371 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6372 return NT_STATUS_ACCESS_DENIED;
6375 if (vfs_set_filelen(fsp, size) == -1) {
6376 return map_nt_error_from_unix(errno);
6378 trigger_write_time_update_immediate(fsp);
6379 return NT_STATUS_OK;
6382 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6383 if (smb_fname_tmp == NULL) {
6384 return NT_STATUS_NO_MEMORY;
6387 smb_fname_tmp->st = *psbuf;
6389 status = SMB_VFS_CREATE_FILE(
6392 0, /* root_dir_fid */
6393 smb_fname_tmp, /* fname */
6394 FILE_WRITE_DATA, /* access_mask */
6395 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6397 FILE_OPEN, /* create_disposition*/
6398 0, /* create_options */
6399 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6400 0, /* oplock_request */
6402 0, /* allocation_size */
6403 0, /* private_flags */
6406 &new_fsp, /* result */
6408 NULL, NULL); /* create context */
6410 TALLOC_FREE(smb_fname_tmp);
6412 if (!NT_STATUS_IS_OK(status)) {
6413 /* NB. We check for open_was_deferred in the caller. */
6417 /* See RAW-SFILEINFO-END-OF-FILE */
6418 if (fail_after_createfile) {
6419 close_file(req, new_fsp,NORMAL_CLOSE);
6420 return NT_STATUS_INVALID_LEVEL;
6423 if (vfs_set_filelen(new_fsp, size) == -1) {
6424 status = map_nt_error_from_unix(errno);
6425 close_file(req, new_fsp,NORMAL_CLOSE);
6429 trigger_write_time_update_immediate(new_fsp);
6430 close_file(req, new_fsp,NORMAL_CLOSE);
6431 return NT_STATUS_OK;
6434 /****************************************************************************
6435 Deal with SMB_INFO_SET_EA.
6436 ****************************************************************************/
6438 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6442 const struct smb_filename *smb_fname)
6444 struct ea_list *ea_list = NULL;
6445 TALLOC_CTX *ctx = NULL;
6446 NTSTATUS status = NT_STATUS_OK;
6448 if (total_data < 10) {
6450 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6451 length. They seem to have no effect. Bug #3212. JRA */
6453 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6454 /* We're done. We only get EA info in this call. */
6455 return NT_STATUS_OK;
6458 return NT_STATUS_INVALID_PARAMETER;
6461 if (IVAL(pdata,0) > total_data) {
6462 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6463 IVAL(pdata,0), (unsigned int)total_data));
6464 return NT_STATUS_INVALID_PARAMETER;
6468 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6470 return NT_STATUS_INVALID_PARAMETER;
6473 status = set_ea(conn, fsp, smb_fname, ea_list);
6478 /****************************************************************************
6479 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6480 ****************************************************************************/
6482 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6487 struct ea_list *ea_list = NULL;
6491 return NT_STATUS_INVALID_HANDLE;
6494 if (!lp_ea_support(SNUM(conn))) {
6495 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6496 "EA's not supported.\n",
6497 (unsigned int)total_data));
6498 return NT_STATUS_EAS_NOT_SUPPORTED;
6501 if (total_data < 10) {
6502 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6504 (unsigned int)total_data));
6505 return NT_STATUS_INVALID_PARAMETER;
6508 ea_list = read_nttrans_ea_list(talloc_tos(),
6513 return NT_STATUS_INVALID_PARAMETER;
6516 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6518 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6519 smb_fname_str_dbg(fsp->fsp_name),
6520 nt_errstr(status) ));
6526 /****************************************************************************
6527 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6528 ****************************************************************************/
6530 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6534 struct smb_filename *smb_fname)
6536 NTSTATUS status = NT_STATUS_OK;
6537 bool delete_on_close;
6538 uint32_t dosmode = 0;
6540 if (total_data < 1) {
6541 return NT_STATUS_INVALID_PARAMETER;
6545 return NT_STATUS_INVALID_HANDLE;
6548 delete_on_close = (CVAL(pdata,0) ? True : False);
6549 dosmode = dos_mode(conn, smb_fname);
6551 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6552 "delete_on_close = %u\n",
6553 smb_fname_str_dbg(smb_fname),
6554 (unsigned int)dosmode,
6555 (unsigned int)delete_on_close ));
6557 if (delete_on_close) {
6558 status = can_set_delete_on_close(fsp, dosmode);
6559 if (!NT_STATUS_IS_OK(status)) {
6564 /* The set is across all open files on this dev/inode pair. */
6565 if (!set_delete_on_close(fsp, delete_on_close,
6566 conn->session_info->security_token,
6567 conn->session_info->unix_token)) {
6568 return NT_STATUS_ACCESS_DENIED;
6570 return NT_STATUS_OK;
6573 /****************************************************************************
6574 Deal with SMB_FILE_POSITION_INFORMATION.
6575 ****************************************************************************/
6577 static NTSTATUS smb_file_position_information(connection_struct *conn,
6582 uint64_t position_information;
6584 if (total_data < 8) {
6585 return NT_STATUS_INVALID_PARAMETER;
6589 /* Ignore on pathname based set. */
6590 return NT_STATUS_OK;
6593 position_information = (uint64_t)IVAL(pdata,0);
6594 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6596 DEBUG(10,("smb_file_position_information: Set file position "
6597 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6598 (double)position_information));
6599 fsp->fh->position_information = position_information;
6600 return NT_STATUS_OK;
6603 /****************************************************************************
6604 Deal with SMB_FILE_MODE_INFORMATION.
6605 ****************************************************************************/
6607 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6613 if (total_data < 4) {
6614 return NT_STATUS_INVALID_PARAMETER;
6616 mode = IVAL(pdata,0);
6617 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6618 return NT_STATUS_INVALID_PARAMETER;
6620 return NT_STATUS_OK;
6623 /****************************************************************************
6624 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6625 ****************************************************************************/
6627 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6628 struct smb_request *req,
6631 const struct smb_filename *new_smb_fname)
6633 char *link_target = NULL;
6634 TALLOC_CTX *ctx = talloc_tos();
6636 /* Set a symbolic link. */
6637 /* Don't allow this if follow links is false. */
6639 if (total_data == 0) {
6640 return NT_STATUS_INVALID_PARAMETER;
6643 if (!lp_follow_symlinks(SNUM(conn))) {
6644 return NT_STATUS_ACCESS_DENIED;
6647 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6648 total_data, STR_TERMINATE);
6651 return NT_STATUS_INVALID_PARAMETER;
6654 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6655 new_smb_fname->base_name, link_target ));
6657 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6658 return map_nt_error_from_unix(errno);
6661 return NT_STATUS_OK;
6664 /****************************************************************************
6665 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6666 ****************************************************************************/
6668 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6669 struct smb_request *req,
6670 const char *pdata, int total_data,
6671 struct smb_filename *smb_fname_new)
6673 char *oldname = NULL;
6674 struct smb_filename *smb_fname_old = NULL;
6675 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6676 TALLOC_CTX *ctx = talloc_tos();
6677 NTSTATUS status = NT_STATUS_OK;
6679 /* Set a hard link. */
6680 if (total_data == 0) {
6681 return NT_STATUS_INVALID_PARAMETER;
6684 if (req->posix_pathnames) {
6685 srvstr_get_path_posix(ctx,
6694 srvstr_get_path(ctx,
6703 if (!NT_STATUS_IS_OK(status)) {
6707 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6708 smb_fname_str_dbg(smb_fname_new), oldname));
6710 status = filename_convert(ctx,
6716 if (!NT_STATUS_IS_OK(status)) {
6720 return hardlink_internals(ctx, conn, req, false,
6721 smb_fname_old, smb_fname_new);
6724 /****************************************************************************
6725 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6726 ****************************************************************************/
6728 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6729 struct smb_request *req,
6733 struct smb_filename *smb_fname_src)
6737 char *newname = NULL;
6738 struct smb_filename *smb_fname_dst = NULL;
6739 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6740 ucf_flags_from_smb_request(req);
6741 NTSTATUS status = NT_STATUS_OK;
6742 TALLOC_CTX *ctx = talloc_tos();
6745 return NT_STATUS_INVALID_HANDLE;
6748 if (total_data < 20) {
6749 return NT_STATUS_INVALID_PARAMETER;
6752 overwrite = (CVAL(pdata,0) ? True : False);
6753 len = IVAL(pdata,16);
6755 if (len > (total_data - 20) || (len == 0)) {
6756 return NT_STATUS_INVALID_PARAMETER;
6759 if (req->posix_pathnames) {
6760 srvstr_get_path_posix(ctx,
6769 srvstr_get_path(ctx,
6778 if (!NT_STATUS_IS_OK(status)) {
6782 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6785 status = filename_convert(ctx,
6791 if (!NT_STATUS_IS_OK(status)) {
6795 if (fsp->base_fsp) {
6796 /* newname must be a stream name. */
6797 if (newname[0] != ':') {
6798 return NT_STATUS_NOT_SUPPORTED;
6801 /* Create an smb_fname to call rename_internals_fsp() with. */
6802 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6803 fsp->base_fsp->fsp_name->base_name,
6806 fsp->base_fsp->fsp_name->flags);
6807 if (smb_fname_dst == NULL) {
6808 status = NT_STATUS_NO_MEMORY;
6813 * Set the original last component, since
6814 * rename_internals_fsp() requires it.
6816 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6818 if (smb_fname_dst->original_lcomp == NULL) {
6819 status = NT_STATUS_NO_MEMORY;
6825 DEBUG(10,("smb2_file_rename_information: "
6826 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6827 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6828 smb_fname_str_dbg(smb_fname_dst)));
6829 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6830 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6834 TALLOC_FREE(smb_fname_dst);
6838 static NTSTATUS smb_file_link_information(connection_struct *conn,
6839 struct smb_request *req,
6843 struct smb_filename *smb_fname_src)
6847 char *newname = NULL;
6848 struct smb_filename *smb_fname_dst = NULL;
6849 NTSTATUS status = NT_STATUS_OK;
6850 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6851 ucf_flags_from_smb_request(req);
6852 TALLOC_CTX *ctx = talloc_tos();
6855 return NT_STATUS_INVALID_HANDLE;
6858 if (total_data < 20) {
6859 return NT_STATUS_INVALID_PARAMETER;
6862 overwrite = (CVAL(pdata,0) ? true : false);
6863 len = IVAL(pdata,16);
6865 if (len > (total_data - 20) || (len == 0)) {
6866 return NT_STATUS_INVALID_PARAMETER;
6869 if (req->posix_pathnames) {
6870 srvstr_get_path_posix(ctx,
6879 srvstr_get_path(ctx,
6888 if (!NT_STATUS_IS_OK(status)) {
6892 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6895 status = filename_convert(ctx,
6901 if (!NT_STATUS_IS_OK(status)) {
6905 if (fsp->base_fsp) {
6906 /* No stream names. */
6907 return NT_STATUS_NOT_SUPPORTED;
6910 DEBUG(10,("smb_file_link_information: "
6911 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6912 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6913 smb_fname_str_dbg(smb_fname_dst)));
6914 status = hardlink_internals(ctx,
6921 TALLOC_FREE(smb_fname_dst);
6925 /****************************************************************************
6926 Deal with SMB_FILE_RENAME_INFORMATION.
6927 ****************************************************************************/
6929 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6930 struct smb_request *req,
6934 struct smb_filename *smb_fname_src)
6939 char *newname = NULL;
6940 struct smb_filename *smb_fname_dst = NULL;
6941 bool dest_has_wcard = False;
6942 NTSTATUS status = NT_STATUS_OK;
6944 TALLOC_CTX *ctx = talloc_tos();
6946 if (total_data < 13) {
6947 return NT_STATUS_INVALID_PARAMETER;
6950 overwrite = (CVAL(pdata,0) ? True : False);
6951 root_fid = IVAL(pdata,4);
6952 len = IVAL(pdata,8);
6954 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6955 return NT_STATUS_INVALID_PARAMETER;
6958 if (req->posix_pathnames) {
6959 srvstr_get_path_wcard_posix(ctx,
6969 srvstr_get_path_wcard(ctx,
6979 if (!NT_STATUS_IS_OK(status)) {
6983 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6986 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
6987 status = resolve_dfspath_wcard(ctx, conn,
6989 UCF_COND_ALLOW_WCARD_LCOMP,
6990 !conn->sconn->using_smb2,
6993 if (!NT_STATUS_IS_OK(status)) {
6998 /* Check the new name has no '/' characters. */
6999 if (strchr_m(newname, '/')) {
7000 return NT_STATUS_NOT_SUPPORTED;
7003 if (fsp && fsp->base_fsp) {
7004 /* newname must be a stream name. */
7005 if (newname[0] != ':') {
7006 return NT_STATUS_NOT_SUPPORTED;
7009 /* Create an smb_fname to call rename_internals_fsp() with. */
7010 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7011 fsp->base_fsp->fsp_name->base_name,
7014 fsp->base_fsp->fsp_name->flags);
7015 if (smb_fname_dst == NULL) {
7016 status = NT_STATUS_NO_MEMORY;
7021 * Set the original last component, since
7022 * rename_internals_fsp() requires it.
7024 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7026 if (smb_fname_dst->original_lcomp == NULL) {
7027 status = NT_STATUS_NO_MEMORY;
7033 * Build up an smb_fname_dst based on the filename passed in.
7034 * We basically just strip off the last component, and put on
7035 * the newname instead.
7037 char *base_name = NULL;
7038 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7039 ucf_flags_from_smb_request(req);
7041 if (dest_has_wcard) {
7042 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7045 /* newname must *not* be a stream name. */
7046 if (newname[0] == ':') {
7047 return NT_STATUS_NOT_SUPPORTED;
7051 * Strip off the last component (filename) of the path passed
7054 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7056 return NT_STATUS_NO_MEMORY;
7058 p = strrchr_m(base_name, '/');
7062 base_name = talloc_strdup(ctx, "");
7064 return NT_STATUS_NO_MEMORY;
7067 /* Append the new name. */
7068 base_name = talloc_asprintf_append(base_name,
7072 return NT_STATUS_NO_MEMORY;
7075 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7078 /* If an error we expect this to be
7079 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7081 if (!NT_STATUS_IS_OK(status)) {
7082 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7086 /* Create an smb_fname to call rename_internals_fsp() */
7087 smb_fname_dst = synthetic_smb_fname(ctx,
7091 smb_fname_src->flags);
7092 if (smb_fname_dst == NULL) {
7093 status = NT_STATUS_NO_MEMORY;
7100 DEBUG(10,("smb_file_rename_information: "
7101 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7102 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7103 smb_fname_str_dbg(smb_fname_dst)));
7104 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7107 DEBUG(10,("smb_file_rename_information: "
7108 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7109 smb_fname_str_dbg(smb_fname_src),
7110 smb_fname_str_dbg(smb_fname_dst)));
7111 status = rename_internals(ctx, conn, req, smb_fname_src,
7112 smb_fname_dst, 0, overwrite, false,
7114 FILE_WRITE_ATTRIBUTES);
7117 TALLOC_FREE(smb_fname_dst);
7121 /****************************************************************************
7122 Deal with SMB_SET_POSIX_ACL.
7123 ****************************************************************************/
7125 #if defined(HAVE_POSIX_ACLS)
7126 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7130 const struct smb_filename *smb_fname)
7132 uint16_t posix_acl_version;
7133 uint16_t num_file_acls;
7134 uint16_t num_def_acls;
7135 bool valid_file_acls = True;
7136 bool valid_def_acls = True;
7139 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7140 return NT_STATUS_INVALID_PARAMETER;
7142 posix_acl_version = SVAL(pdata,0);
7143 num_file_acls = SVAL(pdata,2);
7144 num_def_acls = SVAL(pdata,4);
7146 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7147 valid_file_acls = False;
7151 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7152 valid_def_acls = False;
7156 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7157 return NT_STATUS_INVALID_PARAMETER;
7160 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7161 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7162 return NT_STATUS_INVALID_PARAMETER;
7165 status = refuse_symlink(conn, fsp, smb_fname);
7166 if (!NT_STATUS_IS_OK(status)) {
7170 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7171 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7172 (unsigned int)num_file_acls,
7173 (unsigned int)num_def_acls));
7175 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7176 smb_fname, num_file_acls,
7177 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7178 return map_nt_error_from_unix(errno);
7181 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7182 smb_fname, num_def_acls,
7183 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7184 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7185 return map_nt_error_from_unix(errno);
7187 return NT_STATUS_OK;
7191 /****************************************************************************
7192 Deal with SMB_SET_POSIX_LOCK.
7193 ****************************************************************************/
7195 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7196 struct smb_request *req,
7204 bool blocking_lock = False;
7205 enum brl_type lock_type;
7207 NTSTATUS status = NT_STATUS_OK;
7209 if (fsp == NULL || fsp->fh->fd == -1) {
7210 return NT_STATUS_INVALID_HANDLE;
7213 if (total_data != POSIX_LOCK_DATA_SIZE) {
7214 return NT_STATUS_INVALID_PARAMETER;
7217 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7218 case POSIX_LOCK_TYPE_READ:
7219 lock_type = READ_LOCK;
7221 case POSIX_LOCK_TYPE_WRITE:
7222 /* Return the right POSIX-mappable error code for files opened read-only. */
7223 if (!fsp->can_write) {
7224 return NT_STATUS_INVALID_HANDLE;
7226 lock_type = WRITE_LOCK;
7228 case POSIX_LOCK_TYPE_UNLOCK:
7229 lock_type = UNLOCK_LOCK;
7232 return NT_STATUS_INVALID_PARAMETER;
7235 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7236 blocking_lock = False;
7237 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7238 blocking_lock = True;
7240 return NT_STATUS_INVALID_PARAMETER;
7243 if (!lp_blocking_locks(SNUM(conn))) {
7244 blocking_lock = False;
7247 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7248 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7249 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7250 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7251 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7253 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7254 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7256 (unsigned int)lock_type,
7257 (unsigned long long)smblctx,
7261 if (lock_type == UNLOCK_LOCK) {
7262 status = do_unlock(req->sconn->msg_ctx,
7269 uint64_t block_smblctx;
7271 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7282 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7284 * A blocking lock was requested. Package up
7285 * this smb into a queued request and push it
7286 * onto the blocking lock queue.
7288 if(push_blocking_lock_request(br_lck,
7291 -1, /* infinite timeout. */
7299 TALLOC_FREE(br_lck);
7303 TALLOC_FREE(br_lck);
7309 /****************************************************************************
7310 Deal with SMB_SET_FILE_BASIC_INFO.
7311 ****************************************************************************/
7313 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7317 const struct smb_filename *smb_fname)
7319 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7320 struct smb_file_time ft;
7321 uint32_t dosmode = 0;
7322 NTSTATUS status = NT_STATUS_OK;
7326 if (total_data < 36) {
7327 return NT_STATUS_INVALID_PARAMETER;
7330 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7331 if (!NT_STATUS_IS_OK(status)) {
7335 /* Set the attributes */
7336 dosmode = IVAL(pdata,32);
7337 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7338 if (!NT_STATUS_IS_OK(status)) {
7343 ft.create_time = interpret_long_date(pdata);
7346 ft.atime = interpret_long_date(pdata+8);
7349 ft.mtime = interpret_long_date(pdata+16);
7352 ft.ctime = interpret_long_date(pdata+24);
7354 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7355 smb_fname_str_dbg(smb_fname)));
7357 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7361 /****************************************************************************
7362 Deal with SMB_INFO_STANDARD.
7363 ****************************************************************************/
7365 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7369 const struct smb_filename *smb_fname)
7372 struct smb_file_time ft;
7376 if (total_data < 12) {
7377 return NT_STATUS_INVALID_PARAMETER;
7381 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7383 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7385 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7387 DEBUG(10,("smb_set_info_standard: file %s\n",
7388 smb_fname_str_dbg(smb_fname)));
7390 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7391 if (!NT_STATUS_IS_OK(status)) {
7395 return smb_set_file_time(conn,
7402 /****************************************************************************
7403 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7404 ****************************************************************************/
7406 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7407 struct smb_request *req,
7411 struct smb_filename *smb_fname)
7413 uint64_t allocation_size = 0;
7414 NTSTATUS status = NT_STATUS_OK;
7415 files_struct *new_fsp = NULL;
7417 if (!VALID_STAT(smb_fname->st)) {
7418 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7421 if (total_data < 8) {
7422 return NT_STATUS_INVALID_PARAMETER;
7425 allocation_size = (uint64_t)IVAL(pdata,0);
7426 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7427 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7428 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7429 (double)allocation_size));
7431 if (allocation_size) {
7432 allocation_size = smb_roundup(conn, allocation_size);
7435 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7436 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7437 (double)allocation_size));
7439 if (fsp && fsp->fh->fd != -1) {
7440 /* Open file handle. */
7441 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7442 return NT_STATUS_ACCESS_DENIED;
7445 /* Only change if needed. */
7446 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7447 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7448 return map_nt_error_from_unix(errno);
7451 /* But always update the time. */
7453 * This is equivalent to a write. Ensure it's seen immediately
7454 * if there are no pending writes.
7456 trigger_write_time_update_immediate(fsp);
7457 return NT_STATUS_OK;
7460 /* Pathname or stat or directory file. */
7461 status = SMB_VFS_CREATE_FILE(
7464 0, /* root_dir_fid */
7465 smb_fname, /* fname */
7466 FILE_WRITE_DATA, /* access_mask */
7467 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7469 FILE_OPEN, /* create_disposition*/
7470 0, /* create_options */
7471 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7472 0, /* oplock_request */
7474 0, /* allocation_size */
7475 0, /* private_flags */
7478 &new_fsp, /* result */
7480 NULL, NULL); /* create context */
7482 if (!NT_STATUS_IS_OK(status)) {
7483 /* NB. We check for open_was_deferred in the caller. */
7487 /* Only change if needed. */
7488 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7489 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7490 status = map_nt_error_from_unix(errno);
7491 close_file(req, new_fsp, NORMAL_CLOSE);
7496 /* Changing the allocation size should set the last mod time. */
7498 * This is equivalent to a write. Ensure it's seen immediately
7499 * if there are no pending writes.
7501 trigger_write_time_update_immediate(new_fsp);
7502 close_file(req, new_fsp, NORMAL_CLOSE);
7503 return NT_STATUS_OK;
7506 /****************************************************************************
7507 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7508 ****************************************************************************/
7510 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7511 struct smb_request *req,
7515 const struct smb_filename *smb_fname,
7516 bool fail_after_createfile)
7520 if (total_data < 8) {
7521 return NT_STATUS_INVALID_PARAMETER;
7524 size = IVAL(pdata,0);
7525 size |= (((off_t)IVAL(pdata,4)) << 32);
7526 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7527 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7530 return smb_set_file_size(conn, req,
7535 fail_after_createfile);
7538 /****************************************************************************
7539 Allow a UNIX info mknod.
7540 ****************************************************************************/
7542 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7545 const struct smb_filename *smb_fname)
7547 uint32_t file_type = IVAL(pdata,56);
7548 #if defined(HAVE_MAKEDEV)
7549 uint32_t dev_major = IVAL(pdata,60);
7550 uint32_t dev_minor = IVAL(pdata,68);
7552 SMB_DEV_T dev = (SMB_DEV_T)0;
7553 uint32_t raw_unixmode = IVAL(pdata,84);
7557 if (total_data < 100) {
7558 return NT_STATUS_INVALID_PARAMETER;
7561 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7562 PERM_NEW_FILE, &unixmode);
7563 if (!NT_STATUS_IS_OK(status)) {
7567 #if defined(HAVE_MAKEDEV)
7568 dev = makedev(dev_major, dev_minor);
7571 switch (file_type) {
7572 #if defined(S_IFIFO)
7573 case UNIX_TYPE_FIFO:
7574 unixmode |= S_IFIFO;
7577 #if defined(S_IFSOCK)
7578 case UNIX_TYPE_SOCKET:
7579 unixmode |= S_IFSOCK;
7582 #if defined(S_IFCHR)
7583 case UNIX_TYPE_CHARDEV:
7584 unixmode |= S_IFCHR;
7587 #if defined(S_IFBLK)
7588 case UNIX_TYPE_BLKDEV:
7589 unixmode |= S_IFBLK;
7593 return NT_STATUS_INVALID_PARAMETER;
7596 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7597 "%.0f mode 0%o for file %s\n", (double)dev,
7598 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7600 /* Ok - do the mknod. */
7601 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7602 return map_nt_error_from_unix(errno);
7605 /* If any of the other "set" calls fail we
7606 * don't want to end up with a half-constructed mknod.
7609 if (lp_inherit_permissions(SNUM(conn))) {
7611 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7613 return NT_STATUS_NO_MEMORY;
7615 inherit_access_posix_acl(conn, parent, smb_fname,
7617 TALLOC_FREE(parent);
7620 return NT_STATUS_OK;
7623 /****************************************************************************
7624 Deal with SMB_SET_FILE_UNIX_BASIC.
7625 ****************************************************************************/
7627 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7628 struct smb_request *req,
7632 const struct smb_filename *smb_fname)
7634 struct smb_file_time ft;
7635 uint32_t raw_unixmode;
7638 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7639 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7640 NTSTATUS status = NT_STATUS_OK;
7641 bool delete_on_fail = False;
7642 enum perm_type ptype;
7643 files_struct *all_fsps = NULL;
7644 bool modify_mtime = true;
7646 struct smb_filename *smb_fname_tmp = NULL;
7647 SMB_STRUCT_STAT sbuf;
7651 if (total_data < 100) {
7652 return NT_STATUS_INVALID_PARAMETER;
7655 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7656 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7657 size=IVAL(pdata,0); /* first 8 Bytes are size */
7658 size |= (((off_t)IVAL(pdata,4)) << 32);
7661 ft.atime = interpret_long_date(pdata+24); /* access_time */
7662 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7663 set_owner = (uid_t)IVAL(pdata,40);
7664 set_grp = (gid_t)IVAL(pdata,48);
7665 raw_unixmode = IVAL(pdata,84);
7667 if (VALID_STAT(smb_fname->st)) {
7668 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7669 ptype = PERM_EXISTING_DIR;
7671 ptype = PERM_EXISTING_FILE;
7674 ptype = PERM_NEW_FILE;
7677 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7679 if (!NT_STATUS_IS_OK(status)) {
7683 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7684 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7685 smb_fname_str_dbg(smb_fname), (double)size,
7686 (unsigned int)set_owner, (unsigned int)set_grp,
7687 (int)raw_unixmode));
7689 sbuf = smb_fname->st;
7691 if (!VALID_STAT(sbuf)) {
7693 * The only valid use of this is to create character and block
7694 * devices, and named pipes. This is deprecated (IMHO) and
7695 * a new info level should be used for mknod. JRA.
7698 status = smb_unix_mknod(conn,
7702 if (!NT_STATUS_IS_OK(status)) {
7706 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7707 if (smb_fname_tmp == NULL) {
7708 return NT_STATUS_NO_MEMORY;
7711 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7712 status = map_nt_error_from_unix(errno);
7713 TALLOC_FREE(smb_fname_tmp);
7714 SMB_VFS_UNLINK(conn, smb_fname);
7718 sbuf = smb_fname_tmp->st;
7719 smb_fname = smb_fname_tmp;
7721 /* Ensure we don't try and change anything else. */
7722 raw_unixmode = SMB_MODE_NO_CHANGE;
7723 size = get_file_size_stat(&sbuf);
7724 ft.atime = sbuf.st_ex_atime;
7725 ft.mtime = sbuf.st_ex_mtime;
7727 * We continue here as we might want to change the
7730 delete_on_fail = True;
7734 /* Horrible backwards compatibility hack as an old server bug
7735 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7739 size = get_file_size_stat(&sbuf);
7744 * Deal with the UNIX specific mode set.
7747 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7750 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7751 "setting mode 0%o for file %s\n",
7752 (unsigned int)unixmode,
7753 smb_fname_str_dbg(smb_fname)));
7754 if (fsp && fsp->fh->fd != -1) {
7755 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7757 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7760 return map_nt_error_from_unix(errno);
7765 * Deal with the UNIX specific uid set.
7768 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7769 (sbuf.st_ex_uid != set_owner)) {
7772 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7773 "changing owner %u for path %s\n",
7774 (unsigned int)set_owner,
7775 smb_fname_str_dbg(smb_fname)));
7777 if (fsp && fsp->fh->fd != -1) {
7778 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7781 * UNIX extensions calls must always operate
7784 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7785 set_owner, (gid_t)-1);
7789 status = map_nt_error_from_unix(errno);
7790 if (delete_on_fail) {
7791 SMB_VFS_UNLINK(conn, smb_fname);
7798 * Deal with the UNIX specific gid set.
7801 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7802 (sbuf.st_ex_gid != set_grp)) {
7805 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7806 "changing group %u for file %s\n",
7807 (unsigned int)set_grp,
7808 smb_fname_str_dbg(smb_fname)));
7809 if (fsp && fsp->fh->fd != -1) {
7810 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
7813 * UNIX extensions calls must always operate
7816 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7820 status = map_nt_error_from_unix(errno);
7821 if (delete_on_fail) {
7822 SMB_VFS_UNLINK(conn, smb_fname);
7828 /* Deal with any size changes. */
7830 status = smb_set_file_size(conn, req,
7836 if (!NT_STATUS_IS_OK(status)) {
7840 /* Deal with any time changes. */
7841 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7842 /* No change, don't cancel anything. */
7846 id = vfs_file_id_from_sbuf(conn, &sbuf);
7847 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7848 all_fsps = file_find_di_next(all_fsps)) {
7850 * We're setting the time explicitly for UNIX.
7851 * Cancel any pending changes over all handles.
7853 all_fsps->update_write_time_on_close = false;
7854 TALLOC_FREE(all_fsps->update_write_time_event);
7858 * Override the "setting_write_time"
7859 * parameter here as it almost does what
7860 * we need. Just remember if we modified
7861 * mtime and send the notify ourselves.
7863 if (null_timespec(ft.mtime)) {
7864 modify_mtime = false;
7867 status = smb_set_file_time(conn,
7873 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7874 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7879 /****************************************************************************
7880 Deal with SMB_SET_FILE_UNIX_INFO2.
7881 ****************************************************************************/
7883 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7884 struct smb_request *req,
7888 const struct smb_filename *smb_fname)
7891 uint32_t smb_fflags;
7894 if (total_data < 116) {
7895 return NT_STATUS_INVALID_PARAMETER;
7898 /* Start by setting all the fields that are common between UNIX_BASIC
7901 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7903 if (!NT_STATUS_IS_OK(status)) {
7907 smb_fflags = IVAL(pdata, 108);
7908 smb_fmask = IVAL(pdata, 112);
7910 /* NB: We should only attempt to alter the file flags if the client
7911 * sends a non-zero mask.
7913 if (smb_fmask != 0) {
7914 int stat_fflags = 0;
7916 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7917 smb_fmask, &stat_fflags)) {
7918 /* Client asked to alter a flag we don't understand. */
7919 return NT_STATUS_INVALID_PARAMETER;
7922 if (fsp && fsp->fh->fd != -1) {
7923 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7924 return NT_STATUS_NOT_SUPPORTED;
7926 if (SMB_VFS_CHFLAGS(conn, smb_fname,
7927 stat_fflags) != 0) {
7928 return map_nt_error_from_unix(errno);
7933 /* XXX: need to add support for changing the create_time here. You
7934 * can do this for paths on Darwin with setattrlist(2). The right way
7935 * to hook this up is probably by extending the VFS utimes interface.
7938 return NT_STATUS_OK;
7941 /****************************************************************************
7942 Create a directory with POSIX semantics.
7943 ****************************************************************************/
7945 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7946 struct smb_request *req,
7949 struct smb_filename *smb_fname,
7950 int *pdata_return_size)
7952 NTSTATUS status = NT_STATUS_OK;
7953 uint32_t raw_unixmode = 0;
7954 uint32_t mod_unixmode = 0;
7955 mode_t unixmode = (mode_t)0;
7956 files_struct *fsp = NULL;
7957 uint16_t info_level_return = 0;
7959 char *pdata = *ppdata;
7961 if (total_data < 18) {
7962 return NT_STATUS_INVALID_PARAMETER;
7965 raw_unixmode = IVAL(pdata,8);
7966 /* Next 4 bytes are not yet defined. */
7968 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7969 PERM_NEW_DIR, &unixmode);
7970 if (!NT_STATUS_IS_OK(status)) {
7974 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7976 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7977 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7979 status = SMB_VFS_CREATE_FILE(
7982 0, /* root_dir_fid */
7983 smb_fname, /* fname */
7984 FILE_READ_ATTRIBUTES, /* access_mask */
7985 FILE_SHARE_NONE, /* share_access */
7986 FILE_CREATE, /* create_disposition*/
7987 FILE_DIRECTORY_FILE, /* create_options */
7988 mod_unixmode, /* file_attributes */
7989 0, /* oplock_request */
7991 0, /* allocation_size */
7992 0, /* private_flags */
7997 NULL, NULL); /* create context */
7999 if (NT_STATUS_IS_OK(status)) {
8000 close_file(req, fsp, NORMAL_CLOSE);
8003 info_level_return = SVAL(pdata,16);
8005 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8006 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8007 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8008 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8010 *pdata_return_size = 12;
8013 /* Realloc the data size */
8014 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8015 if (*ppdata == NULL) {
8016 *pdata_return_size = 0;
8017 return NT_STATUS_NO_MEMORY;
8021 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8022 SSVAL(pdata,2,0); /* No fnum. */
8023 SIVAL(pdata,4,info); /* Was directory created. */
8025 switch (info_level_return) {
8026 case SMB_QUERY_FILE_UNIX_BASIC:
8027 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8028 SSVAL(pdata,10,0); /* Padding. */
8029 store_file_unix_basic(conn, pdata + 12, fsp,
8032 case SMB_QUERY_FILE_UNIX_INFO2:
8033 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8034 SSVAL(pdata,10,0); /* Padding. */
8035 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8039 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8040 SSVAL(pdata,10,0); /* Padding. */
8047 /****************************************************************************
8048 Open/Create a file with POSIX semantics.
8049 ****************************************************************************/
8051 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8052 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8054 static NTSTATUS smb_posix_open(connection_struct *conn,
8055 struct smb_request *req,
8058 struct smb_filename *smb_fname,
8059 int *pdata_return_size)
8061 bool extended_oplock_granted = False;
8062 char *pdata = *ppdata;
8064 uint32_t wire_open_mode = 0;
8065 uint32_t raw_unixmode = 0;
8066 uint32_t mod_unixmode = 0;
8067 uint32_t create_disp = 0;
8068 uint32_t access_mask = 0;
8069 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8070 NTSTATUS status = NT_STATUS_OK;
8071 mode_t unixmode = (mode_t)0;
8072 files_struct *fsp = NULL;
8073 int oplock_request = 0;
8075 uint16_t info_level_return = 0;
8077 if (total_data < 18) {
8078 return NT_STATUS_INVALID_PARAMETER;
8081 flags = IVAL(pdata,0);
8082 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8083 if (oplock_request) {
8084 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8087 wire_open_mode = IVAL(pdata,4);
8089 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8090 return smb_posix_mkdir(conn, req,
8097 switch (wire_open_mode & SMB_ACCMODE) {
8099 access_mask = SMB_O_RDONLY_MAPPING;
8102 access_mask = SMB_O_WRONLY_MAPPING;
8105 access_mask = (SMB_O_RDONLY_MAPPING|
8106 SMB_O_WRONLY_MAPPING);
8109 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8110 (unsigned int)wire_open_mode ));
8111 return NT_STATUS_INVALID_PARAMETER;
8114 wire_open_mode &= ~SMB_ACCMODE;
8116 /* First take care of O_CREAT|O_EXCL interactions. */
8117 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8118 case (SMB_O_CREAT | SMB_O_EXCL):
8119 /* File exists fail. File not exist create. */
8120 create_disp = FILE_CREATE;
8123 /* File exists open. File not exist create. */
8124 create_disp = FILE_OPEN_IF;
8127 /* O_EXCL on its own without O_CREAT is undefined.
8128 We deliberately ignore it as some versions of
8129 Linux CIFSFS can send a bare O_EXCL on the
8130 wire which other filesystems in the kernel
8131 ignore. See bug 9519 for details. */
8136 /* File exists open. File not exist fail. */
8137 create_disp = FILE_OPEN;
8140 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8141 (unsigned int)wire_open_mode ));
8142 return NT_STATUS_INVALID_PARAMETER;
8145 /* Next factor in the effects of O_TRUNC. */
8146 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8148 if (wire_open_mode & SMB_O_TRUNC) {
8149 switch (create_disp) {
8151 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8152 /* Leave create_disp alone as
8153 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8155 /* File exists fail. File not exist create. */
8158 /* SMB_O_CREAT | SMB_O_TRUNC */
8159 /* File exists overwrite. File not exist create. */
8160 create_disp = FILE_OVERWRITE_IF;
8164 /* File exists overwrite. File not exist fail. */
8165 create_disp = FILE_OVERWRITE;
8168 /* Cannot get here. */
8169 smb_panic("smb_posix_open: logic error");
8170 return NT_STATUS_INVALID_PARAMETER;
8174 raw_unixmode = IVAL(pdata,8);
8175 /* Next 4 bytes are not yet defined. */
8177 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8178 (VALID_STAT(smb_fname->st) ?
8179 PERM_EXISTING_FILE : PERM_NEW_FILE),
8182 if (!NT_STATUS_IS_OK(status)) {
8186 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8188 if (wire_open_mode & SMB_O_SYNC) {
8189 create_options |= FILE_WRITE_THROUGH;
8191 if (wire_open_mode & SMB_O_APPEND) {
8192 access_mask |= FILE_APPEND_DATA;
8194 if (wire_open_mode & SMB_O_DIRECT) {
8195 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8198 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8199 VALID_STAT_OF_DIR(smb_fname->st)) {
8200 if (access_mask != SMB_O_RDONLY_MAPPING) {
8201 return NT_STATUS_FILE_IS_A_DIRECTORY;
8203 create_options &= ~FILE_NON_DIRECTORY_FILE;
8204 create_options |= FILE_DIRECTORY_FILE;
8207 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8208 smb_fname_str_dbg(smb_fname),
8209 (unsigned int)wire_open_mode,
8210 (unsigned int)unixmode ));
8212 status = SMB_VFS_CREATE_FILE(
8215 0, /* root_dir_fid */
8216 smb_fname, /* fname */
8217 access_mask, /* access_mask */
8218 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8220 create_disp, /* create_disposition*/
8221 create_options, /* create_options */
8222 mod_unixmode, /* file_attributes */
8223 oplock_request, /* oplock_request */
8225 0, /* allocation_size */
8226 0, /* private_flags */
8231 NULL, NULL); /* create context */
8233 if (!NT_STATUS_IS_OK(status)) {
8237 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8238 extended_oplock_granted = True;
8241 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8242 extended_oplock_granted = True;
8245 info_level_return = SVAL(pdata,16);
8247 /* Allocate the correct return size. */
8249 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8250 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8251 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8252 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8254 *pdata_return_size = 12;
8257 /* Realloc the data size */
8258 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8259 if (*ppdata == NULL) {
8260 close_file(req, fsp, ERROR_CLOSE);
8261 *pdata_return_size = 0;
8262 return NT_STATUS_NO_MEMORY;
8266 if (extended_oplock_granted) {
8267 if (flags & REQUEST_BATCH_OPLOCK) {
8268 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8270 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8272 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8273 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8275 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8278 SSVAL(pdata,2,fsp->fnum);
8279 SIVAL(pdata,4,info); /* Was file created etc. */
8281 switch (info_level_return) {
8282 case SMB_QUERY_FILE_UNIX_BASIC:
8283 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8284 SSVAL(pdata,10,0); /* padding. */
8285 store_file_unix_basic(conn, pdata + 12, fsp,
8288 case SMB_QUERY_FILE_UNIX_INFO2:
8289 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8290 SSVAL(pdata,10,0); /* padding. */
8291 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8295 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8296 SSVAL(pdata,10,0); /* padding. */
8299 return NT_STATUS_OK;
8302 /****************************************************************************
8303 Delete a file with POSIX semantics.
8304 ****************************************************************************/
8306 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8307 struct smb_request *req,
8310 struct smb_filename *smb_fname)
8312 struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
8313 NTSTATUS status = NT_STATUS_OK;
8314 files_struct *fsp = NULL;
8318 int create_options = 0;
8319 struct share_mode_lock *lck = NULL;
8320 bool other_nonposix_opens;
8322 if (total_data < 2) {
8323 return NT_STATUS_INVALID_PARAMETER;
8326 flags = SVAL(pdata,0);
8328 if (!VALID_STAT(smb_fname->st)) {
8329 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8332 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8333 !VALID_STAT_OF_DIR(smb_fname->st)) {
8334 return NT_STATUS_NOT_A_DIRECTORY;
8337 DEBUG(10,("smb_posix_unlink: %s %s\n",
8338 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8339 smb_fname_str_dbg(smb_fname)));
8341 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8342 create_options |= FILE_DIRECTORY_FILE;
8345 status = SMB_VFS_CREATE_FILE(
8348 0, /* root_dir_fid */
8349 smb_fname, /* fname */
8350 DELETE_ACCESS, /* access_mask */
8351 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8353 FILE_OPEN, /* create_disposition*/
8354 create_options, /* create_options */
8355 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8356 0, /* oplock_request */
8358 0, /* allocation_size */
8359 0, /* private_flags */
8364 NULL, NULL); /* create context */
8366 if (!NT_STATUS_IS_OK(status)) {
8371 * Don't lie to client. If we can't really delete due to
8372 * non-POSIX opens return SHARING_VIOLATION.
8375 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8377 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8378 "lock for file %s\n", fsp_str_dbg(fsp)));
8379 close_file(req, fsp, NORMAL_CLOSE);
8380 return NT_STATUS_INVALID_PARAMETER;
8383 other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
8384 if (other_nonposix_opens) {
8385 /* Fail with sharing violation. */
8387 close_file(req, fsp, NORMAL_CLOSE);
8388 return NT_STATUS_SHARING_VIOLATION;
8392 * Set the delete on close.
8394 status = smb_set_file_disposition_info(conn,
8402 if (!NT_STATUS_IS_OK(status)) {
8403 close_file(req, fsp, NORMAL_CLOSE);
8406 return close_file(req, fsp, NORMAL_CLOSE);
8409 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8410 struct smb_request *req,
8411 TALLOC_CTX *mem_ctx,
8412 uint16_t info_level,
8414 struct smb_filename *smb_fname,
8415 char **ppdata, int total_data,
8418 char *pdata = *ppdata;
8419 NTSTATUS status = NT_STATUS_OK;
8420 int data_return_size = 0;
8424 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8425 return NT_STATUS_INVALID_LEVEL;
8428 if (!CAN_WRITE(conn)) {
8429 /* Allow POSIX opens. The open path will deny
8430 * any non-readonly opens. */
8431 if (info_level != SMB_POSIX_PATH_OPEN) {
8432 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8436 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8437 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8439 info_level, total_data));
8441 switch (info_level) {
8443 case SMB_INFO_STANDARD:
8445 status = smb_set_info_standard(conn,
8453 case SMB_INFO_SET_EA:
8455 status = smb_info_set_ea(conn,
8463 case SMB_SET_FILE_BASIC_INFO:
8464 case SMB_FILE_BASIC_INFORMATION:
8466 status = smb_set_file_basic_info(conn,
8474 case SMB_FILE_ALLOCATION_INFORMATION:
8475 case SMB_SET_FILE_ALLOCATION_INFO:
8477 status = smb_set_file_allocation_info(conn, req,
8485 case SMB_FILE_END_OF_FILE_INFORMATION:
8486 case SMB_SET_FILE_END_OF_FILE_INFO:
8489 * XP/Win7 both fail after the createfile with
8490 * SMB_SET_FILE_END_OF_FILE_INFO but not
8491 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8492 * The level is known here, so pass it down
8496 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8498 status = smb_set_file_end_of_file_info(conn, req,
8507 case SMB_FILE_DISPOSITION_INFORMATION:
8508 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8511 /* JRA - We used to just ignore this on a path ?
8512 * Shouldn't this be invalid level on a pathname
8515 if (tran_call != TRANSACT2_SETFILEINFO) {
8516 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8519 status = smb_set_file_disposition_info(conn,
8527 case SMB_FILE_POSITION_INFORMATION:
8529 status = smb_file_position_information(conn,
8536 case SMB_FILE_FULL_EA_INFORMATION:
8538 status = smb_set_file_full_ea_info(conn,
8545 /* From tridge Samba4 :
8546 * MODE_INFORMATION in setfileinfo (I have no
8547 * idea what "mode information" on a file is - it takes a value of 0,
8548 * 2, 4 or 6. What could it be?).
8551 case SMB_FILE_MODE_INFORMATION:
8553 status = smb_file_mode_information(conn,
8559 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8560 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8561 case SMB_FILE_SHORT_NAME_INFORMATION:
8562 return NT_STATUS_NOT_SUPPORTED;
8565 * CIFS UNIX extensions.
8568 case SMB_SET_FILE_UNIX_BASIC:
8570 status = smb_set_file_unix_basic(conn, req,
8578 case SMB_SET_FILE_UNIX_INFO2:
8580 status = smb_set_file_unix_info2(conn, req,
8588 case SMB_SET_FILE_UNIX_LINK:
8591 /* We must have a pathname for this. */
8592 return NT_STATUS_INVALID_LEVEL;
8594 status = smb_set_file_unix_link(conn, req, pdata,
8595 total_data, smb_fname);
8599 case SMB_SET_FILE_UNIX_HLINK:
8602 /* We must have a pathname for this. */
8603 return NT_STATUS_INVALID_LEVEL;
8605 status = smb_set_file_unix_hlink(conn, req,
8611 case SMB_FILE_RENAME_INFORMATION:
8613 status = smb_file_rename_information(conn, req,
8619 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8621 /* SMB2 rename information. */
8622 status = smb2_file_rename_information(conn, req,
8628 case SMB_FILE_LINK_INFORMATION:
8630 status = smb_file_link_information(conn, req,
8636 #if defined(HAVE_POSIX_ACLS)
8637 case SMB_SET_POSIX_ACL:
8639 status = smb_set_posix_acl(conn,
8648 case SMB_SET_POSIX_LOCK:
8651 return NT_STATUS_INVALID_LEVEL;
8653 status = smb_set_posix_lock(conn, req,
8654 pdata, total_data, fsp);
8658 case SMB_POSIX_PATH_OPEN:
8661 /* We must have a pathname for this. */
8662 return NT_STATUS_INVALID_LEVEL;
8665 status = smb_posix_open(conn, req,
8673 case SMB_POSIX_PATH_UNLINK:
8676 /* We must have a pathname for this. */
8677 return NT_STATUS_INVALID_LEVEL;
8680 status = smb_posix_unlink(conn, req,
8688 return NT_STATUS_INVALID_LEVEL;
8691 if (!NT_STATUS_IS_OK(status)) {
8695 *ret_data_size = data_return_size;
8696 return NT_STATUS_OK;
8699 /****************************************************************************
8700 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8701 ****************************************************************************/
8703 static void call_trans2setfilepathinfo(connection_struct *conn,
8704 struct smb_request *req,
8705 unsigned int tran_call,
8706 char **pparams, int total_params,
8707 char **ppdata, int total_data,
8708 unsigned int max_data_bytes)
8710 char *params = *pparams;
8711 char *pdata = *ppdata;
8712 uint16_t info_level;
8713 struct smb_filename *smb_fname = NULL;
8714 files_struct *fsp = NULL;
8715 NTSTATUS status = NT_STATUS_OK;
8716 int data_return_size = 0;
8719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8723 if (tran_call == TRANSACT2_SETFILEINFO) {
8724 if (total_params < 4) {
8725 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8729 fsp = file_fsp(req, SVAL(params,0));
8730 /* Basic check for non-null fsp. */
8731 if (!check_fsp_open(conn, req, fsp)) {
8734 info_level = SVAL(params,2);
8736 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8737 if (smb_fname == NULL) {
8738 reply_nterror(req, NT_STATUS_NO_MEMORY);
8742 if(fsp->fh->fd == -1) {
8744 * This is actually a SETFILEINFO on a directory
8745 * handle (returned from an NT SMB). NT5.0 seems
8746 * to do this call. JRA.
8748 if (INFO_LEVEL_IS_UNIX(info_level)) {
8749 /* Always do lstat for UNIX calls. */
8750 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8751 DEBUG(3,("call_trans2setfilepathinfo: "
8752 "SMB_VFS_LSTAT of %s failed "
8754 smb_fname_str_dbg(smb_fname),
8756 reply_nterror(req, map_nt_error_from_unix(errno));
8760 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8761 DEBUG(3,("call_trans2setfilepathinfo: "
8762 "fileinfo of %s failed (%s)\n",
8763 smb_fname_str_dbg(smb_fname),
8765 reply_nterror(req, map_nt_error_from_unix(errno));
8769 } else if (fsp->print_file) {
8771 * Doing a DELETE_ON_CLOSE should cancel a print job.
8773 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8774 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8776 DEBUG(3,("call_trans2setfilepathinfo: "
8777 "Cancelling print job (%s)\n",
8781 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8787 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8792 * Original code - this is an open file.
8794 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8795 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8796 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8798 reply_nterror(req, map_nt_error_from_unix(errno));
8804 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8807 if (total_params < 7) {
8808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8812 info_level = SVAL(params,0);
8813 if (req->posix_pathnames) {
8814 srvstr_get_path_posix(req,
8823 srvstr_get_path(req,
8832 if (!NT_STATUS_IS_OK(status)) {
8833 reply_nterror(req, status);
8837 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8838 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8839 info_level == SMB_FILE_RENAME_INFORMATION ||
8840 info_level == SMB_POSIX_PATH_UNLINK) {
8841 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8844 status = filename_convert(req, conn,
8849 if (!NT_STATUS_IS_OK(status)) {
8850 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8851 reply_botherror(req,
8852 NT_STATUS_PATH_NOT_COVERED,
8853 ERRSRV, ERRbadpath);
8856 reply_nterror(req, status);
8860 if (INFO_LEVEL_IS_UNIX(info_level)) {
8862 * For CIFS UNIX extensions the target name may not exist.
8865 /* Always do lstat for UNIX calls. */
8866 SMB_VFS_LSTAT(conn, smb_fname);
8868 } else if (!VALID_STAT(smb_fname->st) &&
8869 SMB_VFS_STAT(conn, smb_fname)) {
8870 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8872 smb_fname_str_dbg(smb_fname),
8874 reply_nterror(req, map_nt_error_from_unix(errno));
8879 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8880 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8882 info_level,total_data));
8884 /* Realloc the parameter size */
8885 *pparams = (char *)SMB_REALLOC(*pparams,2);
8886 if (*pparams == NULL) {
8887 reply_nterror(req, NT_STATUS_NO_MEMORY);
8894 status = smbd_do_setfilepathinfo(conn, req, req,
8900 if (!NT_STATUS_IS_OK(status)) {
8901 if (open_was_deferred(req->xconn, req->mid)) {
8902 /* We have re-scheduled this call. */
8905 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8906 /* We have re-scheduled this call. */
8909 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8910 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8911 ERRSRV, ERRbadpath);
8914 if (info_level == SMB_POSIX_PATH_OPEN) {
8915 reply_openerror(req, status);
8920 * Invalid EA name needs to return 2 param bytes,
8921 * not a zero-length error packet.
8923 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8924 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8927 reply_nterror(req, status);
8932 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8938 /****************************************************************************
8939 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8940 ****************************************************************************/
8942 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8943 char **pparams, int total_params,
8944 char **ppdata, int total_data,
8945 unsigned int max_data_bytes)
8947 struct smb_filename *smb_dname = NULL;
8948 char *params = *pparams;
8949 char *pdata = *ppdata;
8950 char *directory = NULL;
8951 NTSTATUS status = NT_STATUS_OK;
8952 struct ea_list *ea_list = NULL;
8953 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8954 TALLOC_CTX *ctx = talloc_tos();
8956 if (!CAN_WRITE(conn)) {
8957 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8961 if (total_params < 5) {
8962 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8966 if (req->posix_pathnames) {
8967 srvstr_get_path_posix(ctx,
8976 srvstr_get_path(ctx,
8985 if (!NT_STATUS_IS_OK(status)) {
8986 reply_nterror(req, status);
8990 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8992 status = filename_convert(ctx,
8999 if (!NT_STATUS_IS_OK(status)) {
9000 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9001 reply_botherror(req,
9002 NT_STATUS_PATH_NOT_COVERED,
9003 ERRSRV, ERRbadpath);
9006 reply_nterror(req, status);
9011 * OS/2 workplace shell seems to send SET_EA requests of "null"
9012 * length (4 bytes containing IVAL 4).
9013 * They seem to have no effect. Bug #3212. JRA.
9016 if (total_data && (total_data != 4)) {
9017 /* Any data in this call is an EA list. */
9018 if (total_data < 10) {
9019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9023 if (IVAL(pdata,0) > total_data) {
9024 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9025 IVAL(pdata,0), (unsigned int)total_data));
9026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9030 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9033 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9037 if (!lp_ea_support(SNUM(conn))) {
9038 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9042 /* If total_data == 4 Windows doesn't care what values
9043 * are placed in that field, it just ignores them.
9044 * The System i QNTC IBM SMB client puts bad values here,
9045 * so ignore them. */
9047 status = create_directory(conn, req, smb_dname);
9049 if (!NT_STATUS_IS_OK(status)) {
9050 reply_nterror(req, status);
9054 /* Try and set any given EA. */
9056 status = set_ea(conn, NULL, smb_dname, ea_list);
9057 if (!NT_STATUS_IS_OK(status)) {
9058 reply_nterror(req, status);
9063 /* Realloc the parameter and data sizes */
9064 *pparams = (char *)SMB_REALLOC(*pparams,2);
9065 if(*pparams == NULL) {
9066 reply_nterror(req, NT_STATUS_NO_MEMORY);
9073 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9076 TALLOC_FREE(smb_dname);
9080 /****************************************************************************
9081 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9082 We don't actually do this - we just send a null response.
9083 ****************************************************************************/
9085 static void call_trans2findnotifyfirst(connection_struct *conn,
9086 struct smb_request *req,
9087 char **pparams, int total_params,
9088 char **ppdata, int total_data,
9089 unsigned int max_data_bytes)
9091 char *params = *pparams;
9092 uint16_t info_level;
9094 if (total_params < 6) {
9095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9099 info_level = SVAL(params,4);
9100 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9102 switch (info_level) {
9107 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9111 /* Realloc the parameter and data sizes */
9112 *pparams = (char *)SMB_REALLOC(*pparams,6);
9113 if (*pparams == NULL) {
9114 reply_nterror(req, NT_STATUS_NO_MEMORY);
9119 SSVAL(params,0,fnf_handle);
9120 SSVAL(params,2,0); /* No changes */
9121 SSVAL(params,4,0); /* No EA errors */
9128 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9133 /****************************************************************************
9134 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9135 changes). Currently this does nothing.
9136 ****************************************************************************/
9138 static void call_trans2findnotifynext(connection_struct *conn,
9139 struct smb_request *req,
9140 char **pparams, int total_params,
9141 char **ppdata, int total_data,
9142 unsigned int max_data_bytes)
9144 char *params = *pparams;
9146 DEBUG(3,("call_trans2findnotifynext\n"));
9148 /* Realloc the parameter and data sizes */
9149 *pparams = (char *)SMB_REALLOC(*pparams,4);
9150 if (*pparams == NULL) {
9151 reply_nterror(req, NT_STATUS_NO_MEMORY);
9156 SSVAL(params,0,0); /* No changes */
9157 SSVAL(params,2,0); /* No EA errors */
9159 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9164 /****************************************************************************
9165 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9166 ****************************************************************************/
9168 static void call_trans2getdfsreferral(connection_struct *conn,
9169 struct smb_request *req,
9170 char **pparams, int total_params,
9171 char **ppdata, int total_data,
9172 unsigned int max_data_bytes)
9174 char *params = *pparams;
9175 char *pathname = NULL;
9177 int max_referral_level;
9178 NTSTATUS status = NT_STATUS_OK;
9179 TALLOC_CTX *ctx = talloc_tos();
9181 DEBUG(10,("call_trans2getdfsreferral\n"));
9183 if (total_params < 3) {
9184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9188 max_referral_level = SVAL(params,0);
9190 if(!lp_host_msdfs()) {
9191 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9195 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9196 total_params - 2, STR_TERMINATE);
9198 reply_nterror(req, NT_STATUS_NOT_FOUND);
9201 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9202 ppdata,&status)) < 0) {
9203 reply_nterror(req, status);
9207 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9208 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9209 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9214 #define LMCAT_SPL 0x53
9215 #define LMFUNC_GETJOBID 0x60
9217 /****************************************************************************
9218 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9219 ****************************************************************************/
9221 static void call_trans2ioctl(connection_struct *conn,
9222 struct smb_request *req,
9223 char **pparams, int total_params,
9224 char **ppdata, int total_data,
9225 unsigned int max_data_bytes)
9227 char *pdata = *ppdata;
9228 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9232 /* check for an invalid fid before proceeding */
9235 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9239 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9240 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9241 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9242 if (*ppdata == NULL) {
9243 reply_nterror(req, NT_STATUS_NO_MEMORY);
9248 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9249 CAN ACCEPT THIS IN UNICODE. JRA. */
9252 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9254 status = srvstr_push(pdata, req->flags2, pdata + 2,
9255 lp_netbios_name(), 15,
9256 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9257 if (!NT_STATUS_IS_OK(status)) {
9258 reply_nterror(req, status);
9261 status = srvstr_push(pdata, req->flags2, pdata+18,
9262 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9263 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9264 if (!NT_STATUS_IS_OK(status)) {
9265 reply_nterror(req, status);
9268 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9273 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9274 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9277 /****************************************************************************
9278 Reply to a SMBfindclose (stop trans2 directory search).
9279 ****************************************************************************/
9281 void reply_findclose(struct smb_request *req)
9284 struct smbd_server_connection *sconn = req->sconn;
9286 START_PROFILE(SMBfindclose);
9289 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9290 END_PROFILE(SMBfindclose);
9294 dptr_num = SVALS(req->vwv+0, 0);
9296 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9298 dptr_close(sconn, &dptr_num);
9300 reply_outbuf(req, 0, 0);
9302 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9304 END_PROFILE(SMBfindclose);
9308 /****************************************************************************
9309 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9310 ****************************************************************************/
9312 void reply_findnclose(struct smb_request *req)
9316 START_PROFILE(SMBfindnclose);
9319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9320 END_PROFILE(SMBfindnclose);
9324 dptr_num = SVAL(req->vwv+0, 0);
9326 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9328 /* We never give out valid handles for a
9329 findnotifyfirst - so any dptr_num is ok here.
9332 reply_outbuf(req, 0, 0);
9334 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9336 END_PROFILE(SMBfindnclose);
9340 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9341 struct trans_state *state)
9343 if (get_Protocol() >= PROTOCOL_NT1) {
9344 req->flags2 |= 0x40; /* IS_LONG_NAME */
9345 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9348 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9349 if (state->call != TRANSACT2_QFSINFO &&
9350 state->call != TRANSACT2_SETFSINFO) {
9351 DEBUG(0,("handle_trans2: encryption required "
9353 (unsigned int)state->call));
9354 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9359 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9361 /* Now we must call the relevant TRANS2 function */
9362 switch(state->call) {
9363 case TRANSACT2_OPEN:
9365 START_PROFILE(Trans2_open);
9366 call_trans2open(conn, req,
9367 &state->param, state->total_param,
9368 &state->data, state->total_data,
9369 state->max_data_return);
9370 END_PROFILE(Trans2_open);
9374 case TRANSACT2_FINDFIRST:
9376 START_PROFILE(Trans2_findfirst);
9377 call_trans2findfirst(conn, req,
9378 &state->param, state->total_param,
9379 &state->data, state->total_data,
9380 state->max_data_return);
9381 END_PROFILE(Trans2_findfirst);
9385 case TRANSACT2_FINDNEXT:
9387 START_PROFILE(Trans2_findnext);
9388 call_trans2findnext(conn, req,
9389 &state->param, state->total_param,
9390 &state->data, state->total_data,
9391 state->max_data_return);
9392 END_PROFILE(Trans2_findnext);
9396 case TRANSACT2_QFSINFO:
9398 START_PROFILE(Trans2_qfsinfo);
9399 call_trans2qfsinfo(conn, req,
9400 &state->param, state->total_param,
9401 &state->data, state->total_data,
9402 state->max_data_return);
9403 END_PROFILE(Trans2_qfsinfo);
9407 case TRANSACT2_SETFSINFO:
9409 START_PROFILE(Trans2_setfsinfo);
9410 call_trans2setfsinfo(conn, req,
9411 &state->param, state->total_param,
9412 &state->data, state->total_data,
9413 state->max_data_return);
9414 END_PROFILE(Trans2_setfsinfo);
9418 case TRANSACT2_QPATHINFO:
9419 case TRANSACT2_QFILEINFO:
9421 START_PROFILE(Trans2_qpathinfo);
9422 call_trans2qfilepathinfo(conn, req, state->call,
9423 &state->param, state->total_param,
9424 &state->data, state->total_data,
9425 state->max_data_return);
9426 END_PROFILE(Trans2_qpathinfo);
9430 case TRANSACT2_SETPATHINFO:
9431 case TRANSACT2_SETFILEINFO:
9433 START_PROFILE(Trans2_setpathinfo);
9434 call_trans2setfilepathinfo(conn, req, state->call,
9435 &state->param, state->total_param,
9436 &state->data, state->total_data,
9437 state->max_data_return);
9438 END_PROFILE(Trans2_setpathinfo);
9442 case TRANSACT2_FINDNOTIFYFIRST:
9444 START_PROFILE(Trans2_findnotifyfirst);
9445 call_trans2findnotifyfirst(conn, req,
9446 &state->param, state->total_param,
9447 &state->data, state->total_data,
9448 state->max_data_return);
9449 END_PROFILE(Trans2_findnotifyfirst);
9453 case TRANSACT2_FINDNOTIFYNEXT:
9455 START_PROFILE(Trans2_findnotifynext);
9456 call_trans2findnotifynext(conn, req,
9457 &state->param, state->total_param,
9458 &state->data, state->total_data,
9459 state->max_data_return);
9460 END_PROFILE(Trans2_findnotifynext);
9464 case TRANSACT2_MKDIR:
9466 START_PROFILE(Trans2_mkdir);
9467 call_trans2mkdir(conn, req,
9468 &state->param, state->total_param,
9469 &state->data, state->total_data,
9470 state->max_data_return);
9471 END_PROFILE(Trans2_mkdir);
9475 case TRANSACT2_GET_DFS_REFERRAL:
9477 START_PROFILE(Trans2_get_dfs_referral);
9478 call_trans2getdfsreferral(conn, req,
9479 &state->param, state->total_param,
9480 &state->data, state->total_data,
9481 state->max_data_return);
9482 END_PROFILE(Trans2_get_dfs_referral);
9486 case TRANSACT2_IOCTL:
9488 START_PROFILE(Trans2_ioctl);
9489 call_trans2ioctl(conn, req,
9490 &state->param, state->total_param,
9491 &state->data, state->total_data,
9492 state->max_data_return);
9493 END_PROFILE(Trans2_ioctl);
9498 /* Error in request */
9499 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9500 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9504 /****************************************************************************
9505 Reply to a SMBtrans2.
9506 ****************************************************************************/
9508 void reply_trans2(struct smb_request *req)
9510 connection_struct *conn = req->conn;
9515 unsigned int tran_call;
9516 struct trans_state *state;
9519 START_PROFILE(SMBtrans2);
9521 if (req->wct < 14) {
9522 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9523 END_PROFILE(SMBtrans2);
9527 dsoff = SVAL(req->vwv+12, 0);
9528 dscnt = SVAL(req->vwv+11, 0);
9529 psoff = SVAL(req->vwv+10, 0);
9530 pscnt = SVAL(req->vwv+9, 0);
9531 tran_call = SVAL(req->vwv+14, 0);
9533 result = allow_new_trans(conn->pending_trans, req->mid);
9534 if (!NT_STATUS_IS_OK(result)) {
9535 DEBUG(2, ("Got invalid trans2 request: %s\n",
9536 nt_errstr(result)));
9537 reply_nterror(req, result);
9538 END_PROFILE(SMBtrans2);
9543 switch (tran_call) {
9544 /* List the allowed trans2 calls on IPC$ */
9545 case TRANSACT2_OPEN:
9546 case TRANSACT2_GET_DFS_REFERRAL:
9547 case TRANSACT2_QFILEINFO:
9548 case TRANSACT2_QFSINFO:
9549 case TRANSACT2_SETFSINFO:
9552 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9553 END_PROFILE(SMBtrans2);
9558 if ((state = talloc(conn, struct trans_state)) == NULL) {
9559 DEBUG(0, ("talloc failed\n"));
9560 reply_nterror(req, NT_STATUS_NO_MEMORY);
9561 END_PROFILE(SMBtrans2);
9565 state->cmd = SMBtrans2;
9567 state->mid = req->mid;
9568 state->vuid = req->vuid;
9569 state->setup_count = SVAL(req->vwv+13, 0);
9570 state->setup = NULL;
9571 state->total_param = SVAL(req->vwv+0, 0);
9572 state->param = NULL;
9573 state->total_data = SVAL(req->vwv+1, 0);
9575 state->max_param_return = SVAL(req->vwv+2, 0);
9576 state->max_data_return = SVAL(req->vwv+3, 0);
9577 state->max_setup_return = SVAL(req->vwv+4, 0);
9578 state->close_on_completion = BITSETW(req->vwv+5, 0);
9579 state->one_way = BITSETW(req->vwv+5, 1);
9581 state->call = tran_call;
9583 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9584 is so as a sanity check */
9585 if (state->setup_count != 1) {
9587 * Need to have rc=0 for ioctl to get job id for OS/2.
9588 * Network printing will fail if function is not successful.
9589 * Similar function in reply.c will be used if protocol
9590 * is LANMAN1.0 instead of LM1.2X002.
9591 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9592 * outbuf doesn't have to be set(only job id is used).
9594 if ( (state->setup_count == 4)
9595 && (tran_call == TRANSACT2_IOCTL)
9596 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9597 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9598 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9600 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9601 DEBUG(2,("Transaction is %d\n",tran_call));
9603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9604 END_PROFILE(SMBtrans2);
9609 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9612 if (state->total_data) {
9614 if (trans_oob(state->total_data, 0, dscnt)
9615 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9619 /* Can't use talloc here, the core routines do realloc on the
9620 * params and data. */
9621 state->data = (char *)SMB_MALLOC(state->total_data);
9622 if (state->data == NULL) {
9623 DEBUG(0,("reply_trans2: data malloc fail for %u "
9624 "bytes !\n", (unsigned int)state->total_data));
9626 reply_nterror(req, NT_STATUS_NO_MEMORY);
9627 END_PROFILE(SMBtrans2);
9631 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9634 if (state->total_param) {
9636 if (trans_oob(state->total_param, 0, pscnt)
9637 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9641 /* Can't use talloc here, the core routines do realloc on the
9642 * params and data. */
9643 state->param = (char *)SMB_MALLOC(state->total_param);
9644 if (state->param == NULL) {
9645 DEBUG(0,("reply_trans: param malloc fail for %u "
9646 "bytes !\n", (unsigned int)state->total_param));
9647 SAFE_FREE(state->data);
9649 reply_nterror(req, NT_STATUS_NO_MEMORY);
9650 END_PROFILE(SMBtrans2);
9654 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9657 state->received_data = dscnt;
9658 state->received_param = pscnt;
9660 if ((state->received_param == state->total_param) &&
9661 (state->received_data == state->total_data)) {
9663 handle_trans2(conn, req, state);
9665 SAFE_FREE(state->data);
9666 SAFE_FREE(state->param);
9668 END_PROFILE(SMBtrans2);
9672 DLIST_ADD(conn->pending_trans, state);
9674 /* We need to send an interim response then receive the rest
9675 of the parameter/data bytes */
9676 reply_outbuf(req, 0, 0);
9677 show_msg((char *)req->outbuf);
9678 END_PROFILE(SMBtrans2);
9683 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9684 SAFE_FREE(state->data);
9685 SAFE_FREE(state->param);
9687 END_PROFILE(SMBtrans2);
9688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9692 /****************************************************************************
9693 Reply to a SMBtranss2
9694 ****************************************************************************/
9696 void reply_transs2(struct smb_request *req)
9698 connection_struct *conn = req->conn;
9699 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9700 struct trans_state *state;
9702 START_PROFILE(SMBtranss2);
9704 show_msg((const char *)req->inbuf);
9706 /* Windows clients expect all replies to
9707 a transact secondary (SMBtranss2 0x33)
9708 to have a command code of transact
9709 (SMBtrans2 0x32). See bug #8989
9710 and also [MS-CIFS] section 2.2.4.47.2
9713 req->cmd = SMBtrans2;
9716 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9717 END_PROFILE(SMBtranss2);
9721 for (state = conn->pending_trans; state != NULL;
9722 state = state->next) {
9723 if (state->mid == req->mid) {
9728 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9729 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9730 END_PROFILE(SMBtranss2);
9734 /* Revise state->total_param and state->total_data in case they have
9735 changed downwards */
9737 if (SVAL(req->vwv+0, 0) < state->total_param)
9738 state->total_param = SVAL(req->vwv+0, 0);
9739 if (SVAL(req->vwv+1, 0) < state->total_data)
9740 state->total_data = SVAL(req->vwv+1, 0);
9742 pcnt = SVAL(req->vwv+2, 0);
9743 poff = SVAL(req->vwv+3, 0);
9744 pdisp = SVAL(req->vwv+4, 0);
9746 dcnt = SVAL(req->vwv+5, 0);
9747 doff = SVAL(req->vwv+6, 0);
9748 ddisp = SVAL(req->vwv+7, 0);
9750 state->received_param += pcnt;
9751 state->received_data += dcnt;
9753 if ((state->received_data > state->total_data) ||
9754 (state->received_param > state->total_param))
9758 if (trans_oob(state->total_param, pdisp, pcnt)
9759 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9762 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9766 if (trans_oob(state->total_data, ddisp, dcnt)
9767 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9770 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9773 if ((state->received_param < state->total_param) ||
9774 (state->received_data < state->total_data)) {
9775 END_PROFILE(SMBtranss2);
9779 handle_trans2(conn, req, state);
9781 DLIST_REMOVE(conn->pending_trans, state);
9782 SAFE_FREE(state->data);
9783 SAFE_FREE(state->param);
9786 END_PROFILE(SMBtranss2);
9791 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9792 DLIST_REMOVE(conn->pending_trans, state);
9793 SAFE_FREE(state->data);
9794 SAFE_FREE(state->param);
9796 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9797 END_PROFILE(SMBtranss2);