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 const char *pathname,
1581 SMB_STRUCT_STAT *psbuf)
1583 int saved_errno = errno;
1584 if(lp_host_msdfs() &&
1585 lp_msdfs_root(SNUM(conn)) &&
1586 is_msdfs_link(conn, pathname, psbuf)) {
1588 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1591 psbuf->st_ex_mode = (psbuf->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,
1713 struct smbd_dirptr_lanman2_state *state =
1714 (struct smbd_dirptr_lanman2_state *)private_data;
1715 bool ms_dfs_link = false;
1718 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1719 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1720 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1721 "Couldn't lstat [%s] (%s)\n",
1722 smb_fname_str_dbg(smb_fname),
1726 } else if (!VALID_STAT(smb_fname->st) &&
1727 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1728 /* Needed to show the msdfs symlinks as
1731 ms_dfs_link = check_msdfs_link(state->conn,
1732 smb_fname->base_name,
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);
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,
2459 int space_remaining,
2460 bool *got_exact_match,
2461 int *_last_entry_off,
2462 struct ea_list *name_list,
2463 struct file_id *file_id)
2466 const char *mask = NULL;
2467 long prev_dirpos = 0;
2470 struct smb_filename *smb_fname = NULL;
2471 struct smbd_dirptr_lanman2_state state;
2473 uint64_t last_entry_off = 0;
2475 enum mangled_names_options mangled_names;
2476 bool marshall_with_83_names;
2478 mangled_names = lp_mangled_names(conn->params);
2482 state.info_level = info_level;
2483 if (mangled_names != MANGLED_NAMES_NO) {
2484 state.check_mangled_names = true;
2486 state.has_wild = dptr_has_wild(dirptr);
2487 state.got_exact_match = false;
2489 *got_exact_match = false;
2491 p = strrchr_m(path_mask,'/');
2502 ok = smbd_dirptr_get_entry(ctx,
2508 smbd_dirptr_lanman2_match_fn,
2509 smbd_dirptr_lanman2_mode_fn,
2516 return NT_STATUS_END_OF_FILE;
2519 *got_exact_match = state.got_exact_match;
2521 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2523 status = smbd_marshall_dir_entry(ctx,
2528 marshall_with_83_names,
2529 requires_resume_key,
2540 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2541 DEBUG(1,("Conversion error: illegal character: %s\n",
2542 smb_fname_str_dbg(smb_fname)));
2545 if (file_id != NULL) {
2546 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2550 TALLOC_FREE(smb_fname);
2551 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2552 dptr_SeekDir(dirptr, prev_dirpos);
2555 if (!NT_STATUS_IS_OK(status)) {
2559 *_last_entry_off = last_entry_off;
2560 return NT_STATUS_OK;
2563 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2564 connection_struct *conn,
2565 struct dptr_struct *dirptr,
2567 const char *path_mask,
2570 bool requires_resume_key,
2576 int space_remaining,
2577 bool *got_exact_match,
2578 int *last_entry_off,
2579 struct ea_list *name_list)
2582 const bool do_pad = true;
2584 if (info_level >= 1 && info_level <= 3) {
2585 /* No alignment on earlier info levels. */
2589 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2590 path_mask, dirtype, info_level,
2591 requires_resume_key, dont_descend, ask_sharemode,
2593 ppdata, base_data, end_data,
2596 last_entry_off, name_list, NULL);
2599 /****************************************************************************
2600 Reply to a TRANS2_FINDFIRST.
2601 ****************************************************************************/
2603 static void call_trans2findfirst(connection_struct *conn,
2604 struct smb_request *req,
2605 char **pparams, int total_params,
2606 char **ppdata, int total_data,
2607 unsigned int max_data_bytes)
2609 /* We must be careful here that we don't return more than the
2610 allowed number of data bytes. If this means returning fewer than
2611 maxentries then so be it. We assume that the redirector has
2612 enough room for the fixed number of parameter bytes it has
2614 struct smb_filename *smb_dname = NULL;
2615 char *params = *pparams;
2616 char *pdata = *ppdata;
2620 uint16_t findfirst_flags;
2621 bool close_after_first;
2623 bool requires_resume_key;
2625 char *directory = NULL;
2628 int last_entry_off=0;
2632 bool finished = False;
2633 bool dont_descend = False;
2634 bool out_of_space = False;
2635 int space_remaining;
2636 bool mask_contains_wcard = False;
2637 struct ea_list *ea_list = NULL;
2638 NTSTATUS ntstatus = NT_STATUS_OK;
2639 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2640 struct dptr_struct *dirptr = NULL;
2641 struct smbd_server_connection *sconn = req->sconn;
2642 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2643 ucf_flags_from_smb_request(req);
2644 bool backup_priv = false;
2645 bool as_root = false;
2647 if (total_params < 13) {
2648 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2652 dirtype = SVAL(params,0);
2653 maxentries = SVAL(params,2);
2654 findfirst_flags = SVAL(params,4);
2655 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2656 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2657 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2658 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2659 security_token_has_privilege(get_current_nttok(conn),
2662 info_level = SVAL(params,6);
2664 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2665 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2666 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2668 info_level, max_data_bytes));
2671 /* W2K3 seems to treat zero as 1. */
2675 switch (info_level) {
2676 case SMB_FIND_INFO_STANDARD:
2677 case SMB_FIND_EA_SIZE:
2678 case SMB_FIND_EA_LIST:
2679 case SMB_FIND_FILE_DIRECTORY_INFO:
2680 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2681 case SMB_FIND_FILE_NAMES_INFO:
2682 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2683 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2684 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2686 case SMB_FIND_FILE_UNIX:
2687 case SMB_FIND_FILE_UNIX_INFO2:
2688 /* Always use filesystem for UNIX mtime query. */
2689 ask_sharemode = false;
2690 if (!lp_unix_extensions()) {
2691 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2694 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2697 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2701 if (req->posix_pathnames) {
2702 srvstr_get_path_wcard_posix(talloc_tos(),
2710 &mask_contains_wcard);
2712 srvstr_get_path_wcard(talloc_tos(),
2720 &mask_contains_wcard);
2722 if (!NT_STATUS_IS_OK(ntstatus)) {
2723 reply_nterror(req, ntstatus);
2730 ntstatus = filename_convert_with_privilege(talloc_tos(),
2735 &mask_contains_wcard,
2738 ntstatus = filename_convert(talloc_tos(), conn,
2741 &mask_contains_wcard,
2745 if (!NT_STATUS_IS_OK(ntstatus)) {
2746 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2747 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2748 ERRSRV, ERRbadpath);
2751 reply_nterror(req, ntstatus);
2755 mask = smb_dname->original_lcomp;
2757 directory = smb_dname->base_name;
2759 p = strrchr_m(directory,'/');
2761 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2762 if((directory[0] == '.') && (directory[1] == '\0')) {
2763 mask = talloc_strdup(talloc_tos(),"*");
2765 reply_nterror(req, NT_STATUS_NO_MEMORY);
2768 mask_contains_wcard = True;
2774 if (p == NULL || p == directory) {
2775 /* Ensure we don't have a directory name of "". */
2776 directory = talloc_strdup(talloc_tos(), ".");
2778 reply_nterror(req, NT_STATUS_NO_MEMORY);
2781 /* Ensure smb_dname->base_name matches. */
2782 smb_dname->base_name = directory;
2785 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2787 if (info_level == SMB_FIND_EA_LIST) {
2790 if (total_data < 4) {
2791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2795 ea_size = IVAL(pdata,0);
2796 if (ea_size != total_data) {
2797 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2798 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2799 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2803 if (!lp_ea_support(SNUM(conn))) {
2804 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2808 /* Pull out the list of names. */
2809 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2816 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2817 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2821 *ppdata = (char *)SMB_REALLOC(
2822 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2823 if(*ppdata == NULL ) {
2824 reply_nterror(req, NT_STATUS_NO_MEMORY);
2828 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2830 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2833 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2834 /* Realloc the params space */
2835 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2836 if (*pparams == NULL) {
2837 reply_nterror(req, NT_STATUS_NO_MEMORY);
2842 /* Save the wildcard match and attribs we are using on this directory -
2843 needed as lanman2 assumes these are being saved between calls */
2845 ntstatus = dptr_create(conn,
2853 mask_contains_wcard,
2857 if (!NT_STATUS_IS_OK(ntstatus)) {
2858 reply_nterror(req, ntstatus);
2863 /* Remember this in case we have
2864 to do a findnext. */
2865 dptr_set_priv(dirptr);
2868 dptr_num = dptr_dnum(dirptr);
2869 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2871 /* Initialize per TRANS2_FIND_FIRST operation data */
2872 dptr_init_search_op(dirptr);
2874 /* We don't need to check for VOL here as this is returned by
2875 a different TRANS2 call. */
2877 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2878 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2879 if (in_list(directory,
2880 lp_dont_descend(talloc_tos(), SNUM(conn)),
2881 conn->case_sensitive)) {
2882 dont_descend = True;
2886 space_remaining = max_data_bytes;
2887 out_of_space = False;
2889 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2890 bool got_exact_match = False;
2892 /* this is a heuristic to avoid seeking the dirptr except when
2893 absolutely necessary. It allows for a filename of about 40 chars */
2894 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2895 out_of_space = True;
2898 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2902 mask,dirtype,info_level,
2903 requires_resume_key,dont_descend,
2908 &last_entry_off, ea_list);
2909 if (NT_STATUS_EQUAL(ntstatus,
2910 NT_STATUS_ILLEGAL_CHARACTER)) {
2912 * Bad character conversion on name. Ignore this
2917 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2918 out_of_space = true;
2920 finished = !NT_STATUS_IS_OK(ntstatus);
2924 if (!finished && !out_of_space)
2928 * As an optimisation if we know we aren't looking
2929 * for a wildcard name (ie. the name matches the wildcard exactly)
2930 * then we can finish on any (first) match.
2931 * This speeds up large directory searches. JRA.
2937 /* Ensure space_remaining never goes -ve. */
2938 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2939 space_remaining = 0;
2940 out_of_space = true;
2942 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2946 /* Check if we can close the dirptr */
2947 if(close_after_first || (finished && close_if_end)) {
2948 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2949 dptr_close(sconn, &dptr_num);
2953 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2954 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2955 * the protocol level is less than NT1. Tested with smbclient. JRA.
2956 * This should fix the OS/2 client bug #2335.
2959 if(numentries == 0) {
2960 dptr_close(sconn, &dptr_num);
2961 if (get_Protocol() < PROTOCOL_NT1) {
2962 reply_force_doserror(req, ERRDOS, ERRnofiles);
2965 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2966 ERRDOS, ERRbadfile);
2971 /* At this point pdata points to numentries directory entries. */
2973 /* Set up the return parameter block */
2974 SSVAL(params,0,dptr_num);
2975 SSVAL(params,2,numentries);
2976 SSVAL(params,4,finished);
2977 SSVAL(params,6,0); /* Never an EA error */
2978 SSVAL(params,8,last_entry_off);
2980 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2983 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2984 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2986 reply_nterror(req, NT_STATUS_NO_MEMORY);
2990 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2991 smb_fn_name(req->cmd),
2992 mask, directory, dirtype, numentries ) );
2995 * Force a name mangle here to ensure that the
2996 * mask as an 8.3 name is top of the mangled cache.
2997 * The reasons for this are subtle. Don't remove
2998 * this code unless you know what you are doing
2999 * (see PR#13758). JRA.
3002 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3003 char mangled_name[13];
3004 name_to_8_3(mask, mangled_name, True, conn->params);
3012 TALLOC_FREE(smb_dname);
3016 /****************************************************************************
3017 Reply to a TRANS2_FINDNEXT.
3018 ****************************************************************************/
3020 static void call_trans2findnext(connection_struct *conn,
3021 struct smb_request *req,
3022 char **pparams, int total_params,
3023 char **ppdata, int total_data,
3024 unsigned int max_data_bytes)
3026 /* We must be careful here that we don't return more than the
3027 allowed number of data bytes. If this means returning fewer than
3028 maxentries then so be it. We assume that the redirector has
3029 enough room for the fixed number of parameter bytes it has
3031 char *params = *pparams;
3032 char *pdata = *ppdata;
3036 uint16_t info_level;
3037 uint32_t resume_key;
3038 uint16_t findnext_flags;
3039 bool close_after_request;
3041 bool requires_resume_key;
3043 bool mask_contains_wcard = False;
3044 char *resume_name = NULL;
3045 const char *mask = NULL;
3046 const char *directory = NULL;
3050 int i, last_entry_off=0;
3051 bool finished = False;
3052 bool dont_descend = False;
3053 bool out_of_space = False;
3054 int space_remaining;
3055 struct ea_list *ea_list = NULL;
3056 NTSTATUS ntstatus = NT_STATUS_OK;
3057 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3058 TALLOC_CTX *ctx = talloc_tos();
3059 struct dptr_struct *dirptr;
3060 struct smbd_server_connection *sconn = req->sconn;
3061 bool backup_priv = false;
3062 bool as_root = false;
3064 if (total_params < 13) {
3065 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3069 dptr_num = SVAL(params,0);
3070 maxentries = SVAL(params,2);
3071 info_level = SVAL(params,4);
3072 resume_key = IVAL(params,6);
3073 findnext_flags = SVAL(params,10);
3074 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3075 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3076 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3077 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3079 if (!continue_bit) {
3080 /* We only need resume_name if continue_bit is zero. */
3081 if (req->posix_pathnames) {
3082 srvstr_get_path_wcard_posix(ctx,
3090 &mask_contains_wcard);
3092 srvstr_get_path_wcard(ctx,
3100 &mask_contains_wcard);
3102 if (!NT_STATUS_IS_OK(ntstatus)) {
3103 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3104 complain (it thinks we're asking for the directory above the shared
3105 path or an invalid name). Catch this as the resume name is only compared, never used in
3106 a file access. JRA. */
3107 srvstr_pull_talloc(ctx, params, req->flags2,
3108 &resume_name, params+12,
3112 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3113 reply_nterror(req, ntstatus);
3119 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3120 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3121 resume_key = %d resume name = %s continue=%d level = %d\n",
3122 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3123 requires_resume_key, resume_key,
3124 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3127 /* W2K3 seems to treat zero as 1. */
3131 switch (info_level) {
3132 case SMB_FIND_INFO_STANDARD:
3133 case SMB_FIND_EA_SIZE:
3134 case SMB_FIND_EA_LIST:
3135 case SMB_FIND_FILE_DIRECTORY_INFO:
3136 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3137 case SMB_FIND_FILE_NAMES_INFO:
3138 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3139 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3140 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3142 case SMB_FIND_FILE_UNIX:
3143 case SMB_FIND_FILE_UNIX_INFO2:
3144 /* Always use filesystem for UNIX mtime query. */
3145 ask_sharemode = false;
3146 if (!lp_unix_extensions()) {
3147 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3152 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3156 if (info_level == SMB_FIND_EA_LIST) {
3159 if (total_data < 4) {
3160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3164 ea_size = IVAL(pdata,0);
3165 if (ea_size != total_data) {
3166 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3167 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3168 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3172 if (!lp_ea_support(SNUM(conn))) {
3173 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3177 /* Pull out the list of names. */
3178 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3180 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3185 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3190 *ppdata = (char *)SMB_REALLOC(
3191 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3192 if(*ppdata == NULL) {
3193 reply_nterror(req, NT_STATUS_NO_MEMORY);
3198 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3201 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3204 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3205 /* Realloc the params space */
3206 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3207 if(*pparams == NULL ) {
3208 reply_nterror(req, NT_STATUS_NO_MEMORY);
3214 /* Check that the dptr is valid */
3215 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3216 reply_nterror(req, STATUS_NO_MORE_FILES);
3220 directory = dptr_path(sconn, dptr_num);
3222 /* Get the wildcard mask from the dptr */
3223 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3224 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3225 reply_nterror(req, STATUS_NO_MORE_FILES);
3229 /* Get the attr mask from the dptr */
3230 dirtype = dptr_attr(sconn, dptr_num);
3232 backup_priv = dptr_get_priv(dirptr);
3234 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3235 "backup_priv = %d\n",
3236 dptr_num, mask, dirtype,
3238 dptr_TellDir(dirptr),
3241 /* Initialize per TRANS2_FIND_NEXT operation data */
3242 dptr_init_search_op(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, filename, &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... */
4044 return NT_STATUS_INVALID_LEVEL;
4047 *ret_data_len = data_len;
4051 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4052 struct smb_request *req,
4054 const DATA_BLOB *qdata)
4057 SMB_NTQUOTA_STRUCT quotas;
4059 ZERO_STRUCT(quotas);
4062 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4063 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4064 lp_servicename(talloc_tos(), SNUM(conn)),
4065 conn->session_info->unix_info->unix_name));
4066 return NT_STATUS_ACCESS_DENIED;
4069 if (!check_fsp_ntquota_handle(conn, req,
4071 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4072 return NT_STATUS_INVALID_HANDLE;
4075 /* note: normally there're 48 bytes,
4076 * but we didn't use the last 6 bytes for now
4079 if (qdata->length < 42) {
4080 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4081 (unsigned int)qdata->length));
4082 return NT_STATUS_INVALID_PARAMETER;
4085 /* unknown_1 24 NULL bytes in pdata*/
4087 /* the soft quotas 8 bytes (uint64_t)*/
4088 quotas.softlim = BVAL(qdata->data,24);
4090 /* the hard quotas 8 bytes (uint64_t)*/
4091 quotas.hardlim = BVAL(qdata->data,32);
4093 /* quota_flags 2 bytes **/
4094 quotas.qflags = SVAL(qdata->data,40);
4096 /* unknown_2 6 NULL bytes follow*/
4098 /* now set the quotas */
4099 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4100 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4101 lp_servicename(talloc_tos(), SNUM(conn))));
4102 status = map_nt_error_from_unix(errno);
4104 status = NT_STATUS_OK;
4109 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4110 struct smb_request *req,
4111 TALLOC_CTX *mem_ctx,
4112 uint16_t info_level,
4114 const DATA_BLOB *pdata)
4116 switch (info_level) {
4117 case SMB_FS_QUOTA_INFORMATION:
4119 return smb_set_fsquota(conn,
4128 return NT_STATUS_INVALID_LEVEL;
4131 /****************************************************************************
4132 Reply to a TRANS2_QFSINFO (query filesystem info).
4133 ****************************************************************************/
4135 static void call_trans2qfsinfo(connection_struct *conn,
4136 struct smb_request *req,
4137 char **pparams, int total_params,
4138 char **ppdata, int total_data,
4139 unsigned int max_data_bytes)
4141 char *params = *pparams;
4142 uint16_t info_level;
4144 size_t fixed_portion;
4147 if (total_params < 2) {
4148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4152 info_level = SVAL(params,0);
4154 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4155 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4156 DEBUG(0,("call_trans2qfsinfo: encryption required "
4157 "and info level 0x%x sent.\n",
4158 (unsigned int)info_level));
4159 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4164 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4166 status = smbd_do_qfsinfo(req->xconn, conn, req,
4173 if (!NT_STATUS_IS_OK(status)) {
4174 reply_nterror(req, status);
4178 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4181 DEBUG( 4, ( "%s info_level = %d\n",
4182 smb_fn_name(req->cmd), info_level) );
4187 /****************************************************************************
4188 Reply to a TRANS2_SETFSINFO (set filesystem info).
4189 ****************************************************************************/
4191 static void call_trans2setfsinfo(connection_struct *conn,
4192 struct smb_request *req,
4193 char **pparams, int total_params,
4194 char **ppdata, int total_data,
4195 unsigned int max_data_bytes)
4197 struct smbXsrv_connection *xconn = req->xconn;
4198 char *pdata = *ppdata;
4199 char *params = *pparams;
4200 uint16_t info_level;
4202 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4203 lp_servicename(talloc_tos(), SNUM(conn))));
4206 if (total_params < 4) {
4207 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4213 info_level = SVAL(params,2);
4216 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4217 info_level != SMB_SET_CIFS_UNIX_INFO) {
4218 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4219 "info level (0x%x) on IPC$.\n",
4220 (unsigned int)info_level));
4221 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4226 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4227 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4228 DEBUG(0,("call_trans2setfsinfo: encryption required "
4229 "and info level 0x%x sent.\n",
4230 (unsigned int)info_level));
4231 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4236 switch(info_level) {
4237 case SMB_SET_CIFS_UNIX_INFO:
4238 if (!lp_unix_extensions()) {
4239 DEBUG(2,("call_trans2setfsinfo: "
4240 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4241 "unix extensions off\n"));
4243 NT_STATUS_INVALID_LEVEL);
4247 /* There should be 12 bytes of capabilities set. */
4248 if (total_data < 12) {
4251 NT_STATUS_INVALID_PARAMETER);
4254 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4255 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4256 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4257 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4258 /* Just print these values for now. */
4259 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4260 "major = %u, minor = %u cap_low = 0x%x, "
4262 (unsigned int)xconn->
4263 smb1.unix_info.client_major,
4264 (unsigned int)xconn->
4265 smb1.unix_info.client_minor,
4266 (unsigned int)xconn->
4267 smb1.unix_info.client_cap_low,
4268 (unsigned int)xconn->
4269 smb1.unix_info.client_cap_high));
4271 /* Here is where we must switch to posix pathname processing... */
4272 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4273 lp_set_posix_pathnames();
4274 mangle_change_to_posix();
4277 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4278 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4279 /* Client that knows how to do posix locks,
4280 * but not posix open/mkdir operations. Set a
4281 * default type for read/write checks. */
4283 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4288 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4291 size_t param_len = 0;
4292 size_t data_len = total_data;
4294 if (!lp_unix_extensions()) {
4297 NT_STATUS_INVALID_LEVEL);
4301 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4304 NT_STATUS_NOT_SUPPORTED);
4308 if (xconn->smb1.echo_handler.trusted_fde) {
4309 DEBUG( 2,("call_trans2setfsinfo: "
4310 "request transport encryption disabled"
4311 "with 'fork echo handler = yes'\n"));
4314 NT_STATUS_NOT_SUPPORTED);
4318 DEBUG( 4,("call_trans2setfsinfo: "
4319 "request transport encryption.\n"));
4321 status = srv_request_encryption_setup(conn,
4322 (unsigned char **)ppdata,
4324 (unsigned char **)pparams,
4327 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4328 !NT_STATUS_IS_OK(status)) {
4329 reply_nterror(req, status);
4333 send_trans2_replies(conn, req,
4341 if (NT_STATUS_IS_OK(status)) {
4342 /* Server-side transport
4343 * encryption is now *on*. */
4344 status = srv_encryption_start(conn);
4345 if (!NT_STATUS_IS_OK(status)) {
4346 char *reason = talloc_asprintf(talloc_tos(),
4347 "Failure in setting "
4348 "up encrypted transport: %s",
4350 exit_server_cleanly(reason);
4356 case SMB_FS_QUOTA_INFORMATION:
4360 .data = (uint8_t *)pdata,
4361 .length = total_data
4363 files_struct *fsp = NULL;
4364 fsp = file_fsp(req, SVAL(params,0));
4366 status = smb_set_fsquota(conn,
4370 if (!NT_STATUS_IS_OK(status)) {
4371 reply_nterror(req, status);
4377 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4379 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4385 * sending this reply works fine,
4386 * but I'm not sure it's the same
4387 * like windows do...
4390 reply_outbuf(req, 10, 0);
4393 #if defined(HAVE_POSIX_ACLS)
4394 /****************************************************************************
4395 Utility function to count the number of entries in a POSIX acl.
4396 ****************************************************************************/
4398 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4400 unsigned int ace_count = 0;
4401 int entry_id = SMB_ACL_FIRST_ENTRY;
4402 SMB_ACL_ENTRY_T entry;
4404 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4406 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4407 entry_id = SMB_ACL_NEXT_ENTRY;
4414 /****************************************************************************
4415 Utility function to marshall a POSIX acl into wire format.
4416 ****************************************************************************/
4418 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4420 int entry_id = SMB_ACL_FIRST_ENTRY;
4421 SMB_ACL_ENTRY_T entry;
4423 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4424 SMB_ACL_TAG_T tagtype;
4425 SMB_ACL_PERMSET_T permset;
4426 unsigned char perms = 0;
4427 unsigned int own_grp;
4430 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4431 entry_id = SMB_ACL_NEXT_ENTRY;
4434 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4435 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4439 if (sys_acl_get_permset(entry, &permset) == -1) {
4440 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4444 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4445 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4446 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4448 SCVAL(pdata,1,perms);
4451 case SMB_ACL_USER_OBJ:
4452 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4453 own_grp = (unsigned int)pst->st_ex_uid;
4454 SIVAL(pdata,2,own_grp);
4459 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4461 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4464 own_grp = (unsigned int)*puid;
4465 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4466 SIVAL(pdata,2,own_grp);
4470 case SMB_ACL_GROUP_OBJ:
4471 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4472 own_grp = (unsigned int)pst->st_ex_gid;
4473 SIVAL(pdata,2,own_grp);
4478 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4480 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4483 own_grp = (unsigned int)*pgid;
4484 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4485 SIVAL(pdata,2,own_grp);
4490 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4491 SIVAL(pdata,2,0xFFFFFFFF);
4492 SIVAL(pdata,6,0xFFFFFFFF);
4495 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4496 SIVAL(pdata,2,0xFFFFFFFF);
4497 SIVAL(pdata,6,0xFFFFFFFF);
4500 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4503 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4510 /****************************************************************************
4511 Store the FILE_UNIX_BASIC info.
4512 ****************************************************************************/
4514 static char *store_file_unix_basic(connection_struct *conn,
4517 const SMB_STRUCT_STAT *psbuf)
4519 uint64_t file_index = get_FileIndex(conn, psbuf);
4522 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4523 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4525 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4528 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4531 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4532 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4533 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4536 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4540 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4544 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4547 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4548 devno = psbuf->st_ex_rdev;
4550 devno = psbuf->st_ex_dev;
4553 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4557 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4561 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4564 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4568 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4575 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4576 * the chflags(2) (or equivalent) flags.
4578 * XXX: this really should be behind the VFS interface. To do this, we would
4579 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4580 * Each VFS module could then implement its own mapping as appropriate for the
4581 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4583 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4587 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4591 { UF_IMMUTABLE, EXT_IMMUTABLE },
4595 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4599 { UF_HIDDEN, EXT_HIDDEN },
4602 /* Do not remove. We need to guarantee that this array has at least one
4603 * entry to build on HP-UX.
4609 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4610 uint32_t *smb_fflags, uint32_t *smb_fmask)
4614 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4615 *smb_fmask |= info2_flags_map[i].smb_fflag;
4616 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4617 *smb_fflags |= info2_flags_map[i].smb_fflag;
4622 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4623 const uint32_t smb_fflags,
4624 const uint32_t smb_fmask,
4627 uint32_t max_fmask = 0;
4630 *stat_fflags = psbuf->st_ex_flags;
4632 /* For each flags requested in smb_fmask, check the state of the
4633 * corresponding flag in smb_fflags and set or clear the matching
4637 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4638 max_fmask |= info2_flags_map[i].smb_fflag;
4639 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4640 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4641 *stat_fflags |= info2_flags_map[i].stat_fflag;
4643 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4648 /* If smb_fmask is asking to set any bits that are not supported by
4649 * our flag mappings, we should fail.
4651 if ((smb_fmask & max_fmask) != smb_fmask) {
4659 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4660 * of file flags and birth (create) time.
4662 static char *store_file_unix_basic_info2(connection_struct *conn,
4665 const SMB_STRUCT_STAT *psbuf)
4667 uint32_t file_flags = 0;
4668 uint32_t flags_mask = 0;
4670 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4672 /* Create (birth) time 64 bit */
4673 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4676 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4677 SIVAL(pdata, 0, file_flags); /* flags */
4678 SIVAL(pdata, 4, flags_mask); /* mask */
4684 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4685 const struct stream_struct *streams,
4687 unsigned int max_data_bytes,
4688 unsigned int *data_size)
4691 unsigned int ofs = 0;
4693 if (max_data_bytes < 32) {
4694 return NT_STATUS_INFO_LENGTH_MISMATCH;
4697 for (i = 0; i < num_streams; i++) {
4698 unsigned int next_offset;
4700 smb_ucs2_t *namebuf;
4702 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4703 streams[i].name, &namelen) ||
4706 return NT_STATUS_INVALID_PARAMETER;
4710 * name_buf is now null-terminated, we need to marshall as not
4717 * We cannot overflow ...
4719 if ((ofs + 24 + namelen) > max_data_bytes) {
4720 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4722 TALLOC_FREE(namebuf);
4723 return STATUS_BUFFER_OVERFLOW;
4726 SIVAL(data, ofs+4, namelen);
4727 SOFF_T(data, ofs+8, streams[i].size);
4728 SOFF_T(data, ofs+16, streams[i].alloc_size);
4729 memcpy(data+ofs+24, namebuf, namelen);
4730 TALLOC_FREE(namebuf);
4732 next_offset = ofs + 24 + namelen;
4734 if (i == num_streams-1) {
4735 SIVAL(data, ofs, 0);
4738 unsigned int align = ndr_align_size(next_offset, 8);
4740 if ((next_offset + align) > max_data_bytes) {
4741 DEBUG(10, ("refusing to overflow align "
4742 "reply at stream %u\n",
4744 TALLOC_FREE(namebuf);
4745 return STATUS_BUFFER_OVERFLOW;
4748 memset(data+next_offset, 0, align);
4749 next_offset += align;
4751 SIVAL(data, ofs, next_offset - ofs);
4758 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4762 return NT_STATUS_OK;
4765 /****************************************************************************
4766 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4767 ****************************************************************************/
4769 static void call_trans2qpipeinfo(connection_struct *conn,
4770 struct smb_request *req,
4771 unsigned int tran_call,
4772 char **pparams, int total_params,
4773 char **ppdata, int total_data,
4774 unsigned int max_data_bytes)
4776 char *params = *pparams;
4777 char *pdata = *ppdata;
4778 unsigned int data_size = 0;
4779 unsigned int param_size = 2;
4780 uint16_t info_level;
4784 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4788 if (total_params < 4) {
4789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4793 fsp = file_fsp(req, SVAL(params,0));
4794 if (!fsp_is_np(fsp)) {
4795 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4799 info_level = SVAL(params,2);
4801 *pparams = (char *)SMB_REALLOC(*pparams,2);
4802 if (*pparams == NULL) {
4803 reply_nterror(req, NT_STATUS_NO_MEMORY);
4808 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4809 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4812 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4813 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4814 if (*ppdata == NULL ) {
4815 reply_nterror(req, NT_STATUS_NO_MEMORY);
4820 switch (info_level) {
4821 case SMB_FILE_STANDARD_INFORMATION:
4823 SOFF_T(pdata,0,4096LL);
4830 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4834 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4840 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4841 TALLOC_CTX *mem_ctx,
4842 uint16_t info_level,
4844 struct smb_filename *smb_fname,
4845 bool delete_pending,
4846 struct timespec write_time_ts,
4847 struct ea_list *ea_list,
4848 int lock_data_count,
4851 unsigned int max_data_bytes,
4852 size_t *fixed_portion,
4854 unsigned int *pdata_size)
4856 char *pdata = *ppdata;
4857 char *dstart, *dend;
4858 unsigned int data_size;
4859 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4860 time_t create_time, mtime, atime, c_time;
4861 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4868 uint64_t file_size = 0;
4870 uint64_t allocation_size = 0;
4871 uint64_t file_index = 0;
4872 uint32_t access_mask = 0;
4875 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4876 return NT_STATUS_INVALID_LEVEL;
4879 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4880 smb_fname_str_dbg(smb_fname),
4882 info_level, max_data_bytes));
4884 mode = dos_mode(conn, smb_fname);
4885 nlink = psbuf->st_ex_nlink;
4887 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4891 if ((nlink > 0) && delete_pending) {
4895 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4896 return NT_STATUS_INVALID_PARAMETER;
4899 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4900 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4901 if (*ppdata == NULL) {
4902 return NT_STATUS_NO_MEMORY;
4906 dend = dstart + data_size - 1;
4908 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4909 update_stat_ex_mtime(psbuf, write_time_ts);
4912 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4913 mtime_ts = psbuf->st_ex_mtime;
4914 atime_ts = psbuf->st_ex_atime;
4915 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4917 if (lp_dos_filetime_resolution(SNUM(conn))) {
4918 dos_filetime_timespec(&create_time_ts);
4919 dos_filetime_timespec(&mtime_ts);
4920 dos_filetime_timespec(&atime_ts);
4921 dos_filetime_timespec(&ctime_ts);
4924 create_time = convert_timespec_to_time_t(create_time_ts);
4925 mtime = convert_timespec_to_time_t(mtime_ts);
4926 atime = convert_timespec_to_time_t(atime_ts);
4927 c_time = convert_timespec_to_time_t(ctime_ts);
4929 p = strrchr_m(smb_fname->base_name,'/');
4931 base_name = smb_fname->base_name;
4935 /* NT expects the name to be in an exact form of the *full*
4936 filename. See the trans2 torture test */
4937 if (ISDOT(base_name)) {
4938 dos_fname = talloc_strdup(mem_ctx, "\\");
4940 return NT_STATUS_NO_MEMORY;
4943 dos_fname = talloc_asprintf(mem_ctx,
4945 smb_fname->base_name);
4947 return NT_STATUS_NO_MEMORY;
4949 if (is_ntfs_stream_smb_fname(smb_fname)) {
4950 dos_fname = talloc_asprintf(dos_fname, "%s",
4951 smb_fname->stream_name);
4953 return NT_STATUS_NO_MEMORY;
4957 string_replace(dos_fname, '/', '\\');
4960 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4963 /* Do we have this path open ? */
4965 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4966 fsp1 = file_find_di_first(conn->sconn, fileid);
4967 if (fsp1 && fsp1->initial_allocation_size) {
4968 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4972 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4973 file_size = get_file_size_stat(psbuf);
4977 pos = fsp->fh->position_information;
4981 access_mask = fsp->access_mask;
4983 /* GENERIC_EXECUTE mapping from Windows */
4984 access_mask = 0x12019F;
4987 /* This should be an index number - looks like
4990 I think this causes us to fail the IFSKIT
4991 BasicFileInformationTest. -tpot */
4992 file_index = get_FileIndex(conn, psbuf);
4996 switch (info_level) {
4997 case SMB_INFO_STANDARD:
4998 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5000 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5001 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5002 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5003 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5004 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5005 SSVAL(pdata,l1_attrFile,mode);
5008 case SMB_INFO_QUERY_EA_SIZE:
5010 unsigned int ea_size =
5011 estimate_ea_size(conn, fsp,
5013 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5015 srv_put_dos_date2(pdata,0,create_time);
5016 srv_put_dos_date2(pdata,4,atime);
5017 srv_put_dos_date2(pdata,8,mtime); /* write time */
5018 SIVAL(pdata,12,(uint32_t)file_size);
5019 SIVAL(pdata,16,(uint32_t)allocation_size);
5020 SSVAL(pdata,20,mode);
5021 SIVAL(pdata,22,ea_size);
5025 case SMB_INFO_IS_NAME_VALID:
5026 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5028 /* os/2 needs this ? really ?*/
5029 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5031 /* This is only reached for qpathinfo */
5035 case SMB_INFO_QUERY_EAS_FROM_LIST:
5037 size_t total_ea_len = 0;
5038 struct ea_list *ea_file_list = NULL;
5039 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5042 get_ea_list_from_file(mem_ctx, conn, fsp,
5044 &total_ea_len, &ea_file_list);
5045 if (!NT_STATUS_IS_OK(status)) {
5049 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5051 if (!ea_list || (total_ea_len > data_size)) {
5053 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5057 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5061 case SMB_INFO_QUERY_ALL_EAS:
5063 /* We have data_size bytes to put EA's into. */
5064 size_t total_ea_len = 0;
5065 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5067 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5069 &total_ea_len, &ea_list);
5070 if (!NT_STATUS_IS_OK(status)) {
5074 if (!ea_list || (total_ea_len > data_size)) {
5076 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5080 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5084 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5086 /* This is FileFullEaInformation - 0xF which maps to
5087 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5089 /* We have data_size bytes to put EA's into. */
5090 size_t total_ea_len = 0;
5091 struct ea_list *ea_file_list = NULL;
5093 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5095 /*TODO: add filtering and index handling */
5098 get_ea_list_from_file(mem_ctx, conn, fsp,
5100 &total_ea_len, &ea_file_list);
5101 if (!NT_STATUS_IS_OK(status)) {
5104 if (!ea_file_list) {
5105 return NT_STATUS_NO_EAS_ON_FILE;
5108 status = fill_ea_chained_buffer(mem_ctx,
5112 conn, ea_file_list);
5113 if (!NT_STATUS_IS_OK(status)) {
5119 case SMB_FILE_BASIC_INFORMATION:
5120 case SMB_QUERY_FILE_BASIC_INFO:
5122 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5123 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5124 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5126 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5130 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5131 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5132 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5133 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5134 SIVAL(pdata,32,mode);
5136 DEBUG(5,("SMB_QFBI - "));
5137 DEBUG(5,("create: %s ", ctime(&create_time)));
5138 DEBUG(5,("access: %s ", ctime(&atime)));
5139 DEBUG(5,("write: %s ", ctime(&mtime)));
5140 DEBUG(5,("change: %s ", ctime(&c_time)));
5141 DEBUG(5,("mode: %x\n", mode));
5142 *fixed_portion = data_size;
5145 case SMB_FILE_STANDARD_INFORMATION:
5146 case SMB_QUERY_FILE_STANDARD_INFO:
5148 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5150 SOFF_T(pdata,0,allocation_size);
5151 SOFF_T(pdata,8,file_size);
5152 SIVAL(pdata,16,nlink);
5153 SCVAL(pdata,20,delete_pending?1:0);
5154 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5155 SSVAL(pdata,22,0); /* Padding. */
5156 *fixed_portion = 24;
5159 case SMB_FILE_EA_INFORMATION:
5160 case SMB_QUERY_FILE_EA_INFO:
5162 unsigned int ea_size =
5163 estimate_ea_size(conn, fsp, smb_fname);
5164 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5167 SIVAL(pdata,0,ea_size);
5171 /* Get the 8.3 name - used if NT SMB was negotiated. */
5172 case SMB_QUERY_FILE_ALT_NAME_INFO:
5173 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5175 char mangled_name[13];
5176 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5177 if (!name_to_8_3(base_name,mangled_name,
5178 True,conn->params)) {
5179 return NT_STATUS_NO_MEMORY;
5181 status = srvstr_push(dstart, flags2,
5182 pdata+4, mangled_name,
5183 PTR_DIFF(dend, pdata+4),
5185 if (!NT_STATUS_IS_OK(status)) {
5188 data_size = 4 + len;
5194 case SMB_QUERY_FILE_NAME_INFO:
5197 this must be *exactly* right for ACLs on mapped drives to work
5199 status = srvstr_push(dstart, flags2,
5201 PTR_DIFF(dend, pdata+4),
5203 if (!NT_STATUS_IS_OK(status)) {
5206 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5207 data_size = 4 + len;
5212 case SMB_FILE_ALLOCATION_INFORMATION:
5213 case SMB_QUERY_FILE_ALLOCATION_INFO:
5214 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5216 SOFF_T(pdata,0,allocation_size);
5219 case SMB_FILE_END_OF_FILE_INFORMATION:
5220 case SMB_QUERY_FILE_END_OF_FILEINFO:
5221 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5223 SOFF_T(pdata,0,file_size);
5226 case SMB_QUERY_FILE_ALL_INFO:
5227 case SMB_FILE_ALL_INFORMATION:
5229 unsigned int ea_size =
5230 estimate_ea_size(conn, fsp, smb_fname);
5231 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5232 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5233 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5234 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5235 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5236 SIVAL(pdata,32,mode);
5237 SIVAL(pdata,36,0); /* padding. */
5239 SOFF_T(pdata,0,allocation_size);
5240 SOFF_T(pdata,8,file_size);
5241 SIVAL(pdata,16,nlink);
5242 SCVAL(pdata,20,delete_pending);
5243 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5246 SIVAL(pdata,0,ea_size);
5247 pdata += 4; /* EA info */
5248 status = srvstr_push(dstart, flags2,
5250 PTR_DIFF(dend, pdata+4),
5252 if (!NT_STATUS_IS_OK(status)) {
5257 data_size = PTR_DIFF(pdata,(*ppdata));
5258 *fixed_portion = 10;
5262 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5264 unsigned int ea_size =
5265 estimate_ea_size(conn, fsp, smb_fname);
5266 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5267 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5268 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5269 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5270 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5271 SIVAL(pdata, 0x20, mode);
5272 SIVAL(pdata, 0x24, 0); /* padding. */
5273 SBVAL(pdata, 0x28, allocation_size);
5274 SBVAL(pdata, 0x30, file_size);
5275 SIVAL(pdata, 0x38, nlink);
5276 SCVAL(pdata, 0x3C, delete_pending);
5277 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5278 SSVAL(pdata, 0x3E, 0); /* padding */
5279 SBVAL(pdata, 0x40, file_index);
5280 SIVAL(pdata, 0x48, ea_size);
5281 SIVAL(pdata, 0x4C, access_mask);
5282 SBVAL(pdata, 0x50, pos);
5283 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5284 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5288 status = srvstr_push(dstart, flags2,
5290 PTR_DIFF(dend, pdata+4),
5292 if (!NT_STATUS_IS_OK(status)) {
5297 data_size = PTR_DIFF(pdata,(*ppdata));
5298 *fixed_portion = 104;
5301 case SMB_FILE_INTERNAL_INFORMATION:
5303 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5304 SBVAL(pdata, 0, file_index);
5309 case SMB_FILE_ACCESS_INFORMATION:
5310 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5311 SIVAL(pdata, 0, access_mask);
5316 case SMB_FILE_NAME_INFORMATION:
5317 /* Pathname with leading '\'. */
5320 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5321 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5322 SIVAL(pdata,0,byte_len);
5323 data_size = 4 + byte_len;
5327 case SMB_FILE_DISPOSITION_INFORMATION:
5328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5330 SCVAL(pdata,0,delete_pending);
5334 case SMB_FILE_POSITION_INFORMATION:
5335 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5337 SOFF_T(pdata,0,pos);
5341 case SMB_FILE_MODE_INFORMATION:
5342 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5343 SIVAL(pdata,0,mode);
5348 case SMB_FILE_ALIGNMENT_INFORMATION:
5349 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5350 SIVAL(pdata,0,0); /* No alignment needed. */
5356 * NT4 server just returns "invalid query" to this - if we try
5357 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5360 /* The first statement above is false - verified using Thursby
5361 * client against NT4 -- gcolley.
5363 case SMB_QUERY_FILE_STREAM_INFO:
5364 case SMB_FILE_STREAM_INFORMATION: {
5365 unsigned int num_streams = 0;
5366 struct stream_struct *streams = NULL;
5368 DEBUG(10,("smbd_do_qfilepathinfo: "
5369 "SMB_FILE_STREAM_INFORMATION\n"));
5371 if (is_ntfs_stream_smb_fname(smb_fname)) {
5372 return NT_STATUS_INVALID_PARAMETER;
5375 status = vfs_streaminfo(conn,
5382 if (!NT_STATUS_IS_OK(status)) {
5383 DEBUG(10, ("could not get stream info: %s\n",
5384 nt_errstr(status)));
5388 status = marshall_stream_info(num_streams, streams,
5389 pdata, max_data_bytes,
5392 if (!NT_STATUS_IS_OK(status)) {
5393 DEBUG(10, ("marshall_stream_info failed: %s\n",
5394 nt_errstr(status)));
5395 TALLOC_FREE(streams);
5399 TALLOC_FREE(streams);
5401 *fixed_portion = 32;
5405 case SMB_QUERY_COMPRESSION_INFO:
5406 case SMB_FILE_COMPRESSION_INFORMATION:
5407 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5408 SOFF_T(pdata,0,file_size);
5409 SIVAL(pdata,8,0); /* ??? */
5410 SIVAL(pdata,12,0); /* ??? */
5412 *fixed_portion = 16;
5415 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5416 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5417 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5418 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5419 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5420 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5421 SOFF_T(pdata,32,allocation_size);
5422 SOFF_T(pdata,40,file_size);
5423 SIVAL(pdata,48,mode);
5424 SIVAL(pdata,52,0); /* ??? */
5426 *fixed_portion = 56;
5429 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5430 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5431 SIVAL(pdata,0,mode);
5438 * CIFS UNIX Extensions.
5441 case SMB_QUERY_FILE_UNIX_BASIC:
5443 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5444 data_size = PTR_DIFF(pdata,(*ppdata));
5446 DEBUG(4,("smbd_do_qfilepathinfo: "
5447 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5448 dump_data(4, (uint8_t *)(*ppdata), data_size);
5452 case SMB_QUERY_FILE_UNIX_INFO2:
5454 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5455 data_size = PTR_DIFF(pdata,(*ppdata));
5459 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5461 for (i=0; i<100; i++)
5462 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5468 case SMB_QUERY_FILE_UNIX_LINK:
5471 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5474 return NT_STATUS_NO_MEMORY;
5477 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5479 if(!S_ISLNK(psbuf->st_ex_mode)) {
5480 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5483 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5485 link_len = SMB_VFS_READLINK(conn,
5486 smb_fname->base_name,
5488 if (link_len == -1) {
5489 return map_nt_error_from_unix(errno);
5491 buffer[link_len] = 0;
5492 status = srvstr_push(dstart, flags2,
5494 PTR_DIFF(dend, pdata),
5495 STR_TERMINATE, &len);
5496 if (!NT_STATUS_IS_OK(status)) {
5500 data_size = PTR_DIFF(pdata,(*ppdata));
5505 #if defined(HAVE_POSIX_ACLS)
5506 case SMB_QUERY_POSIX_ACL:
5508 SMB_ACL_T file_acl = NULL;
5509 SMB_ACL_T def_acl = NULL;
5510 uint16_t num_file_acls = 0;
5511 uint16_t num_def_acls = 0;
5513 status = refuse_symlink(conn,
5516 if (!NT_STATUS_IS_OK(status)) {
5520 if (fsp && fsp->fh->fd != -1) {
5521 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5525 SMB_VFS_SYS_ACL_GET_FILE(conn,
5527 SMB_ACL_TYPE_ACCESS,
5531 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5532 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5533 "not implemented on "
5534 "filesystem containing %s\n",
5535 smb_fname->base_name));
5536 return NT_STATUS_NOT_IMPLEMENTED;
5539 if (S_ISDIR(psbuf->st_ex_mode)) {
5540 if (fsp && fsp->is_directory) {
5542 SMB_VFS_SYS_ACL_GET_FILE(
5545 SMB_ACL_TYPE_DEFAULT,
5549 SMB_VFS_SYS_ACL_GET_FILE(
5552 SMB_ACL_TYPE_DEFAULT,
5555 def_acl = free_empty_sys_acl(conn, def_acl);
5558 num_file_acls = count_acl_entries(conn, file_acl);
5559 num_def_acls = count_acl_entries(conn, def_acl);
5561 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5562 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5564 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5565 SMB_POSIX_ACL_HEADER_SIZE) ));
5567 TALLOC_FREE(file_acl);
5570 TALLOC_FREE(def_acl);
5572 return NT_STATUS_BUFFER_TOO_SMALL;
5575 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5576 SSVAL(pdata,2,num_file_acls);
5577 SSVAL(pdata,4,num_def_acls);
5578 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5580 TALLOC_FREE(file_acl);
5583 TALLOC_FREE(def_acl);
5585 return NT_STATUS_INTERNAL_ERROR;
5587 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5589 TALLOC_FREE(file_acl);
5592 TALLOC_FREE(def_acl);
5594 return NT_STATUS_INTERNAL_ERROR;
5598 TALLOC_FREE(file_acl);
5601 TALLOC_FREE(def_acl);
5603 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5609 case SMB_QUERY_POSIX_LOCK:
5614 enum brl_type lock_type;
5616 /* We need an open file with a real fd for this. */
5617 if (!fsp || fsp->fh->fd == -1) {
5618 return NT_STATUS_INVALID_LEVEL;
5621 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5622 return NT_STATUS_INVALID_PARAMETER;
5625 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5626 case POSIX_LOCK_TYPE_READ:
5627 lock_type = READ_LOCK;
5629 case POSIX_LOCK_TYPE_WRITE:
5630 lock_type = WRITE_LOCK;
5632 case POSIX_LOCK_TYPE_UNLOCK:
5634 /* There's no point in asking for an unlock... */
5635 return NT_STATUS_INVALID_PARAMETER;
5638 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5639 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5640 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5642 status = query_lock(fsp,
5649 if (ERROR_WAS_LOCK_DENIED(status)) {
5650 /* Here we need to report who has it locked... */
5651 data_size = POSIX_LOCK_DATA_SIZE;
5653 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5654 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5655 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5656 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5657 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5659 } else if (NT_STATUS_IS_OK(status)) {
5660 /* For success we just return a copy of what we sent
5661 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5662 data_size = POSIX_LOCK_DATA_SIZE;
5663 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5664 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5672 return NT_STATUS_INVALID_LEVEL;
5675 *pdata_size = data_size;
5676 return NT_STATUS_OK;
5679 /****************************************************************************
5680 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5681 file name or file id).
5682 ****************************************************************************/
5684 static void call_trans2qfilepathinfo(connection_struct *conn,
5685 struct smb_request *req,
5686 unsigned int tran_call,
5687 char **pparams, int total_params,
5688 char **ppdata, int total_data,
5689 unsigned int max_data_bytes)
5691 char *params = *pparams;
5692 char *pdata = *ppdata;
5693 uint16_t info_level;
5694 unsigned int data_size = 0;
5695 unsigned int param_size = 2;
5696 struct smb_filename *smb_fname = NULL;
5697 bool delete_pending = False;
5698 struct timespec write_time_ts;
5699 files_struct *fsp = NULL;
5700 struct file_id fileid;
5701 struct ea_list *ea_list = NULL;
5702 int lock_data_count = 0;
5703 char *lock_data = NULL;
5704 size_t fixed_portion;
5705 NTSTATUS status = NT_STATUS_OK;
5708 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5712 ZERO_STRUCT(write_time_ts);
5714 if (tran_call == TRANSACT2_QFILEINFO) {
5715 if (total_params < 4) {
5716 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5721 call_trans2qpipeinfo(conn, req, tran_call,
5722 pparams, total_params,
5728 fsp = file_fsp(req, SVAL(params,0));
5729 info_level = SVAL(params,2);
5731 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5733 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5734 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5738 /* Initial check for valid fsp ptr. */
5739 if (!check_fsp_open(conn, req, fsp)) {
5743 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5744 if (smb_fname == NULL) {
5745 reply_nterror(req, NT_STATUS_NO_MEMORY);
5749 if(fsp->fake_file_handle) {
5751 * This is actually for the QUOTA_FAKE_FILE --metze
5754 /* We know this name is ok, it's already passed the checks. */
5756 } else if(fsp->fh->fd == -1) {
5758 * This is actually a QFILEINFO on a directory
5759 * handle (returned from an NT SMB). NT5.0 seems
5760 * to do this call. JRA.
5763 if (INFO_LEVEL_IS_UNIX(info_level)) {
5764 /* Always do lstat for UNIX calls. */
5765 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5766 DEBUG(3,("call_trans2qfilepathinfo: "
5767 "SMB_VFS_LSTAT of %s failed "
5769 smb_fname_str_dbg(smb_fname),
5772 map_nt_error_from_unix(errno));
5775 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5776 DEBUG(3,("call_trans2qfilepathinfo: "
5777 "SMB_VFS_STAT of %s failed (%s)\n",
5778 smb_fname_str_dbg(smb_fname),
5781 map_nt_error_from_unix(errno));
5785 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5786 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5789 * Original code - this is an open file.
5791 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5792 DEBUG(3, ("fstat of %s failed (%s)\n",
5793 fsp_fnum_dbg(fsp), strerror(errno)));
5795 map_nt_error_from_unix(errno));
5798 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5799 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5805 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5808 if (total_params < 7) {
5809 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5813 info_level = SVAL(params,0);
5815 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5817 if (INFO_LEVEL_IS_UNIX(info_level)) {
5818 if (!lp_unix_extensions()) {
5819 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5822 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5823 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5824 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5825 req->posix_pathnames) {
5826 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5830 if (req->posix_pathnames) {
5831 srvstr_get_path_posix(req,
5840 srvstr_get_path(req,
5849 if (!NT_STATUS_IS_OK(status)) {
5850 reply_nterror(req, status);
5854 status = filename_convert(req,
5860 if (!NT_STATUS_IS_OK(status)) {
5861 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5862 reply_botherror(req,
5863 NT_STATUS_PATH_NOT_COVERED,
5864 ERRSRV, ERRbadpath);
5867 reply_nterror(req, status);
5871 /* If this is a stream, check if there is a delete_pending. */
5872 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5873 && is_ntfs_stream_smb_fname(smb_fname)) {
5874 struct smb_filename *smb_fname_base;
5876 /* Create an smb_filename with stream_name == NULL. */
5877 smb_fname_base = synthetic_smb_fname(
5879 smb_fname->base_name,
5883 if (smb_fname_base == NULL) {
5884 reply_nterror(req, NT_STATUS_NO_MEMORY);
5888 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5889 /* Always do lstat for UNIX calls. */
5890 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5891 DEBUG(3,("call_trans2qfilepathinfo: "
5892 "SMB_VFS_LSTAT of %s failed "
5894 smb_fname_str_dbg(smb_fname_base),
5896 TALLOC_FREE(smb_fname_base);
5898 map_nt_error_from_unix(errno));
5902 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5903 DEBUG(3,("call_trans2qfilepathinfo: "
5904 "fileinfo of %s failed "
5906 smb_fname_str_dbg(smb_fname_base),
5908 TALLOC_FREE(smb_fname_base);
5910 map_nt_error_from_unix(errno));
5915 status = file_name_hash(conn,
5916 smb_fname_str_dbg(smb_fname_base),
5918 if (!NT_STATUS_IS_OK(status)) {
5919 TALLOC_FREE(smb_fname_base);
5920 reply_nterror(req, status);
5924 fileid = vfs_file_id_from_sbuf(conn,
5925 &smb_fname_base->st);
5926 TALLOC_FREE(smb_fname_base);
5927 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5928 if (delete_pending) {
5929 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5934 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5935 /* Always do lstat for UNIX calls. */
5936 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5937 DEBUG(3,("call_trans2qfilepathinfo: "
5938 "SMB_VFS_LSTAT of %s failed (%s)\n",
5939 smb_fname_str_dbg(smb_fname),
5942 map_nt_error_from_unix(errno));
5947 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5948 DEBUG(3,("call_trans2qfilepathinfo: "
5949 "SMB_VFS_STAT of %s failed (%s)\n",
5950 smb_fname_str_dbg(smb_fname),
5953 map_nt_error_from_unix(errno));
5958 status = file_name_hash(conn,
5959 smb_fname_str_dbg(smb_fname),
5961 if (!NT_STATUS_IS_OK(status)) {
5962 reply_nterror(req, status);
5966 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5967 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5968 if (delete_pending) {
5969 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5974 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5975 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5977 info_level,tran_call,total_data));
5979 /* Pull out any data sent here before we realloc. */
5980 switch (info_level) {
5981 case SMB_INFO_QUERY_EAS_FROM_LIST:
5983 /* Pull any EA list from the data portion. */
5986 if (total_data < 4) {
5988 req, NT_STATUS_INVALID_PARAMETER);
5991 ea_size = IVAL(pdata,0);
5993 if (total_data > 0 && ea_size != total_data) {
5994 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5995 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5997 req, NT_STATUS_INVALID_PARAMETER);
6001 if (!lp_ea_support(SNUM(conn))) {
6002 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6006 /* Pull out the list of names. */
6007 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6010 req, NT_STATUS_INVALID_PARAMETER);
6016 case SMB_QUERY_POSIX_LOCK:
6018 if (fsp == NULL || fsp->fh->fd == -1) {
6019 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6023 if (total_data != POSIX_LOCK_DATA_SIZE) {
6025 req, NT_STATUS_INVALID_PARAMETER);
6029 /* Copy the lock range data. */
6030 lock_data = (char *)talloc_memdup(
6031 req, pdata, total_data);
6033 reply_nterror(req, NT_STATUS_NO_MEMORY);
6036 lock_data_count = total_data;
6042 *pparams = (char *)SMB_REALLOC(*pparams,2);
6043 if (*pparams == NULL) {
6044 reply_nterror(req, NT_STATUS_NO_MEMORY);
6051 * draft-leach-cifs-v1-spec-02.txt
6052 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6055 * The requested information is placed in the Data portion of the
6056 * transaction response. For the information levels greater than 0x100,
6057 * the transaction response has 1 parameter word which should be
6058 * ignored by the client.
6060 * However Windows only follows this rule for the IS_NAME_VALID call.
6062 switch (info_level) {
6063 case SMB_INFO_IS_NAME_VALID:
6068 if ((info_level & 0xFF00) == 0xFF00) {
6070 * We use levels that start with 0xFF00
6071 * internally to represent SMB2 specific levels
6073 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6077 status = smbd_do_qfilepathinfo(conn, req, info_level,
6079 delete_pending, write_time_ts,
6081 lock_data_count, lock_data,
6082 req->flags2, max_data_bytes,
6084 ppdata, &data_size);
6085 if (!NT_STATUS_IS_OK(status)) {
6086 reply_nterror(req, status);
6089 if (fixed_portion > max_data_bytes) {
6090 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6094 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6100 /****************************************************************************
6101 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6103 ****************************************************************************/
6105 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6106 connection_struct *conn,
6107 struct smb_request *req,
6108 bool overwrite_if_exists,
6109 const struct smb_filename *smb_fname_old,
6110 struct smb_filename *smb_fname_new)
6112 NTSTATUS status = NT_STATUS_OK;
6114 /* source must already exist. */
6115 if (!VALID_STAT(smb_fname_old->st)) {
6116 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6119 if (VALID_STAT(smb_fname_new->st)) {
6120 if (overwrite_if_exists) {
6121 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6122 return NT_STATUS_FILE_IS_A_DIRECTORY;
6124 status = unlink_internals(conn,
6126 FILE_ATTRIBUTE_NORMAL,
6129 if (!NT_STATUS_IS_OK(status)) {
6133 /* Disallow if newname already exists. */
6134 return NT_STATUS_OBJECT_NAME_COLLISION;
6138 /* No links from a directory. */
6139 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6140 return NT_STATUS_FILE_IS_A_DIRECTORY;
6143 /* Setting a hardlink to/from a stream isn't currently supported. */
6144 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6145 is_ntfs_stream_smb_fname(smb_fname_new)) {
6146 return NT_STATUS_INVALID_PARAMETER;
6149 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6150 smb_fname_old->base_name, smb_fname_new->base_name));
6152 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
6153 smb_fname_new->base_name) != 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 *smb_fname)
6614 char *link_target = NULL;
6615 const char *newname = smb_fname->base_name;
6616 TALLOC_CTX *ctx = talloc_tos();
6618 /* Set a symbolic link. */
6619 /* Don't allow this if follow links is false. */
6621 if (total_data == 0) {
6622 return NT_STATUS_INVALID_PARAMETER;
6625 if (!lp_follow_symlinks(SNUM(conn))) {
6626 return NT_STATUS_ACCESS_DENIED;
6629 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6630 total_data, STR_TERMINATE);
6633 return NT_STATUS_INVALID_PARAMETER;
6636 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6637 newname, link_target ));
6639 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6640 return map_nt_error_from_unix(errno);
6643 return NT_STATUS_OK;
6646 /****************************************************************************
6647 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6648 ****************************************************************************/
6650 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6651 struct smb_request *req,
6652 const char *pdata, int total_data,
6653 struct smb_filename *smb_fname_new)
6655 char *oldname = NULL;
6656 struct smb_filename *smb_fname_old = NULL;
6657 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6658 TALLOC_CTX *ctx = talloc_tos();
6659 NTSTATUS status = NT_STATUS_OK;
6661 /* Set a hard link. */
6662 if (total_data == 0) {
6663 return NT_STATUS_INVALID_PARAMETER;
6666 if (req->posix_pathnames) {
6667 srvstr_get_path_posix(ctx,
6676 srvstr_get_path(ctx,
6685 if (!NT_STATUS_IS_OK(status)) {
6689 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6690 smb_fname_str_dbg(smb_fname_new), oldname));
6692 status = filename_convert(ctx,
6698 if (!NT_STATUS_IS_OK(status)) {
6702 return hardlink_internals(ctx, conn, req, false,
6703 smb_fname_old, smb_fname_new);
6706 /****************************************************************************
6707 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6708 ****************************************************************************/
6710 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6711 struct smb_request *req,
6715 struct smb_filename *smb_fname_src)
6719 char *newname = NULL;
6720 struct smb_filename *smb_fname_dst = NULL;
6721 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6722 ucf_flags_from_smb_request(req);
6723 NTSTATUS status = NT_STATUS_OK;
6724 TALLOC_CTX *ctx = talloc_tos();
6727 return NT_STATUS_INVALID_HANDLE;
6730 if (total_data < 20) {
6731 return NT_STATUS_INVALID_PARAMETER;
6734 overwrite = (CVAL(pdata,0) ? True : False);
6735 len = IVAL(pdata,16);
6737 if (len > (total_data - 20) || (len == 0)) {
6738 return NT_STATUS_INVALID_PARAMETER;
6741 if (req->posix_pathnames) {
6742 srvstr_get_path_posix(ctx,
6751 srvstr_get_path(ctx,
6760 if (!NT_STATUS_IS_OK(status)) {
6764 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6767 status = filename_convert(ctx,
6773 if (!NT_STATUS_IS_OK(status)) {
6777 if (fsp->base_fsp) {
6778 /* newname must be a stream name. */
6779 if (newname[0] != ':') {
6780 return NT_STATUS_NOT_SUPPORTED;
6783 /* Create an smb_fname to call rename_internals_fsp() with. */
6784 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6785 fsp->base_fsp->fsp_name->base_name,
6788 fsp->base_fsp->fsp_name->flags);
6789 if (smb_fname_dst == NULL) {
6790 status = NT_STATUS_NO_MEMORY;
6795 * Set the original last component, since
6796 * rename_internals_fsp() requires it.
6798 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6800 if (smb_fname_dst->original_lcomp == NULL) {
6801 status = NT_STATUS_NO_MEMORY;
6807 DEBUG(10,("smb2_file_rename_information: "
6808 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6809 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6810 smb_fname_str_dbg(smb_fname_dst)));
6811 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6812 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6816 TALLOC_FREE(smb_fname_dst);
6820 static NTSTATUS smb_file_link_information(connection_struct *conn,
6821 struct smb_request *req,
6825 struct smb_filename *smb_fname_src)
6829 char *newname = NULL;
6830 struct smb_filename *smb_fname_dst = NULL;
6831 NTSTATUS status = NT_STATUS_OK;
6832 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6833 ucf_flags_from_smb_request(req);
6834 TALLOC_CTX *ctx = talloc_tos();
6837 return NT_STATUS_INVALID_HANDLE;
6840 if (total_data < 20) {
6841 return NT_STATUS_INVALID_PARAMETER;
6844 overwrite = (CVAL(pdata,0) ? true : false);
6845 len = IVAL(pdata,16);
6847 if (len > (total_data - 20) || (len == 0)) {
6848 return NT_STATUS_INVALID_PARAMETER;
6851 if (req->posix_pathnames) {
6852 srvstr_get_path_posix(ctx,
6861 srvstr_get_path(ctx,
6870 if (!NT_STATUS_IS_OK(status)) {
6874 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6877 status = filename_convert(ctx,
6883 if (!NT_STATUS_IS_OK(status)) {
6887 if (fsp->base_fsp) {
6888 /* No stream names. */
6889 return NT_STATUS_NOT_SUPPORTED;
6892 DEBUG(10,("smb_file_link_information: "
6893 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6894 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6895 smb_fname_str_dbg(smb_fname_dst)));
6896 status = hardlink_internals(ctx,
6903 TALLOC_FREE(smb_fname_dst);
6907 /****************************************************************************
6908 Deal with SMB_FILE_RENAME_INFORMATION.
6909 ****************************************************************************/
6911 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6912 struct smb_request *req,
6916 struct smb_filename *smb_fname_src)
6921 char *newname = NULL;
6922 struct smb_filename *smb_fname_dst = NULL;
6923 bool dest_has_wcard = False;
6924 NTSTATUS status = NT_STATUS_OK;
6926 TALLOC_CTX *ctx = talloc_tos();
6928 if (total_data < 13) {
6929 return NT_STATUS_INVALID_PARAMETER;
6932 overwrite = (CVAL(pdata,0) ? True : False);
6933 root_fid = IVAL(pdata,4);
6934 len = IVAL(pdata,8);
6936 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6937 return NT_STATUS_INVALID_PARAMETER;
6940 if (req->posix_pathnames) {
6941 srvstr_get_path_wcard_posix(ctx,
6951 srvstr_get_path_wcard(ctx,
6961 if (!NT_STATUS_IS_OK(status)) {
6965 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6968 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
6969 status = resolve_dfspath_wcard(ctx, conn,
6971 UCF_COND_ALLOW_WCARD_LCOMP,
6972 !conn->sconn->using_smb2,
6975 if (!NT_STATUS_IS_OK(status)) {
6980 /* Check the new name has no '/' characters. */
6981 if (strchr_m(newname, '/')) {
6982 return NT_STATUS_NOT_SUPPORTED;
6985 if (fsp && fsp->base_fsp) {
6986 /* newname must be a stream name. */
6987 if (newname[0] != ':') {
6988 return NT_STATUS_NOT_SUPPORTED;
6991 /* Create an smb_fname to call rename_internals_fsp() with. */
6992 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6993 fsp->base_fsp->fsp_name->base_name,
6996 fsp->base_fsp->fsp_name->flags);
6997 if (smb_fname_dst == NULL) {
6998 status = NT_STATUS_NO_MEMORY;
7003 * Set the original last component, since
7004 * rename_internals_fsp() requires it.
7006 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7008 if (smb_fname_dst->original_lcomp == NULL) {
7009 status = NT_STATUS_NO_MEMORY;
7015 * Build up an smb_fname_dst based on the filename passed in.
7016 * We basically just strip off the last component, and put on
7017 * the newname instead.
7019 char *base_name = NULL;
7020 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7021 ucf_flags_from_smb_request(req);
7023 if (dest_has_wcard) {
7024 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7027 /* newname must *not* be a stream name. */
7028 if (newname[0] == ':') {
7029 return NT_STATUS_NOT_SUPPORTED;
7033 * Strip off the last component (filename) of the path passed
7036 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7038 return NT_STATUS_NO_MEMORY;
7040 p = strrchr_m(base_name, '/');
7044 base_name = talloc_strdup(ctx, "");
7046 return NT_STATUS_NO_MEMORY;
7049 /* Append the new name. */
7050 base_name = talloc_asprintf_append(base_name,
7054 return NT_STATUS_NO_MEMORY;
7057 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7060 /* If an error we expect this to be
7061 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7063 if (!NT_STATUS_IS_OK(status)) {
7064 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7068 /* Create an smb_fname to call rename_internals_fsp() */
7069 smb_fname_dst = synthetic_smb_fname(ctx,
7073 smb_fname_src->flags);
7074 if (smb_fname_dst == NULL) {
7075 status = NT_STATUS_NO_MEMORY;
7082 DEBUG(10,("smb_file_rename_information: "
7083 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7084 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7085 smb_fname_str_dbg(smb_fname_dst)));
7086 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7089 DEBUG(10,("smb_file_rename_information: "
7090 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7091 smb_fname_str_dbg(smb_fname_src),
7092 smb_fname_str_dbg(smb_fname_dst)));
7093 status = rename_internals(ctx, conn, req, smb_fname_src,
7094 smb_fname_dst, 0, overwrite, false,
7096 FILE_WRITE_ATTRIBUTES);
7099 TALLOC_FREE(smb_fname_dst);
7103 /****************************************************************************
7104 Deal with SMB_SET_POSIX_ACL.
7105 ****************************************************************************/
7107 #if defined(HAVE_POSIX_ACLS)
7108 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7112 const struct smb_filename *smb_fname)
7114 uint16_t posix_acl_version;
7115 uint16_t num_file_acls;
7116 uint16_t num_def_acls;
7117 bool valid_file_acls = True;
7118 bool valid_def_acls = True;
7121 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7122 return NT_STATUS_INVALID_PARAMETER;
7124 posix_acl_version = SVAL(pdata,0);
7125 num_file_acls = SVAL(pdata,2);
7126 num_def_acls = SVAL(pdata,4);
7128 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7129 valid_file_acls = False;
7133 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7134 valid_def_acls = False;
7138 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7139 return NT_STATUS_INVALID_PARAMETER;
7142 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7143 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7144 return NT_STATUS_INVALID_PARAMETER;
7147 status = refuse_symlink(conn, fsp, smb_fname);
7148 if (!NT_STATUS_IS_OK(status)) {
7152 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7153 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7154 (unsigned int)num_file_acls,
7155 (unsigned int)num_def_acls));
7157 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7158 smb_fname, num_file_acls,
7159 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7160 return map_nt_error_from_unix(errno);
7163 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7164 smb_fname, num_def_acls,
7165 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7166 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7167 return map_nt_error_from_unix(errno);
7169 return NT_STATUS_OK;
7173 /****************************************************************************
7174 Deal with SMB_SET_POSIX_LOCK.
7175 ****************************************************************************/
7177 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7178 struct smb_request *req,
7186 bool blocking_lock = False;
7187 enum brl_type lock_type;
7189 NTSTATUS status = NT_STATUS_OK;
7191 if (fsp == NULL || fsp->fh->fd == -1) {
7192 return NT_STATUS_INVALID_HANDLE;
7195 if (total_data != POSIX_LOCK_DATA_SIZE) {
7196 return NT_STATUS_INVALID_PARAMETER;
7199 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7200 case POSIX_LOCK_TYPE_READ:
7201 lock_type = READ_LOCK;
7203 case POSIX_LOCK_TYPE_WRITE:
7204 /* Return the right POSIX-mappable error code for files opened read-only. */
7205 if (!fsp->can_write) {
7206 return NT_STATUS_INVALID_HANDLE;
7208 lock_type = WRITE_LOCK;
7210 case POSIX_LOCK_TYPE_UNLOCK:
7211 lock_type = UNLOCK_LOCK;
7214 return NT_STATUS_INVALID_PARAMETER;
7217 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7218 blocking_lock = False;
7219 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7220 blocking_lock = True;
7222 return NT_STATUS_INVALID_PARAMETER;
7225 if (!lp_blocking_locks(SNUM(conn))) {
7226 blocking_lock = False;
7229 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7230 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7231 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7232 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7233 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7235 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7236 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7238 (unsigned int)lock_type,
7239 (unsigned long long)smblctx,
7243 if (lock_type == UNLOCK_LOCK) {
7244 status = do_unlock(req->sconn->msg_ctx,
7251 uint64_t block_smblctx;
7253 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7264 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7266 * A blocking lock was requested. Package up
7267 * this smb into a queued request and push it
7268 * onto the blocking lock queue.
7270 if(push_blocking_lock_request(br_lck,
7273 -1, /* infinite timeout. */
7281 TALLOC_FREE(br_lck);
7285 TALLOC_FREE(br_lck);
7291 /****************************************************************************
7292 Deal with SMB_SET_FILE_BASIC_INFO.
7293 ****************************************************************************/
7295 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7299 const struct smb_filename *smb_fname)
7301 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7302 struct smb_file_time ft;
7303 uint32_t dosmode = 0;
7304 NTSTATUS status = NT_STATUS_OK;
7308 if (total_data < 36) {
7309 return NT_STATUS_INVALID_PARAMETER;
7312 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7313 if (!NT_STATUS_IS_OK(status)) {
7317 /* Set the attributes */
7318 dosmode = IVAL(pdata,32);
7319 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7320 if (!NT_STATUS_IS_OK(status)) {
7325 ft.create_time = interpret_long_date(pdata);
7328 ft.atime = interpret_long_date(pdata+8);
7331 ft.mtime = interpret_long_date(pdata+16);
7334 ft.ctime = interpret_long_date(pdata+24);
7336 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7337 smb_fname_str_dbg(smb_fname)));
7339 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7343 /****************************************************************************
7344 Deal with SMB_INFO_STANDARD.
7345 ****************************************************************************/
7347 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7351 const struct smb_filename *smb_fname)
7354 struct smb_file_time ft;
7358 if (total_data < 12) {
7359 return NT_STATUS_INVALID_PARAMETER;
7363 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7365 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7367 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7369 DEBUG(10,("smb_set_info_standard: file %s\n",
7370 smb_fname_str_dbg(smb_fname)));
7372 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7373 if (!NT_STATUS_IS_OK(status)) {
7377 return smb_set_file_time(conn,
7384 /****************************************************************************
7385 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7386 ****************************************************************************/
7388 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7389 struct smb_request *req,
7393 struct smb_filename *smb_fname)
7395 uint64_t allocation_size = 0;
7396 NTSTATUS status = NT_STATUS_OK;
7397 files_struct *new_fsp = NULL;
7399 if (!VALID_STAT(smb_fname->st)) {
7400 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7403 if (total_data < 8) {
7404 return NT_STATUS_INVALID_PARAMETER;
7407 allocation_size = (uint64_t)IVAL(pdata,0);
7408 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7409 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7410 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7411 (double)allocation_size));
7413 if (allocation_size) {
7414 allocation_size = smb_roundup(conn, allocation_size);
7417 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7418 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7419 (double)allocation_size));
7421 if (fsp && fsp->fh->fd != -1) {
7422 /* Open file handle. */
7423 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7424 return NT_STATUS_ACCESS_DENIED;
7427 /* Only change if needed. */
7428 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7429 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7430 return map_nt_error_from_unix(errno);
7433 /* But always update the time. */
7435 * This is equivalent to a write. Ensure it's seen immediately
7436 * if there are no pending writes.
7438 trigger_write_time_update_immediate(fsp);
7439 return NT_STATUS_OK;
7442 /* Pathname or stat or directory file. */
7443 status = SMB_VFS_CREATE_FILE(
7446 0, /* root_dir_fid */
7447 smb_fname, /* fname */
7448 FILE_WRITE_DATA, /* access_mask */
7449 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7451 FILE_OPEN, /* create_disposition*/
7452 0, /* create_options */
7453 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7454 0, /* oplock_request */
7456 0, /* allocation_size */
7457 0, /* private_flags */
7460 &new_fsp, /* result */
7462 NULL, NULL); /* create context */
7464 if (!NT_STATUS_IS_OK(status)) {
7465 /* NB. We check for open_was_deferred in the caller. */
7469 /* Only change if needed. */
7470 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7471 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7472 status = map_nt_error_from_unix(errno);
7473 close_file(req, new_fsp, NORMAL_CLOSE);
7478 /* Changing the allocation size should set the last mod time. */
7480 * This is equivalent to a write. Ensure it's seen immediately
7481 * if there are no pending writes.
7483 trigger_write_time_update_immediate(new_fsp);
7484 close_file(req, new_fsp, NORMAL_CLOSE);
7485 return NT_STATUS_OK;
7488 /****************************************************************************
7489 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7490 ****************************************************************************/
7492 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7493 struct smb_request *req,
7497 const struct smb_filename *smb_fname,
7498 bool fail_after_createfile)
7502 if (total_data < 8) {
7503 return NT_STATUS_INVALID_PARAMETER;
7506 size = IVAL(pdata,0);
7507 size |= (((off_t)IVAL(pdata,4)) << 32);
7508 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7509 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7512 return smb_set_file_size(conn, req,
7517 fail_after_createfile);
7520 /****************************************************************************
7521 Allow a UNIX info mknod.
7522 ****************************************************************************/
7524 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7527 const struct smb_filename *smb_fname)
7529 uint32_t file_type = IVAL(pdata,56);
7530 #if defined(HAVE_MAKEDEV)
7531 uint32_t dev_major = IVAL(pdata,60);
7532 uint32_t dev_minor = IVAL(pdata,68);
7534 SMB_DEV_T dev = (SMB_DEV_T)0;
7535 uint32_t raw_unixmode = IVAL(pdata,84);
7539 if (total_data < 100) {
7540 return NT_STATUS_INVALID_PARAMETER;
7543 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7544 PERM_NEW_FILE, &unixmode);
7545 if (!NT_STATUS_IS_OK(status)) {
7549 #if defined(HAVE_MAKEDEV)
7550 dev = makedev(dev_major, dev_minor);
7553 switch (file_type) {
7554 #if defined(S_IFIFO)
7555 case UNIX_TYPE_FIFO:
7556 unixmode |= S_IFIFO;
7559 #if defined(S_IFSOCK)
7560 case UNIX_TYPE_SOCKET:
7561 unixmode |= S_IFSOCK;
7564 #if defined(S_IFCHR)
7565 case UNIX_TYPE_CHARDEV:
7566 unixmode |= S_IFCHR;
7569 #if defined(S_IFBLK)
7570 case UNIX_TYPE_BLKDEV:
7571 unixmode |= S_IFBLK;
7575 return NT_STATUS_INVALID_PARAMETER;
7578 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7579 "%.0f mode 0%o for file %s\n", (double)dev,
7580 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7582 /* Ok - do the mknod. */
7583 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7584 return map_nt_error_from_unix(errno);
7587 /* If any of the other "set" calls fail we
7588 * don't want to end up with a half-constructed mknod.
7591 if (lp_inherit_permissions(SNUM(conn))) {
7593 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7595 return NT_STATUS_NO_MEMORY;
7597 inherit_access_posix_acl(conn, parent, smb_fname,
7599 TALLOC_FREE(parent);
7602 return NT_STATUS_OK;
7605 /****************************************************************************
7606 Deal with SMB_SET_FILE_UNIX_BASIC.
7607 ****************************************************************************/
7609 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7610 struct smb_request *req,
7614 const struct smb_filename *smb_fname)
7616 struct smb_file_time ft;
7617 uint32_t raw_unixmode;
7620 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7621 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7622 NTSTATUS status = NT_STATUS_OK;
7623 bool delete_on_fail = False;
7624 enum perm_type ptype;
7625 files_struct *all_fsps = NULL;
7626 bool modify_mtime = true;
7628 struct smb_filename *smb_fname_tmp = NULL;
7629 SMB_STRUCT_STAT sbuf;
7633 if (total_data < 100) {
7634 return NT_STATUS_INVALID_PARAMETER;
7637 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7638 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7639 size=IVAL(pdata,0); /* first 8 Bytes are size */
7640 size |= (((off_t)IVAL(pdata,4)) << 32);
7643 ft.atime = interpret_long_date(pdata+24); /* access_time */
7644 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7645 set_owner = (uid_t)IVAL(pdata,40);
7646 set_grp = (gid_t)IVAL(pdata,48);
7647 raw_unixmode = IVAL(pdata,84);
7649 if (VALID_STAT(smb_fname->st)) {
7650 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7651 ptype = PERM_EXISTING_DIR;
7653 ptype = PERM_EXISTING_FILE;
7656 ptype = PERM_NEW_FILE;
7659 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7661 if (!NT_STATUS_IS_OK(status)) {
7665 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7666 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7667 smb_fname_str_dbg(smb_fname), (double)size,
7668 (unsigned int)set_owner, (unsigned int)set_grp,
7669 (int)raw_unixmode));
7671 sbuf = smb_fname->st;
7673 if (!VALID_STAT(sbuf)) {
7675 * The only valid use of this is to create character and block
7676 * devices, and named pipes. This is deprecated (IMHO) and
7677 * a new info level should be used for mknod. JRA.
7680 status = smb_unix_mknod(conn,
7684 if (!NT_STATUS_IS_OK(status)) {
7688 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7689 if (smb_fname_tmp == NULL) {
7690 return NT_STATUS_NO_MEMORY;
7693 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7694 status = map_nt_error_from_unix(errno);
7695 TALLOC_FREE(smb_fname_tmp);
7696 SMB_VFS_UNLINK(conn, smb_fname);
7700 sbuf = smb_fname_tmp->st;
7701 smb_fname = smb_fname_tmp;
7703 /* Ensure we don't try and change anything else. */
7704 raw_unixmode = SMB_MODE_NO_CHANGE;
7705 size = get_file_size_stat(&sbuf);
7706 ft.atime = sbuf.st_ex_atime;
7707 ft.mtime = sbuf.st_ex_mtime;
7709 * We continue here as we might want to change the
7712 delete_on_fail = True;
7716 /* Horrible backwards compatibility hack as an old server bug
7717 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7721 size = get_file_size_stat(&sbuf);
7726 * Deal with the UNIX specific mode set.
7729 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7732 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7733 "setting mode 0%o for file %s\n",
7734 (unsigned int)unixmode,
7735 smb_fname_str_dbg(smb_fname)));
7736 if (fsp && fsp->fh->fd != -1) {
7737 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7739 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7742 return map_nt_error_from_unix(errno);
7747 * Deal with the UNIX specific uid set.
7750 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7751 (sbuf.st_ex_uid != set_owner)) {
7754 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7755 "changing owner %u for path %s\n",
7756 (unsigned int)set_owner,
7757 smb_fname_str_dbg(smb_fname)));
7759 if (fsp && fsp->fh->fd != -1) {
7760 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7763 * UNIX extensions calls must always operate
7766 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7767 set_owner, (gid_t)-1);
7771 status = map_nt_error_from_unix(errno);
7772 if (delete_on_fail) {
7773 SMB_VFS_UNLINK(conn, smb_fname);
7780 * Deal with the UNIX specific gid set.
7783 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7784 (sbuf.st_ex_gid != set_grp)) {
7787 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7788 "changing group %u for file %s\n",
7789 (unsigned int)set_owner,
7790 smb_fname_str_dbg(smb_fname)));
7791 if (fsp && fsp->fh->fd != -1) {
7792 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7795 * UNIX extensions calls must always operate
7798 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7802 status = map_nt_error_from_unix(errno);
7803 if (delete_on_fail) {
7804 SMB_VFS_UNLINK(conn, smb_fname);
7810 /* Deal with any size changes. */
7812 status = smb_set_file_size(conn, req,
7818 if (!NT_STATUS_IS_OK(status)) {
7822 /* Deal with any time changes. */
7823 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7824 /* No change, don't cancel anything. */
7828 id = vfs_file_id_from_sbuf(conn, &sbuf);
7829 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7830 all_fsps = file_find_di_next(all_fsps)) {
7832 * We're setting the time explicitly for UNIX.
7833 * Cancel any pending changes over all handles.
7835 all_fsps->update_write_time_on_close = false;
7836 TALLOC_FREE(all_fsps->update_write_time_event);
7840 * Override the "setting_write_time"
7841 * parameter here as it almost does what
7842 * we need. Just remember if we modified
7843 * mtime and send the notify ourselves.
7845 if (null_timespec(ft.mtime)) {
7846 modify_mtime = false;
7849 status = smb_set_file_time(conn,
7855 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7856 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7861 /****************************************************************************
7862 Deal with SMB_SET_FILE_UNIX_INFO2.
7863 ****************************************************************************/
7865 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7866 struct smb_request *req,
7870 const struct smb_filename *smb_fname)
7873 uint32_t smb_fflags;
7876 if (total_data < 116) {
7877 return NT_STATUS_INVALID_PARAMETER;
7880 /* Start by setting all the fields that are common between UNIX_BASIC
7883 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7885 if (!NT_STATUS_IS_OK(status)) {
7889 smb_fflags = IVAL(pdata, 108);
7890 smb_fmask = IVAL(pdata, 112);
7892 /* NB: We should only attempt to alter the file flags if the client
7893 * sends a non-zero mask.
7895 if (smb_fmask != 0) {
7896 int stat_fflags = 0;
7898 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7899 smb_fmask, &stat_fflags)) {
7900 /* Client asked to alter a flag we don't understand. */
7901 return NT_STATUS_INVALID_PARAMETER;
7904 if (fsp && fsp->fh->fd != -1) {
7905 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7906 return NT_STATUS_NOT_SUPPORTED;
7908 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7909 stat_fflags) != 0) {
7910 return map_nt_error_from_unix(errno);
7915 /* XXX: need to add support for changing the create_time here. You
7916 * can do this for paths on Darwin with setattrlist(2). The right way
7917 * to hook this up is probably by extending the VFS utimes interface.
7920 return NT_STATUS_OK;
7923 /****************************************************************************
7924 Create a directory with POSIX semantics.
7925 ****************************************************************************/
7927 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7928 struct smb_request *req,
7931 struct smb_filename *smb_fname,
7932 int *pdata_return_size)
7934 NTSTATUS status = NT_STATUS_OK;
7935 uint32_t raw_unixmode = 0;
7936 uint32_t mod_unixmode = 0;
7937 mode_t unixmode = (mode_t)0;
7938 files_struct *fsp = NULL;
7939 uint16_t info_level_return = 0;
7941 char *pdata = *ppdata;
7943 if (total_data < 18) {
7944 return NT_STATUS_INVALID_PARAMETER;
7947 raw_unixmode = IVAL(pdata,8);
7948 /* Next 4 bytes are not yet defined. */
7950 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7951 PERM_NEW_DIR, &unixmode);
7952 if (!NT_STATUS_IS_OK(status)) {
7956 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7958 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7959 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7961 status = SMB_VFS_CREATE_FILE(
7964 0, /* root_dir_fid */
7965 smb_fname, /* fname */
7966 FILE_READ_ATTRIBUTES, /* access_mask */
7967 FILE_SHARE_NONE, /* share_access */
7968 FILE_CREATE, /* create_disposition*/
7969 FILE_DIRECTORY_FILE, /* create_options */
7970 mod_unixmode, /* file_attributes */
7971 0, /* oplock_request */
7973 0, /* allocation_size */
7974 0, /* private_flags */
7979 NULL, NULL); /* create context */
7981 if (NT_STATUS_IS_OK(status)) {
7982 close_file(req, fsp, NORMAL_CLOSE);
7985 info_level_return = SVAL(pdata,16);
7987 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7988 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7989 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7990 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7992 *pdata_return_size = 12;
7995 /* Realloc the data size */
7996 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7997 if (*ppdata == NULL) {
7998 *pdata_return_size = 0;
7999 return NT_STATUS_NO_MEMORY;
8003 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8004 SSVAL(pdata,2,0); /* No fnum. */
8005 SIVAL(pdata,4,info); /* Was directory created. */
8007 switch (info_level_return) {
8008 case SMB_QUERY_FILE_UNIX_BASIC:
8009 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8010 SSVAL(pdata,10,0); /* Padding. */
8011 store_file_unix_basic(conn, pdata + 12, fsp,
8014 case SMB_QUERY_FILE_UNIX_INFO2:
8015 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8016 SSVAL(pdata,10,0); /* Padding. */
8017 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8021 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8022 SSVAL(pdata,10,0); /* Padding. */
8029 /****************************************************************************
8030 Open/Create a file with POSIX semantics.
8031 ****************************************************************************/
8033 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8034 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8036 static NTSTATUS smb_posix_open(connection_struct *conn,
8037 struct smb_request *req,
8040 struct smb_filename *smb_fname,
8041 int *pdata_return_size)
8043 bool extended_oplock_granted = False;
8044 char *pdata = *ppdata;
8046 uint32_t wire_open_mode = 0;
8047 uint32_t raw_unixmode = 0;
8048 uint32_t mod_unixmode = 0;
8049 uint32_t create_disp = 0;
8050 uint32_t access_mask = 0;
8051 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8052 NTSTATUS status = NT_STATUS_OK;
8053 mode_t unixmode = (mode_t)0;
8054 files_struct *fsp = NULL;
8055 int oplock_request = 0;
8057 uint16_t info_level_return = 0;
8059 if (total_data < 18) {
8060 return NT_STATUS_INVALID_PARAMETER;
8063 flags = IVAL(pdata,0);
8064 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8065 if (oplock_request) {
8066 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8069 wire_open_mode = IVAL(pdata,4);
8071 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8072 return smb_posix_mkdir(conn, req,
8079 switch (wire_open_mode & SMB_ACCMODE) {
8081 access_mask = SMB_O_RDONLY_MAPPING;
8084 access_mask = SMB_O_WRONLY_MAPPING;
8087 access_mask = (SMB_O_RDONLY_MAPPING|
8088 SMB_O_WRONLY_MAPPING);
8091 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8092 (unsigned int)wire_open_mode ));
8093 return NT_STATUS_INVALID_PARAMETER;
8096 wire_open_mode &= ~SMB_ACCMODE;
8098 /* First take care of O_CREAT|O_EXCL interactions. */
8099 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8100 case (SMB_O_CREAT | SMB_O_EXCL):
8101 /* File exists fail. File not exist create. */
8102 create_disp = FILE_CREATE;
8105 /* File exists open. File not exist create. */
8106 create_disp = FILE_OPEN_IF;
8109 /* O_EXCL on its own without O_CREAT is undefined.
8110 We deliberately ignore it as some versions of
8111 Linux CIFSFS can send a bare O_EXCL on the
8112 wire which other filesystems in the kernel
8113 ignore. See bug 9519 for details. */
8118 /* File exists open. File not exist fail. */
8119 create_disp = FILE_OPEN;
8122 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8123 (unsigned int)wire_open_mode ));
8124 return NT_STATUS_INVALID_PARAMETER;
8127 /* Next factor in the effects of O_TRUNC. */
8128 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8130 if (wire_open_mode & SMB_O_TRUNC) {
8131 switch (create_disp) {
8133 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8134 /* Leave create_disp alone as
8135 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8137 /* File exists fail. File not exist create. */
8140 /* SMB_O_CREAT | SMB_O_TRUNC */
8141 /* File exists overwrite. File not exist create. */
8142 create_disp = FILE_OVERWRITE_IF;
8146 /* File exists overwrite. File not exist fail. */
8147 create_disp = FILE_OVERWRITE;
8150 /* Cannot get here. */
8151 smb_panic("smb_posix_open: logic error");
8152 return NT_STATUS_INVALID_PARAMETER;
8156 raw_unixmode = IVAL(pdata,8);
8157 /* Next 4 bytes are not yet defined. */
8159 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8160 (VALID_STAT(smb_fname->st) ?
8161 PERM_EXISTING_FILE : PERM_NEW_FILE),
8164 if (!NT_STATUS_IS_OK(status)) {
8168 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8170 if (wire_open_mode & SMB_O_SYNC) {
8171 create_options |= FILE_WRITE_THROUGH;
8173 if (wire_open_mode & SMB_O_APPEND) {
8174 access_mask |= FILE_APPEND_DATA;
8176 if (wire_open_mode & SMB_O_DIRECT) {
8177 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8180 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8181 VALID_STAT_OF_DIR(smb_fname->st)) {
8182 if (access_mask != SMB_O_RDONLY_MAPPING) {
8183 return NT_STATUS_FILE_IS_A_DIRECTORY;
8185 create_options &= ~FILE_NON_DIRECTORY_FILE;
8186 create_options |= FILE_DIRECTORY_FILE;
8189 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8190 smb_fname_str_dbg(smb_fname),
8191 (unsigned int)wire_open_mode,
8192 (unsigned int)unixmode ));
8194 status = SMB_VFS_CREATE_FILE(
8197 0, /* root_dir_fid */
8198 smb_fname, /* fname */
8199 access_mask, /* access_mask */
8200 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8202 create_disp, /* create_disposition*/
8203 create_options, /* create_options */
8204 mod_unixmode, /* file_attributes */
8205 oplock_request, /* oplock_request */
8207 0, /* allocation_size */
8208 0, /* private_flags */
8213 NULL, NULL); /* create context */
8215 if (!NT_STATUS_IS_OK(status)) {
8219 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8220 extended_oplock_granted = True;
8223 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8224 extended_oplock_granted = True;
8227 info_level_return = SVAL(pdata,16);
8229 /* Allocate the correct return size. */
8231 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8232 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8233 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8234 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8236 *pdata_return_size = 12;
8239 /* Realloc the data size */
8240 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8241 if (*ppdata == NULL) {
8242 close_file(req, fsp, ERROR_CLOSE);
8243 *pdata_return_size = 0;
8244 return NT_STATUS_NO_MEMORY;
8248 if (extended_oplock_granted) {
8249 if (flags & REQUEST_BATCH_OPLOCK) {
8250 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8252 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8254 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8255 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8257 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8260 SSVAL(pdata,2,fsp->fnum);
8261 SIVAL(pdata,4,info); /* Was file created etc. */
8263 switch (info_level_return) {
8264 case SMB_QUERY_FILE_UNIX_BASIC:
8265 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8266 SSVAL(pdata,10,0); /* padding. */
8267 store_file_unix_basic(conn, pdata + 12, fsp,
8270 case SMB_QUERY_FILE_UNIX_INFO2:
8271 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8272 SSVAL(pdata,10,0); /* padding. */
8273 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8277 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8278 SSVAL(pdata,10,0); /* padding. */
8281 return NT_STATUS_OK;
8284 /****************************************************************************
8285 Delete a file with POSIX semantics.
8286 ****************************************************************************/
8288 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8289 struct smb_request *req,
8292 struct smb_filename *smb_fname)
8294 NTSTATUS status = NT_STATUS_OK;
8295 files_struct *fsp = NULL;
8299 int create_options = 0;
8301 struct share_mode_lock *lck = NULL;
8303 if (total_data < 2) {
8304 return NT_STATUS_INVALID_PARAMETER;
8307 flags = SVAL(pdata,0);
8309 if (!VALID_STAT(smb_fname->st)) {
8310 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8313 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8314 !VALID_STAT_OF_DIR(smb_fname->st)) {
8315 return NT_STATUS_NOT_A_DIRECTORY;
8318 DEBUG(10,("smb_posix_unlink: %s %s\n",
8319 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8320 smb_fname_str_dbg(smb_fname)));
8322 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8323 create_options |= FILE_DIRECTORY_FILE;
8326 status = SMB_VFS_CREATE_FILE(
8329 0, /* root_dir_fid */
8330 smb_fname, /* fname */
8331 DELETE_ACCESS, /* access_mask */
8332 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8334 FILE_OPEN, /* create_disposition*/
8335 create_options, /* create_options */
8336 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8337 0, /* oplock_request */
8339 0, /* allocation_size */
8340 0, /* private_flags */
8345 NULL, NULL); /* create context */
8347 if (!NT_STATUS_IS_OK(status)) {
8352 * Don't lie to client. If we can't really delete due to
8353 * non-POSIX opens return SHARING_VIOLATION.
8356 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8358 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8359 "lock for file %s\n", fsp_str_dbg(fsp)));
8360 close_file(req, fsp, NORMAL_CLOSE);
8361 return NT_STATUS_INVALID_PARAMETER;
8365 * See if others still have the file open. If this is the case, then
8366 * don't delete. If all opens are POSIX delete we can set the delete
8367 * on close disposition.
8369 for (i=0; i<lck->data->num_share_modes; i++) {
8370 struct share_mode_entry *e = &lck->data->share_modes[i];
8371 if (is_valid_share_mode_entry(e)) {
8372 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8375 if (share_mode_stale_pid(lck->data, i)) {
8378 /* Fail with sharing violation. */
8380 close_file(req, fsp, NORMAL_CLOSE);
8381 return NT_STATUS_SHARING_VIOLATION;
8386 * Set the delete on close.
8388 status = smb_set_file_disposition_info(conn,
8396 if (!NT_STATUS_IS_OK(status)) {
8397 close_file(req, fsp, NORMAL_CLOSE);
8400 return close_file(req, fsp, NORMAL_CLOSE);
8403 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8404 struct smb_request *req,
8405 TALLOC_CTX *mem_ctx,
8406 uint16_t info_level,
8408 struct smb_filename *smb_fname,
8409 char **ppdata, int total_data,
8412 char *pdata = *ppdata;
8413 NTSTATUS status = NT_STATUS_OK;
8414 int data_return_size = 0;
8418 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8419 return NT_STATUS_INVALID_LEVEL;
8422 if (!CAN_WRITE(conn)) {
8423 /* Allow POSIX opens. The open path will deny
8424 * any non-readonly opens. */
8425 if (info_level != SMB_POSIX_PATH_OPEN) {
8426 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8430 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8431 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8433 info_level, total_data));
8435 switch (info_level) {
8437 case SMB_INFO_STANDARD:
8439 status = smb_set_info_standard(conn,
8447 case SMB_INFO_SET_EA:
8449 status = smb_info_set_ea(conn,
8457 case SMB_SET_FILE_BASIC_INFO:
8458 case SMB_FILE_BASIC_INFORMATION:
8460 status = smb_set_file_basic_info(conn,
8468 case SMB_FILE_ALLOCATION_INFORMATION:
8469 case SMB_SET_FILE_ALLOCATION_INFO:
8471 status = smb_set_file_allocation_info(conn, req,
8479 case SMB_FILE_END_OF_FILE_INFORMATION:
8480 case SMB_SET_FILE_END_OF_FILE_INFO:
8483 * XP/Win7 both fail after the createfile with
8484 * SMB_SET_FILE_END_OF_FILE_INFO but not
8485 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8486 * The level is known here, so pass it down
8490 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8492 status = smb_set_file_end_of_file_info(conn, req,
8501 case SMB_FILE_DISPOSITION_INFORMATION:
8502 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8505 /* JRA - We used to just ignore this on a path ?
8506 * Shouldn't this be invalid level on a pathname
8509 if (tran_call != TRANSACT2_SETFILEINFO) {
8510 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8513 status = smb_set_file_disposition_info(conn,
8521 case SMB_FILE_POSITION_INFORMATION:
8523 status = smb_file_position_information(conn,
8530 case SMB_FILE_FULL_EA_INFORMATION:
8532 status = smb_set_file_full_ea_info(conn,
8539 /* From tridge Samba4 :
8540 * MODE_INFORMATION in setfileinfo (I have no
8541 * idea what "mode information" on a file is - it takes a value of 0,
8542 * 2, 4 or 6. What could it be?).
8545 case SMB_FILE_MODE_INFORMATION:
8547 status = smb_file_mode_information(conn,
8554 * CIFS UNIX extensions.
8557 case SMB_SET_FILE_UNIX_BASIC:
8559 status = smb_set_file_unix_basic(conn, req,
8567 case SMB_SET_FILE_UNIX_INFO2:
8569 status = smb_set_file_unix_info2(conn, req,
8577 case SMB_SET_FILE_UNIX_LINK:
8580 /* We must have a pathname for this. */
8581 return NT_STATUS_INVALID_LEVEL;
8583 status = smb_set_file_unix_link(conn, req, pdata,
8584 total_data, smb_fname);
8588 case SMB_SET_FILE_UNIX_HLINK:
8591 /* We must have a pathname for this. */
8592 return NT_STATUS_INVALID_LEVEL;
8594 status = smb_set_file_unix_hlink(conn, req,
8600 case SMB_FILE_RENAME_INFORMATION:
8602 status = smb_file_rename_information(conn, req,
8608 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8610 /* SMB2 rename information. */
8611 status = smb2_file_rename_information(conn, req,
8617 case SMB_FILE_LINK_INFORMATION:
8619 status = smb_file_link_information(conn, req,
8625 #if defined(HAVE_POSIX_ACLS)
8626 case SMB_SET_POSIX_ACL:
8628 status = smb_set_posix_acl(conn,
8637 case SMB_SET_POSIX_LOCK:
8640 return NT_STATUS_INVALID_LEVEL;
8642 status = smb_set_posix_lock(conn, req,
8643 pdata, total_data, fsp);
8647 case SMB_POSIX_PATH_OPEN:
8650 /* We must have a pathname for this. */
8651 return NT_STATUS_INVALID_LEVEL;
8654 status = smb_posix_open(conn, req,
8662 case SMB_POSIX_PATH_UNLINK:
8665 /* We must have a pathname for this. */
8666 return NT_STATUS_INVALID_LEVEL;
8669 status = smb_posix_unlink(conn, req,
8677 return NT_STATUS_INVALID_LEVEL;
8680 if (!NT_STATUS_IS_OK(status)) {
8684 *ret_data_size = data_return_size;
8685 return NT_STATUS_OK;
8688 /****************************************************************************
8689 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8690 ****************************************************************************/
8692 static void call_trans2setfilepathinfo(connection_struct *conn,
8693 struct smb_request *req,
8694 unsigned int tran_call,
8695 char **pparams, int total_params,
8696 char **ppdata, int total_data,
8697 unsigned int max_data_bytes)
8699 char *params = *pparams;
8700 char *pdata = *ppdata;
8701 uint16_t info_level;
8702 struct smb_filename *smb_fname = NULL;
8703 files_struct *fsp = NULL;
8704 NTSTATUS status = NT_STATUS_OK;
8705 int data_return_size = 0;
8708 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8712 if (tran_call == TRANSACT2_SETFILEINFO) {
8713 if (total_params < 4) {
8714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8718 fsp = file_fsp(req, SVAL(params,0));
8719 /* Basic check for non-null fsp. */
8720 if (!check_fsp_open(conn, req, fsp)) {
8723 info_level = SVAL(params,2);
8725 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8726 if (smb_fname == NULL) {
8727 reply_nterror(req, NT_STATUS_NO_MEMORY);
8731 if(fsp->fh->fd == -1) {
8733 * This is actually a SETFILEINFO on a directory
8734 * handle (returned from an NT SMB). NT5.0 seems
8735 * to do this call. JRA.
8737 if (INFO_LEVEL_IS_UNIX(info_level)) {
8738 /* Always do lstat for UNIX calls. */
8739 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8740 DEBUG(3,("call_trans2setfilepathinfo: "
8741 "SMB_VFS_LSTAT of %s failed "
8743 smb_fname_str_dbg(smb_fname),
8745 reply_nterror(req, map_nt_error_from_unix(errno));
8749 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8750 DEBUG(3,("call_trans2setfilepathinfo: "
8751 "fileinfo of %s failed (%s)\n",
8752 smb_fname_str_dbg(smb_fname),
8754 reply_nterror(req, map_nt_error_from_unix(errno));
8758 } else if (fsp->print_file) {
8760 * Doing a DELETE_ON_CLOSE should cancel a print job.
8762 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8763 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8765 DEBUG(3,("call_trans2setfilepathinfo: "
8766 "Cancelling print job (%s)\n",
8770 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8776 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8781 * Original code - this is an open file.
8783 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8784 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8785 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8787 reply_nterror(req, map_nt_error_from_unix(errno));
8793 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8796 if (total_params < 7) {
8797 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8801 info_level = SVAL(params,0);
8802 if (req->posix_pathnames) {
8803 srvstr_get_path_posix(req,
8812 srvstr_get_path(req,
8821 if (!NT_STATUS_IS_OK(status)) {
8822 reply_nterror(req, status);
8826 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8827 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8828 info_level == SMB_FILE_RENAME_INFORMATION ||
8829 info_level == SMB_POSIX_PATH_UNLINK) {
8830 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8833 status = filename_convert(req, conn,
8838 if (!NT_STATUS_IS_OK(status)) {
8839 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8840 reply_botherror(req,
8841 NT_STATUS_PATH_NOT_COVERED,
8842 ERRSRV, ERRbadpath);
8845 reply_nterror(req, status);
8849 if (INFO_LEVEL_IS_UNIX(info_level)) {
8851 * For CIFS UNIX extensions the target name may not exist.
8854 /* Always do lstat for UNIX calls. */
8855 SMB_VFS_LSTAT(conn, smb_fname);
8857 } else if (!VALID_STAT(smb_fname->st) &&
8858 SMB_VFS_STAT(conn, smb_fname)) {
8859 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8861 smb_fname_str_dbg(smb_fname),
8863 reply_nterror(req, map_nt_error_from_unix(errno));
8868 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8869 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8871 info_level,total_data));
8873 /* Realloc the parameter size */
8874 *pparams = (char *)SMB_REALLOC(*pparams,2);
8875 if (*pparams == NULL) {
8876 reply_nterror(req, NT_STATUS_NO_MEMORY);
8883 status = smbd_do_setfilepathinfo(conn, req, req,
8889 if (!NT_STATUS_IS_OK(status)) {
8890 if (open_was_deferred(req->xconn, req->mid)) {
8891 /* We have re-scheduled this call. */
8894 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8895 /* We have re-scheduled this call. */
8898 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8899 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8900 ERRSRV, ERRbadpath);
8903 if (info_level == SMB_POSIX_PATH_OPEN) {
8904 reply_openerror(req, status);
8909 * Invalid EA name needs to return 2 param bytes,
8910 * not a zero-length error packet.
8912 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8913 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8916 reply_nterror(req, status);
8921 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8927 /****************************************************************************
8928 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8929 ****************************************************************************/
8931 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8932 char **pparams, int total_params,
8933 char **ppdata, int total_data,
8934 unsigned int max_data_bytes)
8936 struct smb_filename *smb_dname = NULL;
8937 char *params = *pparams;
8938 char *pdata = *ppdata;
8939 char *directory = NULL;
8940 NTSTATUS status = NT_STATUS_OK;
8941 struct ea_list *ea_list = NULL;
8942 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8943 TALLOC_CTX *ctx = talloc_tos();
8945 if (!CAN_WRITE(conn)) {
8946 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8950 if (total_params < 5) {
8951 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8955 if (req->posix_pathnames) {
8956 srvstr_get_path_posix(ctx,
8965 srvstr_get_path(ctx,
8974 if (!NT_STATUS_IS_OK(status)) {
8975 reply_nterror(req, status);
8979 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8981 status = filename_convert(ctx,
8988 if (!NT_STATUS_IS_OK(status)) {
8989 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8990 reply_botherror(req,
8991 NT_STATUS_PATH_NOT_COVERED,
8992 ERRSRV, ERRbadpath);
8995 reply_nterror(req, status);
9000 * OS/2 workplace shell seems to send SET_EA requests of "null"
9001 * length (4 bytes containing IVAL 4).
9002 * They seem to have no effect. Bug #3212. JRA.
9005 if (total_data && (total_data != 4)) {
9006 /* Any data in this call is an EA list. */
9007 if (total_data < 10) {
9008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9012 if (IVAL(pdata,0) > total_data) {
9013 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9014 IVAL(pdata,0), (unsigned int)total_data));
9015 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9019 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9026 if (!lp_ea_support(SNUM(conn))) {
9027 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9031 /* If total_data == 4 Windows doesn't care what values
9032 * are placed in that field, it just ignores them.
9033 * The System i QNTC IBM SMB client puts bad values here,
9034 * so ignore them. */
9036 status = create_directory(conn, req, smb_dname);
9038 if (!NT_STATUS_IS_OK(status)) {
9039 reply_nterror(req, status);
9043 /* Try and set any given EA. */
9045 status = set_ea(conn, NULL, smb_dname, ea_list);
9046 if (!NT_STATUS_IS_OK(status)) {
9047 reply_nterror(req, status);
9052 /* Realloc the parameter and data sizes */
9053 *pparams = (char *)SMB_REALLOC(*pparams,2);
9054 if(*pparams == NULL) {
9055 reply_nterror(req, NT_STATUS_NO_MEMORY);
9062 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9065 TALLOC_FREE(smb_dname);
9069 /****************************************************************************
9070 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9071 We don't actually do this - we just send a null response.
9072 ****************************************************************************/
9074 static void call_trans2findnotifyfirst(connection_struct *conn,
9075 struct smb_request *req,
9076 char **pparams, int total_params,
9077 char **ppdata, int total_data,
9078 unsigned int max_data_bytes)
9080 char *params = *pparams;
9081 uint16_t info_level;
9083 if (total_params < 6) {
9084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9088 info_level = SVAL(params,4);
9089 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9091 switch (info_level) {
9096 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9100 /* Realloc the parameter and data sizes */
9101 *pparams = (char *)SMB_REALLOC(*pparams,6);
9102 if (*pparams == NULL) {
9103 reply_nterror(req, NT_STATUS_NO_MEMORY);
9108 SSVAL(params,0,fnf_handle);
9109 SSVAL(params,2,0); /* No changes */
9110 SSVAL(params,4,0); /* No EA errors */
9117 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9122 /****************************************************************************
9123 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9124 changes). Currently this does nothing.
9125 ****************************************************************************/
9127 static void call_trans2findnotifynext(connection_struct *conn,
9128 struct smb_request *req,
9129 char **pparams, int total_params,
9130 char **ppdata, int total_data,
9131 unsigned int max_data_bytes)
9133 char *params = *pparams;
9135 DEBUG(3,("call_trans2findnotifynext\n"));
9137 /* Realloc the parameter and data sizes */
9138 *pparams = (char *)SMB_REALLOC(*pparams,4);
9139 if (*pparams == NULL) {
9140 reply_nterror(req, NT_STATUS_NO_MEMORY);
9145 SSVAL(params,0,0); /* No changes */
9146 SSVAL(params,2,0); /* No EA errors */
9148 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9153 /****************************************************************************
9154 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9155 ****************************************************************************/
9157 static void call_trans2getdfsreferral(connection_struct *conn,
9158 struct smb_request *req,
9159 char **pparams, int total_params,
9160 char **ppdata, int total_data,
9161 unsigned int max_data_bytes)
9163 char *params = *pparams;
9164 char *pathname = NULL;
9166 int max_referral_level;
9167 NTSTATUS status = NT_STATUS_OK;
9168 TALLOC_CTX *ctx = talloc_tos();
9170 DEBUG(10,("call_trans2getdfsreferral\n"));
9172 if (total_params < 3) {
9173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9177 max_referral_level = SVAL(params,0);
9179 if(!lp_host_msdfs()) {
9180 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9184 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9185 total_params - 2, STR_TERMINATE);
9187 reply_nterror(req, NT_STATUS_NOT_FOUND);
9190 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9191 ppdata,&status)) < 0) {
9192 reply_nterror(req, status);
9196 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9197 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9198 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9203 #define LMCAT_SPL 0x53
9204 #define LMFUNC_GETJOBID 0x60
9206 /****************************************************************************
9207 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9208 ****************************************************************************/
9210 static void call_trans2ioctl(connection_struct *conn,
9211 struct smb_request *req,
9212 char **pparams, int total_params,
9213 char **ppdata, int total_data,
9214 unsigned int max_data_bytes)
9216 char *pdata = *ppdata;
9217 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9221 /* check for an invalid fid before proceeding */
9224 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9228 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9229 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9230 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9231 if (*ppdata == NULL) {
9232 reply_nterror(req, NT_STATUS_NO_MEMORY);
9237 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9238 CAN ACCEPT THIS IN UNICODE. JRA. */
9241 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9243 status = srvstr_push(pdata, req->flags2, pdata + 2,
9244 lp_netbios_name(), 15,
9245 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9246 if (!NT_STATUS_IS_OK(status)) {
9247 reply_nterror(req, status);
9250 status = srvstr_push(pdata, req->flags2, pdata+18,
9251 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9252 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9253 if (!NT_STATUS_IS_OK(status)) {
9254 reply_nterror(req, status);
9257 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9262 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9263 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9266 /****************************************************************************
9267 Reply to a SMBfindclose (stop trans2 directory search).
9268 ****************************************************************************/
9270 void reply_findclose(struct smb_request *req)
9273 struct smbd_server_connection *sconn = req->sconn;
9275 START_PROFILE(SMBfindclose);
9278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9279 END_PROFILE(SMBfindclose);
9283 dptr_num = SVALS(req->vwv+0, 0);
9285 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9287 dptr_close(sconn, &dptr_num);
9289 reply_outbuf(req, 0, 0);
9291 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9293 END_PROFILE(SMBfindclose);
9297 /****************************************************************************
9298 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9299 ****************************************************************************/
9301 void reply_findnclose(struct smb_request *req)
9305 START_PROFILE(SMBfindnclose);
9308 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9309 END_PROFILE(SMBfindnclose);
9313 dptr_num = SVAL(req->vwv+0, 0);
9315 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9317 /* We never give out valid handles for a
9318 findnotifyfirst - so any dptr_num is ok here.
9321 reply_outbuf(req, 0, 0);
9323 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9325 END_PROFILE(SMBfindnclose);
9329 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9330 struct trans_state *state)
9332 if (get_Protocol() >= PROTOCOL_NT1) {
9333 req->flags2 |= 0x40; /* IS_LONG_NAME */
9334 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9337 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9338 if (state->call != TRANSACT2_QFSINFO &&
9339 state->call != TRANSACT2_SETFSINFO) {
9340 DEBUG(0,("handle_trans2: encryption required "
9342 (unsigned int)state->call));
9343 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9348 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9350 /* Now we must call the relevant TRANS2 function */
9351 switch(state->call) {
9352 case TRANSACT2_OPEN:
9354 START_PROFILE(Trans2_open);
9355 call_trans2open(conn, req,
9356 &state->param, state->total_param,
9357 &state->data, state->total_data,
9358 state->max_data_return);
9359 END_PROFILE(Trans2_open);
9363 case TRANSACT2_FINDFIRST:
9365 START_PROFILE(Trans2_findfirst);
9366 call_trans2findfirst(conn, req,
9367 &state->param, state->total_param,
9368 &state->data, state->total_data,
9369 state->max_data_return);
9370 END_PROFILE(Trans2_findfirst);
9374 case TRANSACT2_FINDNEXT:
9376 START_PROFILE(Trans2_findnext);
9377 call_trans2findnext(conn, req,
9378 &state->param, state->total_param,
9379 &state->data, state->total_data,
9380 state->max_data_return);
9381 END_PROFILE(Trans2_findnext);
9385 case TRANSACT2_QFSINFO:
9387 START_PROFILE(Trans2_qfsinfo);
9388 call_trans2qfsinfo(conn, req,
9389 &state->param, state->total_param,
9390 &state->data, state->total_data,
9391 state->max_data_return);
9392 END_PROFILE(Trans2_qfsinfo);
9396 case TRANSACT2_SETFSINFO:
9398 START_PROFILE(Trans2_setfsinfo);
9399 call_trans2setfsinfo(conn, req,
9400 &state->param, state->total_param,
9401 &state->data, state->total_data,
9402 state->max_data_return);
9403 END_PROFILE(Trans2_setfsinfo);
9407 case TRANSACT2_QPATHINFO:
9408 case TRANSACT2_QFILEINFO:
9410 START_PROFILE(Trans2_qpathinfo);
9411 call_trans2qfilepathinfo(conn, req, state->call,
9412 &state->param, state->total_param,
9413 &state->data, state->total_data,
9414 state->max_data_return);
9415 END_PROFILE(Trans2_qpathinfo);
9419 case TRANSACT2_SETPATHINFO:
9420 case TRANSACT2_SETFILEINFO:
9422 START_PROFILE(Trans2_setpathinfo);
9423 call_trans2setfilepathinfo(conn, req, state->call,
9424 &state->param, state->total_param,
9425 &state->data, state->total_data,
9426 state->max_data_return);
9427 END_PROFILE(Trans2_setpathinfo);
9431 case TRANSACT2_FINDNOTIFYFIRST:
9433 START_PROFILE(Trans2_findnotifyfirst);
9434 call_trans2findnotifyfirst(conn, req,
9435 &state->param, state->total_param,
9436 &state->data, state->total_data,
9437 state->max_data_return);
9438 END_PROFILE(Trans2_findnotifyfirst);
9442 case TRANSACT2_FINDNOTIFYNEXT:
9444 START_PROFILE(Trans2_findnotifynext);
9445 call_trans2findnotifynext(conn, req,
9446 &state->param, state->total_param,
9447 &state->data, state->total_data,
9448 state->max_data_return);
9449 END_PROFILE(Trans2_findnotifynext);
9453 case TRANSACT2_MKDIR:
9455 START_PROFILE(Trans2_mkdir);
9456 call_trans2mkdir(conn, req,
9457 &state->param, state->total_param,
9458 &state->data, state->total_data,
9459 state->max_data_return);
9460 END_PROFILE(Trans2_mkdir);
9464 case TRANSACT2_GET_DFS_REFERRAL:
9466 START_PROFILE(Trans2_get_dfs_referral);
9467 call_trans2getdfsreferral(conn, req,
9468 &state->param, state->total_param,
9469 &state->data, state->total_data,
9470 state->max_data_return);
9471 END_PROFILE(Trans2_get_dfs_referral);
9475 case TRANSACT2_IOCTL:
9477 START_PROFILE(Trans2_ioctl);
9478 call_trans2ioctl(conn, req,
9479 &state->param, state->total_param,
9480 &state->data, state->total_data,
9481 state->max_data_return);
9482 END_PROFILE(Trans2_ioctl);
9487 /* Error in request */
9488 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9489 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9493 /****************************************************************************
9494 Reply to a SMBtrans2.
9495 ****************************************************************************/
9497 void reply_trans2(struct smb_request *req)
9499 connection_struct *conn = req->conn;
9504 unsigned int tran_call;
9505 struct trans_state *state;
9508 START_PROFILE(SMBtrans2);
9510 if (req->wct < 14) {
9511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9512 END_PROFILE(SMBtrans2);
9516 dsoff = SVAL(req->vwv+12, 0);
9517 dscnt = SVAL(req->vwv+11, 0);
9518 psoff = SVAL(req->vwv+10, 0);
9519 pscnt = SVAL(req->vwv+9, 0);
9520 tran_call = SVAL(req->vwv+14, 0);
9522 result = allow_new_trans(conn->pending_trans, req->mid);
9523 if (!NT_STATUS_IS_OK(result)) {
9524 DEBUG(2, ("Got invalid trans2 request: %s\n",
9525 nt_errstr(result)));
9526 reply_nterror(req, result);
9527 END_PROFILE(SMBtrans2);
9532 switch (tran_call) {
9533 /* List the allowed trans2 calls on IPC$ */
9534 case TRANSACT2_OPEN:
9535 case TRANSACT2_GET_DFS_REFERRAL:
9536 case TRANSACT2_QFILEINFO:
9537 case TRANSACT2_QFSINFO:
9538 case TRANSACT2_SETFSINFO:
9541 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9542 END_PROFILE(SMBtrans2);
9547 if ((state = talloc(conn, struct trans_state)) == NULL) {
9548 DEBUG(0, ("talloc failed\n"));
9549 reply_nterror(req, NT_STATUS_NO_MEMORY);
9550 END_PROFILE(SMBtrans2);
9554 state->cmd = SMBtrans2;
9556 state->mid = req->mid;
9557 state->vuid = req->vuid;
9558 state->setup_count = SVAL(req->vwv+13, 0);
9559 state->setup = NULL;
9560 state->total_param = SVAL(req->vwv+0, 0);
9561 state->param = NULL;
9562 state->total_data = SVAL(req->vwv+1, 0);
9564 state->max_param_return = SVAL(req->vwv+2, 0);
9565 state->max_data_return = SVAL(req->vwv+3, 0);
9566 state->max_setup_return = SVAL(req->vwv+4, 0);
9567 state->close_on_completion = BITSETW(req->vwv+5, 0);
9568 state->one_way = BITSETW(req->vwv+5, 1);
9570 state->call = tran_call;
9572 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9573 is so as a sanity check */
9574 if (state->setup_count != 1) {
9576 * Need to have rc=0 for ioctl to get job id for OS/2.
9577 * Network printing will fail if function is not successful.
9578 * Similar function in reply.c will be used if protocol
9579 * is LANMAN1.0 instead of LM1.2X002.
9580 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9581 * outbuf doesn't have to be set(only job id is used).
9583 if ( (state->setup_count == 4)
9584 && (tran_call == TRANSACT2_IOCTL)
9585 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9586 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9587 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9589 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9590 DEBUG(2,("Transaction is %d\n",tran_call));
9592 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9593 END_PROFILE(SMBtrans2);
9598 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9601 if (state->total_data) {
9603 if (trans_oob(state->total_data, 0, dscnt)
9604 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9608 /* Can't use talloc here, the core routines do realloc on the
9609 * params and data. */
9610 state->data = (char *)SMB_MALLOC(state->total_data);
9611 if (state->data == NULL) {
9612 DEBUG(0,("reply_trans2: data malloc fail for %u "
9613 "bytes !\n", (unsigned int)state->total_data));
9615 reply_nterror(req, NT_STATUS_NO_MEMORY);
9616 END_PROFILE(SMBtrans2);
9620 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9623 if (state->total_param) {
9625 if (trans_oob(state->total_param, 0, pscnt)
9626 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9630 /* Can't use talloc here, the core routines do realloc on the
9631 * params and data. */
9632 state->param = (char *)SMB_MALLOC(state->total_param);
9633 if (state->param == NULL) {
9634 DEBUG(0,("reply_trans: param malloc fail for %u "
9635 "bytes !\n", (unsigned int)state->total_param));
9636 SAFE_FREE(state->data);
9638 reply_nterror(req, NT_STATUS_NO_MEMORY);
9639 END_PROFILE(SMBtrans2);
9643 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9646 state->received_data = dscnt;
9647 state->received_param = pscnt;
9649 if ((state->received_param == state->total_param) &&
9650 (state->received_data == state->total_data)) {
9652 handle_trans2(conn, req, state);
9654 SAFE_FREE(state->data);
9655 SAFE_FREE(state->param);
9657 END_PROFILE(SMBtrans2);
9661 DLIST_ADD(conn->pending_trans, state);
9663 /* We need to send an interim response then receive the rest
9664 of the parameter/data bytes */
9665 reply_outbuf(req, 0, 0);
9666 show_msg((char *)req->outbuf);
9667 END_PROFILE(SMBtrans2);
9672 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9673 SAFE_FREE(state->data);
9674 SAFE_FREE(state->param);
9676 END_PROFILE(SMBtrans2);
9677 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9681 /****************************************************************************
9682 Reply to a SMBtranss2
9683 ****************************************************************************/
9685 void reply_transs2(struct smb_request *req)
9687 connection_struct *conn = req->conn;
9688 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9689 struct trans_state *state;
9691 START_PROFILE(SMBtranss2);
9693 show_msg((const char *)req->inbuf);
9695 /* Windows clients expect all replies to
9696 a transact secondary (SMBtranss2 0x33)
9697 to have a command code of transact
9698 (SMBtrans2 0x32). See bug #8989
9699 and also [MS-CIFS] section 2.2.4.47.2
9702 req->cmd = SMBtrans2;
9705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9706 END_PROFILE(SMBtranss2);
9710 for (state = conn->pending_trans; state != NULL;
9711 state = state->next) {
9712 if (state->mid == req->mid) {
9717 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9719 END_PROFILE(SMBtranss2);
9723 /* Revise state->total_param and state->total_data in case they have
9724 changed downwards */
9726 if (SVAL(req->vwv+0, 0) < state->total_param)
9727 state->total_param = SVAL(req->vwv+0, 0);
9728 if (SVAL(req->vwv+1, 0) < state->total_data)
9729 state->total_data = SVAL(req->vwv+1, 0);
9731 pcnt = SVAL(req->vwv+2, 0);
9732 poff = SVAL(req->vwv+3, 0);
9733 pdisp = SVAL(req->vwv+4, 0);
9735 dcnt = SVAL(req->vwv+5, 0);
9736 doff = SVAL(req->vwv+6, 0);
9737 ddisp = SVAL(req->vwv+7, 0);
9739 state->received_param += pcnt;
9740 state->received_data += dcnt;
9742 if ((state->received_data > state->total_data) ||
9743 (state->received_param > state->total_param))
9747 if (trans_oob(state->total_param, pdisp, pcnt)
9748 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9751 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9755 if (trans_oob(state->total_data, ddisp, dcnt)
9756 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9759 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9762 if ((state->received_param < state->total_param) ||
9763 (state->received_data < state->total_data)) {
9764 END_PROFILE(SMBtranss2);
9768 handle_trans2(conn, req, state);
9770 DLIST_REMOVE(conn->pending_trans, state);
9771 SAFE_FREE(state->data);
9772 SAFE_FREE(state->param);
9775 END_PROFILE(SMBtranss2);
9780 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9781 DLIST_REMOVE(conn->pending_trans, state);
9782 SAFE_FREE(state->data);
9783 SAFE_FREE(state->param);
9785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9786 END_PROFILE(SMBtranss2);