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 "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #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 bool *got_exact_match,
2462 int *_last_entry_off,
2463 struct ea_list *name_list,
2464 struct file_id *file_id)
2467 const char *mask = NULL;
2468 long prev_dirpos = 0;
2471 struct smb_filename *smb_fname = NULL;
2472 struct smbd_dirptr_lanman2_state state;
2474 uint64_t last_entry_off = 0;
2476 enum mangled_names_options mangled_names;
2477 bool marshall_with_83_names;
2479 mangled_names = lp_mangled_names(conn->params);
2483 state.info_level = info_level;
2484 if (mangled_names != MANGLED_NAMES_NO) {
2485 state.check_mangled_names = true;
2487 state.has_wild = dptr_has_wild(dirptr);
2488 state.got_exact_match = false;
2490 *got_exact_match = false;
2492 p = strrchr_m(path_mask,'/');
2503 ok = smbd_dirptr_get_entry(ctx,
2510 smbd_dirptr_lanman2_match_fn,
2511 smbd_dirptr_lanman2_mode_fn,
2518 return NT_STATUS_END_OF_FILE;
2521 *got_exact_match = state.got_exact_match;
2523 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2525 status = smbd_marshall_dir_entry(ctx,
2530 marshall_with_83_names,
2531 requires_resume_key,
2542 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2543 DEBUG(1,("Conversion error: illegal character: %s\n",
2544 smb_fname_str_dbg(smb_fname)));
2547 if (file_id != NULL) {
2548 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2552 TALLOC_FREE(smb_fname);
2554 if (!NT_STATUS_IS_OK(status) &&
2555 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2560 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2561 dptr_SeekDir(dirptr, prev_dirpos);
2565 *_last_entry_off = last_entry_off;
2566 return NT_STATUS_OK;
2569 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2570 connection_struct *conn,
2571 struct dptr_struct *dirptr,
2573 const char *path_mask,
2576 bool requires_resume_key,
2582 int space_remaining,
2583 bool *got_exact_match,
2584 int *last_entry_off,
2585 struct ea_list *name_list)
2588 const bool do_pad = true;
2590 if (info_level >= 1 && info_level <= 3) {
2591 /* No alignment on earlier info levels. */
2595 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2596 path_mask, dirtype, info_level,
2597 requires_resume_key, dont_descend, ask_sharemode,
2598 true, align, do_pad,
2599 ppdata, base_data, end_data,
2602 last_entry_off, name_list, NULL);
2605 /****************************************************************************
2606 Reply to a TRANS2_FINDFIRST.
2607 ****************************************************************************/
2609 static void call_trans2findfirst(connection_struct *conn,
2610 struct smb_request *req,
2611 char **pparams, int total_params,
2612 char **ppdata, int total_data,
2613 unsigned int max_data_bytes)
2615 /* We must be careful here that we don't return more than the
2616 allowed number of data bytes. If this means returning fewer than
2617 maxentries then so be it. We assume that the redirector has
2618 enough room for the fixed number of parameter bytes it has
2620 struct smb_filename *smb_dname = NULL;
2621 char *params = *pparams;
2622 char *pdata = *ppdata;
2626 uint16_t findfirst_flags;
2627 bool close_after_first;
2629 bool requires_resume_key;
2631 char *directory = NULL;
2634 int last_entry_off=0;
2638 bool finished = False;
2639 bool dont_descend = False;
2640 bool out_of_space = False;
2641 int space_remaining;
2642 bool mask_contains_wcard = False;
2643 struct ea_list *ea_list = NULL;
2644 NTSTATUS ntstatus = NT_STATUS_OK;
2645 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2646 struct dptr_struct *dirptr = NULL;
2647 struct smbd_server_connection *sconn = req->sconn;
2648 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2649 ucf_flags_from_smb_request(req);
2650 bool backup_priv = false;
2651 bool as_root = false;
2653 if (total_params < 13) {
2654 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2658 dirtype = SVAL(params,0);
2659 maxentries = SVAL(params,2);
2660 findfirst_flags = SVAL(params,4);
2661 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2662 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2663 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2664 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2665 security_token_has_privilege(get_current_nttok(conn),
2668 info_level = SVAL(params,6);
2670 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2671 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2672 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2674 info_level, max_data_bytes));
2677 /* W2K3 seems to treat zero as 1. */
2681 switch (info_level) {
2682 case SMB_FIND_INFO_STANDARD:
2683 case SMB_FIND_EA_SIZE:
2684 case SMB_FIND_EA_LIST:
2685 case SMB_FIND_FILE_DIRECTORY_INFO:
2686 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2687 case SMB_FIND_FILE_NAMES_INFO:
2688 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2689 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2690 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2692 case SMB_FIND_FILE_UNIX:
2693 case SMB_FIND_FILE_UNIX_INFO2:
2694 /* Always use filesystem for UNIX mtime query. */
2695 ask_sharemode = false;
2696 if (!lp_unix_extensions()) {
2697 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2700 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2703 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2707 if (req->posix_pathnames) {
2708 srvstr_get_path_wcard_posix(talloc_tos(),
2716 &mask_contains_wcard);
2718 srvstr_get_path_wcard(talloc_tos(),
2726 &mask_contains_wcard);
2728 if (!NT_STATUS_IS_OK(ntstatus)) {
2729 reply_nterror(req, ntstatus);
2736 ntstatus = filename_convert_with_privilege(talloc_tos(),
2741 &mask_contains_wcard,
2744 ntstatus = filename_convert(talloc_tos(), conn,
2747 &mask_contains_wcard,
2751 if (!NT_STATUS_IS_OK(ntstatus)) {
2752 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2753 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2754 ERRSRV, ERRbadpath);
2757 reply_nterror(req, ntstatus);
2761 mask = smb_dname->original_lcomp;
2763 directory = smb_dname->base_name;
2765 p = strrchr_m(directory,'/');
2767 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2768 if((directory[0] == '.') && (directory[1] == '\0')) {
2769 mask = talloc_strdup(talloc_tos(),"*");
2771 reply_nterror(req, NT_STATUS_NO_MEMORY);
2774 mask_contains_wcard = True;
2780 if (p == NULL || p == directory) {
2781 /* Ensure we don't have a directory name of "". */
2782 directory = talloc_strdup(talloc_tos(), ".");
2784 reply_nterror(req, NT_STATUS_NO_MEMORY);
2787 /* Ensure smb_dname->base_name matches. */
2788 smb_dname->base_name = directory;
2791 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2793 if (info_level == SMB_FIND_EA_LIST) {
2796 if (total_data < 4) {
2797 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2801 ea_size = IVAL(pdata,0);
2802 if (ea_size != total_data) {
2803 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2804 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2805 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2809 if (!lp_ea_support(SNUM(conn))) {
2810 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2814 /* Pull out the list of names. */
2815 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2822 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2823 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2827 *ppdata = (char *)SMB_REALLOC(
2828 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2829 if(*ppdata == NULL ) {
2830 reply_nterror(req, NT_STATUS_NO_MEMORY);
2834 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2836 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2839 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2840 /* Realloc the params space */
2841 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2842 if (*pparams == NULL) {
2843 reply_nterror(req, NT_STATUS_NO_MEMORY);
2848 /* Save the wildcard match and attribs we are using on this directory -
2849 needed as lanman2 assumes these are being saved between calls */
2851 ntstatus = dptr_create(conn,
2859 mask_contains_wcard,
2863 if (!NT_STATUS_IS_OK(ntstatus)) {
2864 reply_nterror(req, ntstatus);
2869 /* Remember this in case we have
2870 to do a findnext. */
2871 dptr_set_priv(dirptr);
2874 dptr_num = dptr_dnum(dirptr);
2875 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2877 /* We don't need to check for VOL here as this is returned by
2878 a different TRANS2 call. */
2880 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2881 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2882 if (in_list(directory,
2883 lp_dont_descend(talloc_tos(), SNUM(conn)),
2884 conn->case_sensitive)) {
2885 dont_descend = True;
2889 space_remaining = max_data_bytes;
2890 out_of_space = False;
2892 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2893 bool got_exact_match = False;
2895 /* this is a heuristic to avoid seeking the dirptr except when
2896 absolutely necessary. It allows for a filename of about 40 chars */
2897 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2898 out_of_space = True;
2901 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2905 mask,dirtype,info_level,
2906 requires_resume_key,dont_descend,
2911 &last_entry_off, ea_list);
2912 if (NT_STATUS_EQUAL(ntstatus,
2913 NT_STATUS_ILLEGAL_CHARACTER)) {
2915 * Bad character conversion on name. Ignore this
2920 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2921 out_of_space = true;
2923 finished = !NT_STATUS_IS_OK(ntstatus);
2927 if (!finished && !out_of_space)
2931 * As an optimisation if we know we aren't looking
2932 * for a wildcard name (ie. the name matches the wildcard exactly)
2933 * then we can finish on any (first) match.
2934 * This speeds up large directory searches. JRA.
2940 /* Ensure space_remaining never goes -ve. */
2941 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2942 space_remaining = 0;
2943 out_of_space = true;
2945 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2949 /* Check if we can close the dirptr */
2950 if(close_after_first || (finished && close_if_end)) {
2951 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2952 dptr_close(sconn, &dptr_num);
2956 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2957 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2958 * the protocol level is less than NT1. Tested with smbclient. JRA.
2959 * This should fix the OS/2 client bug #2335.
2962 if(numentries == 0) {
2963 dptr_close(sconn, &dptr_num);
2964 if (get_Protocol() < PROTOCOL_NT1) {
2965 reply_force_doserror(req, ERRDOS, ERRnofiles);
2968 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2969 ERRDOS, ERRbadfile);
2974 /* At this point pdata points to numentries directory entries. */
2976 /* Set up the return parameter block */
2977 SSVAL(params,0,dptr_num);
2978 SSVAL(params,2,numentries);
2979 SSVAL(params,4,finished);
2980 SSVAL(params,6,0); /* Never an EA error */
2981 SSVAL(params,8,last_entry_off);
2983 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2986 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2987 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2989 reply_nterror(req, NT_STATUS_NO_MEMORY);
2993 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2994 smb_fn_name(req->cmd),
2995 mask, directory, dirtype, numentries ) );
2998 * Force a name mangle here to ensure that the
2999 * mask as an 8.3 name is top of the mangled cache.
3000 * The reasons for this are subtle. Don't remove
3001 * this code unless you know what you are doing
3002 * (see PR#13758). JRA.
3005 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3006 char mangled_name[13];
3007 name_to_8_3(mask, mangled_name, True, conn->params);
3015 TALLOC_FREE(smb_dname);
3019 /****************************************************************************
3020 Reply to a TRANS2_FINDNEXT.
3021 ****************************************************************************/
3023 static void call_trans2findnext(connection_struct *conn,
3024 struct smb_request *req,
3025 char **pparams, int total_params,
3026 char **ppdata, int total_data,
3027 unsigned int max_data_bytes)
3029 /* We must be careful here that we don't return more than the
3030 allowed number of data bytes. If this means returning fewer than
3031 maxentries then so be it. We assume that the redirector has
3032 enough room for the fixed number of parameter bytes it has
3034 char *params = *pparams;
3035 char *pdata = *ppdata;
3039 uint16_t info_level;
3040 uint32_t resume_key;
3041 uint16_t findnext_flags;
3042 bool close_after_request;
3044 bool requires_resume_key;
3046 bool mask_contains_wcard = False;
3047 char *resume_name = NULL;
3048 const char *mask = NULL;
3049 const char *directory = NULL;
3053 int i, last_entry_off=0;
3054 bool finished = False;
3055 bool dont_descend = False;
3056 bool out_of_space = False;
3057 int space_remaining;
3058 struct ea_list *ea_list = NULL;
3059 NTSTATUS ntstatus = NT_STATUS_OK;
3060 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3061 TALLOC_CTX *ctx = talloc_tos();
3062 struct dptr_struct *dirptr;
3063 struct smbd_server_connection *sconn = req->sconn;
3064 bool backup_priv = false;
3065 bool as_root = false;
3067 if (total_params < 13) {
3068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3072 dptr_num = SVAL(params,0);
3073 maxentries = SVAL(params,2);
3074 info_level = SVAL(params,4);
3075 resume_key = IVAL(params,6);
3076 findnext_flags = SVAL(params,10);
3077 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3078 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3079 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3080 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3082 if (!continue_bit) {
3083 /* We only need resume_name if continue_bit is zero. */
3084 if (req->posix_pathnames) {
3085 srvstr_get_path_wcard_posix(ctx,
3093 &mask_contains_wcard);
3095 srvstr_get_path_wcard(ctx,
3103 &mask_contains_wcard);
3105 if (!NT_STATUS_IS_OK(ntstatus)) {
3106 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3107 complain (it thinks we're asking for the directory above the shared
3108 path or an invalid name). Catch this as the resume name is only compared, never used in
3109 a file access. JRA. */
3110 srvstr_pull_talloc(ctx, params, req->flags2,
3111 &resume_name, params+12,
3115 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3116 reply_nterror(req, ntstatus);
3122 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3123 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3124 resume_key = %d resume name = %s continue=%d level = %d\n",
3125 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3126 requires_resume_key, resume_key,
3127 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3130 /* W2K3 seems to treat zero as 1. */
3134 switch (info_level) {
3135 case SMB_FIND_INFO_STANDARD:
3136 case SMB_FIND_EA_SIZE:
3137 case SMB_FIND_EA_LIST:
3138 case SMB_FIND_FILE_DIRECTORY_INFO:
3139 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3140 case SMB_FIND_FILE_NAMES_INFO:
3141 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3142 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3143 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3145 case SMB_FIND_FILE_UNIX:
3146 case SMB_FIND_FILE_UNIX_INFO2:
3147 /* Always use filesystem for UNIX mtime query. */
3148 ask_sharemode = false;
3149 if (!lp_unix_extensions()) {
3150 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3155 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3159 if (info_level == SMB_FIND_EA_LIST) {
3162 if (total_data < 4) {
3163 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3167 ea_size = IVAL(pdata,0);
3168 if (ea_size != total_data) {
3169 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3170 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3171 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3175 if (!lp_ea_support(SNUM(conn))) {
3176 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3180 /* Pull out the list of names. */
3181 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3188 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3193 *ppdata = (char *)SMB_REALLOC(
3194 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3195 if(*ppdata == NULL) {
3196 reply_nterror(req, NT_STATUS_NO_MEMORY);
3201 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3204 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3207 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3208 /* Realloc the params space */
3209 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3210 if(*pparams == NULL ) {
3211 reply_nterror(req, NT_STATUS_NO_MEMORY);
3217 /* Check that the dptr is valid */
3218 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3219 reply_nterror(req, STATUS_NO_MORE_FILES);
3223 directory = dptr_path(sconn, dptr_num);
3225 /* Get the wildcard mask from the dptr */
3226 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3227 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3228 reply_nterror(req, STATUS_NO_MORE_FILES);
3232 /* Get the attr mask from the dptr */
3233 dirtype = dptr_attr(sconn, dptr_num);
3235 backup_priv = dptr_get_priv(dirptr);
3237 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3238 "backup_priv = %d\n",
3239 dptr_num, mask, dirtype,
3241 dptr_TellDir(dirptr),
3244 /* We don't need to check for VOL here as this is returned by
3245 a different TRANS2 call. */
3247 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3248 directory,lp_dont_descend(ctx, SNUM(conn))));
3249 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3250 dont_descend = True;
3253 space_remaining = max_data_bytes;
3254 out_of_space = False;
3262 * Seek to the correct position. We no longer use the resume key but
3263 * depend on the last file name instead.
3266 if(!continue_bit && resume_name && *resume_name) {
3269 long current_pos = 0;
3271 * Remember, name_to_8_3 is called by
3272 * get_lanman2_dir_entry(), so the resume name
3273 * could be mangled. Ensure we check the unmangled name.
3276 if (mangle_is_mangled(resume_name, conn->params)) {
3277 char *new_resume_name = NULL;
3278 mangle_lookup_name_from_8_3(ctx,
3282 if (new_resume_name) {
3283 resume_name = new_resume_name;
3288 * Fix for NT redirector problem triggered by resume key indexes
3289 * changing between directory scans. We now return a resume key of 0
3290 * and instead look for the filename to continue from (also given
3291 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3292 * findfirst/findnext (as is usual) then the directory pointer
3293 * should already be at the correct place.
3296 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3297 } /* end if resume_name && !continue_bit */
3299 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3300 bool got_exact_match = False;
3302 /* this is a heuristic to avoid seeking the dirptr except when
3303 absolutely necessary. It allows for a filename of about 40 chars */
3304 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3305 out_of_space = True;
3308 ntstatus = get_lanman2_dir_entry(ctx,
3312 mask,dirtype,info_level,
3313 requires_resume_key,dont_descend,
3318 &last_entry_off, ea_list);
3319 if (NT_STATUS_EQUAL(ntstatus,
3320 NT_STATUS_ILLEGAL_CHARACTER)) {
3322 * Bad character conversion on name. Ignore this
3327 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3328 out_of_space = true;
3330 finished = !NT_STATUS_IS_OK(ntstatus);
3334 if (!finished && !out_of_space)
3338 * As an optimisation if we know we aren't looking
3339 * for a wildcard name (ie. the name matches the wildcard exactly)
3340 * then we can finish on any (first) match.
3341 * This speeds up large directory searches. JRA.
3347 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3350 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3351 smb_fn_name(req->cmd),
3352 mask, directory, dirtype, numentries ) );
3354 /* Check if we can close the dirptr */
3355 if(close_after_request || (finished && close_if_end)) {
3356 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3357 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3364 /* Set up the return parameter block */
3365 SSVAL(params,0,numentries);
3366 SSVAL(params,2,finished);
3367 SSVAL(params,4,0); /* Never an EA error */
3368 SSVAL(params,6,last_entry_off);
3370 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3376 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3378 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3382 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3384 SMB_ASSERT(extended_info != NULL);
3386 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3387 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3388 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3389 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3390 #ifdef SAMBA_VERSION_REVISION
3391 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3393 extended_info->samba_subversion = 0;
3394 #ifdef SAMBA_VERSION_RC_RELEASE
3395 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3397 #ifdef SAMBA_VERSION_PRE_RELEASE
3398 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3401 #ifdef SAMBA_VERSION_VENDOR_PATCH
3402 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3404 extended_info->samba_gitcommitdate = 0;
3405 #ifdef SAMBA_VERSION_COMMIT_TIME
3406 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3409 memset(extended_info->samba_version_string, 0,
3410 sizeof(extended_info->samba_version_string));
3412 snprintf (extended_info->samba_version_string,
3413 sizeof(extended_info->samba_version_string),
3414 "%s", samba_version_string());
3417 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3418 connection_struct *conn,
3419 TALLOC_CTX *mem_ctx,
3420 uint16_t info_level,
3422 unsigned int max_data_bytes,
3423 size_t *fixed_portion,
3424 struct smb_filename *fname,
3428 char *pdata, *end_data;
3431 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3432 int snum = SNUM(conn);
3433 const char *fstype = lp_fstype(SNUM(conn));
3434 const char *filename = NULL;
3435 const uint64_t bytes_per_sector = 512;
3436 uint32_t additional_flags = 0;
3437 struct smb_filename smb_fname;
3439 NTSTATUS status = NT_STATUS_OK;
3442 if (fname == NULL || fname->base_name == NULL) {
3445 filename = fname->base_name;
3449 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3450 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3451 "info level (0x%x) on IPC$.\n",
3452 (unsigned int)info_level));
3453 return NT_STATUS_ACCESS_DENIED;
3457 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3459 ZERO_STRUCT(smb_fname);
3460 smb_fname.base_name = discard_const_p(char, filename);
3462 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3463 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3464 return map_nt_error_from_unix(errno);
3469 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3470 return NT_STATUS_INVALID_PARAMETER;
3473 *ppdata = (char *)SMB_REALLOC(
3474 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3475 if (*ppdata == NULL) {
3476 return NT_STATUS_NO_MEMORY;
3480 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3481 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3485 switch (info_level) {
3486 case SMB_INFO_ALLOCATION:
3488 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3490 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3492 if (df_ret == (uint64_t)-1) {
3493 return map_nt_error_from_unix(errno);
3496 block_size = lp_block_size(snum);
3497 if (bsize < block_size) {
3498 uint64_t factor = block_size/bsize;
3503 if (bsize > block_size) {
3504 uint64_t factor = bsize/block_size;
3509 sectors_per_unit = bsize/bytes_per_sector;
3511 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3512 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3513 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3516 * For large drives, return max values and not modulo.
3518 dsize = MIN(dsize, UINT32_MAX);
3519 dfree = MIN(dfree, UINT32_MAX);
3521 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3522 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3523 SIVAL(pdata,l1_cUnit,dsize);
3524 SIVAL(pdata,l1_cUnitAvail,dfree);
3525 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3529 case SMB_INFO_VOLUME:
3530 /* Return volume name */
3532 * Add volume serial number - hash of a combination of
3533 * the called hostname and the service name.
3535 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3537 * Win2k3 and previous mess this up by sending a name length
3538 * one byte short. I believe only older clients (OS/2 Win9x) use
3539 * this call so try fixing this by adding a terminating null to
3540 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3542 status = srvstr_push(
3544 pdata+l2_vol_szVolLabel, vname,
3545 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3546 STR_NOALIGN|STR_TERMINATE, &len);
3547 if (!NT_STATUS_IS_OK(status)) {
3550 SCVAL(pdata,l2_vol_cch,len);
3551 data_len = l2_vol_szVolLabel + len;
3552 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3553 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3554 (unsigned)len, vname));
3557 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3558 case SMB_FS_ATTRIBUTE_INFORMATION:
3560 additional_flags = 0;
3561 #if defined(HAVE_SYS_QUOTAS)
3562 additional_flags |= FILE_VOLUME_QUOTAS;
3565 if(lp_nt_acl_support(SNUM(conn))) {
3566 additional_flags |= FILE_PERSISTENT_ACLS;
3569 /* Capabilities are filled in at connection time through STATVFS call */
3570 additional_flags |= conn->fs_capabilities;
3571 additional_flags |= lp_parm_int(conn->params->service,
3572 "share", "fake_fscaps",
3575 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3576 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3577 additional_flags); /* FS ATTRIBUTES */
3579 SIVAL(pdata,4,255); /* Max filename component length */
3580 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3581 and will think we can't do long filenames */
3582 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3583 PTR_DIFF(end_data, pdata+12),
3585 if (!NT_STATUS_IS_OK(status)) {
3589 data_len = 12 + len;
3590 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3591 /* the client only requested a portion of the
3593 data_len = max_data_bytes;
3594 status = STATUS_BUFFER_OVERFLOW;
3596 *fixed_portion = 16;
3599 case SMB_QUERY_FS_LABEL_INFO:
3600 case SMB_FS_LABEL_INFORMATION:
3601 status = srvstr_push(pdata, flags2, pdata+4, vname,
3602 PTR_DIFF(end_data, pdata+4), 0, &len);
3603 if (!NT_STATUS_IS_OK(status)) {
3610 case SMB_QUERY_FS_VOLUME_INFO:
3611 case SMB_FS_VOLUME_INFORMATION:
3614 * Add volume serial number - hash of a combination of
3615 * the called hostname and the service name.
3617 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3618 (str_checksum(get_local_machine_name())<<16));
3620 /* Max label len is 32 characters. */
3621 status = srvstr_push(pdata, flags2, pdata+18, vname,
3622 PTR_DIFF(end_data, pdata+18),
3624 if (!NT_STATUS_IS_OK(status)) {
3627 SIVAL(pdata,12,len);
3630 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3631 (int)strlen(vname),vname,
3632 lp_servicename(talloc_tos(), snum)));
3633 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3634 /* the client only requested a portion of the
3636 data_len = max_data_bytes;
3637 status = STATUS_BUFFER_OVERFLOW;
3639 *fixed_portion = 24;
3642 case SMB_QUERY_FS_SIZE_INFO:
3643 case SMB_FS_SIZE_INFORMATION:
3645 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3647 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3649 if (df_ret == (uint64_t)-1) {
3650 return map_nt_error_from_unix(errno);
3652 block_size = lp_block_size(snum);
3653 if (bsize < block_size) {
3654 uint64_t factor = block_size/bsize;
3659 if (bsize > block_size) {
3660 uint64_t factor = bsize/block_size;
3665 sectors_per_unit = bsize/bytes_per_sector;
3666 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3667 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3668 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3669 SBIG_UINT(pdata,0,dsize);
3670 SBIG_UINT(pdata,8,dfree);
3671 SIVAL(pdata,16,sectors_per_unit);
3672 SIVAL(pdata,20,bytes_per_sector);
3673 *fixed_portion = 24;
3677 case SMB_FS_FULL_SIZE_INFORMATION:
3679 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3681 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3683 if (df_ret == (uint64_t)-1) {
3684 return map_nt_error_from_unix(errno);
3686 block_size = lp_block_size(snum);
3687 if (bsize < block_size) {
3688 uint64_t factor = block_size/bsize;
3693 if (bsize > block_size) {
3694 uint64_t factor = bsize/block_size;
3699 sectors_per_unit = bsize/bytes_per_sector;
3700 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3701 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3702 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3703 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3704 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3705 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3706 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3707 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3708 *fixed_portion = 32;
3712 case SMB_QUERY_FS_DEVICE_INFO:
3713 case SMB_FS_DEVICE_INFORMATION:
3715 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3717 if (!CAN_WRITE(conn)) {
3718 characteristics |= FILE_READ_ONLY_DEVICE;
3721 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3722 SIVAL(pdata,4,characteristics);
3727 #ifdef HAVE_SYS_QUOTAS
3728 case SMB_FS_QUOTA_INFORMATION:
3730 * what we have to send --metze:
3732 * Unknown1: 24 NULL bytes
3733 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3734 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3735 * Quota Flags: 2 byte :
3736 * Unknown3: 6 NULL bytes
3740 * details for Quota Flags:
3742 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3743 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3744 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3745 * 0x0001 Enable Quotas: enable quota for this fs
3749 /* we need to fake up a fsp here,
3750 * because its not send in this call
3753 SMB_NTQUOTA_STRUCT quotas;
3756 ZERO_STRUCT(quotas);
3759 fsp.fnum = FNUM_FIELD_INVALID;
3762 if (get_current_uid(conn) != 0) {
3763 DEBUG(0,("get_user_quota: access_denied "
3764 "service [%s] user [%s]\n",
3765 lp_servicename(talloc_tos(), SNUM(conn)),
3766 conn->session_info->unix_info->unix_name));
3767 return NT_STATUS_ACCESS_DENIED;
3770 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3772 if (!NT_STATUS_IS_OK(status)) {
3773 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3779 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3780 lp_servicename(talloc_tos(), SNUM(conn))));
3782 /* Unknown1 24 NULL bytes*/
3783 SBIG_UINT(pdata,0,(uint64_t)0);
3784 SBIG_UINT(pdata,8,(uint64_t)0);
3785 SBIG_UINT(pdata,16,(uint64_t)0);
3787 /* Default Soft Quota 8 bytes */
3788 SBIG_UINT(pdata,24,quotas.softlim);
3790 /* Default Hard Quota 8 bytes */
3791 SBIG_UINT(pdata,32,quotas.hardlim);
3793 /* Quota flag 2 bytes */
3794 SSVAL(pdata,40,quotas.qflags);
3796 /* Unknown3 6 NULL bytes */
3802 #endif /* HAVE_SYS_QUOTAS */
3803 case SMB_FS_OBJECTID_INFORMATION:
3805 unsigned char objid[16];
3806 struct smb_extended_info extended_info;
3807 memcpy(pdata,create_volume_objectid(conn, objid),16);
3808 samba_extended_info_version (&extended_info);
3809 SIVAL(pdata,16,extended_info.samba_magic);
3810 SIVAL(pdata,20,extended_info.samba_version);
3811 SIVAL(pdata,24,extended_info.samba_subversion);
3812 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3813 memcpy(pdata+36,extended_info.samba_version_string,28);
3818 case SMB_FS_SECTOR_SIZE_INFORMATION:
3822 * These values match a physical Windows Server 2012
3823 * share backed by NTFS atop spinning rust.
3825 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3826 /* logical_bytes_per_sector */
3827 SIVAL(pdata, 0, bytes_per_sector);
3828 /* phys_bytes_per_sector_atomic */
3829 SIVAL(pdata, 4, bytes_per_sector);
3830 /* phys_bytes_per_sector_perf */
3831 SIVAL(pdata, 8, bytes_per_sector);
3832 /* fs_effective_phys_bytes_per_sector_atomic */
3833 SIVAL(pdata, 12, bytes_per_sector);
3835 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3836 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3837 /* byte_off_sector_align */
3838 SIVAL(pdata, 20, 0);
3839 /* byte_off_partition_align */
3840 SIVAL(pdata, 24, 0);
3841 *fixed_portion = 28;
3847 * Query the version and capabilities of the CIFS UNIX extensions
3851 case SMB_QUERY_CIFS_UNIX_INFO:
3853 bool large_write = lp_min_receive_file_size() &&
3854 !srv_is_signing_active(xconn);
3855 bool large_read = !srv_is_signing_active(xconn);
3856 int encrypt_caps = 0;
3858 if (!lp_unix_extensions()) {
3859 return NT_STATUS_INVALID_LEVEL;
3862 switch (conn->encrypt_level) {
3863 case SMB_SIGNING_OFF:
3866 case SMB_SIGNING_DESIRED:
3867 case SMB_SIGNING_IF_REQUIRED:
3868 case SMB_SIGNING_DEFAULT:
3869 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3871 case SMB_SIGNING_REQUIRED:
3872 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3873 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3874 large_write = false;
3880 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3881 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3883 /* We have POSIX ACLs, pathname, encryption,
3884 * large read/write, and locking capability. */
3886 SBIG_UINT(pdata,4,((uint64_t)(
3887 CIFS_UNIX_POSIX_ACLS_CAP|
3888 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3889 CIFS_UNIX_FCNTL_LOCKS_CAP|
3890 CIFS_UNIX_EXTATTR_CAP|
3891 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3893 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3895 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3899 case SMB_QUERY_POSIX_FS_INFO:
3902 vfs_statvfs_struct svfs;
3904 if (!lp_unix_extensions()) {
3905 return NT_STATUS_INVALID_LEVEL;
3908 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3912 SIVAL(pdata,0,svfs.OptimalTransferSize);
3913 SIVAL(pdata,4,svfs.BlockSize);
3914 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3915 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3916 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3917 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3918 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3919 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3920 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3922 } else if (rc == EOPNOTSUPP) {
3923 return NT_STATUS_INVALID_LEVEL;
3924 #endif /* EOPNOTSUPP */
3926 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3927 return NT_STATUS_DOS(ERRSRV, ERRerror);
3932 case SMB_QUERY_POSIX_WHOAMI:
3938 if (!lp_unix_extensions()) {
3939 return NT_STATUS_INVALID_LEVEL;
3942 if (max_data_bytes < 40) {
3943 return NT_STATUS_BUFFER_TOO_SMALL;
3946 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3947 flags |= SMB_WHOAMI_GUEST;
3950 /* NOTE: 8 bytes for UID/GID, irrespective of native
3951 * platform size. This matches
3952 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3954 data_len = 4 /* flags */
3961 + 4 /* pad/reserved */
3962 + (conn->session_info->unix_token->ngroups * 8)
3964 + (conn->session_info->security_token->num_sids *
3968 SIVAL(pdata, 0, flags);
3969 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3971 (uint64_t)conn->session_info->unix_token->uid);
3972 SBIG_UINT(pdata, 16,
3973 (uint64_t)conn->session_info->unix_token->gid);
3976 if (data_len >= max_data_bytes) {
3977 /* Potential overflow, skip the GIDs and SIDs. */
3979 SIVAL(pdata, 24, 0); /* num_groups */
3980 SIVAL(pdata, 28, 0); /* num_sids */
3981 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3982 SIVAL(pdata, 36, 0); /* reserved */
3988 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3989 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3991 /* We walk the SID list twice, but this call is fairly
3992 * infrequent, and I don't expect that it's performance
3993 * sensitive -- jpeach
3995 for (i = 0, sid_bytes = 0;
3996 i < conn->session_info->security_token->num_sids; ++i) {
3997 sid_bytes += ndr_size_dom_sid(
3998 &conn->session_info->security_token->sids[i],
4002 /* SID list byte count */
4003 SIVAL(pdata, 32, sid_bytes);
4005 /* 4 bytes pad/reserved - must be zero */
4006 SIVAL(pdata, 36, 0);
4010 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4011 SBIG_UINT(pdata, data_len,
4012 (uint64_t)conn->session_info->unix_token->groups[i]);
4018 i < conn->session_info->security_token->num_sids; ++i) {
4019 int sid_len = ndr_size_dom_sid(
4020 &conn->session_info->security_token->sids[i],
4023 sid_linearize((uint8_t *)(pdata + data_len),
4025 &conn->session_info->security_token->sids[i]);
4026 data_len += sid_len;
4032 case SMB_MAC_QUERY_FS_INFO:
4034 * Thursby MAC extension... ONLY on NTFS filesystems
4035 * once we do streams then we don't need this
4037 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4039 SIVAL(pdata,84,0x100); /* Don't support mac... */
4045 return NT_STATUS_INVALID_LEVEL;
4048 *ret_data_len = data_len;
4052 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4053 struct smb_request *req,
4055 const DATA_BLOB *qdata)
4058 SMB_NTQUOTA_STRUCT quotas;
4060 ZERO_STRUCT(quotas);
4063 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4064 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4065 lp_servicename(talloc_tos(), SNUM(conn)),
4066 conn->session_info->unix_info->unix_name));
4067 return NT_STATUS_ACCESS_DENIED;
4070 if (!check_fsp_ntquota_handle(conn, req,
4072 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4073 return NT_STATUS_INVALID_HANDLE;
4076 /* note: normally there're 48 bytes,
4077 * but we didn't use the last 6 bytes for now
4080 if (qdata->length < 42) {
4081 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4082 (unsigned int)qdata->length));
4083 return NT_STATUS_INVALID_PARAMETER;
4086 /* unknown_1 24 NULL bytes in pdata*/
4088 /* the soft quotas 8 bytes (uint64_t)*/
4089 quotas.softlim = BVAL(qdata->data,24);
4091 /* the hard quotas 8 bytes (uint64_t)*/
4092 quotas.hardlim = BVAL(qdata->data,32);
4094 /* quota_flags 2 bytes **/
4095 quotas.qflags = SVAL(qdata->data,40);
4097 /* unknown_2 6 NULL bytes follow*/
4099 /* now set the quotas */
4100 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4101 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4102 lp_servicename(talloc_tos(), SNUM(conn))));
4103 status = map_nt_error_from_unix(errno);
4105 status = NT_STATUS_OK;
4110 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4111 struct smb_request *req,
4112 TALLOC_CTX *mem_ctx,
4113 uint16_t info_level,
4115 const DATA_BLOB *pdata)
4117 switch (info_level) {
4118 case SMB_FS_QUOTA_INFORMATION:
4120 return smb_set_fsquota(conn,
4129 return NT_STATUS_INVALID_LEVEL;
4132 /****************************************************************************
4133 Reply to a TRANS2_QFSINFO (query filesystem info).
4134 ****************************************************************************/
4136 static void call_trans2qfsinfo(connection_struct *conn,
4137 struct smb_request *req,
4138 char **pparams, int total_params,
4139 char **ppdata, int total_data,
4140 unsigned int max_data_bytes)
4142 char *params = *pparams;
4143 uint16_t info_level;
4145 size_t fixed_portion;
4148 if (total_params < 2) {
4149 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4153 info_level = SVAL(params,0);
4155 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4156 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4157 DEBUG(0,("call_trans2qfsinfo: encryption required "
4158 "and info level 0x%x sent.\n",
4159 (unsigned int)info_level));
4160 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4165 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4167 status = smbd_do_qfsinfo(req->xconn, conn, req,
4174 if (!NT_STATUS_IS_OK(status)) {
4175 reply_nterror(req, status);
4179 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4182 DEBUG( 4, ( "%s info_level = %d\n",
4183 smb_fn_name(req->cmd), info_level) );
4188 /****************************************************************************
4189 Reply to a TRANS2_SETFSINFO (set filesystem info).
4190 ****************************************************************************/
4192 static void call_trans2setfsinfo(connection_struct *conn,
4193 struct smb_request *req,
4194 char **pparams, int total_params,
4195 char **ppdata, int total_data,
4196 unsigned int max_data_bytes)
4198 struct smbXsrv_connection *xconn = req->xconn;
4199 char *pdata = *ppdata;
4200 char *params = *pparams;
4201 uint16_t info_level;
4203 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4204 lp_servicename(talloc_tos(), SNUM(conn))));
4207 if (total_params < 4) {
4208 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4210 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4214 info_level = SVAL(params,2);
4217 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4218 info_level != SMB_SET_CIFS_UNIX_INFO) {
4219 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4220 "info level (0x%x) on IPC$.\n",
4221 (unsigned int)info_level));
4222 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4227 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4228 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4229 DEBUG(0,("call_trans2setfsinfo: encryption required "
4230 "and info level 0x%x sent.\n",
4231 (unsigned int)info_level));
4232 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4237 switch(info_level) {
4238 case SMB_SET_CIFS_UNIX_INFO:
4239 if (!lp_unix_extensions()) {
4240 DEBUG(2,("call_trans2setfsinfo: "
4241 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4242 "unix extensions off\n"));
4244 NT_STATUS_INVALID_LEVEL);
4248 /* There should be 12 bytes of capabilities set. */
4249 if (total_data < 12) {
4252 NT_STATUS_INVALID_PARAMETER);
4255 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4256 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4257 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4258 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4259 /* Just print these values for now. */
4260 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4261 "major = %u, minor = %u cap_low = 0x%x, "
4263 (unsigned int)xconn->
4264 smb1.unix_info.client_major,
4265 (unsigned int)xconn->
4266 smb1.unix_info.client_minor,
4267 (unsigned int)xconn->
4268 smb1.unix_info.client_cap_low,
4269 (unsigned int)xconn->
4270 smb1.unix_info.client_cap_high));
4272 /* Here is where we must switch to posix pathname processing... */
4273 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4274 lp_set_posix_pathnames();
4275 mangle_change_to_posix();
4278 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4279 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4280 /* Client that knows how to do posix locks,
4281 * but not posix open/mkdir operations. Set a
4282 * default type for read/write checks. */
4284 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4289 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4292 size_t param_len = 0;
4293 size_t data_len = total_data;
4295 if (!lp_unix_extensions()) {
4298 NT_STATUS_INVALID_LEVEL);
4302 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4305 NT_STATUS_NOT_SUPPORTED);
4309 if (xconn->smb1.echo_handler.trusted_fde) {
4310 DEBUG( 2,("call_trans2setfsinfo: "
4311 "request transport encryption disabled"
4312 "with 'fork echo handler = yes'\n"));
4315 NT_STATUS_NOT_SUPPORTED);
4319 DEBUG( 4,("call_trans2setfsinfo: "
4320 "request transport encryption.\n"));
4322 status = srv_request_encryption_setup(conn,
4323 (unsigned char **)ppdata,
4325 (unsigned char **)pparams,
4328 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4329 !NT_STATUS_IS_OK(status)) {
4330 reply_nterror(req, status);
4334 send_trans2_replies(conn, req,
4342 if (NT_STATUS_IS_OK(status)) {
4343 /* Server-side transport
4344 * encryption is now *on*. */
4345 status = srv_encryption_start(conn);
4346 if (!NT_STATUS_IS_OK(status)) {
4347 char *reason = talloc_asprintf(talloc_tos(),
4348 "Failure in setting "
4349 "up encrypted transport: %s",
4351 exit_server_cleanly(reason);
4357 case SMB_FS_QUOTA_INFORMATION:
4361 .data = (uint8_t *)pdata,
4362 .length = total_data
4364 files_struct *fsp = NULL;
4365 fsp = file_fsp(req, SVAL(params,0));
4367 status = smb_set_fsquota(conn,
4371 if (!NT_STATUS_IS_OK(status)) {
4372 reply_nterror(req, status);
4378 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4380 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4386 * sending this reply works fine,
4387 * but I'm not sure it's the same
4388 * like windows do...
4391 reply_outbuf(req, 10, 0);
4394 #if defined(HAVE_POSIX_ACLS)
4395 /****************************************************************************
4396 Utility function to count the number of entries in a POSIX acl.
4397 ****************************************************************************/
4399 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4401 unsigned int ace_count = 0;
4402 int entry_id = SMB_ACL_FIRST_ENTRY;
4403 SMB_ACL_ENTRY_T entry;
4405 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4407 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4408 entry_id = SMB_ACL_NEXT_ENTRY;
4415 /****************************************************************************
4416 Utility function to marshall a POSIX acl into wire format.
4417 ****************************************************************************/
4419 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4421 int entry_id = SMB_ACL_FIRST_ENTRY;
4422 SMB_ACL_ENTRY_T entry;
4424 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4425 SMB_ACL_TAG_T tagtype;
4426 SMB_ACL_PERMSET_T permset;
4427 unsigned char perms = 0;
4428 unsigned int own_grp;
4431 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4432 entry_id = SMB_ACL_NEXT_ENTRY;
4435 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4436 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4440 if (sys_acl_get_permset(entry, &permset) == -1) {
4441 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4445 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4446 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4447 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4449 SCVAL(pdata,1,perms);
4452 case SMB_ACL_USER_OBJ:
4453 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4454 own_grp = (unsigned int)pst->st_ex_uid;
4455 SIVAL(pdata,2,own_grp);
4460 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4462 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4465 own_grp = (unsigned int)*puid;
4466 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4467 SIVAL(pdata,2,own_grp);
4471 case SMB_ACL_GROUP_OBJ:
4472 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4473 own_grp = (unsigned int)pst->st_ex_gid;
4474 SIVAL(pdata,2,own_grp);
4479 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4481 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4484 own_grp = (unsigned int)*pgid;
4485 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4486 SIVAL(pdata,2,own_grp);
4491 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4492 SIVAL(pdata,2,0xFFFFFFFF);
4493 SIVAL(pdata,6,0xFFFFFFFF);
4496 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4497 SIVAL(pdata,2,0xFFFFFFFF);
4498 SIVAL(pdata,6,0xFFFFFFFF);
4501 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4504 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4511 /****************************************************************************
4512 Store the FILE_UNIX_BASIC info.
4513 ****************************************************************************/
4515 static char *store_file_unix_basic(connection_struct *conn,
4518 const SMB_STRUCT_STAT *psbuf)
4520 uint64_t file_index = get_FileIndex(conn, psbuf);
4523 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4524 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4526 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4529 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4532 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4533 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4534 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4537 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4541 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4545 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4548 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4549 devno = psbuf->st_ex_rdev;
4551 devno = psbuf->st_ex_dev;
4554 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4558 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4562 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4565 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4569 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4576 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4577 * the chflags(2) (or equivalent) flags.
4579 * XXX: this really should be behind the VFS interface. To do this, we would
4580 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4581 * Each VFS module could then implement its own mapping as appropriate for the
4582 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4584 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4588 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4592 { UF_IMMUTABLE, EXT_IMMUTABLE },
4596 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4600 { UF_HIDDEN, EXT_HIDDEN },
4603 /* Do not remove. We need to guarantee that this array has at least one
4604 * entry to build on HP-UX.
4610 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4611 uint32_t *smb_fflags, uint32_t *smb_fmask)
4615 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4616 *smb_fmask |= info2_flags_map[i].smb_fflag;
4617 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4618 *smb_fflags |= info2_flags_map[i].smb_fflag;
4623 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4624 const uint32_t smb_fflags,
4625 const uint32_t smb_fmask,
4628 uint32_t max_fmask = 0;
4631 *stat_fflags = psbuf->st_ex_flags;
4633 /* For each flags requested in smb_fmask, check the state of the
4634 * corresponding flag in smb_fflags and set or clear the matching
4638 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4639 max_fmask |= info2_flags_map[i].smb_fflag;
4640 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4641 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4642 *stat_fflags |= info2_flags_map[i].stat_fflag;
4644 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4649 /* If smb_fmask is asking to set any bits that are not supported by
4650 * our flag mappings, we should fail.
4652 if ((smb_fmask & max_fmask) != smb_fmask) {
4660 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4661 * of file flags and birth (create) time.
4663 static char *store_file_unix_basic_info2(connection_struct *conn,
4666 const SMB_STRUCT_STAT *psbuf)
4668 uint32_t file_flags = 0;
4669 uint32_t flags_mask = 0;
4671 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4673 /* Create (birth) time 64 bit */
4674 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4677 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4678 SIVAL(pdata, 0, file_flags); /* flags */
4679 SIVAL(pdata, 4, flags_mask); /* mask */
4685 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4686 const struct stream_struct *streams,
4688 unsigned int max_data_bytes,
4689 unsigned int *data_size)
4692 unsigned int ofs = 0;
4694 if (max_data_bytes < 32) {
4695 return NT_STATUS_INFO_LENGTH_MISMATCH;
4698 for (i = 0; i < num_streams; i++) {
4699 unsigned int next_offset;
4701 smb_ucs2_t *namebuf;
4703 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4704 streams[i].name, &namelen) ||
4707 return NT_STATUS_INVALID_PARAMETER;
4711 * name_buf is now null-terminated, we need to marshall as not
4718 * We cannot overflow ...
4720 if ((ofs + 24 + namelen) > max_data_bytes) {
4721 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4723 TALLOC_FREE(namebuf);
4724 return STATUS_BUFFER_OVERFLOW;
4727 SIVAL(data, ofs+4, namelen);
4728 SOFF_T(data, ofs+8, streams[i].size);
4729 SOFF_T(data, ofs+16, streams[i].alloc_size);
4730 memcpy(data+ofs+24, namebuf, namelen);
4731 TALLOC_FREE(namebuf);
4733 next_offset = ofs + 24 + namelen;
4735 if (i == num_streams-1) {
4736 SIVAL(data, ofs, 0);
4739 unsigned int align = ndr_align_size(next_offset, 8);
4741 if ((next_offset + align) > max_data_bytes) {
4742 DEBUG(10, ("refusing to overflow align "
4743 "reply at stream %u\n",
4745 TALLOC_FREE(namebuf);
4746 return STATUS_BUFFER_OVERFLOW;
4749 memset(data+next_offset, 0, align);
4750 next_offset += align;
4752 SIVAL(data, ofs, next_offset - ofs);
4759 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4763 return NT_STATUS_OK;
4766 /****************************************************************************
4767 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4768 ****************************************************************************/
4770 static void call_trans2qpipeinfo(connection_struct *conn,
4771 struct smb_request *req,
4772 unsigned int tran_call,
4773 char **pparams, int total_params,
4774 char **ppdata, int total_data,
4775 unsigned int max_data_bytes)
4777 char *params = *pparams;
4778 char *pdata = *ppdata;
4779 unsigned int data_size = 0;
4780 unsigned int param_size = 2;
4781 uint16_t info_level;
4785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4789 if (total_params < 4) {
4790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4794 fsp = file_fsp(req, SVAL(params,0));
4795 if (!fsp_is_np(fsp)) {
4796 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4800 info_level = SVAL(params,2);
4802 *pparams = (char *)SMB_REALLOC(*pparams,2);
4803 if (*pparams == NULL) {
4804 reply_nterror(req, NT_STATUS_NO_MEMORY);
4809 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4813 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4814 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4815 if (*ppdata == NULL ) {
4816 reply_nterror(req, NT_STATUS_NO_MEMORY);
4821 switch (info_level) {
4822 case SMB_FILE_STANDARD_INFORMATION:
4824 SOFF_T(pdata,0,4096LL);
4831 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4835 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4841 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4842 TALLOC_CTX *mem_ctx,
4843 uint16_t info_level,
4845 struct smb_filename *smb_fname,
4846 bool delete_pending,
4847 struct timespec write_time_ts,
4848 struct ea_list *ea_list,
4849 int lock_data_count,
4852 unsigned int max_data_bytes,
4853 size_t *fixed_portion,
4855 unsigned int *pdata_size)
4857 char *pdata = *ppdata;
4858 char *dstart, *dend;
4859 unsigned int data_size;
4860 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4861 time_t create_time, mtime, atime, c_time;
4862 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4869 uint64_t file_size = 0;
4871 uint64_t allocation_size = 0;
4872 uint64_t file_index = 0;
4873 uint32_t access_mask = 0;
4876 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4877 return NT_STATUS_INVALID_LEVEL;
4880 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4881 smb_fname_str_dbg(smb_fname),
4883 info_level, max_data_bytes));
4885 mode = dos_mode(conn, smb_fname);
4886 nlink = psbuf->st_ex_nlink;
4888 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4892 if ((nlink > 0) && delete_pending) {
4896 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4897 return NT_STATUS_INVALID_PARAMETER;
4900 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4901 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4902 if (*ppdata == NULL) {
4903 return NT_STATUS_NO_MEMORY;
4907 dend = dstart + data_size - 1;
4909 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4910 update_stat_ex_mtime(psbuf, write_time_ts);
4913 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4914 mtime_ts = psbuf->st_ex_mtime;
4915 atime_ts = psbuf->st_ex_atime;
4916 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4918 if (lp_dos_filetime_resolution(SNUM(conn))) {
4919 dos_filetime_timespec(&create_time_ts);
4920 dos_filetime_timespec(&mtime_ts);
4921 dos_filetime_timespec(&atime_ts);
4922 dos_filetime_timespec(&ctime_ts);
4925 create_time = convert_timespec_to_time_t(create_time_ts);
4926 mtime = convert_timespec_to_time_t(mtime_ts);
4927 atime = convert_timespec_to_time_t(atime_ts);
4928 c_time = convert_timespec_to_time_t(ctime_ts);
4930 p = strrchr_m(smb_fname->base_name,'/');
4932 base_name = smb_fname->base_name;
4936 /* NT expects the name to be in an exact form of the *full*
4937 filename. See the trans2 torture test */
4938 if (ISDOT(base_name)) {
4939 dos_fname = talloc_strdup(mem_ctx, "\\");
4941 return NT_STATUS_NO_MEMORY;
4944 dos_fname = talloc_asprintf(mem_ctx,
4946 smb_fname->base_name);
4948 return NT_STATUS_NO_MEMORY;
4950 if (is_ntfs_stream_smb_fname(smb_fname)) {
4951 dos_fname = talloc_asprintf(dos_fname, "%s",
4952 smb_fname->stream_name);
4954 return NT_STATUS_NO_MEMORY;
4958 string_replace(dos_fname, '/', '\\');
4961 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4964 /* Do we have this path open ? */
4966 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4967 fsp1 = file_find_di_first(conn->sconn, fileid);
4968 if (fsp1 && fsp1->initial_allocation_size) {
4969 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4973 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4974 file_size = get_file_size_stat(psbuf);
4978 pos = fsp->fh->position_information;
4982 access_mask = fsp->access_mask;
4984 /* GENERIC_EXECUTE mapping from Windows */
4985 access_mask = 0x12019F;
4988 /* This should be an index number - looks like
4991 I think this causes us to fail the IFSKIT
4992 BasicFileInformationTest. -tpot */
4993 file_index = get_FileIndex(conn, psbuf);
4997 switch (info_level) {
4998 case SMB_INFO_STANDARD:
4999 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5001 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5002 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5003 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5004 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5005 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5006 SSVAL(pdata,l1_attrFile,mode);
5009 case SMB_INFO_QUERY_EA_SIZE:
5011 unsigned int ea_size =
5012 estimate_ea_size(conn, fsp,
5014 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5016 srv_put_dos_date2(pdata,0,create_time);
5017 srv_put_dos_date2(pdata,4,atime);
5018 srv_put_dos_date2(pdata,8,mtime); /* write time */
5019 SIVAL(pdata,12,(uint32_t)file_size);
5020 SIVAL(pdata,16,(uint32_t)allocation_size);
5021 SSVAL(pdata,20,mode);
5022 SIVAL(pdata,22,ea_size);
5026 case SMB_INFO_IS_NAME_VALID:
5027 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5029 /* os/2 needs this ? really ?*/
5030 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5032 /* This is only reached for qpathinfo */
5036 case SMB_INFO_QUERY_EAS_FROM_LIST:
5038 size_t total_ea_len = 0;
5039 struct ea_list *ea_file_list = NULL;
5040 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5043 get_ea_list_from_file(mem_ctx, conn, fsp,
5045 &total_ea_len, &ea_file_list);
5046 if (!NT_STATUS_IS_OK(status)) {
5050 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5052 if (!ea_list || (total_ea_len > data_size)) {
5054 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5058 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5062 case SMB_INFO_QUERY_ALL_EAS:
5064 /* We have data_size bytes to put EA's into. */
5065 size_t total_ea_len = 0;
5066 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5068 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5070 &total_ea_len, &ea_list);
5071 if (!NT_STATUS_IS_OK(status)) {
5075 if (!ea_list || (total_ea_len > data_size)) {
5077 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5081 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5085 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5087 /* This is FileFullEaInformation - 0xF which maps to
5088 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5090 /* We have data_size bytes to put EA's into. */
5091 size_t total_ea_len = 0;
5092 struct ea_list *ea_file_list = NULL;
5094 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5096 /*TODO: add filtering and index handling */
5099 get_ea_list_from_file(mem_ctx, conn, fsp,
5101 &total_ea_len, &ea_file_list);
5102 if (!NT_STATUS_IS_OK(status)) {
5105 if (!ea_file_list) {
5106 return NT_STATUS_NO_EAS_ON_FILE;
5109 status = fill_ea_chained_buffer(mem_ctx,
5113 conn, ea_file_list);
5114 if (!NT_STATUS_IS_OK(status)) {
5120 case SMB_FILE_BASIC_INFORMATION:
5121 case SMB_QUERY_FILE_BASIC_INFO:
5123 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5124 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5125 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5127 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5131 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5132 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5133 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5134 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5135 SIVAL(pdata,32,mode);
5137 DEBUG(5,("SMB_QFBI - "));
5138 DEBUG(5,("create: %s ", ctime(&create_time)));
5139 DEBUG(5,("access: %s ", ctime(&atime)));
5140 DEBUG(5,("write: %s ", ctime(&mtime)));
5141 DEBUG(5,("change: %s ", ctime(&c_time)));
5142 DEBUG(5,("mode: %x\n", mode));
5143 *fixed_portion = data_size;
5146 case SMB_FILE_STANDARD_INFORMATION:
5147 case SMB_QUERY_FILE_STANDARD_INFO:
5149 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5151 SOFF_T(pdata,0,allocation_size);
5152 SOFF_T(pdata,8,file_size);
5153 SIVAL(pdata,16,nlink);
5154 SCVAL(pdata,20,delete_pending?1:0);
5155 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5156 SSVAL(pdata,22,0); /* Padding. */
5157 *fixed_portion = 24;
5160 case SMB_FILE_EA_INFORMATION:
5161 case SMB_QUERY_FILE_EA_INFO:
5163 unsigned int ea_size =
5164 estimate_ea_size(conn, fsp, smb_fname);
5165 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5168 SIVAL(pdata,0,ea_size);
5172 /* Get the 8.3 name - used if NT SMB was negotiated. */
5173 case SMB_QUERY_FILE_ALT_NAME_INFO:
5174 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5176 char mangled_name[13];
5177 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5178 if (!name_to_8_3(base_name,mangled_name,
5179 True,conn->params)) {
5180 return NT_STATUS_NO_MEMORY;
5182 status = srvstr_push(dstart, flags2,
5183 pdata+4, mangled_name,
5184 PTR_DIFF(dend, pdata+4),
5186 if (!NT_STATUS_IS_OK(status)) {
5189 data_size = 4 + len;
5195 case SMB_QUERY_FILE_NAME_INFO:
5198 this must be *exactly* right for ACLs on mapped drives to work
5200 status = srvstr_push(dstart, flags2,
5202 PTR_DIFF(dend, pdata+4),
5204 if (!NT_STATUS_IS_OK(status)) {
5207 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5208 data_size = 4 + len;
5213 case SMB_FILE_ALLOCATION_INFORMATION:
5214 case SMB_QUERY_FILE_ALLOCATION_INFO:
5215 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5217 SOFF_T(pdata,0,allocation_size);
5220 case SMB_FILE_END_OF_FILE_INFORMATION:
5221 case SMB_QUERY_FILE_END_OF_FILEINFO:
5222 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5224 SOFF_T(pdata,0,file_size);
5227 case SMB_QUERY_FILE_ALL_INFO:
5228 case SMB_FILE_ALL_INFORMATION:
5230 unsigned int ea_size =
5231 estimate_ea_size(conn, fsp, smb_fname);
5232 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5233 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5234 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5235 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5236 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5237 SIVAL(pdata,32,mode);
5238 SIVAL(pdata,36,0); /* padding. */
5240 SOFF_T(pdata,0,allocation_size);
5241 SOFF_T(pdata,8,file_size);
5242 SIVAL(pdata,16,nlink);
5243 SCVAL(pdata,20,delete_pending);
5244 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5247 SIVAL(pdata,0,ea_size);
5248 pdata += 4; /* EA info */
5249 status = srvstr_push(dstart, flags2,
5251 PTR_DIFF(dend, pdata+4),
5253 if (!NT_STATUS_IS_OK(status)) {
5258 data_size = PTR_DIFF(pdata,(*ppdata));
5259 *fixed_portion = 10;
5263 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5265 unsigned int ea_size =
5266 estimate_ea_size(conn, fsp, smb_fname);
5267 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5268 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5269 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5270 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5271 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5272 SIVAL(pdata, 0x20, mode);
5273 SIVAL(pdata, 0x24, 0); /* padding. */
5274 SBVAL(pdata, 0x28, allocation_size);
5275 SBVAL(pdata, 0x30, file_size);
5276 SIVAL(pdata, 0x38, nlink);
5277 SCVAL(pdata, 0x3C, delete_pending);
5278 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5279 SSVAL(pdata, 0x3E, 0); /* padding */
5280 SBVAL(pdata, 0x40, file_index);
5281 SIVAL(pdata, 0x48, ea_size);
5282 SIVAL(pdata, 0x4C, access_mask);
5283 SBVAL(pdata, 0x50, pos);
5284 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5285 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5289 status = srvstr_push(dstart, flags2,
5291 PTR_DIFF(dend, pdata+4),
5293 if (!NT_STATUS_IS_OK(status)) {
5298 data_size = PTR_DIFF(pdata,(*ppdata));
5299 *fixed_portion = 104;
5302 case SMB_FILE_INTERNAL_INFORMATION:
5304 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5305 SBVAL(pdata, 0, file_index);
5310 case SMB_FILE_ACCESS_INFORMATION:
5311 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5312 SIVAL(pdata, 0, access_mask);
5317 case SMB_FILE_NAME_INFORMATION:
5318 /* Pathname with leading '\'. */
5321 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5322 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5323 SIVAL(pdata,0,byte_len);
5324 data_size = 4 + byte_len;
5328 case SMB_FILE_DISPOSITION_INFORMATION:
5329 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5331 SCVAL(pdata,0,delete_pending);
5335 case SMB_FILE_POSITION_INFORMATION:
5336 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5338 SOFF_T(pdata,0,pos);
5342 case SMB_FILE_MODE_INFORMATION:
5343 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5344 SIVAL(pdata,0,mode);
5349 case SMB_FILE_ALIGNMENT_INFORMATION:
5350 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5351 SIVAL(pdata,0,0); /* No alignment needed. */
5357 * NT4 server just returns "invalid query" to this - if we try
5358 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5361 /* The first statement above is false - verified using Thursby
5362 * client against NT4 -- gcolley.
5364 case SMB_QUERY_FILE_STREAM_INFO:
5365 case SMB_FILE_STREAM_INFORMATION: {
5366 unsigned int num_streams = 0;
5367 struct stream_struct *streams = NULL;
5369 DEBUG(10,("smbd_do_qfilepathinfo: "
5370 "SMB_FILE_STREAM_INFORMATION\n"));
5372 if (is_ntfs_stream_smb_fname(smb_fname)) {
5373 return NT_STATUS_INVALID_PARAMETER;
5376 status = vfs_streaminfo(conn,
5383 if (!NT_STATUS_IS_OK(status)) {
5384 DEBUG(10, ("could not get stream info: %s\n",
5385 nt_errstr(status)));
5389 status = marshall_stream_info(num_streams, streams,
5390 pdata, max_data_bytes,
5393 if (!NT_STATUS_IS_OK(status)) {
5394 DEBUG(10, ("marshall_stream_info failed: %s\n",
5395 nt_errstr(status)));
5396 TALLOC_FREE(streams);
5400 TALLOC_FREE(streams);
5402 *fixed_portion = 32;
5406 case SMB_QUERY_COMPRESSION_INFO:
5407 case SMB_FILE_COMPRESSION_INFORMATION:
5408 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5409 SOFF_T(pdata,0,file_size);
5410 SIVAL(pdata,8,0); /* ??? */
5411 SIVAL(pdata,12,0); /* ??? */
5413 *fixed_portion = 16;
5416 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5417 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5418 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5419 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5420 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5421 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5422 SOFF_T(pdata,32,allocation_size);
5423 SOFF_T(pdata,40,file_size);
5424 SIVAL(pdata,48,mode);
5425 SIVAL(pdata,52,0); /* ??? */
5427 *fixed_portion = 56;
5430 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5431 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5432 SIVAL(pdata,0,mode);
5439 * CIFS UNIX Extensions.
5442 case SMB_QUERY_FILE_UNIX_BASIC:
5444 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5445 data_size = PTR_DIFF(pdata,(*ppdata));
5447 DEBUG(4,("smbd_do_qfilepathinfo: "
5448 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5449 dump_data(4, (uint8_t *)(*ppdata), data_size);
5453 case SMB_QUERY_FILE_UNIX_INFO2:
5455 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5456 data_size = PTR_DIFF(pdata,(*ppdata));
5460 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5462 for (i=0; i<100; i++)
5463 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5469 case SMB_QUERY_FILE_UNIX_LINK:
5472 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5475 return NT_STATUS_NO_MEMORY;
5478 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5480 if(!S_ISLNK(psbuf->st_ex_mode)) {
5481 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5484 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5486 link_len = SMB_VFS_READLINK(conn,
5489 if (link_len == -1) {
5490 return map_nt_error_from_unix(errno);
5492 buffer[link_len] = 0;
5493 status = srvstr_push(dstart, flags2,
5495 PTR_DIFF(dend, pdata),
5496 STR_TERMINATE, &len);
5497 if (!NT_STATUS_IS_OK(status)) {
5501 data_size = PTR_DIFF(pdata,(*ppdata));
5506 #if defined(HAVE_POSIX_ACLS)
5507 case SMB_QUERY_POSIX_ACL:
5509 SMB_ACL_T file_acl = NULL;
5510 SMB_ACL_T def_acl = NULL;
5511 uint16_t num_file_acls = 0;
5512 uint16_t num_def_acls = 0;
5514 status = refuse_symlink(conn,
5517 if (!NT_STATUS_IS_OK(status)) {
5521 if (fsp && fsp->fh->fd != -1) {
5522 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5526 SMB_VFS_SYS_ACL_GET_FILE(conn,
5528 SMB_ACL_TYPE_ACCESS,
5532 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5533 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5534 "not implemented on "
5535 "filesystem containing %s\n",
5536 smb_fname->base_name));
5537 return NT_STATUS_NOT_IMPLEMENTED;
5540 if (S_ISDIR(psbuf->st_ex_mode)) {
5541 if (fsp && fsp->is_directory) {
5543 SMB_VFS_SYS_ACL_GET_FILE(
5546 SMB_ACL_TYPE_DEFAULT,
5550 SMB_VFS_SYS_ACL_GET_FILE(
5553 SMB_ACL_TYPE_DEFAULT,
5556 def_acl = free_empty_sys_acl(conn, def_acl);
5559 num_file_acls = count_acl_entries(conn, file_acl);
5560 num_def_acls = count_acl_entries(conn, def_acl);
5562 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5563 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5565 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5566 SMB_POSIX_ACL_HEADER_SIZE) ));
5568 TALLOC_FREE(file_acl);
5571 TALLOC_FREE(def_acl);
5573 return NT_STATUS_BUFFER_TOO_SMALL;
5576 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5577 SSVAL(pdata,2,num_file_acls);
5578 SSVAL(pdata,4,num_def_acls);
5579 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5581 TALLOC_FREE(file_acl);
5584 TALLOC_FREE(def_acl);
5586 return NT_STATUS_INTERNAL_ERROR;
5588 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5590 TALLOC_FREE(file_acl);
5593 TALLOC_FREE(def_acl);
5595 return NT_STATUS_INTERNAL_ERROR;
5599 TALLOC_FREE(file_acl);
5602 TALLOC_FREE(def_acl);
5604 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5610 case SMB_QUERY_POSIX_LOCK:
5615 enum brl_type lock_type;
5617 /* We need an open file with a real fd for this. */
5618 if (!fsp || fsp->fh->fd == -1) {
5619 return NT_STATUS_INVALID_LEVEL;
5622 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5623 return NT_STATUS_INVALID_PARAMETER;
5626 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5627 case POSIX_LOCK_TYPE_READ:
5628 lock_type = READ_LOCK;
5630 case POSIX_LOCK_TYPE_WRITE:
5631 lock_type = WRITE_LOCK;
5633 case POSIX_LOCK_TYPE_UNLOCK:
5635 /* There's no point in asking for an unlock... */
5636 return NT_STATUS_INVALID_PARAMETER;
5639 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5640 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5641 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5643 status = query_lock(fsp,
5650 if (ERROR_WAS_LOCK_DENIED(status)) {
5651 /* Here we need to report who has it locked... */
5652 data_size = POSIX_LOCK_DATA_SIZE;
5654 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5655 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5656 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5657 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5658 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5660 } else if (NT_STATUS_IS_OK(status)) {
5661 /* For success we just return a copy of what we sent
5662 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5663 data_size = POSIX_LOCK_DATA_SIZE;
5664 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5665 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5673 return NT_STATUS_INVALID_LEVEL;
5676 *pdata_size = data_size;
5677 return NT_STATUS_OK;
5680 /****************************************************************************
5681 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5682 file name or file id).
5683 ****************************************************************************/
5685 static void call_trans2qfilepathinfo(connection_struct *conn,
5686 struct smb_request *req,
5687 unsigned int tran_call,
5688 char **pparams, int total_params,
5689 char **ppdata, int total_data,
5690 unsigned int max_data_bytes)
5692 char *params = *pparams;
5693 char *pdata = *ppdata;
5694 uint16_t info_level;
5695 unsigned int data_size = 0;
5696 unsigned int param_size = 2;
5697 struct smb_filename *smb_fname = NULL;
5698 bool delete_pending = False;
5699 struct timespec write_time_ts;
5700 files_struct *fsp = NULL;
5701 struct file_id fileid;
5702 struct ea_list *ea_list = NULL;
5703 int lock_data_count = 0;
5704 char *lock_data = NULL;
5705 size_t fixed_portion;
5706 NTSTATUS status = NT_STATUS_OK;
5709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5713 ZERO_STRUCT(write_time_ts);
5715 if (tran_call == TRANSACT2_QFILEINFO) {
5716 if (total_params < 4) {
5717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5722 call_trans2qpipeinfo(conn, req, tran_call,
5723 pparams, total_params,
5729 fsp = file_fsp(req, SVAL(params,0));
5730 info_level = SVAL(params,2);
5732 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5734 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5735 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5739 /* Initial check for valid fsp ptr. */
5740 if (!check_fsp_open(conn, req, fsp)) {
5744 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5745 if (smb_fname == NULL) {
5746 reply_nterror(req, NT_STATUS_NO_MEMORY);
5750 if(fsp->fake_file_handle) {
5752 * This is actually for the QUOTA_FAKE_FILE --metze
5755 /* We know this name is ok, it's already passed the checks. */
5757 } else if(fsp->fh->fd == -1) {
5759 * This is actually a QFILEINFO on a directory
5760 * handle (returned from an NT SMB). NT5.0 seems
5761 * to do this call. JRA.
5764 if (INFO_LEVEL_IS_UNIX(info_level)) {
5765 /* Always do lstat for UNIX calls. */
5766 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5767 DEBUG(3,("call_trans2qfilepathinfo: "
5768 "SMB_VFS_LSTAT of %s failed "
5770 smb_fname_str_dbg(smb_fname),
5773 map_nt_error_from_unix(errno));
5776 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5777 DEBUG(3,("call_trans2qfilepathinfo: "
5778 "SMB_VFS_STAT of %s failed (%s)\n",
5779 smb_fname_str_dbg(smb_fname),
5782 map_nt_error_from_unix(errno));
5786 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5787 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5790 * Original code - this is an open file.
5792 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5793 DEBUG(3, ("fstat of %s failed (%s)\n",
5794 fsp_fnum_dbg(fsp), strerror(errno)));
5796 map_nt_error_from_unix(errno));
5799 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5800 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5806 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5809 if (total_params < 7) {
5810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5814 info_level = SVAL(params,0);
5816 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5818 if (INFO_LEVEL_IS_UNIX(info_level)) {
5819 if (!lp_unix_extensions()) {
5820 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5823 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5824 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5825 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5826 req->posix_pathnames) {
5827 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5831 if (req->posix_pathnames) {
5832 srvstr_get_path_posix(req,
5841 srvstr_get_path(req,
5850 if (!NT_STATUS_IS_OK(status)) {
5851 reply_nterror(req, status);
5855 status = filename_convert(req,
5861 if (!NT_STATUS_IS_OK(status)) {
5862 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5863 reply_botherror(req,
5864 NT_STATUS_PATH_NOT_COVERED,
5865 ERRSRV, ERRbadpath);
5868 reply_nterror(req, status);
5872 /* If this is a stream, check if there is a delete_pending. */
5873 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5874 && is_ntfs_stream_smb_fname(smb_fname)) {
5875 struct smb_filename *smb_fname_base;
5877 /* Create an smb_filename with stream_name == NULL. */
5878 smb_fname_base = synthetic_smb_fname(
5880 smb_fname->base_name,
5884 if (smb_fname_base == NULL) {
5885 reply_nterror(req, NT_STATUS_NO_MEMORY);
5889 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5890 /* Always do lstat for UNIX calls. */
5891 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5892 DEBUG(3,("call_trans2qfilepathinfo: "
5893 "SMB_VFS_LSTAT of %s failed "
5895 smb_fname_str_dbg(smb_fname_base),
5897 TALLOC_FREE(smb_fname_base);
5899 map_nt_error_from_unix(errno));
5903 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5904 DEBUG(3,("call_trans2qfilepathinfo: "
5905 "fileinfo of %s failed "
5907 smb_fname_str_dbg(smb_fname_base),
5909 TALLOC_FREE(smb_fname_base);
5911 map_nt_error_from_unix(errno));
5916 status = file_name_hash(conn,
5917 smb_fname_str_dbg(smb_fname_base),
5919 if (!NT_STATUS_IS_OK(status)) {
5920 TALLOC_FREE(smb_fname_base);
5921 reply_nterror(req, status);
5925 fileid = vfs_file_id_from_sbuf(conn,
5926 &smb_fname_base->st);
5927 TALLOC_FREE(smb_fname_base);
5928 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5929 if (delete_pending) {
5930 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5935 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5936 /* Always do lstat for UNIX calls. */
5937 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5938 DEBUG(3,("call_trans2qfilepathinfo: "
5939 "SMB_VFS_LSTAT of %s failed (%s)\n",
5940 smb_fname_str_dbg(smb_fname),
5943 map_nt_error_from_unix(errno));
5948 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5949 DEBUG(3,("call_trans2qfilepathinfo: "
5950 "SMB_VFS_STAT of %s failed (%s)\n",
5951 smb_fname_str_dbg(smb_fname),
5954 map_nt_error_from_unix(errno));
5959 status = file_name_hash(conn,
5960 smb_fname_str_dbg(smb_fname),
5962 if (!NT_STATUS_IS_OK(status)) {
5963 reply_nterror(req, status);
5967 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5968 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5969 if (delete_pending) {
5970 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5975 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5976 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5978 info_level,tran_call,total_data));
5980 /* Pull out any data sent here before we realloc. */
5981 switch (info_level) {
5982 case SMB_INFO_QUERY_EAS_FROM_LIST:
5984 /* Pull any EA list from the data portion. */
5987 if (total_data < 4) {
5989 req, NT_STATUS_INVALID_PARAMETER);
5992 ea_size = IVAL(pdata,0);
5994 if (total_data > 0 && ea_size != total_data) {
5995 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5996 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5998 req, NT_STATUS_INVALID_PARAMETER);
6002 if (!lp_ea_support(SNUM(conn))) {
6003 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6007 /* Pull out the list of names. */
6008 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6011 req, NT_STATUS_INVALID_PARAMETER);
6017 case SMB_QUERY_POSIX_LOCK:
6019 if (fsp == NULL || fsp->fh->fd == -1) {
6020 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6024 if (total_data != POSIX_LOCK_DATA_SIZE) {
6026 req, NT_STATUS_INVALID_PARAMETER);
6030 /* Copy the lock range data. */
6031 lock_data = (char *)talloc_memdup(
6032 req, pdata, total_data);
6034 reply_nterror(req, NT_STATUS_NO_MEMORY);
6037 lock_data_count = total_data;
6043 *pparams = (char *)SMB_REALLOC(*pparams,2);
6044 if (*pparams == NULL) {
6045 reply_nterror(req, NT_STATUS_NO_MEMORY);
6052 * draft-leach-cifs-v1-spec-02.txt
6053 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6056 * The requested information is placed in the Data portion of the
6057 * transaction response. For the information levels greater than 0x100,
6058 * the transaction response has 1 parameter word which should be
6059 * ignored by the client.
6061 * However Windows only follows this rule for the IS_NAME_VALID call.
6063 switch (info_level) {
6064 case SMB_INFO_IS_NAME_VALID:
6069 if ((info_level & 0xFF00) == 0xFF00) {
6071 * We use levels that start with 0xFF00
6072 * internally to represent SMB2 specific levels
6074 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6078 status = smbd_do_qfilepathinfo(conn, req, info_level,
6080 delete_pending, write_time_ts,
6082 lock_data_count, lock_data,
6083 req->flags2, max_data_bytes,
6085 ppdata, &data_size);
6086 if (!NT_STATUS_IS_OK(status)) {
6087 reply_nterror(req, status);
6090 if (fixed_portion > max_data_bytes) {
6091 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6095 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6101 /****************************************************************************
6102 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6104 ****************************************************************************/
6106 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6107 connection_struct *conn,
6108 struct smb_request *req,
6109 bool overwrite_if_exists,
6110 const struct smb_filename *smb_fname_old,
6111 struct smb_filename *smb_fname_new)
6113 NTSTATUS status = NT_STATUS_OK;
6115 /* source must already exist. */
6116 if (!VALID_STAT(smb_fname_old->st)) {
6117 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6120 if (VALID_STAT(smb_fname_new->st)) {
6121 if (overwrite_if_exists) {
6122 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6123 return NT_STATUS_FILE_IS_A_DIRECTORY;
6125 status = unlink_internals(conn,
6127 FILE_ATTRIBUTE_NORMAL,
6130 if (!NT_STATUS_IS_OK(status)) {
6134 /* Disallow if newname already exists. */
6135 return NT_STATUS_OBJECT_NAME_COLLISION;
6139 /* No links from a directory. */
6140 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6141 return NT_STATUS_FILE_IS_A_DIRECTORY;
6144 /* Setting a hardlink to/from a stream isn't currently supported. */
6145 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6146 is_ntfs_stream_smb_fname(smb_fname_new)) {
6147 return NT_STATUS_INVALID_PARAMETER;
6150 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6151 smb_fname_old->base_name, smb_fname_new->base_name));
6153 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6154 status = map_nt_error_from_unix(errno);
6155 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6156 nt_errstr(status), smb_fname_old->base_name,
6157 smb_fname_new->base_name));
6162 /****************************************************************************
6163 Deal with setting the time from any of the setfilepathinfo functions.
6164 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6165 calling this function.
6166 ****************************************************************************/
6168 NTSTATUS smb_set_file_time(connection_struct *conn,
6170 const struct smb_filename *smb_fname,
6171 struct smb_file_time *ft,
6172 bool setting_write_time)
6174 struct smb_filename smb_fname_base;
6176 FILE_NOTIFY_CHANGE_LAST_ACCESS
6177 |FILE_NOTIFY_CHANGE_LAST_WRITE
6178 |FILE_NOTIFY_CHANGE_CREATION;
6180 if (!VALID_STAT(smb_fname->st)) {
6181 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6184 /* get some defaults (no modifications) if any info is zero or -1. */
6185 if (null_timespec(ft->create_time)) {
6186 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6189 if (null_timespec(ft->atime)) {
6190 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6193 if (null_timespec(ft->mtime)) {
6194 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6197 if (!setting_write_time) {
6198 /* ft->mtime comes from change time, not write time. */
6199 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6202 /* Ensure the resolution is the correct for
6203 * what we can store on this filesystem. */
6205 round_timespec(conn->ts_res, &ft->create_time);
6206 round_timespec(conn->ts_res, &ft->ctime);
6207 round_timespec(conn->ts_res, &ft->atime);
6208 round_timespec(conn->ts_res, &ft->mtime);
6210 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6211 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6212 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6213 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6214 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6215 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6216 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6217 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6219 if (setting_write_time) {
6221 * This was a Windows setfileinfo on an open file.
6222 * NT does this a lot. We also need to
6223 * set the time here, as it can be read by
6224 * FindFirst/FindNext and with the patch for bug #2045
6225 * in smbd/fileio.c it ensures that this timestamp is
6226 * kept sticky even after a write. We save the request
6227 * away and will set it on file close and after a write. JRA.
6230 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6231 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6234 if (fsp->base_fsp) {
6235 set_sticky_write_time_fsp(fsp->base_fsp,
6238 set_sticky_write_time_fsp(fsp, ft->mtime);
6241 set_sticky_write_time_path(
6242 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6247 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6249 /* Always call ntimes on the base, even if a stream was passed in. */
6250 smb_fname_base = *smb_fname;
6251 smb_fname_base.stream_name = NULL;
6253 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6254 return map_nt_error_from_unix(errno);
6257 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6258 smb_fname->base_name);
6259 return NT_STATUS_OK;
6262 /****************************************************************************
6263 Deal with setting the dosmode from any of the setfilepathinfo functions.
6264 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6265 done before calling this function.
6266 ****************************************************************************/
6268 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6269 const struct smb_filename *smb_fname,
6272 struct smb_filename *smb_fname_base;
6275 if (!VALID_STAT(smb_fname->st)) {
6276 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6279 /* Always operate on the base_name, even if a stream was passed in. */
6280 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6281 smb_fname->base_name,
6285 if (smb_fname_base == NULL) {
6286 return NT_STATUS_NO_MEMORY;
6290 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6291 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6293 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6297 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6299 /* check the mode isn't different, before changing it */
6300 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6301 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6302 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6303 (unsigned int)dosmode));
6305 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6307 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6309 smb_fname_str_dbg(smb_fname_base),
6311 status = map_nt_error_from_unix(errno);
6315 status = NT_STATUS_OK;
6317 TALLOC_FREE(smb_fname_base);
6321 /****************************************************************************
6322 Deal with setting the size from any of the setfilepathinfo functions.
6323 ****************************************************************************/
6325 static NTSTATUS smb_set_file_size(connection_struct *conn,
6326 struct smb_request *req,
6328 const struct smb_filename *smb_fname,
6329 const SMB_STRUCT_STAT *psbuf,
6331 bool fail_after_createfile)
6333 NTSTATUS status = NT_STATUS_OK;
6334 struct smb_filename *smb_fname_tmp = NULL;
6335 files_struct *new_fsp = NULL;
6337 if (!VALID_STAT(*psbuf)) {
6338 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6341 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6343 if (size == get_file_size_stat(psbuf)) {
6344 return NT_STATUS_OK;
6347 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6348 smb_fname_str_dbg(smb_fname), (double)size));
6350 if (fsp && fsp->fh->fd != -1) {
6351 /* Handle based call. */
6352 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6353 return NT_STATUS_ACCESS_DENIED;
6356 if (vfs_set_filelen(fsp, size) == -1) {
6357 return map_nt_error_from_unix(errno);
6359 trigger_write_time_update_immediate(fsp);
6360 return NT_STATUS_OK;
6363 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6364 if (smb_fname_tmp == NULL) {
6365 return NT_STATUS_NO_MEMORY;
6368 smb_fname_tmp->st = *psbuf;
6370 status = SMB_VFS_CREATE_FILE(
6373 0, /* root_dir_fid */
6374 smb_fname_tmp, /* fname */
6375 FILE_WRITE_DATA, /* access_mask */
6376 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6378 FILE_OPEN, /* create_disposition*/
6379 0, /* create_options */
6380 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6381 0, /* oplock_request */
6383 0, /* allocation_size */
6384 0, /* private_flags */
6387 &new_fsp, /* result */
6389 NULL, NULL); /* create context */
6391 TALLOC_FREE(smb_fname_tmp);
6393 if (!NT_STATUS_IS_OK(status)) {
6394 /* NB. We check for open_was_deferred in the caller. */
6398 /* See RAW-SFILEINFO-END-OF-FILE */
6399 if (fail_after_createfile) {
6400 close_file(req, new_fsp,NORMAL_CLOSE);
6401 return NT_STATUS_INVALID_LEVEL;
6404 if (vfs_set_filelen(new_fsp, size) == -1) {
6405 status = map_nt_error_from_unix(errno);
6406 close_file(req, new_fsp,NORMAL_CLOSE);
6410 trigger_write_time_update_immediate(new_fsp);
6411 close_file(req, new_fsp,NORMAL_CLOSE);
6412 return NT_STATUS_OK;
6415 /****************************************************************************
6416 Deal with SMB_INFO_SET_EA.
6417 ****************************************************************************/
6419 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6423 const struct smb_filename *smb_fname)
6425 struct ea_list *ea_list = NULL;
6426 TALLOC_CTX *ctx = NULL;
6427 NTSTATUS status = NT_STATUS_OK;
6429 if (total_data < 10) {
6431 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6432 length. They seem to have no effect. Bug #3212. JRA */
6434 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6435 /* We're done. We only get EA info in this call. */
6436 return NT_STATUS_OK;
6439 return NT_STATUS_INVALID_PARAMETER;
6442 if (IVAL(pdata,0) > total_data) {
6443 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6444 IVAL(pdata,0), (unsigned int)total_data));
6445 return NT_STATUS_INVALID_PARAMETER;
6449 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6451 return NT_STATUS_INVALID_PARAMETER;
6454 status = set_ea(conn, fsp, smb_fname, ea_list);
6459 /****************************************************************************
6460 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6461 ****************************************************************************/
6463 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6468 struct ea_list *ea_list = NULL;
6472 return NT_STATUS_INVALID_HANDLE;
6475 if (!lp_ea_support(SNUM(conn))) {
6476 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6477 "EA's not supported.\n",
6478 (unsigned int)total_data));
6479 return NT_STATUS_EAS_NOT_SUPPORTED;
6482 if (total_data < 10) {
6483 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6485 (unsigned int)total_data));
6486 return NT_STATUS_INVALID_PARAMETER;
6489 ea_list = read_nttrans_ea_list(talloc_tos(),
6494 return NT_STATUS_INVALID_PARAMETER;
6497 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6499 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6500 smb_fname_str_dbg(fsp->fsp_name),
6501 nt_errstr(status) ));
6507 /****************************************************************************
6508 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6509 ****************************************************************************/
6511 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6515 struct smb_filename *smb_fname)
6517 NTSTATUS status = NT_STATUS_OK;
6518 bool delete_on_close;
6519 uint32_t dosmode = 0;
6521 if (total_data < 1) {
6522 return NT_STATUS_INVALID_PARAMETER;
6526 return NT_STATUS_INVALID_HANDLE;
6529 delete_on_close = (CVAL(pdata,0) ? True : False);
6530 dosmode = dos_mode(conn, smb_fname);
6532 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6533 "delete_on_close = %u\n",
6534 smb_fname_str_dbg(smb_fname),
6535 (unsigned int)dosmode,
6536 (unsigned int)delete_on_close ));
6538 if (delete_on_close) {
6539 status = can_set_delete_on_close(fsp, dosmode);
6540 if (!NT_STATUS_IS_OK(status)) {
6545 /* The set is across all open files on this dev/inode pair. */
6546 if (!set_delete_on_close(fsp, delete_on_close,
6547 conn->session_info->security_token,
6548 conn->session_info->unix_token)) {
6549 return NT_STATUS_ACCESS_DENIED;
6551 return NT_STATUS_OK;
6554 /****************************************************************************
6555 Deal with SMB_FILE_POSITION_INFORMATION.
6556 ****************************************************************************/
6558 static NTSTATUS smb_file_position_information(connection_struct *conn,
6563 uint64_t position_information;
6565 if (total_data < 8) {
6566 return NT_STATUS_INVALID_PARAMETER;
6570 /* Ignore on pathname based set. */
6571 return NT_STATUS_OK;
6574 position_information = (uint64_t)IVAL(pdata,0);
6575 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6577 DEBUG(10,("smb_file_position_information: Set file position "
6578 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6579 (double)position_information));
6580 fsp->fh->position_information = position_information;
6581 return NT_STATUS_OK;
6584 /****************************************************************************
6585 Deal with SMB_FILE_MODE_INFORMATION.
6586 ****************************************************************************/
6588 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6594 if (total_data < 4) {
6595 return NT_STATUS_INVALID_PARAMETER;
6597 mode = IVAL(pdata,0);
6598 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6599 return NT_STATUS_INVALID_PARAMETER;
6601 return NT_STATUS_OK;
6604 /****************************************************************************
6605 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6606 ****************************************************************************/
6608 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6609 struct smb_request *req,
6612 const struct smb_filename *new_smb_fname)
6614 char *link_target = NULL;
6615 TALLOC_CTX *ctx = talloc_tos();
6617 /* Set a symbolic link. */
6618 /* Don't allow this if follow links is false. */
6620 if (total_data == 0) {
6621 return NT_STATUS_INVALID_PARAMETER;
6624 if (!lp_follow_symlinks(SNUM(conn))) {
6625 return NT_STATUS_ACCESS_DENIED;
6628 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6629 total_data, STR_TERMINATE);
6632 return NT_STATUS_INVALID_PARAMETER;
6635 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6636 new_smb_fname->base_name, link_target ));
6638 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6639 return map_nt_error_from_unix(errno);
6642 return NT_STATUS_OK;
6645 /****************************************************************************
6646 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6647 ****************************************************************************/
6649 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6650 struct smb_request *req,
6651 const char *pdata, int total_data,
6652 struct smb_filename *smb_fname_new)
6654 char *oldname = NULL;
6655 struct smb_filename *smb_fname_old = NULL;
6656 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6657 TALLOC_CTX *ctx = talloc_tos();
6658 NTSTATUS status = NT_STATUS_OK;
6660 /* Set a hard link. */
6661 if (total_data == 0) {
6662 return NT_STATUS_INVALID_PARAMETER;
6665 if (req->posix_pathnames) {
6666 srvstr_get_path_posix(ctx,
6675 srvstr_get_path(ctx,
6684 if (!NT_STATUS_IS_OK(status)) {
6688 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6689 smb_fname_str_dbg(smb_fname_new), oldname));
6691 status = filename_convert(ctx,
6697 if (!NT_STATUS_IS_OK(status)) {
6701 return hardlink_internals(ctx, conn, req, false,
6702 smb_fname_old, smb_fname_new);
6705 /****************************************************************************
6706 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6707 ****************************************************************************/
6709 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6710 struct smb_request *req,
6714 struct smb_filename *smb_fname_src)
6718 char *newname = NULL;
6719 struct smb_filename *smb_fname_dst = NULL;
6720 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6721 ucf_flags_from_smb_request(req);
6722 NTSTATUS status = NT_STATUS_OK;
6723 TALLOC_CTX *ctx = talloc_tos();
6726 return NT_STATUS_INVALID_HANDLE;
6729 if (total_data < 20) {
6730 return NT_STATUS_INVALID_PARAMETER;
6733 overwrite = (CVAL(pdata,0) ? True : False);
6734 len = IVAL(pdata,16);
6736 if (len > (total_data - 20) || (len == 0)) {
6737 return NT_STATUS_INVALID_PARAMETER;
6740 if (req->posix_pathnames) {
6741 srvstr_get_path_posix(ctx,
6750 srvstr_get_path(ctx,
6759 if (!NT_STATUS_IS_OK(status)) {
6763 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6766 status = filename_convert(ctx,
6772 if (!NT_STATUS_IS_OK(status)) {
6776 if (fsp->base_fsp) {
6777 /* newname must be a stream name. */
6778 if (newname[0] != ':') {
6779 return NT_STATUS_NOT_SUPPORTED;
6782 /* Create an smb_fname to call rename_internals_fsp() with. */
6783 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6784 fsp->base_fsp->fsp_name->base_name,
6787 fsp->base_fsp->fsp_name->flags);
6788 if (smb_fname_dst == NULL) {
6789 status = NT_STATUS_NO_MEMORY;
6794 * Set the original last component, since
6795 * rename_internals_fsp() requires it.
6797 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6799 if (smb_fname_dst->original_lcomp == NULL) {
6800 status = NT_STATUS_NO_MEMORY;
6806 DEBUG(10,("smb2_file_rename_information: "
6807 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6808 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6809 smb_fname_str_dbg(smb_fname_dst)));
6810 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6811 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6815 TALLOC_FREE(smb_fname_dst);
6819 static NTSTATUS smb_file_link_information(connection_struct *conn,
6820 struct smb_request *req,
6824 struct smb_filename *smb_fname_src)
6828 char *newname = NULL;
6829 struct smb_filename *smb_fname_dst = NULL;
6830 NTSTATUS status = NT_STATUS_OK;
6831 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6832 ucf_flags_from_smb_request(req);
6833 TALLOC_CTX *ctx = talloc_tos();
6836 return NT_STATUS_INVALID_HANDLE;
6839 if (total_data < 20) {
6840 return NT_STATUS_INVALID_PARAMETER;
6843 overwrite = (CVAL(pdata,0) ? true : false);
6844 len = IVAL(pdata,16);
6846 if (len > (total_data - 20) || (len == 0)) {
6847 return NT_STATUS_INVALID_PARAMETER;
6850 if (req->posix_pathnames) {
6851 srvstr_get_path_posix(ctx,
6860 srvstr_get_path(ctx,
6869 if (!NT_STATUS_IS_OK(status)) {
6873 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6876 status = filename_convert(ctx,
6882 if (!NT_STATUS_IS_OK(status)) {
6886 if (fsp->base_fsp) {
6887 /* No stream names. */
6888 return NT_STATUS_NOT_SUPPORTED;
6891 DEBUG(10,("smb_file_link_information: "
6892 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6893 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6894 smb_fname_str_dbg(smb_fname_dst)));
6895 status = hardlink_internals(ctx,
6902 TALLOC_FREE(smb_fname_dst);
6906 /****************************************************************************
6907 Deal with SMB_FILE_RENAME_INFORMATION.
6908 ****************************************************************************/
6910 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6911 struct smb_request *req,
6915 struct smb_filename *smb_fname_src)
6920 char *newname = NULL;
6921 struct smb_filename *smb_fname_dst = NULL;
6922 bool dest_has_wcard = False;
6923 NTSTATUS status = NT_STATUS_OK;
6925 TALLOC_CTX *ctx = talloc_tos();
6927 if (total_data < 13) {
6928 return NT_STATUS_INVALID_PARAMETER;
6931 overwrite = (CVAL(pdata,0) ? True : False);
6932 root_fid = IVAL(pdata,4);
6933 len = IVAL(pdata,8);
6935 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6936 return NT_STATUS_INVALID_PARAMETER;
6939 if (req->posix_pathnames) {
6940 srvstr_get_path_wcard_posix(ctx,
6950 srvstr_get_path_wcard(ctx,
6960 if (!NT_STATUS_IS_OK(status)) {
6964 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6967 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
6968 status = resolve_dfspath_wcard(ctx, conn,
6970 UCF_COND_ALLOW_WCARD_LCOMP,
6971 !conn->sconn->using_smb2,
6974 if (!NT_STATUS_IS_OK(status)) {
6979 /* Check the new name has no '/' characters. */
6980 if (strchr_m(newname, '/')) {
6981 return NT_STATUS_NOT_SUPPORTED;
6984 if (fsp && fsp->base_fsp) {
6985 /* newname must be a stream name. */
6986 if (newname[0] != ':') {
6987 return NT_STATUS_NOT_SUPPORTED;
6990 /* Create an smb_fname to call rename_internals_fsp() with. */
6991 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6992 fsp->base_fsp->fsp_name->base_name,
6995 fsp->base_fsp->fsp_name->flags);
6996 if (smb_fname_dst == NULL) {
6997 status = NT_STATUS_NO_MEMORY;
7002 * Set the original last component, since
7003 * rename_internals_fsp() requires it.
7005 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7007 if (smb_fname_dst->original_lcomp == NULL) {
7008 status = NT_STATUS_NO_MEMORY;
7014 * Build up an smb_fname_dst based on the filename passed in.
7015 * We basically just strip off the last component, and put on
7016 * the newname instead.
7018 char *base_name = NULL;
7019 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7020 ucf_flags_from_smb_request(req);
7022 if (dest_has_wcard) {
7023 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7026 /* newname must *not* be a stream name. */
7027 if (newname[0] == ':') {
7028 return NT_STATUS_NOT_SUPPORTED;
7032 * Strip off the last component (filename) of the path passed
7035 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7037 return NT_STATUS_NO_MEMORY;
7039 p = strrchr_m(base_name, '/');
7043 base_name = talloc_strdup(ctx, "");
7045 return NT_STATUS_NO_MEMORY;
7048 /* Append the new name. */
7049 base_name = talloc_asprintf_append(base_name,
7053 return NT_STATUS_NO_MEMORY;
7056 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7059 /* If an error we expect this to be
7060 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7062 if (!NT_STATUS_IS_OK(status)) {
7063 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7067 /* Create an smb_fname to call rename_internals_fsp() */
7068 smb_fname_dst = synthetic_smb_fname(ctx,
7072 smb_fname_src->flags);
7073 if (smb_fname_dst == NULL) {
7074 status = NT_STATUS_NO_MEMORY;
7081 DEBUG(10,("smb_file_rename_information: "
7082 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7083 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7084 smb_fname_str_dbg(smb_fname_dst)));
7085 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7088 DEBUG(10,("smb_file_rename_information: "
7089 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7090 smb_fname_str_dbg(smb_fname_src),
7091 smb_fname_str_dbg(smb_fname_dst)));
7092 status = rename_internals(ctx, conn, req, smb_fname_src,
7093 smb_fname_dst, 0, overwrite, false,
7095 FILE_WRITE_ATTRIBUTES);
7098 TALLOC_FREE(smb_fname_dst);
7102 /****************************************************************************
7103 Deal with SMB_SET_POSIX_ACL.
7104 ****************************************************************************/
7106 #if defined(HAVE_POSIX_ACLS)
7107 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7111 const struct smb_filename *smb_fname)
7113 uint16_t posix_acl_version;
7114 uint16_t num_file_acls;
7115 uint16_t num_def_acls;
7116 bool valid_file_acls = True;
7117 bool valid_def_acls = True;
7120 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7121 return NT_STATUS_INVALID_PARAMETER;
7123 posix_acl_version = SVAL(pdata,0);
7124 num_file_acls = SVAL(pdata,2);
7125 num_def_acls = SVAL(pdata,4);
7127 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7128 valid_file_acls = False;
7132 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7133 valid_def_acls = False;
7137 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7138 return NT_STATUS_INVALID_PARAMETER;
7141 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7142 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7143 return NT_STATUS_INVALID_PARAMETER;
7146 status = refuse_symlink(conn, fsp, smb_fname);
7147 if (!NT_STATUS_IS_OK(status)) {
7151 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7152 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7153 (unsigned int)num_file_acls,
7154 (unsigned int)num_def_acls));
7156 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7157 smb_fname, num_file_acls,
7158 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7159 return map_nt_error_from_unix(errno);
7162 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7163 smb_fname, num_def_acls,
7164 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7165 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7166 return map_nt_error_from_unix(errno);
7168 return NT_STATUS_OK;
7172 /****************************************************************************
7173 Deal with SMB_SET_POSIX_LOCK.
7174 ****************************************************************************/
7176 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7177 struct smb_request *req,
7185 bool blocking_lock = False;
7186 enum brl_type lock_type;
7188 NTSTATUS status = NT_STATUS_OK;
7190 if (fsp == NULL || fsp->fh->fd == -1) {
7191 return NT_STATUS_INVALID_HANDLE;
7194 if (total_data != POSIX_LOCK_DATA_SIZE) {
7195 return NT_STATUS_INVALID_PARAMETER;
7198 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7199 case POSIX_LOCK_TYPE_READ:
7200 lock_type = READ_LOCK;
7202 case POSIX_LOCK_TYPE_WRITE:
7203 /* Return the right POSIX-mappable error code for files opened read-only. */
7204 if (!fsp->can_write) {
7205 return NT_STATUS_INVALID_HANDLE;
7207 lock_type = WRITE_LOCK;
7209 case POSIX_LOCK_TYPE_UNLOCK:
7210 lock_type = UNLOCK_LOCK;
7213 return NT_STATUS_INVALID_PARAMETER;
7216 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7217 blocking_lock = False;
7218 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7219 blocking_lock = True;
7221 return NT_STATUS_INVALID_PARAMETER;
7224 if (!lp_blocking_locks(SNUM(conn))) {
7225 blocking_lock = False;
7228 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7229 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7230 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7231 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7232 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7234 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7235 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7237 (unsigned int)lock_type,
7238 (unsigned long long)smblctx,
7242 if (lock_type == UNLOCK_LOCK) {
7243 status = do_unlock(req->sconn->msg_ctx,
7250 uint64_t block_smblctx;
7252 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7263 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7265 * A blocking lock was requested. Package up
7266 * this smb into a queued request and push it
7267 * onto the blocking lock queue.
7269 if(push_blocking_lock_request(br_lck,
7272 -1, /* infinite timeout. */
7280 TALLOC_FREE(br_lck);
7284 TALLOC_FREE(br_lck);
7290 /****************************************************************************
7291 Deal with SMB_SET_FILE_BASIC_INFO.
7292 ****************************************************************************/
7294 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7298 const struct smb_filename *smb_fname)
7300 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7301 struct smb_file_time ft;
7302 uint32_t dosmode = 0;
7303 NTSTATUS status = NT_STATUS_OK;
7307 if (total_data < 36) {
7308 return NT_STATUS_INVALID_PARAMETER;
7311 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7312 if (!NT_STATUS_IS_OK(status)) {
7316 /* Set the attributes */
7317 dosmode = IVAL(pdata,32);
7318 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7319 if (!NT_STATUS_IS_OK(status)) {
7324 ft.create_time = interpret_long_date(pdata);
7327 ft.atime = interpret_long_date(pdata+8);
7330 ft.mtime = interpret_long_date(pdata+16);
7333 ft.ctime = interpret_long_date(pdata+24);
7335 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7336 smb_fname_str_dbg(smb_fname)));
7338 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7342 /****************************************************************************
7343 Deal with SMB_INFO_STANDARD.
7344 ****************************************************************************/
7346 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7350 const struct smb_filename *smb_fname)
7353 struct smb_file_time ft;
7357 if (total_data < 12) {
7358 return NT_STATUS_INVALID_PARAMETER;
7362 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7364 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7366 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7368 DEBUG(10,("smb_set_info_standard: file %s\n",
7369 smb_fname_str_dbg(smb_fname)));
7371 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7372 if (!NT_STATUS_IS_OK(status)) {
7376 return smb_set_file_time(conn,
7383 /****************************************************************************
7384 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7385 ****************************************************************************/
7387 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7388 struct smb_request *req,
7392 struct smb_filename *smb_fname)
7394 uint64_t allocation_size = 0;
7395 NTSTATUS status = NT_STATUS_OK;
7396 files_struct *new_fsp = NULL;
7398 if (!VALID_STAT(smb_fname->st)) {
7399 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7402 if (total_data < 8) {
7403 return NT_STATUS_INVALID_PARAMETER;
7406 allocation_size = (uint64_t)IVAL(pdata,0);
7407 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7408 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7409 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7410 (double)allocation_size));
7412 if (allocation_size) {
7413 allocation_size = smb_roundup(conn, allocation_size);
7416 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7417 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7418 (double)allocation_size));
7420 if (fsp && fsp->fh->fd != -1) {
7421 /* Open file handle. */
7422 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7423 return NT_STATUS_ACCESS_DENIED;
7426 /* Only change if needed. */
7427 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7428 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7429 return map_nt_error_from_unix(errno);
7432 /* But always update the time. */
7434 * This is equivalent to a write. Ensure it's seen immediately
7435 * if there are no pending writes.
7437 trigger_write_time_update_immediate(fsp);
7438 return NT_STATUS_OK;
7441 /* Pathname or stat or directory file. */
7442 status = SMB_VFS_CREATE_FILE(
7445 0, /* root_dir_fid */
7446 smb_fname, /* fname */
7447 FILE_WRITE_DATA, /* access_mask */
7448 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7450 FILE_OPEN, /* create_disposition*/
7451 0, /* create_options */
7452 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7453 0, /* oplock_request */
7455 0, /* allocation_size */
7456 0, /* private_flags */
7459 &new_fsp, /* result */
7461 NULL, NULL); /* create context */
7463 if (!NT_STATUS_IS_OK(status)) {
7464 /* NB. We check for open_was_deferred in the caller. */
7468 /* Only change if needed. */
7469 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7470 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7471 status = map_nt_error_from_unix(errno);
7472 close_file(req, new_fsp, NORMAL_CLOSE);
7477 /* Changing the allocation size should set the last mod time. */
7479 * This is equivalent to a write. Ensure it's seen immediately
7480 * if there are no pending writes.
7482 trigger_write_time_update_immediate(new_fsp);
7483 close_file(req, new_fsp, NORMAL_CLOSE);
7484 return NT_STATUS_OK;
7487 /****************************************************************************
7488 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7489 ****************************************************************************/
7491 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7492 struct smb_request *req,
7496 const struct smb_filename *smb_fname,
7497 bool fail_after_createfile)
7501 if (total_data < 8) {
7502 return NT_STATUS_INVALID_PARAMETER;
7505 size = IVAL(pdata,0);
7506 size |= (((off_t)IVAL(pdata,4)) << 32);
7507 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7508 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7511 return smb_set_file_size(conn, req,
7516 fail_after_createfile);
7519 /****************************************************************************
7520 Allow a UNIX info mknod.
7521 ****************************************************************************/
7523 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7526 const struct smb_filename *smb_fname)
7528 uint32_t file_type = IVAL(pdata,56);
7529 #if defined(HAVE_MAKEDEV)
7530 uint32_t dev_major = IVAL(pdata,60);
7531 uint32_t dev_minor = IVAL(pdata,68);
7533 SMB_DEV_T dev = (SMB_DEV_T)0;
7534 uint32_t raw_unixmode = IVAL(pdata,84);
7538 if (total_data < 100) {
7539 return NT_STATUS_INVALID_PARAMETER;
7542 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7543 PERM_NEW_FILE, &unixmode);
7544 if (!NT_STATUS_IS_OK(status)) {
7548 #if defined(HAVE_MAKEDEV)
7549 dev = makedev(dev_major, dev_minor);
7552 switch (file_type) {
7553 #if defined(S_IFIFO)
7554 case UNIX_TYPE_FIFO:
7555 unixmode |= S_IFIFO;
7558 #if defined(S_IFSOCK)
7559 case UNIX_TYPE_SOCKET:
7560 unixmode |= S_IFSOCK;
7563 #if defined(S_IFCHR)
7564 case UNIX_TYPE_CHARDEV:
7565 unixmode |= S_IFCHR;
7568 #if defined(S_IFBLK)
7569 case UNIX_TYPE_BLKDEV:
7570 unixmode |= S_IFBLK;
7574 return NT_STATUS_INVALID_PARAMETER;
7577 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7578 "%.0f mode 0%o for file %s\n", (double)dev,
7579 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7581 /* Ok - do the mknod. */
7582 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7583 return map_nt_error_from_unix(errno);
7586 /* If any of the other "set" calls fail we
7587 * don't want to end up with a half-constructed mknod.
7590 if (lp_inherit_permissions(SNUM(conn))) {
7592 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7594 return NT_STATUS_NO_MEMORY;
7596 inherit_access_posix_acl(conn, parent, smb_fname,
7598 TALLOC_FREE(parent);
7601 return NT_STATUS_OK;
7604 /****************************************************************************
7605 Deal with SMB_SET_FILE_UNIX_BASIC.
7606 ****************************************************************************/
7608 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7609 struct smb_request *req,
7613 const struct smb_filename *smb_fname)
7615 struct smb_file_time ft;
7616 uint32_t raw_unixmode;
7619 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7620 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7621 NTSTATUS status = NT_STATUS_OK;
7622 bool delete_on_fail = False;
7623 enum perm_type ptype;
7624 files_struct *all_fsps = NULL;
7625 bool modify_mtime = true;
7627 struct smb_filename *smb_fname_tmp = NULL;
7628 SMB_STRUCT_STAT sbuf;
7632 if (total_data < 100) {
7633 return NT_STATUS_INVALID_PARAMETER;
7636 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7637 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7638 size=IVAL(pdata,0); /* first 8 Bytes are size */
7639 size |= (((off_t)IVAL(pdata,4)) << 32);
7642 ft.atime = interpret_long_date(pdata+24); /* access_time */
7643 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7644 set_owner = (uid_t)IVAL(pdata,40);
7645 set_grp = (gid_t)IVAL(pdata,48);
7646 raw_unixmode = IVAL(pdata,84);
7648 if (VALID_STAT(smb_fname->st)) {
7649 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7650 ptype = PERM_EXISTING_DIR;
7652 ptype = PERM_EXISTING_FILE;
7655 ptype = PERM_NEW_FILE;
7658 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7660 if (!NT_STATUS_IS_OK(status)) {
7664 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7665 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7666 smb_fname_str_dbg(smb_fname), (double)size,
7667 (unsigned int)set_owner, (unsigned int)set_grp,
7668 (int)raw_unixmode));
7670 sbuf = smb_fname->st;
7672 if (!VALID_STAT(sbuf)) {
7674 * The only valid use of this is to create character and block
7675 * devices, and named pipes. This is deprecated (IMHO) and
7676 * a new info level should be used for mknod. JRA.
7679 status = smb_unix_mknod(conn,
7683 if (!NT_STATUS_IS_OK(status)) {
7687 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7688 if (smb_fname_tmp == NULL) {
7689 return NT_STATUS_NO_MEMORY;
7692 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7693 status = map_nt_error_from_unix(errno);
7694 TALLOC_FREE(smb_fname_tmp);
7695 SMB_VFS_UNLINK(conn, smb_fname);
7699 sbuf = smb_fname_tmp->st;
7700 smb_fname = smb_fname_tmp;
7702 /* Ensure we don't try and change anything else. */
7703 raw_unixmode = SMB_MODE_NO_CHANGE;
7704 size = get_file_size_stat(&sbuf);
7705 ft.atime = sbuf.st_ex_atime;
7706 ft.mtime = sbuf.st_ex_mtime;
7708 * We continue here as we might want to change the
7711 delete_on_fail = True;
7715 /* Horrible backwards compatibility hack as an old server bug
7716 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7720 size = get_file_size_stat(&sbuf);
7725 * Deal with the UNIX specific mode set.
7728 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7731 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7732 "setting mode 0%o for file %s\n",
7733 (unsigned int)unixmode,
7734 smb_fname_str_dbg(smb_fname)));
7735 if (fsp && fsp->fh->fd != -1) {
7736 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7738 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7741 return map_nt_error_from_unix(errno);
7746 * Deal with the UNIX specific uid set.
7749 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7750 (sbuf.st_ex_uid != set_owner)) {
7753 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7754 "changing owner %u for path %s\n",
7755 (unsigned int)set_owner,
7756 smb_fname_str_dbg(smb_fname)));
7758 if (fsp && fsp->fh->fd != -1) {
7759 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7762 * UNIX extensions calls must always operate
7765 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7766 set_owner, (gid_t)-1);
7770 status = map_nt_error_from_unix(errno);
7771 if (delete_on_fail) {
7772 SMB_VFS_UNLINK(conn, smb_fname);
7779 * Deal with the UNIX specific gid set.
7782 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7783 (sbuf.st_ex_gid != set_grp)) {
7786 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7787 "changing group %u for file %s\n",
7788 (unsigned int)set_grp,
7789 smb_fname_str_dbg(smb_fname)));
7790 if (fsp && fsp->fh->fd != -1) {
7791 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
7794 * UNIX extensions calls must always operate
7797 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7801 status = map_nt_error_from_unix(errno);
7802 if (delete_on_fail) {
7803 SMB_VFS_UNLINK(conn, smb_fname);
7809 /* Deal with any size changes. */
7811 status = smb_set_file_size(conn, req,
7817 if (!NT_STATUS_IS_OK(status)) {
7821 /* Deal with any time changes. */
7822 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7823 /* No change, don't cancel anything. */
7827 id = vfs_file_id_from_sbuf(conn, &sbuf);
7828 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7829 all_fsps = file_find_di_next(all_fsps)) {
7831 * We're setting the time explicitly for UNIX.
7832 * Cancel any pending changes over all handles.
7834 all_fsps->update_write_time_on_close = false;
7835 TALLOC_FREE(all_fsps->update_write_time_event);
7839 * Override the "setting_write_time"
7840 * parameter here as it almost does what
7841 * we need. Just remember if we modified
7842 * mtime and send the notify ourselves.
7844 if (null_timespec(ft.mtime)) {
7845 modify_mtime = false;
7848 status = smb_set_file_time(conn,
7854 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7855 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7860 /****************************************************************************
7861 Deal with SMB_SET_FILE_UNIX_INFO2.
7862 ****************************************************************************/
7864 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7865 struct smb_request *req,
7869 const struct smb_filename *smb_fname)
7872 uint32_t smb_fflags;
7875 if (total_data < 116) {
7876 return NT_STATUS_INVALID_PARAMETER;
7879 /* Start by setting all the fields that are common between UNIX_BASIC
7882 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7884 if (!NT_STATUS_IS_OK(status)) {
7888 smb_fflags = IVAL(pdata, 108);
7889 smb_fmask = IVAL(pdata, 112);
7891 /* NB: We should only attempt to alter the file flags if the client
7892 * sends a non-zero mask.
7894 if (smb_fmask != 0) {
7895 int stat_fflags = 0;
7897 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7898 smb_fmask, &stat_fflags)) {
7899 /* Client asked to alter a flag we don't understand. */
7900 return NT_STATUS_INVALID_PARAMETER;
7903 if (fsp && fsp->fh->fd != -1) {
7904 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7905 return NT_STATUS_NOT_SUPPORTED;
7907 if (SMB_VFS_CHFLAGS(conn, smb_fname,
7908 stat_fflags) != 0) {
7909 return map_nt_error_from_unix(errno);
7914 /* XXX: need to add support for changing the create_time here. You
7915 * can do this for paths on Darwin with setattrlist(2). The right way
7916 * to hook this up is probably by extending the VFS utimes interface.
7919 return NT_STATUS_OK;
7922 /****************************************************************************
7923 Create a directory with POSIX semantics.
7924 ****************************************************************************/
7926 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7927 struct smb_request *req,
7930 struct smb_filename *smb_fname,
7931 int *pdata_return_size)
7933 NTSTATUS status = NT_STATUS_OK;
7934 uint32_t raw_unixmode = 0;
7935 uint32_t mod_unixmode = 0;
7936 mode_t unixmode = (mode_t)0;
7937 files_struct *fsp = NULL;
7938 uint16_t info_level_return = 0;
7940 char *pdata = *ppdata;
7942 if (total_data < 18) {
7943 return NT_STATUS_INVALID_PARAMETER;
7946 raw_unixmode = IVAL(pdata,8);
7947 /* Next 4 bytes are not yet defined. */
7949 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7950 PERM_NEW_DIR, &unixmode);
7951 if (!NT_STATUS_IS_OK(status)) {
7955 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7957 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7958 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7960 status = SMB_VFS_CREATE_FILE(
7963 0, /* root_dir_fid */
7964 smb_fname, /* fname */
7965 FILE_READ_ATTRIBUTES, /* access_mask */
7966 FILE_SHARE_NONE, /* share_access */
7967 FILE_CREATE, /* create_disposition*/
7968 FILE_DIRECTORY_FILE, /* create_options */
7969 mod_unixmode, /* file_attributes */
7970 0, /* oplock_request */
7972 0, /* allocation_size */
7973 0, /* private_flags */
7978 NULL, NULL); /* create context */
7980 if (NT_STATUS_IS_OK(status)) {
7981 close_file(req, fsp, NORMAL_CLOSE);
7984 info_level_return = SVAL(pdata,16);
7986 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7987 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7988 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7989 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7991 *pdata_return_size = 12;
7994 /* Realloc the data size */
7995 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7996 if (*ppdata == NULL) {
7997 *pdata_return_size = 0;
7998 return NT_STATUS_NO_MEMORY;
8002 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8003 SSVAL(pdata,2,0); /* No fnum. */
8004 SIVAL(pdata,4,info); /* Was directory created. */
8006 switch (info_level_return) {
8007 case SMB_QUERY_FILE_UNIX_BASIC:
8008 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8009 SSVAL(pdata,10,0); /* Padding. */
8010 store_file_unix_basic(conn, pdata + 12, fsp,
8013 case SMB_QUERY_FILE_UNIX_INFO2:
8014 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8015 SSVAL(pdata,10,0); /* Padding. */
8016 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8020 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8021 SSVAL(pdata,10,0); /* Padding. */
8028 /****************************************************************************
8029 Open/Create a file with POSIX semantics.
8030 ****************************************************************************/
8032 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8033 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8035 static NTSTATUS smb_posix_open(connection_struct *conn,
8036 struct smb_request *req,
8039 struct smb_filename *smb_fname,
8040 int *pdata_return_size)
8042 bool extended_oplock_granted = False;
8043 char *pdata = *ppdata;
8045 uint32_t wire_open_mode = 0;
8046 uint32_t raw_unixmode = 0;
8047 uint32_t mod_unixmode = 0;
8048 uint32_t create_disp = 0;
8049 uint32_t access_mask = 0;
8050 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8051 NTSTATUS status = NT_STATUS_OK;
8052 mode_t unixmode = (mode_t)0;
8053 files_struct *fsp = NULL;
8054 int oplock_request = 0;
8056 uint16_t info_level_return = 0;
8058 if (total_data < 18) {
8059 return NT_STATUS_INVALID_PARAMETER;
8062 flags = IVAL(pdata,0);
8063 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8064 if (oplock_request) {
8065 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8068 wire_open_mode = IVAL(pdata,4);
8070 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8071 return smb_posix_mkdir(conn, req,
8078 switch (wire_open_mode & SMB_ACCMODE) {
8080 access_mask = SMB_O_RDONLY_MAPPING;
8083 access_mask = SMB_O_WRONLY_MAPPING;
8086 access_mask = (SMB_O_RDONLY_MAPPING|
8087 SMB_O_WRONLY_MAPPING);
8090 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8091 (unsigned int)wire_open_mode ));
8092 return NT_STATUS_INVALID_PARAMETER;
8095 wire_open_mode &= ~SMB_ACCMODE;
8097 /* First take care of O_CREAT|O_EXCL interactions. */
8098 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8099 case (SMB_O_CREAT | SMB_O_EXCL):
8100 /* File exists fail. File not exist create. */
8101 create_disp = FILE_CREATE;
8104 /* File exists open. File not exist create. */
8105 create_disp = FILE_OPEN_IF;
8108 /* O_EXCL on its own without O_CREAT is undefined.
8109 We deliberately ignore it as some versions of
8110 Linux CIFSFS can send a bare O_EXCL on the
8111 wire which other filesystems in the kernel
8112 ignore. See bug 9519 for details. */
8117 /* File exists open. File not exist fail. */
8118 create_disp = FILE_OPEN;
8121 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8122 (unsigned int)wire_open_mode ));
8123 return NT_STATUS_INVALID_PARAMETER;
8126 /* Next factor in the effects of O_TRUNC. */
8127 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8129 if (wire_open_mode & SMB_O_TRUNC) {
8130 switch (create_disp) {
8132 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8133 /* Leave create_disp alone as
8134 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8136 /* File exists fail. File not exist create. */
8139 /* SMB_O_CREAT | SMB_O_TRUNC */
8140 /* File exists overwrite. File not exist create. */
8141 create_disp = FILE_OVERWRITE_IF;
8145 /* File exists overwrite. File not exist fail. */
8146 create_disp = FILE_OVERWRITE;
8149 /* Cannot get here. */
8150 smb_panic("smb_posix_open: logic error");
8151 return NT_STATUS_INVALID_PARAMETER;
8155 raw_unixmode = IVAL(pdata,8);
8156 /* Next 4 bytes are not yet defined. */
8158 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8159 (VALID_STAT(smb_fname->st) ?
8160 PERM_EXISTING_FILE : PERM_NEW_FILE),
8163 if (!NT_STATUS_IS_OK(status)) {
8167 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8169 if (wire_open_mode & SMB_O_SYNC) {
8170 create_options |= FILE_WRITE_THROUGH;
8172 if (wire_open_mode & SMB_O_APPEND) {
8173 access_mask |= FILE_APPEND_DATA;
8175 if (wire_open_mode & SMB_O_DIRECT) {
8176 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8179 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8180 VALID_STAT_OF_DIR(smb_fname->st)) {
8181 if (access_mask != SMB_O_RDONLY_MAPPING) {
8182 return NT_STATUS_FILE_IS_A_DIRECTORY;
8184 create_options &= ~FILE_NON_DIRECTORY_FILE;
8185 create_options |= FILE_DIRECTORY_FILE;
8188 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8189 smb_fname_str_dbg(smb_fname),
8190 (unsigned int)wire_open_mode,
8191 (unsigned int)unixmode ));
8193 status = SMB_VFS_CREATE_FILE(
8196 0, /* root_dir_fid */
8197 smb_fname, /* fname */
8198 access_mask, /* access_mask */
8199 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8201 create_disp, /* create_disposition*/
8202 create_options, /* create_options */
8203 mod_unixmode, /* file_attributes */
8204 oplock_request, /* oplock_request */
8206 0, /* allocation_size */
8207 0, /* private_flags */
8212 NULL, NULL); /* create context */
8214 if (!NT_STATUS_IS_OK(status)) {
8218 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8219 extended_oplock_granted = True;
8222 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8223 extended_oplock_granted = True;
8226 info_level_return = SVAL(pdata,16);
8228 /* Allocate the correct return size. */
8230 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8231 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8232 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8233 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8235 *pdata_return_size = 12;
8238 /* Realloc the data size */
8239 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8240 if (*ppdata == NULL) {
8241 close_file(req, fsp, ERROR_CLOSE);
8242 *pdata_return_size = 0;
8243 return NT_STATUS_NO_MEMORY;
8247 if (extended_oplock_granted) {
8248 if (flags & REQUEST_BATCH_OPLOCK) {
8249 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8251 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8253 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8254 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8256 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8259 SSVAL(pdata,2,fsp->fnum);
8260 SIVAL(pdata,4,info); /* Was file created etc. */
8262 switch (info_level_return) {
8263 case SMB_QUERY_FILE_UNIX_BASIC:
8264 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8265 SSVAL(pdata,10,0); /* padding. */
8266 store_file_unix_basic(conn, pdata + 12, fsp,
8269 case SMB_QUERY_FILE_UNIX_INFO2:
8270 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8271 SSVAL(pdata,10,0); /* padding. */
8272 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8276 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8277 SSVAL(pdata,10,0); /* padding. */
8280 return NT_STATUS_OK;
8283 /****************************************************************************
8284 Delete a file with POSIX semantics.
8285 ****************************************************************************/
8287 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8288 struct smb_request *req,
8291 struct smb_filename *smb_fname)
8293 NTSTATUS status = NT_STATUS_OK;
8294 files_struct *fsp = NULL;
8298 int create_options = 0;
8300 struct share_mode_lock *lck = NULL;
8302 if (total_data < 2) {
8303 return NT_STATUS_INVALID_PARAMETER;
8306 flags = SVAL(pdata,0);
8308 if (!VALID_STAT(smb_fname->st)) {
8309 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8312 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8313 !VALID_STAT_OF_DIR(smb_fname->st)) {
8314 return NT_STATUS_NOT_A_DIRECTORY;
8317 DEBUG(10,("smb_posix_unlink: %s %s\n",
8318 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8319 smb_fname_str_dbg(smb_fname)));
8321 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8322 create_options |= FILE_DIRECTORY_FILE;
8325 status = SMB_VFS_CREATE_FILE(
8328 0, /* root_dir_fid */
8329 smb_fname, /* fname */
8330 DELETE_ACCESS, /* access_mask */
8331 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8333 FILE_OPEN, /* create_disposition*/
8334 create_options, /* create_options */
8335 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8336 0, /* oplock_request */
8338 0, /* allocation_size */
8339 0, /* private_flags */
8344 NULL, NULL); /* create context */
8346 if (!NT_STATUS_IS_OK(status)) {
8351 * Don't lie to client. If we can't really delete due to
8352 * non-POSIX opens return SHARING_VIOLATION.
8355 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8357 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8358 "lock for file %s\n", fsp_str_dbg(fsp)));
8359 close_file(req, fsp, NORMAL_CLOSE);
8360 return NT_STATUS_INVALID_PARAMETER;
8364 * See if others still have the file open. If this is the case, then
8365 * don't delete. If all opens are POSIX delete we can set the delete
8366 * on close disposition.
8368 for (i=0; i<lck->data->num_share_modes; i++) {
8369 struct share_mode_entry *e = &lck->data->share_modes[i];
8370 if (is_valid_share_mode_entry(e)) {
8371 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8374 if (share_mode_stale_pid(lck->data, i)) {
8377 /* Fail with sharing violation. */
8379 close_file(req, fsp, NORMAL_CLOSE);
8380 return NT_STATUS_SHARING_VIOLATION;
8385 * Set the delete on close.
8387 status = smb_set_file_disposition_info(conn,
8395 if (!NT_STATUS_IS_OK(status)) {
8396 close_file(req, fsp, NORMAL_CLOSE);
8399 return close_file(req, fsp, NORMAL_CLOSE);
8402 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8403 struct smb_request *req,
8404 TALLOC_CTX *mem_ctx,
8405 uint16_t info_level,
8407 struct smb_filename *smb_fname,
8408 char **ppdata, int total_data,
8411 char *pdata = *ppdata;
8412 NTSTATUS status = NT_STATUS_OK;
8413 int data_return_size = 0;
8417 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8418 return NT_STATUS_INVALID_LEVEL;
8421 if (!CAN_WRITE(conn)) {
8422 /* Allow POSIX opens. The open path will deny
8423 * any non-readonly opens. */
8424 if (info_level != SMB_POSIX_PATH_OPEN) {
8425 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8429 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8430 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8432 info_level, total_data));
8434 switch (info_level) {
8436 case SMB_INFO_STANDARD:
8438 status = smb_set_info_standard(conn,
8446 case SMB_INFO_SET_EA:
8448 status = smb_info_set_ea(conn,
8456 case SMB_SET_FILE_BASIC_INFO:
8457 case SMB_FILE_BASIC_INFORMATION:
8459 status = smb_set_file_basic_info(conn,
8467 case SMB_FILE_ALLOCATION_INFORMATION:
8468 case SMB_SET_FILE_ALLOCATION_INFO:
8470 status = smb_set_file_allocation_info(conn, req,
8478 case SMB_FILE_END_OF_FILE_INFORMATION:
8479 case SMB_SET_FILE_END_OF_FILE_INFO:
8482 * XP/Win7 both fail after the createfile with
8483 * SMB_SET_FILE_END_OF_FILE_INFO but not
8484 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8485 * The level is known here, so pass it down
8489 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8491 status = smb_set_file_end_of_file_info(conn, req,
8500 case SMB_FILE_DISPOSITION_INFORMATION:
8501 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8504 /* JRA - We used to just ignore this on a path ?
8505 * Shouldn't this be invalid level on a pathname
8508 if (tran_call != TRANSACT2_SETFILEINFO) {
8509 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8512 status = smb_set_file_disposition_info(conn,
8520 case SMB_FILE_POSITION_INFORMATION:
8522 status = smb_file_position_information(conn,
8529 case SMB_FILE_FULL_EA_INFORMATION:
8531 status = smb_set_file_full_ea_info(conn,
8538 /* From tridge Samba4 :
8539 * MODE_INFORMATION in setfileinfo (I have no
8540 * idea what "mode information" on a file is - it takes a value of 0,
8541 * 2, 4 or 6. What could it be?).
8544 case SMB_FILE_MODE_INFORMATION:
8546 status = smb_file_mode_information(conn,
8552 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8553 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8554 case SMB_FILE_SHORT_NAME_INFORMATION:
8555 return NT_STATUS_NOT_SUPPORTED;
8558 * CIFS UNIX extensions.
8561 case SMB_SET_FILE_UNIX_BASIC:
8563 status = smb_set_file_unix_basic(conn, req,
8571 case SMB_SET_FILE_UNIX_INFO2:
8573 status = smb_set_file_unix_info2(conn, req,
8581 case SMB_SET_FILE_UNIX_LINK:
8584 /* We must have a pathname for this. */
8585 return NT_STATUS_INVALID_LEVEL;
8587 status = smb_set_file_unix_link(conn, req, pdata,
8588 total_data, smb_fname);
8592 case SMB_SET_FILE_UNIX_HLINK:
8595 /* We must have a pathname for this. */
8596 return NT_STATUS_INVALID_LEVEL;
8598 status = smb_set_file_unix_hlink(conn, req,
8604 case SMB_FILE_RENAME_INFORMATION:
8606 status = smb_file_rename_information(conn, req,
8612 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8614 /* SMB2 rename information. */
8615 status = smb2_file_rename_information(conn, req,
8621 case SMB_FILE_LINK_INFORMATION:
8623 status = smb_file_link_information(conn, req,
8629 #if defined(HAVE_POSIX_ACLS)
8630 case SMB_SET_POSIX_ACL:
8632 status = smb_set_posix_acl(conn,
8641 case SMB_SET_POSIX_LOCK:
8644 return NT_STATUS_INVALID_LEVEL;
8646 status = smb_set_posix_lock(conn, req,
8647 pdata, total_data, fsp);
8651 case SMB_POSIX_PATH_OPEN:
8654 /* We must have a pathname for this. */
8655 return NT_STATUS_INVALID_LEVEL;
8658 status = smb_posix_open(conn, req,
8666 case SMB_POSIX_PATH_UNLINK:
8669 /* We must have a pathname for this. */
8670 return NT_STATUS_INVALID_LEVEL;
8673 status = smb_posix_unlink(conn, req,
8681 return NT_STATUS_INVALID_LEVEL;
8684 if (!NT_STATUS_IS_OK(status)) {
8688 *ret_data_size = data_return_size;
8689 return NT_STATUS_OK;
8692 /****************************************************************************
8693 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8694 ****************************************************************************/
8696 static void call_trans2setfilepathinfo(connection_struct *conn,
8697 struct smb_request *req,
8698 unsigned int tran_call,
8699 char **pparams, int total_params,
8700 char **ppdata, int total_data,
8701 unsigned int max_data_bytes)
8703 char *params = *pparams;
8704 char *pdata = *ppdata;
8705 uint16_t info_level;
8706 struct smb_filename *smb_fname = NULL;
8707 files_struct *fsp = NULL;
8708 NTSTATUS status = NT_STATUS_OK;
8709 int data_return_size = 0;
8712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8716 if (tran_call == TRANSACT2_SETFILEINFO) {
8717 if (total_params < 4) {
8718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8722 fsp = file_fsp(req, SVAL(params,0));
8723 /* Basic check for non-null fsp. */
8724 if (!check_fsp_open(conn, req, fsp)) {
8727 info_level = SVAL(params,2);
8729 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8730 if (smb_fname == NULL) {
8731 reply_nterror(req, NT_STATUS_NO_MEMORY);
8735 if(fsp->fh->fd == -1) {
8737 * This is actually a SETFILEINFO on a directory
8738 * handle (returned from an NT SMB). NT5.0 seems
8739 * to do this call. JRA.
8741 if (INFO_LEVEL_IS_UNIX(info_level)) {
8742 /* Always do lstat for UNIX calls. */
8743 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8744 DEBUG(3,("call_trans2setfilepathinfo: "
8745 "SMB_VFS_LSTAT of %s failed "
8747 smb_fname_str_dbg(smb_fname),
8749 reply_nterror(req, map_nt_error_from_unix(errno));
8753 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8754 DEBUG(3,("call_trans2setfilepathinfo: "
8755 "fileinfo of %s failed (%s)\n",
8756 smb_fname_str_dbg(smb_fname),
8758 reply_nterror(req, map_nt_error_from_unix(errno));
8762 } else if (fsp->print_file) {
8764 * Doing a DELETE_ON_CLOSE should cancel a print job.
8766 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8767 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8769 DEBUG(3,("call_trans2setfilepathinfo: "
8770 "Cancelling print job (%s)\n",
8774 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8780 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8785 * Original code - this is an open file.
8787 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8788 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8789 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8791 reply_nterror(req, map_nt_error_from_unix(errno));
8797 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8800 if (total_params < 7) {
8801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8805 info_level = SVAL(params,0);
8806 if (req->posix_pathnames) {
8807 srvstr_get_path_posix(req,
8816 srvstr_get_path(req,
8825 if (!NT_STATUS_IS_OK(status)) {
8826 reply_nterror(req, status);
8830 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8831 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8832 info_level == SMB_FILE_RENAME_INFORMATION ||
8833 info_level == SMB_POSIX_PATH_UNLINK) {
8834 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8837 status = filename_convert(req, conn,
8842 if (!NT_STATUS_IS_OK(status)) {
8843 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8844 reply_botherror(req,
8845 NT_STATUS_PATH_NOT_COVERED,
8846 ERRSRV, ERRbadpath);
8849 reply_nterror(req, status);
8853 if (INFO_LEVEL_IS_UNIX(info_level)) {
8855 * For CIFS UNIX extensions the target name may not exist.
8858 /* Always do lstat for UNIX calls. */
8859 SMB_VFS_LSTAT(conn, smb_fname);
8861 } else if (!VALID_STAT(smb_fname->st) &&
8862 SMB_VFS_STAT(conn, smb_fname)) {
8863 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8865 smb_fname_str_dbg(smb_fname),
8867 reply_nterror(req, map_nt_error_from_unix(errno));
8872 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8873 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8875 info_level,total_data));
8877 /* Realloc the parameter size */
8878 *pparams = (char *)SMB_REALLOC(*pparams,2);
8879 if (*pparams == NULL) {
8880 reply_nterror(req, NT_STATUS_NO_MEMORY);
8887 status = smbd_do_setfilepathinfo(conn, req, req,
8893 if (!NT_STATUS_IS_OK(status)) {
8894 if (open_was_deferred(req->xconn, req->mid)) {
8895 /* We have re-scheduled this call. */
8898 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8899 /* We have re-scheduled this call. */
8902 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8903 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8904 ERRSRV, ERRbadpath);
8907 if (info_level == SMB_POSIX_PATH_OPEN) {
8908 reply_openerror(req, status);
8913 * Invalid EA name needs to return 2 param bytes,
8914 * not a zero-length error packet.
8916 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8917 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8920 reply_nterror(req, status);
8925 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8931 /****************************************************************************
8932 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8933 ****************************************************************************/
8935 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8936 char **pparams, int total_params,
8937 char **ppdata, int total_data,
8938 unsigned int max_data_bytes)
8940 struct smb_filename *smb_dname = NULL;
8941 char *params = *pparams;
8942 char *pdata = *ppdata;
8943 char *directory = NULL;
8944 NTSTATUS status = NT_STATUS_OK;
8945 struct ea_list *ea_list = NULL;
8946 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8947 TALLOC_CTX *ctx = talloc_tos();
8949 if (!CAN_WRITE(conn)) {
8950 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8954 if (total_params < 5) {
8955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8959 if (req->posix_pathnames) {
8960 srvstr_get_path_posix(ctx,
8969 srvstr_get_path(ctx,
8978 if (!NT_STATUS_IS_OK(status)) {
8979 reply_nterror(req, status);
8983 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8985 status = filename_convert(ctx,
8992 if (!NT_STATUS_IS_OK(status)) {
8993 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8994 reply_botherror(req,
8995 NT_STATUS_PATH_NOT_COVERED,
8996 ERRSRV, ERRbadpath);
8999 reply_nterror(req, status);
9004 * OS/2 workplace shell seems to send SET_EA requests of "null"
9005 * length (4 bytes containing IVAL 4).
9006 * They seem to have no effect. Bug #3212. JRA.
9009 if (total_data && (total_data != 4)) {
9010 /* Any data in this call is an EA list. */
9011 if (total_data < 10) {
9012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9016 if (IVAL(pdata,0) > total_data) {
9017 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9018 IVAL(pdata,0), (unsigned int)total_data));
9019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9023 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9026 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9030 if (!lp_ea_support(SNUM(conn))) {
9031 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9035 /* If total_data == 4 Windows doesn't care what values
9036 * are placed in that field, it just ignores them.
9037 * The System i QNTC IBM SMB client puts bad values here,
9038 * so ignore them. */
9040 status = create_directory(conn, req, smb_dname);
9042 if (!NT_STATUS_IS_OK(status)) {
9043 reply_nterror(req, status);
9047 /* Try and set any given EA. */
9049 status = set_ea(conn, NULL, smb_dname, ea_list);
9050 if (!NT_STATUS_IS_OK(status)) {
9051 reply_nterror(req, status);
9056 /* Realloc the parameter and data sizes */
9057 *pparams = (char *)SMB_REALLOC(*pparams,2);
9058 if(*pparams == NULL) {
9059 reply_nterror(req, NT_STATUS_NO_MEMORY);
9066 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9069 TALLOC_FREE(smb_dname);
9073 /****************************************************************************
9074 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9075 We don't actually do this - we just send a null response.
9076 ****************************************************************************/
9078 static void call_trans2findnotifyfirst(connection_struct *conn,
9079 struct smb_request *req,
9080 char **pparams, int total_params,
9081 char **ppdata, int total_data,
9082 unsigned int max_data_bytes)
9084 char *params = *pparams;
9085 uint16_t info_level;
9087 if (total_params < 6) {
9088 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9092 info_level = SVAL(params,4);
9093 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9095 switch (info_level) {
9100 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9104 /* Realloc the parameter and data sizes */
9105 *pparams = (char *)SMB_REALLOC(*pparams,6);
9106 if (*pparams == NULL) {
9107 reply_nterror(req, NT_STATUS_NO_MEMORY);
9112 SSVAL(params,0,fnf_handle);
9113 SSVAL(params,2,0); /* No changes */
9114 SSVAL(params,4,0); /* No EA errors */
9121 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9126 /****************************************************************************
9127 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9128 changes). Currently this does nothing.
9129 ****************************************************************************/
9131 static void call_trans2findnotifynext(connection_struct *conn,
9132 struct smb_request *req,
9133 char **pparams, int total_params,
9134 char **ppdata, int total_data,
9135 unsigned int max_data_bytes)
9137 char *params = *pparams;
9139 DEBUG(3,("call_trans2findnotifynext\n"));
9141 /* Realloc the parameter and data sizes */
9142 *pparams = (char *)SMB_REALLOC(*pparams,4);
9143 if (*pparams == NULL) {
9144 reply_nterror(req, NT_STATUS_NO_MEMORY);
9149 SSVAL(params,0,0); /* No changes */
9150 SSVAL(params,2,0); /* No EA errors */
9152 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9157 /****************************************************************************
9158 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9159 ****************************************************************************/
9161 static void call_trans2getdfsreferral(connection_struct *conn,
9162 struct smb_request *req,
9163 char **pparams, int total_params,
9164 char **ppdata, int total_data,
9165 unsigned int max_data_bytes)
9167 char *params = *pparams;
9168 char *pathname = NULL;
9170 int max_referral_level;
9171 NTSTATUS status = NT_STATUS_OK;
9172 TALLOC_CTX *ctx = talloc_tos();
9174 DEBUG(10,("call_trans2getdfsreferral\n"));
9176 if (total_params < 3) {
9177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9181 max_referral_level = SVAL(params,0);
9183 if(!lp_host_msdfs()) {
9184 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9188 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9189 total_params - 2, STR_TERMINATE);
9191 reply_nterror(req, NT_STATUS_NOT_FOUND);
9194 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9195 ppdata,&status)) < 0) {
9196 reply_nterror(req, status);
9200 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9201 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9202 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9207 #define LMCAT_SPL 0x53
9208 #define LMFUNC_GETJOBID 0x60
9210 /****************************************************************************
9211 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9212 ****************************************************************************/
9214 static void call_trans2ioctl(connection_struct *conn,
9215 struct smb_request *req,
9216 char **pparams, int total_params,
9217 char **ppdata, int total_data,
9218 unsigned int max_data_bytes)
9220 char *pdata = *ppdata;
9221 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9225 /* check for an invalid fid before proceeding */
9228 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9232 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9233 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9234 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9235 if (*ppdata == NULL) {
9236 reply_nterror(req, NT_STATUS_NO_MEMORY);
9241 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9242 CAN ACCEPT THIS IN UNICODE. JRA. */
9245 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9247 status = srvstr_push(pdata, req->flags2, pdata + 2,
9248 lp_netbios_name(), 15,
9249 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9250 if (!NT_STATUS_IS_OK(status)) {
9251 reply_nterror(req, status);
9254 status = srvstr_push(pdata, req->flags2, pdata+18,
9255 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9256 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9257 if (!NT_STATUS_IS_OK(status)) {
9258 reply_nterror(req, status);
9261 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9266 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9267 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9270 /****************************************************************************
9271 Reply to a SMBfindclose (stop trans2 directory search).
9272 ****************************************************************************/
9274 void reply_findclose(struct smb_request *req)
9277 struct smbd_server_connection *sconn = req->sconn;
9279 START_PROFILE(SMBfindclose);
9282 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9283 END_PROFILE(SMBfindclose);
9287 dptr_num = SVALS(req->vwv+0, 0);
9289 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9291 dptr_close(sconn, &dptr_num);
9293 reply_outbuf(req, 0, 0);
9295 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9297 END_PROFILE(SMBfindclose);
9301 /****************************************************************************
9302 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9303 ****************************************************************************/
9305 void reply_findnclose(struct smb_request *req)
9309 START_PROFILE(SMBfindnclose);
9312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9313 END_PROFILE(SMBfindnclose);
9317 dptr_num = SVAL(req->vwv+0, 0);
9319 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9321 /* We never give out valid handles for a
9322 findnotifyfirst - so any dptr_num is ok here.
9325 reply_outbuf(req, 0, 0);
9327 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9329 END_PROFILE(SMBfindnclose);
9333 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9334 struct trans_state *state)
9336 if (get_Protocol() >= PROTOCOL_NT1) {
9337 req->flags2 |= 0x40; /* IS_LONG_NAME */
9338 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9341 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9342 if (state->call != TRANSACT2_QFSINFO &&
9343 state->call != TRANSACT2_SETFSINFO) {
9344 DEBUG(0,("handle_trans2: encryption required "
9346 (unsigned int)state->call));
9347 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9352 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9354 /* Now we must call the relevant TRANS2 function */
9355 switch(state->call) {
9356 case TRANSACT2_OPEN:
9358 START_PROFILE(Trans2_open);
9359 call_trans2open(conn, req,
9360 &state->param, state->total_param,
9361 &state->data, state->total_data,
9362 state->max_data_return);
9363 END_PROFILE(Trans2_open);
9367 case TRANSACT2_FINDFIRST:
9369 START_PROFILE(Trans2_findfirst);
9370 call_trans2findfirst(conn, req,
9371 &state->param, state->total_param,
9372 &state->data, state->total_data,
9373 state->max_data_return);
9374 END_PROFILE(Trans2_findfirst);
9378 case TRANSACT2_FINDNEXT:
9380 START_PROFILE(Trans2_findnext);
9381 call_trans2findnext(conn, req,
9382 &state->param, state->total_param,
9383 &state->data, state->total_data,
9384 state->max_data_return);
9385 END_PROFILE(Trans2_findnext);
9389 case TRANSACT2_QFSINFO:
9391 START_PROFILE(Trans2_qfsinfo);
9392 call_trans2qfsinfo(conn, req,
9393 &state->param, state->total_param,
9394 &state->data, state->total_data,
9395 state->max_data_return);
9396 END_PROFILE(Trans2_qfsinfo);
9400 case TRANSACT2_SETFSINFO:
9402 START_PROFILE(Trans2_setfsinfo);
9403 call_trans2setfsinfo(conn, req,
9404 &state->param, state->total_param,
9405 &state->data, state->total_data,
9406 state->max_data_return);
9407 END_PROFILE(Trans2_setfsinfo);
9411 case TRANSACT2_QPATHINFO:
9412 case TRANSACT2_QFILEINFO:
9414 START_PROFILE(Trans2_qpathinfo);
9415 call_trans2qfilepathinfo(conn, req, state->call,
9416 &state->param, state->total_param,
9417 &state->data, state->total_data,
9418 state->max_data_return);
9419 END_PROFILE(Trans2_qpathinfo);
9423 case TRANSACT2_SETPATHINFO:
9424 case TRANSACT2_SETFILEINFO:
9426 START_PROFILE(Trans2_setpathinfo);
9427 call_trans2setfilepathinfo(conn, req, state->call,
9428 &state->param, state->total_param,
9429 &state->data, state->total_data,
9430 state->max_data_return);
9431 END_PROFILE(Trans2_setpathinfo);
9435 case TRANSACT2_FINDNOTIFYFIRST:
9437 START_PROFILE(Trans2_findnotifyfirst);
9438 call_trans2findnotifyfirst(conn, req,
9439 &state->param, state->total_param,
9440 &state->data, state->total_data,
9441 state->max_data_return);
9442 END_PROFILE(Trans2_findnotifyfirst);
9446 case TRANSACT2_FINDNOTIFYNEXT:
9448 START_PROFILE(Trans2_findnotifynext);
9449 call_trans2findnotifynext(conn, req,
9450 &state->param, state->total_param,
9451 &state->data, state->total_data,
9452 state->max_data_return);
9453 END_PROFILE(Trans2_findnotifynext);
9457 case TRANSACT2_MKDIR:
9459 START_PROFILE(Trans2_mkdir);
9460 call_trans2mkdir(conn, req,
9461 &state->param, state->total_param,
9462 &state->data, state->total_data,
9463 state->max_data_return);
9464 END_PROFILE(Trans2_mkdir);
9468 case TRANSACT2_GET_DFS_REFERRAL:
9470 START_PROFILE(Trans2_get_dfs_referral);
9471 call_trans2getdfsreferral(conn, req,
9472 &state->param, state->total_param,
9473 &state->data, state->total_data,
9474 state->max_data_return);
9475 END_PROFILE(Trans2_get_dfs_referral);
9479 case TRANSACT2_IOCTL:
9481 START_PROFILE(Trans2_ioctl);
9482 call_trans2ioctl(conn, req,
9483 &state->param, state->total_param,
9484 &state->data, state->total_data,
9485 state->max_data_return);
9486 END_PROFILE(Trans2_ioctl);
9491 /* Error in request */
9492 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9493 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9497 /****************************************************************************
9498 Reply to a SMBtrans2.
9499 ****************************************************************************/
9501 void reply_trans2(struct smb_request *req)
9503 connection_struct *conn = req->conn;
9508 unsigned int tran_call;
9509 struct trans_state *state;
9512 START_PROFILE(SMBtrans2);
9514 if (req->wct < 14) {
9515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9516 END_PROFILE(SMBtrans2);
9520 dsoff = SVAL(req->vwv+12, 0);
9521 dscnt = SVAL(req->vwv+11, 0);
9522 psoff = SVAL(req->vwv+10, 0);
9523 pscnt = SVAL(req->vwv+9, 0);
9524 tran_call = SVAL(req->vwv+14, 0);
9526 result = allow_new_trans(conn->pending_trans, req->mid);
9527 if (!NT_STATUS_IS_OK(result)) {
9528 DEBUG(2, ("Got invalid trans2 request: %s\n",
9529 nt_errstr(result)));
9530 reply_nterror(req, result);
9531 END_PROFILE(SMBtrans2);
9536 switch (tran_call) {
9537 /* List the allowed trans2 calls on IPC$ */
9538 case TRANSACT2_OPEN:
9539 case TRANSACT2_GET_DFS_REFERRAL:
9540 case TRANSACT2_QFILEINFO:
9541 case TRANSACT2_QFSINFO:
9542 case TRANSACT2_SETFSINFO:
9545 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9546 END_PROFILE(SMBtrans2);
9551 if ((state = talloc(conn, struct trans_state)) == NULL) {
9552 DEBUG(0, ("talloc failed\n"));
9553 reply_nterror(req, NT_STATUS_NO_MEMORY);
9554 END_PROFILE(SMBtrans2);
9558 state->cmd = SMBtrans2;
9560 state->mid = req->mid;
9561 state->vuid = req->vuid;
9562 state->setup_count = SVAL(req->vwv+13, 0);
9563 state->setup = NULL;
9564 state->total_param = SVAL(req->vwv+0, 0);
9565 state->param = NULL;
9566 state->total_data = SVAL(req->vwv+1, 0);
9568 state->max_param_return = SVAL(req->vwv+2, 0);
9569 state->max_data_return = SVAL(req->vwv+3, 0);
9570 state->max_setup_return = SVAL(req->vwv+4, 0);
9571 state->close_on_completion = BITSETW(req->vwv+5, 0);
9572 state->one_way = BITSETW(req->vwv+5, 1);
9574 state->call = tran_call;
9576 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9577 is so as a sanity check */
9578 if (state->setup_count != 1) {
9580 * Need to have rc=0 for ioctl to get job id for OS/2.
9581 * Network printing will fail if function is not successful.
9582 * Similar function in reply.c will be used if protocol
9583 * is LANMAN1.0 instead of LM1.2X002.
9584 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9585 * outbuf doesn't have to be set(only job id is used).
9587 if ( (state->setup_count == 4)
9588 && (tran_call == TRANSACT2_IOCTL)
9589 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9590 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9591 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9593 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9594 DEBUG(2,("Transaction is %d\n",tran_call));
9596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9597 END_PROFILE(SMBtrans2);
9602 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9605 if (state->total_data) {
9607 if (trans_oob(state->total_data, 0, dscnt)
9608 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9612 /* Can't use talloc here, the core routines do realloc on the
9613 * params and data. */
9614 state->data = (char *)SMB_MALLOC(state->total_data);
9615 if (state->data == NULL) {
9616 DEBUG(0,("reply_trans2: data malloc fail for %u "
9617 "bytes !\n", (unsigned int)state->total_data));
9619 reply_nterror(req, NT_STATUS_NO_MEMORY);
9620 END_PROFILE(SMBtrans2);
9624 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9627 if (state->total_param) {
9629 if (trans_oob(state->total_param, 0, pscnt)
9630 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9634 /* Can't use talloc here, the core routines do realloc on the
9635 * params and data. */
9636 state->param = (char *)SMB_MALLOC(state->total_param);
9637 if (state->param == NULL) {
9638 DEBUG(0,("reply_trans: param malloc fail for %u "
9639 "bytes !\n", (unsigned int)state->total_param));
9640 SAFE_FREE(state->data);
9642 reply_nterror(req, NT_STATUS_NO_MEMORY);
9643 END_PROFILE(SMBtrans2);
9647 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9650 state->received_data = dscnt;
9651 state->received_param = pscnt;
9653 if ((state->received_param == state->total_param) &&
9654 (state->received_data == state->total_data)) {
9656 handle_trans2(conn, req, state);
9658 SAFE_FREE(state->data);
9659 SAFE_FREE(state->param);
9661 END_PROFILE(SMBtrans2);
9665 DLIST_ADD(conn->pending_trans, state);
9667 /* We need to send an interim response then receive the rest
9668 of the parameter/data bytes */
9669 reply_outbuf(req, 0, 0);
9670 show_msg((char *)req->outbuf);
9671 END_PROFILE(SMBtrans2);
9676 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9677 SAFE_FREE(state->data);
9678 SAFE_FREE(state->param);
9680 END_PROFILE(SMBtrans2);
9681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9685 /****************************************************************************
9686 Reply to a SMBtranss2
9687 ****************************************************************************/
9689 void reply_transs2(struct smb_request *req)
9691 connection_struct *conn = req->conn;
9692 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9693 struct trans_state *state;
9695 START_PROFILE(SMBtranss2);
9697 show_msg((const char *)req->inbuf);
9699 /* Windows clients expect all replies to
9700 a transact secondary (SMBtranss2 0x33)
9701 to have a command code of transact
9702 (SMBtrans2 0x32). See bug #8989
9703 and also [MS-CIFS] section 2.2.4.47.2
9706 req->cmd = SMBtrans2;
9709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9710 END_PROFILE(SMBtranss2);
9714 for (state = conn->pending_trans; state != NULL;
9715 state = state->next) {
9716 if (state->mid == req->mid) {
9721 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9722 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9723 END_PROFILE(SMBtranss2);
9727 /* Revise state->total_param and state->total_data in case they have
9728 changed downwards */
9730 if (SVAL(req->vwv+0, 0) < state->total_param)
9731 state->total_param = SVAL(req->vwv+0, 0);
9732 if (SVAL(req->vwv+1, 0) < state->total_data)
9733 state->total_data = SVAL(req->vwv+1, 0);
9735 pcnt = SVAL(req->vwv+2, 0);
9736 poff = SVAL(req->vwv+3, 0);
9737 pdisp = SVAL(req->vwv+4, 0);
9739 dcnt = SVAL(req->vwv+5, 0);
9740 doff = SVAL(req->vwv+6, 0);
9741 ddisp = SVAL(req->vwv+7, 0);
9743 state->received_param += pcnt;
9744 state->received_data += dcnt;
9746 if ((state->received_data > state->total_data) ||
9747 (state->received_param > state->total_param))
9751 if (trans_oob(state->total_param, pdisp, pcnt)
9752 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9755 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9759 if (trans_oob(state->total_data, ddisp, dcnt)
9760 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9763 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9766 if ((state->received_param < state->total_param) ||
9767 (state->received_data < state->total_data)) {
9768 END_PROFILE(SMBtranss2);
9772 handle_trans2(conn, req, state);
9774 DLIST_REMOVE(conn->pending_trans, state);
9775 SAFE_FREE(state->data);
9776 SAFE_FREE(state->param);
9779 END_PROFILE(SMBtranss2);
9784 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9785 DLIST_REMOVE(conn->pending_trans, state);
9786 SAFE_FREE(state->data);
9787 SAFE_FREE(state->param);
9789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9790 END_PROFILE(SMBtranss2);