2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
55 const SMB_STRUCT_STAT *psbuf);
57 /****************************************************************************
58 Check if an open file handle or smb_fname is a symlink.
59 ****************************************************************************/
61 static NTSTATUS refuse_symlink(connection_struct *conn,
62 const files_struct *fsp,
63 const struct smb_filename *smb_fname)
66 const SMB_STRUCT_STAT *pst = NULL;
69 pst = &fsp->fsp_name->st;
74 if (!VALID_STAT(*pst)) {
75 int ret = vfs_stat_smb_basename(conn,
78 if (ret == -1 && errno != ENOENT) {
79 return map_nt_error_from_unix(errno);
80 } else if (ret == -1) {
81 /* it's not a symlink.. */
87 if (S_ISLNK(pst->st_ex_mode)) {
88 return NT_STATUS_ACCESS_DENIED;
93 NTSTATUS check_access_fsp(const struct files_struct *fsp,
96 if (!(fsp->access_mask & access_mask)) {
97 return NT_STATUS_ACCESS_DENIED;
102 /********************************************************************
103 The canonical "check access" based on object handle or path function.
104 ********************************************************************/
106 NTSTATUS check_access(connection_struct *conn,
108 const struct smb_filename *smb_fname,
109 uint32_t access_mask)
114 status = check_access_fsp(fsp, access_mask);
116 status = smbd_check_access_rights(conn, smb_fname,
123 /********************************************************************
124 Roundup a value to the nearest allocation roundup size boundary.
125 Only do this for Windows clients.
126 ********************************************************************/
128 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
130 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
132 /* Only roundup for Windows clients. */
133 enum remote_arch_types ra_type = get_remote_arch();
134 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
135 val = SMB_ROUNDUP(val,rval);
140 /********************************************************************
141 Create a 64 bit FileIndex. If the file is on the same device as
142 the root of the share, just return the 64-bit inode. If it isn't,
143 mangle as we used to do.
144 ********************************************************************/
146 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
149 if (conn->sconn->aapl_zero_file_id) {
152 if (conn->base_share_dev == psbuf->st_ex_dev) {
153 return (uint64_t)psbuf->st_ex_ino;
155 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
156 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
161 /********************************************************************
162 Globally (for this connection / multi-channel) disable file-ID
163 calculation. This is required to be global because it serves
164 Macs in AAPL mode, which is globally set.
165 ********************************************************************/
166 void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
168 sconn->aapl_zero_file_id = true;
171 /****************************************************************************
172 Utility functions for dealing with extended attributes.
173 ****************************************************************************/
175 /****************************************************************************
176 Refuse to allow clients to overwrite our private xattrs.
177 ****************************************************************************/
179 bool samba_private_attr_name(const char *unix_ea_name)
181 static const char * const prohibited_ea_names[] = {
182 SAMBA_POSIX_INHERITANCE_EA_NAME,
183 SAMBA_XATTR_DOS_ATTRIB,
191 for (i = 0; prohibited_ea_names[i]; i++) {
192 if (strequal( prohibited_ea_names[i], unix_ea_name))
195 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
196 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
202 /****************************************************************************
203 Get one EA value. Fill in a struct ea_struct.
204 ****************************************************************************/
206 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
207 connection_struct *conn,
209 const struct smb_filename *smb_fname,
211 struct ea_struct *pea)
213 /* Get the value of this xattr. Max size is 64k. */
214 size_t attr_size = 256;
220 val = talloc_realloc(mem_ctx, val, char, attr_size);
222 return NT_STATUS_NO_MEMORY;
225 if (fsp && fsp->fh->fd != -1) {
226 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
228 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
229 ea_name, val, attr_size);
232 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
238 return map_nt_error_from_unix(errno);
241 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
242 dump_data(10, (uint8_t *)val, sizeret);
245 if (strnequal(ea_name, "user.", 5)) {
246 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
248 pea->name = talloc_strdup(mem_ctx, ea_name);
250 if (pea->name == NULL) {
252 return NT_STATUS_NO_MEMORY;
254 pea->value.data = (unsigned char *)val;
255 pea->value.length = (size_t)sizeret;
259 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
260 connection_struct *conn,
262 const struct smb_filename *smb_fname,
267 /* Get a list of all xattrs. Max namesize is 64k. */
268 size_t ea_namelist_size = 1024;
269 char *ea_namelist = smallbuf;
270 char *to_free = NULL;
275 ssize_t sizeret = -1;
283 status = refuse_symlink(conn, fsp, smb_fname);
284 if (!NT_STATUS_IS_OK(status)) {
286 * Just return no EA's on a symlink.
291 if (fsp && fsp->fh->fd != -1) {
292 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
295 sizeret = SMB_VFS_LISTXATTR(conn,
301 if ((sizeret == -1) && (errno == ERANGE)) {
302 ea_namelist_size = 65536;
303 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
304 if (ea_namelist == NULL) {
305 return NT_STATUS_NO_MEMORY;
307 to_free = ea_namelist;
309 if (fsp && fsp->fh->fd != -1) {
310 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
313 sizeret = SMB_VFS_LISTXATTR(conn,
321 status = map_nt_error_from_unix(errno);
322 TALLOC_FREE(to_free);
326 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
329 TALLOC_FREE(to_free);
334 * Ensure the result is 0-terminated
337 if (ea_namelist[sizeret-1] != '\0') {
338 TALLOC_FREE(to_free);
339 return NT_STATUS_INTERNAL_ERROR;
347 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
351 *pnum_names = num_names;
353 if (pnames == NULL) {
354 TALLOC_FREE(to_free);
358 names = talloc_array(mem_ctx, char *, num_names);
360 DEBUG(0, ("talloc failed\n"));
361 TALLOC_FREE(to_free);
362 return NT_STATUS_NO_MEMORY;
365 if (ea_namelist == smallbuf) {
366 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
367 if (ea_namelist == NULL) {
369 return NT_STATUS_NO_MEMORY;
372 talloc_steal(names, ea_namelist);
374 ea_namelist = talloc_realloc(names, ea_namelist, char,
376 if (ea_namelist == NULL) {
378 return NT_STATUS_NO_MEMORY;
384 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
385 names[num_names++] = p;
393 /****************************************************************************
394 Return a linked list of the total EA's. Plus the total size
395 ****************************************************************************/
397 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
398 connection_struct *conn,
400 const struct smb_filename *smb_fname,
401 size_t *pea_total_len,
402 struct ea_list **ea_list)
404 /* Get a list of all xattrs. Max namesize is 64k. */
407 struct ea_list *ea_list_head = NULL;
408 bool posix_pathnames = false;
414 if (!lp_ea_support(SNUM(conn))) {
420 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
422 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
425 status = get_ea_names_from_file(talloc_tos(),
432 if (!NT_STATUS_IS_OK(status)) {
436 if (num_names == 0) {
440 for (i=0; i<num_names; i++) {
441 struct ea_list *listp;
444 if (strnequal(names[i], "system.", 7)
445 || samba_private_attr_name(names[i]))
449 * Filter out any underlying POSIX EA names
450 * that a Windows client can't handle.
452 if (!posix_pathnames &&
453 is_invalid_windows_ea_name(names[i])) {
457 listp = talloc(mem_ctx, struct ea_list);
459 return NT_STATUS_NO_MEMORY;
462 status = get_ea_value(listp,
469 if (!NT_STATUS_IS_OK(status)) {
474 if (listp->ea.value.length == 0) {
476 * We can never return a zero length EA.
477 * Windows reports the EA's as corrupted.
483 push_ascii_fstring(dos_ea_name, listp->ea.name);
486 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
488 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
489 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
490 (unsigned int)listp->ea.value.length));
492 DLIST_ADD_END(ea_list_head, listp);
496 /* Add on 4 for total length. */
497 if (*pea_total_len) {
501 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
502 (unsigned int)*pea_total_len));
504 *ea_list = ea_list_head;
508 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
509 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
514 if (!lp_ea_support(SNUM(conn))) {
518 if (is_ntfs_stream_smb_fname(smb_fname)) {
519 return NT_STATUS_INVALID_PARAMETER;
522 return get_ea_list_from_file_path(mem_ctx,
530 /****************************************************************************
531 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
533 ****************************************************************************/
535 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
536 connection_struct *conn, struct ea_list *ea_list)
538 unsigned int ret_data_size = 4;
541 SMB_ASSERT(total_data_size >= 4);
543 if (!lp_ea_support(SNUM(conn))) {
548 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
551 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
552 dos_namelen = strlen(dos_ea_name);
553 if (dos_namelen > 255 || dos_namelen == 0) {
556 if (ea_list->ea.value.length > 65535) {
559 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
563 /* We know we have room. */
564 SCVAL(p,0,ea_list->ea.flags);
565 SCVAL(p,1,dos_namelen);
566 SSVAL(p,2,ea_list->ea.value.length);
567 strlcpy(p+4, dos_ea_name, dos_namelen+1);
568 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
570 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
571 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
574 ret_data_size = PTR_DIFF(p, pdata);
575 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
576 SIVAL(pdata,0,ret_data_size);
577 return ret_data_size;
580 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
582 unsigned int total_data_size,
583 unsigned int *ret_data_size,
584 connection_struct *conn,
585 struct ea_list *ea_list)
587 uint8_t *p = (uint8_t *)pdata;
588 uint8_t *last_start = NULL;
589 bool do_store_data = (pdata != NULL);
593 if (!lp_ea_support(SNUM(conn))) {
594 return NT_STATUS_NO_EAS_ON_FILE;
597 for (; ea_list; ea_list = ea_list->next) {
603 if (last_start != NULL && do_store_data) {
604 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
608 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
609 dos_namelen = strlen(dos_ea_name);
610 if (dos_namelen > 255 || dos_namelen == 0) {
611 return NT_STATUS_INTERNAL_ERROR;
613 if (ea_list->ea.value.length > 65535) {
614 return NT_STATUS_INTERNAL_ERROR;
617 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
620 pad = (4 - (this_size % 4)) % 4;
625 if (this_size > total_data_size) {
626 return NT_STATUS_INFO_LENGTH_MISMATCH;
629 /* We know we have room. */
630 SIVAL(p, 0x00, 0); /* next offset */
631 SCVAL(p, 0x04, ea_list->ea.flags);
632 SCVAL(p, 0x05, dos_namelen);
633 SSVAL(p, 0x06, ea_list->ea.value.length);
634 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
635 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
637 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
641 total_data_size -= this_size;
647 *ret_data_size = PTR_DIFF(p, pdata);
648 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
652 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
654 size_t total_ea_len = 0;
656 struct ea_list *ea_list = NULL;
658 if (!lp_ea_support(SNUM(conn))) {
661 mem_ctx = talloc_stackframe();
663 /* If this is a stream fsp, then we need to instead find the
664 * estimated ea len from the main file, not the stream
665 * (streams cannot have EAs), but the estimate isn't just 0 in
667 if (is_ntfs_stream_smb_fname(smb_fname)) {
670 (void)get_ea_list_from_file_path(mem_ctx,
676 if(conn->sconn->using_smb2) {
678 unsigned int ret_data_size;
680 * We're going to be using fill_ea_chained_buffer() to
681 * marshall EA's - this size is significantly larger
682 * than the SMB1 buffer. Re-calculate the size without
685 status = fill_ea_chained_buffer(mem_ctx,
691 if (!NT_STATUS_IS_OK(status)) {
694 total_ea_len = ret_data_size;
696 TALLOC_FREE(mem_ctx);
700 /****************************************************************************
701 Ensure the EA name is case insensitive by matching any existing EA name.
702 ****************************************************************************/
704 static void canonicalize_ea_name(connection_struct *conn,
706 const struct smb_filename *smb_fname,
707 fstring unix_ea_name)
710 TALLOC_CTX *mem_ctx = talloc_tos();
711 struct ea_list *ea_list;
712 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
718 if (!NT_STATUS_IS_OK(status)) {
722 for (; ea_list; ea_list = ea_list->next) {
723 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
724 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
725 &unix_ea_name[5], ea_list->ea.name));
726 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
732 /****************************************************************************
733 Set or delete an extended attribute.
734 ****************************************************************************/
736 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
737 const struct smb_filename *smb_fname, struct ea_list *ea_list)
740 bool posix_pathnames = false;
742 if (!lp_ea_support(SNUM(conn))) {
743 return NT_STATUS_EAS_NOT_SUPPORTED;
748 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
750 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
753 status = refuse_symlink(conn, fsp, smb_fname);
754 if (!NT_STATUS_IS_OK(status)) {
758 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
759 if (!NT_STATUS_IS_OK(status)) {
763 /* Setting EAs on streams isn't supported. */
764 if (is_ntfs_stream_smb_fname(smb_fname)) {
765 return NT_STATUS_INVALID_PARAMETER;
769 * Filter out invalid Windows EA names - before
770 * we set *any* of them.
773 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
774 return STATUS_INVALID_EA_NAME;
777 for (;ea_list; ea_list = ea_list->next) {
779 fstring unix_ea_name;
781 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
782 fstrcat(unix_ea_name, ea_list->ea.name);
784 canonicalize_ea_name(conn,
789 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
791 if (samba_private_attr_name(unix_ea_name)) {
792 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
793 return NT_STATUS_ACCESS_DENIED;
796 if (ea_list->ea.value.length == 0) {
797 /* Remove the attribute. */
798 if (fsp && (fsp->fh->fd != -1)) {
799 DEBUG(10,("set_ea: deleting ea name %s on "
800 "file %s by file descriptor.\n",
801 unix_ea_name, fsp_str_dbg(fsp)));
802 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
804 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
805 unix_ea_name, smb_fname->base_name));
806 ret = SMB_VFS_REMOVEXATTR(conn,
811 /* Removing a non existent attribute always succeeds. */
812 if (ret == -1 && errno == ENOATTR) {
813 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
819 if (fsp && (fsp->fh->fd != -1)) {
820 DEBUG(10,("set_ea: setting ea name %s on file "
821 "%s by file descriptor.\n",
822 unix_ea_name, fsp_str_dbg(fsp)));
823 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
824 ea_list->ea.value.data, ea_list->ea.value.length, 0);
826 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
827 unix_ea_name, smb_fname->base_name));
828 ret = SMB_VFS_SETXATTR(conn,
831 ea_list->ea.value.data,
832 ea_list->ea.value.length,
839 if (errno == ENOTSUP) {
840 return NT_STATUS_EAS_NOT_SUPPORTED;
843 return map_nt_error_from_unix(errno);
849 /****************************************************************************
850 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
851 ****************************************************************************/
853 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
855 struct ea_list *ea_list_head = NULL;
856 size_t converted_size, offset = 0;
858 while (offset + 2 < data_size) {
859 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
860 unsigned int namelen = CVAL(pdata,offset);
862 offset++; /* Go past the namelen byte. */
864 /* integer wrap paranioa. */
865 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
866 (offset > data_size) || (namelen > data_size) ||
867 (offset + namelen >= data_size)) {
870 /* Ensure the name is null terminated. */
871 if (pdata[offset + namelen] != '\0') {
874 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
876 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
877 "failed: %s", strerror(errno)));
883 offset += (namelen + 1); /* Go past the name + terminating zero. */
884 DLIST_ADD_END(ea_list_head, eal);
885 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
891 /****************************************************************************
892 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
893 ****************************************************************************/
895 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
897 struct ea_list *ea_list_head = NULL;
899 size_t bytes_used = 0;
901 while (offset < data_size) {
902 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
908 DLIST_ADD_END(ea_list_head, eal);
909 offset += bytes_used;
915 /****************************************************************************
916 Count the total EA size needed.
917 ****************************************************************************/
919 static size_t ea_list_size(struct ea_list *ealist)
922 struct ea_list *listp;
925 for (listp = ealist; listp; listp = listp->next) {
926 push_ascii_fstring(dos_ea_name, listp->ea.name);
927 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
929 /* Add on 4 for total length. */
937 /****************************************************************************
938 Return a union of EA's from a file list and a list of names.
939 The TALLOC context for the two lists *MUST* be identical as we steal
940 memory from one list to add to another. JRA.
941 ****************************************************************************/
943 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
945 struct ea_list *nlistp, *flistp;
947 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
948 for (flistp = file_list; flistp; flistp = flistp->next) {
949 if (strequal(nlistp->ea.name, flistp->ea.name)) {
955 /* Copy the data from this entry. */
956 nlistp->ea.flags = flistp->ea.flags;
957 nlistp->ea.value = flistp->ea.value;
960 nlistp->ea.flags = 0;
961 ZERO_STRUCT(nlistp->ea.value);
965 *total_ea_len = ea_list_size(name_list);
969 /****************************************************************************
970 Send the required number of replies back.
971 We assume all fields other than the data fields are
972 set correctly for the type of call.
973 HACK ! Always assumes smb_setup field is zero.
974 ****************************************************************************/
976 void send_trans2_replies(connection_struct *conn,
977 struct smb_request *req,
985 /* As we are using a protocol > LANMAN1 then the max_send
986 variable must have been set in the sessetupX call.
987 This takes precedence over the max_xmit field in the
988 global struct. These different max_xmit variables should
989 be merged as this is now too confusing */
991 int data_to_send = datasize;
992 int params_to_send = paramsize;
994 const char *pp = params;
995 const char *pd = pdata;
996 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
997 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
998 int data_alignment_offset = 0;
999 bool overflow = False;
1000 struct smbXsrv_connection *xconn = req->xconn;
1001 int max_send = xconn->smb1.sessions.max_send;
1003 /* Modify the data_to_send and datasize and set the error if
1004 we're trying to send more than max_data_bytes. We still send
1005 the part of the packet(s) that fit. Strange, but needed
1008 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1009 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1010 max_data_bytes, datasize ));
1011 datasize = data_to_send = max_data_bytes;
1015 /* If there genuinely are no parameters or data to send just send the empty packet */
1017 if(params_to_send == 0 && data_to_send == 0) {
1018 reply_outbuf(req, 10, 0);
1019 if (NT_STATUS_V(status)) {
1022 ntstatus_to_dos(status, &eclass, &ecode);
1023 error_packet_set((char *)req->outbuf,
1024 eclass, ecode, status,
1027 show_msg((char *)req->outbuf);
1028 if (!srv_send_smb(xconn,
1029 (char *)req->outbuf,
1030 true, req->seqnum+1,
1031 IS_CONN_ENCRYPTED(conn),
1033 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1035 TALLOC_FREE(req->outbuf);
1039 /* When sending params and data ensure that both are nicely aligned */
1040 /* Only do this alignment when there is also data to send - else
1041 can cause NT redirector problems. */
1043 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1044 data_alignment_offset = 4 - (params_to_send % 4);
1046 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1047 /* The alignment_offset is to align the param bytes on an even byte
1048 boundary. NT 4.0 Beta needs this to work correctly. */
1050 useable_space = max_send - (smb_size
1053 + data_alignment_offset);
1055 if (useable_space < 0) {
1056 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1057 "= %d!!!", useable_space));
1058 exit_server_cleanly("send_trans2_replies: Not enough space");
1061 while (params_to_send || data_to_send) {
1062 /* Calculate whether we will totally or partially fill this packet */
1064 total_sent_thistime = params_to_send + data_to_send;
1066 /* We can never send more than useable_space */
1068 * Note that 'useable_space' does not include the alignment offsets,
1069 * but we must include the alignment offsets in the calculation of
1070 * the length of the data we send over the wire, as the alignment offsets
1071 * are sent here. Fix from Marc_Jacobsen@hp.com.
1074 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1076 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1077 + data_alignment_offset);
1079 /* Set total params and data to be sent */
1080 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1081 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1083 /* Calculate how many parameters and data we can fit into
1084 * this packet. Parameters get precedence
1087 params_sent_thistime = MIN(params_to_send,useable_space);
1088 data_sent_thistime = useable_space - params_sent_thistime;
1089 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1091 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1093 /* smb_proff is the offset from the start of the SMB header to the
1094 parameter bytes, however the first 4 bytes of outbuf are
1095 the Netbios over TCP header. Thus use smb_base() to subtract
1096 them from the calculation */
1098 SSVAL(req->outbuf,smb_proff,
1099 ((smb_buf(req->outbuf)+alignment_offset)
1100 - smb_base(req->outbuf)));
1102 if(params_sent_thistime == 0)
1103 SSVAL(req->outbuf,smb_prdisp,0);
1105 /* Absolute displacement of param bytes sent in this packet */
1106 SSVAL(req->outbuf,smb_prdisp,pp - params);
1108 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1109 if(data_sent_thistime == 0) {
1110 SSVAL(req->outbuf,smb_droff,0);
1111 SSVAL(req->outbuf,smb_drdisp, 0);
1113 /* The offset of the data bytes is the offset of the
1114 parameter bytes plus the number of parameters being sent this time */
1115 SSVAL(req->outbuf, smb_droff,
1116 ((smb_buf(req->outbuf)+alignment_offset)
1117 - smb_base(req->outbuf))
1118 + params_sent_thistime + data_alignment_offset);
1119 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1122 /* Initialize the padding for alignment */
1124 if (alignment_offset != 0) {
1125 memset(smb_buf(req->outbuf), 0, alignment_offset);
1128 /* Copy the param bytes into the packet */
1130 if(params_sent_thistime) {
1131 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1132 params_sent_thistime);
1135 /* Copy in the data bytes */
1136 if(data_sent_thistime) {
1137 if (data_alignment_offset != 0) {
1138 memset((smb_buf(req->outbuf)+alignment_offset+
1139 params_sent_thistime), 0,
1140 data_alignment_offset);
1142 memcpy(smb_buf(req->outbuf)+alignment_offset
1143 +params_sent_thistime+data_alignment_offset,
1144 pd,data_sent_thistime);
1147 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1148 params_sent_thistime, data_sent_thistime, useable_space));
1149 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1150 params_to_send, data_to_send, paramsize, datasize));
1153 error_packet_set((char *)req->outbuf,
1154 ERRDOS,ERRbufferoverflow,
1155 STATUS_BUFFER_OVERFLOW,
1157 } else if (NT_STATUS_V(status)) {
1160 ntstatus_to_dos(status, &eclass, &ecode);
1161 error_packet_set((char *)req->outbuf,
1162 eclass, ecode, status,
1166 /* Send the packet */
1167 show_msg((char *)req->outbuf);
1168 if (!srv_send_smb(xconn,
1169 (char *)req->outbuf,
1170 true, req->seqnum+1,
1171 IS_CONN_ENCRYPTED(conn),
1173 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1175 TALLOC_FREE(req->outbuf);
1177 pp += params_sent_thistime;
1178 pd += data_sent_thistime;
1180 params_to_send -= params_sent_thistime;
1181 data_to_send -= data_sent_thistime;
1184 if(params_to_send < 0 || data_to_send < 0) {
1185 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1186 params_to_send, data_to_send));
1194 /****************************************************************************
1195 Reply to a TRANSACT2_OPEN.
1196 ****************************************************************************/
1198 static void call_trans2open(connection_struct *conn,
1199 struct smb_request *req,
1200 char **pparams, int total_params,
1201 char **ppdata, int total_data,
1202 unsigned int max_data_bytes)
1204 struct smb_filename *smb_fname = NULL;
1205 char *params = *pparams;
1206 char *pdata = *ppdata;
1209 bool oplock_request;
1211 bool return_additional_info;
1220 int fattr=0,mtime=0;
1221 SMB_INO_T inode = 0;
1224 struct ea_list *ea_list = NULL;
1227 uint32_t access_mask;
1228 uint32_t share_mode;
1229 uint32_t create_disposition;
1230 uint32_t create_options = 0;
1231 uint32_t private_flags = 0;
1232 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1233 TALLOC_CTX *ctx = talloc_tos();
1236 * Ensure we have enough parameters to perform the operation.
1239 if (total_params < 29) {
1240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1244 flags = SVAL(params, 0);
1245 deny_mode = SVAL(params, 2);
1246 open_attr = SVAL(params,6);
1247 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1248 if (oplock_request) {
1249 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1253 return_additional_info = BITSETW(params,0);
1254 open_sattr = SVAL(params, 4);
1255 open_time = make_unix_date3(params+8);
1257 open_ofun = SVAL(params,12);
1258 open_size = IVAL(params,14);
1259 pname = ¶ms[28];
1262 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1266 if (req->posix_pathnames) {
1267 srvstr_get_path_posix(ctx,
1276 srvstr_get_path(ctx,
1285 if (!NT_STATUS_IS_OK(status)) {
1286 reply_nterror(req, status);
1290 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1291 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1292 (unsigned int)open_ofun, open_size));
1294 status = filename_convert(ctx,
1300 if (!NT_STATUS_IS_OK(status)) {
1301 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1302 reply_botherror(req,
1303 NT_STATUS_PATH_NOT_COVERED,
1304 ERRSRV, ERRbadpath);
1307 reply_nterror(req, status);
1311 if (open_ofun == 0) {
1312 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1316 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1318 &access_mask, &share_mode,
1319 &create_disposition,
1322 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1326 /* Any data in this call is an EA list. */
1327 if (total_data && (total_data != 4)) {
1328 if (total_data < 10) {
1329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1333 if (IVAL(pdata,0) > total_data) {
1334 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1335 IVAL(pdata,0), (unsigned int)total_data));
1336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1340 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1347 if (!lp_ea_support(SNUM(conn))) {
1348 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1352 if (!req->posix_pathnames &&
1353 ea_list_has_invalid_name(ea_list)) {
1355 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1356 if(*pparams == NULL ) {
1357 reply_nterror(req, NT_STATUS_NO_MEMORY);
1361 memset(params, '\0', param_len);
1362 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1363 params, param_len, NULL, 0, max_data_bytes);
1368 status = SMB_VFS_CREATE_FILE(
1371 0, /* root_dir_fid */
1372 smb_fname, /* fname */
1373 access_mask, /* access_mask */
1374 share_mode, /* share_access */
1375 create_disposition, /* create_disposition*/
1376 create_options, /* create_options */
1377 open_attr, /* file_attributes */
1378 oplock_request, /* oplock_request */
1380 open_size, /* allocation_size */
1383 ea_list, /* ea_list */
1385 &smb_action, /* psbuf */
1386 NULL, NULL); /* create context */
1388 if (!NT_STATUS_IS_OK(status)) {
1389 if (open_was_deferred(req->xconn, req->mid)) {
1390 /* We have re-scheduled this call. */
1393 reply_openerror(req, status);
1397 size = get_file_size_stat(&smb_fname->st);
1398 fattr = dos_mode(conn, smb_fname);
1399 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1400 inode = smb_fname->st.st_ex_ino;
1401 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1402 close_file(req, fsp, ERROR_CLOSE);
1403 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1407 /* Realloc the size of parameters and data we will return */
1408 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1409 if(*pparams == NULL ) {
1410 reply_nterror(req, NT_STATUS_NO_MEMORY);
1415 SSVAL(params,0,fsp->fnum);
1416 SSVAL(params,2,fattr);
1417 srv_put_dos_date2(params,4, mtime);
1418 SIVAL(params,8, (uint32_t)size);
1419 SSVAL(params,12,deny_mode);
1420 SSVAL(params,14,0); /* open_type - file or directory. */
1421 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1423 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1424 smb_action |= EXTENDED_OPLOCK_GRANTED;
1427 SSVAL(params,18,smb_action);
1430 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1432 SIVAL(params,20,inode);
1433 SSVAL(params,24,0); /* Padding. */
1435 uint32_t ea_size = estimate_ea_size(conn, fsp,
1437 SIVAL(params, 26, ea_size);
1439 SIVAL(params, 26, 0);
1442 /* Send the required number of replies */
1443 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1445 TALLOC_FREE(smb_fname);
1448 /*********************************************************
1449 Routine to check if a given string matches exactly.
1450 as a special case a mask of "." does NOT match. That
1451 is required for correct wildcard semantics
1452 Case can be significant or not.
1453 **********************************************************/
1455 static bool exact_match(bool has_wild,
1456 bool case_sensitive,
1460 if (mask[0] == '.' && mask[1] == 0) {
1468 if (case_sensitive) {
1469 return strcmp(str,mask)==0;
1471 return strcasecmp_m(str,mask) == 0;
1475 /****************************************************************************
1476 Return the filetype for UNIX extensions.
1477 ****************************************************************************/
1479 static uint32_t unix_filetype(mode_t mode)
1482 return UNIX_TYPE_FILE;
1483 else if(S_ISDIR(mode))
1484 return UNIX_TYPE_DIR;
1486 else if(S_ISLNK(mode))
1487 return UNIX_TYPE_SYMLINK;
1490 else if(S_ISCHR(mode))
1491 return UNIX_TYPE_CHARDEV;
1494 else if(S_ISBLK(mode))
1495 return UNIX_TYPE_BLKDEV;
1498 else if(S_ISFIFO(mode))
1499 return UNIX_TYPE_FIFO;
1502 else if(S_ISSOCK(mode))
1503 return UNIX_TYPE_SOCKET;
1506 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1507 return UNIX_TYPE_UNKNOWN;
1510 /****************************************************************************
1511 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1512 ****************************************************************************/
1514 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1516 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1517 const SMB_STRUCT_STAT *psbuf,
1519 enum perm_type ptype,
1524 if (perms == SMB_MODE_NO_CHANGE) {
1525 if (!VALID_STAT(*psbuf)) {
1526 return NT_STATUS_INVALID_PARAMETER;
1528 *ret_perms = psbuf->st_ex_mode;
1529 return NT_STATUS_OK;
1533 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1534 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1535 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1536 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1537 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1538 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1539 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1540 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1541 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1543 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1546 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1549 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1552 if (ptype == PERM_NEW_FILE) {
1554 * "create mask"/"force create mode" are
1555 * only applied to new files, not existing ones.
1557 ret &= lp_create_mask(SNUM(conn));
1558 /* Add in force bits */
1559 ret |= lp_force_create_mode(SNUM(conn));
1560 } else if (ptype == PERM_NEW_DIR) {
1562 * "directory mask"/"force directory mode" are
1563 * only applied to new directories, not existing ones.
1565 ret &= lp_directory_mask(SNUM(conn));
1566 /* Add in force bits */
1567 ret |= lp_force_directory_mode(SNUM(conn));
1571 return NT_STATUS_OK;
1574 /****************************************************************************
1575 Needed to show the msdfs symlinks as directories. Modifies psbuf
1576 to be a directory if it's a msdfs link.
1577 ****************************************************************************/
1579 static bool check_msdfs_link(connection_struct *conn,
1580 struct smb_filename *smb_fname)
1582 int saved_errno = errno;
1583 if(lp_host_msdfs() &&
1584 lp_msdfs_root(SNUM(conn)) &&
1585 is_msdfs_link(conn, smb_fname)) {
1587 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1589 smb_fname->base_name));
1590 smb_fname->st.st_ex_mode =
1591 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1592 errno = saved_errno;
1595 errno = saved_errno;
1600 /****************************************************************************
1601 Get a level dependent lanman2 dir entry.
1602 ****************************************************************************/
1604 struct smbd_dirptr_lanman2_state {
1605 connection_struct *conn;
1606 uint32_t info_level;
1607 bool check_mangled_names;
1609 bool got_exact_match;
1612 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1618 struct smbd_dirptr_lanman2_state *state =
1619 (struct smbd_dirptr_lanman2_state *)private_data;
1621 char mangled_name[13]; /* mangled 8.3 name. */
1625 /* Mangle fname if it's an illegal name. */
1626 if (mangle_must_mangle(dname, state->conn->params)) {
1628 * Slow path - ensure we can push the original name as UCS2. If
1629 * not, then just don't return this name.
1633 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1634 uint8_t *tmp = talloc_array(talloc_tos(),
1638 status = srvstr_push(NULL,
1639 FLAGS2_UNICODE_STRINGS,
1648 if (!NT_STATUS_IS_OK(status)) {
1652 ok = name_to_8_3(dname, mangled_name,
1653 true, state->conn->params);
1657 fname = mangled_name;
1662 got_match = exact_match(state->has_wild,
1663 state->conn->case_sensitive,
1665 state->got_exact_match = got_match;
1667 got_match = mask_match(fname, mask,
1668 state->conn->case_sensitive);
1671 if(!got_match && state->check_mangled_names &&
1672 !mangle_is_8_3(fname, false, state->conn->params)) {
1674 * It turns out that NT matches wildcards against
1675 * both long *and* short names. This may explain some
1676 * of the wildcard wierdness from old DOS clients
1677 * that some people have been seeing.... JRA.
1679 /* Force the mangling into 8.3. */
1680 ok = name_to_8_3(fname, mangled_name,
1681 false, state->conn->params);
1686 got_match = exact_match(state->has_wild,
1687 state->conn->case_sensitive,
1688 mangled_name, mask);
1689 state->got_exact_match = got_match;
1691 got_match = mask_match(mangled_name, mask,
1692 state->conn->case_sensitive);
1700 *_fname = talloc_strdup(ctx, fname);
1701 if (*_fname == NULL) {
1708 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1710 struct smb_filename *smb_fname,
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,
1734 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1735 "Couldn't stat [%s] (%s)\n",
1736 smb_fname_str_dbg(smb_fname),
1743 mode = dos_mode_msdfs(state->conn, smb_fname);
1745 mode = dos_mode(state->conn, smb_fname);
1752 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1753 connection_struct *conn,
1755 uint32_t info_level,
1756 struct ea_list *name_list,
1757 bool check_mangled_names,
1758 bool requires_resume_key,
1761 const struct smb_filename *smb_fname,
1762 int space_remaining,
1768 uint64_t *last_entry_off)
1770 char *p, *q, *pdata = *ppdata;
1772 uint64_t file_size = 0;
1773 uint64_t allocation_size = 0;
1774 uint64_t file_index = 0;
1776 struct timespec mdate_ts = {0};
1777 struct timespec adate_ts = {0};
1778 struct timespec cdate_ts = {0};
1779 struct timespec create_date_ts = {0};
1780 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1782 char *last_entry_ptr;
1787 struct readdir_attr_data *readdir_attr_data = NULL;
1789 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1790 file_size = get_file_size_stat(&smb_fname->st);
1792 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1794 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1801 file_index = get_FileIndex(conn, &smb_fname->st);
1803 mdate_ts = smb_fname->st.st_ex_mtime;
1804 adate_ts = smb_fname->st.st_ex_atime;
1805 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1806 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1808 if (lp_dos_filetime_resolution(SNUM(conn))) {
1809 dos_filetime_timespec(&create_date_ts);
1810 dos_filetime_timespec(&mdate_ts);
1811 dos_filetime_timespec(&adate_ts);
1812 dos_filetime_timespec(&cdate_ts);
1815 create_date = convert_timespec_to_time_t(create_date_ts);
1816 mdate = convert_timespec_to_time_t(mdate_ts);
1817 adate = convert_timespec_to_time_t(adate_ts);
1819 /* align the record */
1820 SMB_ASSERT(align >= 1);
1822 off = (int)PTR_DIFF(pdata, base_data);
1823 pad = (off + (align-1)) & ~(align-1);
1826 if (pad && pad > space_remaining) {
1827 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1828 "for padding (wanted %u, had %d)\n",
1831 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1835 /* initialize padding to 0 */
1837 memset(pdata, 0, pad);
1839 space_remaining -= pad;
1841 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1851 switch (info_level) {
1852 case SMB_FIND_INFO_STANDARD:
1853 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1854 if(requires_resume_key) {
1858 srv_put_dos_date2(p,0,create_date);
1859 srv_put_dos_date2(p,4,adate);
1860 srv_put_dos_date2(p,8,mdate);
1861 SIVAL(p,12,(uint32_t)file_size);
1862 SIVAL(p,16,(uint32_t)allocation_size);
1866 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1867 p += ucs2_align(base_data, p, 0);
1869 status = srvstr_push(base_data, flags2, p,
1870 fname, PTR_DIFF(end_data, p),
1871 STR_TERMINATE, &len);
1872 if (!NT_STATUS_IS_OK(status)) {
1875 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1877 SCVAL(nameptr, -1, len - 2);
1879 SCVAL(nameptr, -1, 0);
1883 SCVAL(nameptr, -1, len - 1);
1885 SCVAL(nameptr, -1, 0);
1891 case SMB_FIND_EA_SIZE:
1892 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1893 if (requires_resume_key) {
1897 srv_put_dos_date2(p,0,create_date);
1898 srv_put_dos_date2(p,4,adate);
1899 srv_put_dos_date2(p,8,mdate);
1900 SIVAL(p,12,(uint32_t)file_size);
1901 SIVAL(p,16,(uint32_t)allocation_size);
1904 unsigned int ea_size = estimate_ea_size(conn, NULL,
1906 SIVAL(p,22,ea_size); /* Extended attributes */
1910 status = srvstr_push(base_data, flags2,
1911 p, fname, PTR_DIFF(end_data, p),
1912 STR_TERMINATE | STR_NOALIGN, &len);
1913 if (!NT_STATUS_IS_OK(status)) {
1916 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1929 SCVAL(nameptr,0,len);
1931 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1934 case SMB_FIND_EA_LIST:
1936 struct ea_list *file_list = NULL;
1939 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1941 return NT_STATUS_INVALID_PARAMETER;
1943 if (requires_resume_key) {
1947 srv_put_dos_date2(p,0,create_date);
1948 srv_put_dos_date2(p,4,adate);
1949 srv_put_dos_date2(p,8,mdate);
1950 SIVAL(p,12,(uint32_t)file_size);
1951 SIVAL(p,16,(uint32_t)allocation_size);
1953 p += 22; /* p now points to the EA area. */
1955 status = get_ea_list_from_file(ctx, conn, NULL,
1957 &ea_len, &file_list);
1958 if (!NT_STATUS_IS_OK(status)) {
1961 name_list = ea_list_union(name_list, file_list, &ea_len);
1963 /* We need to determine if this entry will fit in the space available. */
1964 /* Max string size is 255 bytes. */
1965 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1966 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1967 "(wanted %u, had %d)\n",
1968 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1970 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1973 /* Push the ea_data followed by the name. */
1974 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1976 status = srvstr_push(base_data, flags2,
1977 p + 1, fname, PTR_DIFF(end_data, p+1),
1978 STR_TERMINATE | STR_NOALIGN, &len);
1979 if (!NT_STATUS_IS_OK(status)) {
1982 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1995 SCVAL(nameptr,0,len);
1997 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2001 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2002 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2003 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2005 SIVAL(p,0,reskey); p += 4;
2006 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2007 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2008 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2009 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2010 SOFF_T(p,0,file_size); p += 8;
2011 SOFF_T(p,0,allocation_size); p += 8;
2012 SIVAL(p,0,mode); p += 4;
2013 q = p; p += 4; /* q is placeholder for name length. */
2014 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2015 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2017 unsigned int ea_size = estimate_ea_size(conn, NULL,
2019 SIVAL(p,0,ea_size); /* Extended attributes */
2022 /* Clear the short name buffer. This is
2023 * IMPORTANT as not doing so will trigger
2024 * a Win2k client bug. JRA.
2026 if (!was_8_3 && check_mangled_names) {
2027 char mangled_name[13]; /* mangled 8.3 name. */
2028 if (!name_to_8_3(fname,mangled_name,True,
2030 /* Error - mangle failed ! */
2031 memset(mangled_name,'\0',12);
2033 mangled_name[12] = 0;
2034 status = srvstr_push(base_data, flags2,
2035 p+2, mangled_name, 24,
2036 STR_UPPER|STR_UNICODE, &len);
2037 if (!NT_STATUS_IS_OK(status)) {
2041 memset(p + 2 + len,'\0',24 - len);
2048 status = srvstr_push(base_data, flags2, p,
2049 fname, PTR_DIFF(end_data, p),
2050 STR_TERMINATE_ASCII, &len);
2051 if (!NT_STATUS_IS_OK(status)) {
2057 len = PTR_DIFF(p, pdata);
2058 pad = (len + (align-1)) & ~(align-1);
2060 * offset to the next entry, the caller
2061 * will overwrite it for the last entry
2062 * that's why we always include the padding
2066 * set padding to zero
2069 memset(p, 0, pad - len);
2076 case SMB_FIND_FILE_DIRECTORY_INFO:
2077 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2079 SIVAL(p,0,reskey); p += 4;
2080 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2081 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2082 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2083 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2084 SOFF_T(p,0,file_size); p += 8;
2085 SOFF_T(p,0,allocation_size); p += 8;
2086 SIVAL(p,0,mode); p += 4;
2087 status = srvstr_push(base_data, flags2,
2088 p + 4, fname, PTR_DIFF(end_data, p+4),
2089 STR_TERMINATE_ASCII, &len);
2090 if (!NT_STATUS_IS_OK(status)) {
2096 len = PTR_DIFF(p, pdata);
2097 pad = (len + (align-1)) & ~(align-1);
2099 * offset to the next entry, the caller
2100 * will overwrite it for the last entry
2101 * that's why we always include the padding
2105 * set padding to zero
2108 memset(p, 0, pad - len);
2115 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2116 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2118 SIVAL(p,0,reskey); p += 4;
2119 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2120 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2121 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2122 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2123 SOFF_T(p,0,file_size); p += 8;
2124 SOFF_T(p,0,allocation_size); p += 8;
2125 SIVAL(p,0,mode); p += 4;
2126 q = p; p += 4; /* q is placeholder for name length. */
2128 unsigned int ea_size = estimate_ea_size(conn, NULL,
2130 SIVAL(p,0,ea_size); /* Extended attributes */
2133 status = srvstr_push(base_data, flags2, p,
2134 fname, PTR_DIFF(end_data, p),
2135 STR_TERMINATE_ASCII, &len);
2136 if (!NT_STATUS_IS_OK(status)) {
2142 len = PTR_DIFF(p, pdata);
2143 pad = (len + (align-1)) & ~(align-1);
2145 * offset to the next entry, the caller
2146 * will overwrite it for the last entry
2147 * that's why we always include the padding
2151 * set padding to zero
2154 memset(p, 0, pad - len);
2161 case SMB_FIND_FILE_NAMES_INFO:
2162 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2164 SIVAL(p,0,reskey); p += 4;
2166 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2167 acl on a dir (tridge) */
2168 status = srvstr_push(base_data, flags2, p,
2169 fname, PTR_DIFF(end_data, p),
2170 STR_TERMINATE_ASCII, &len);
2171 if (!NT_STATUS_IS_OK(status)) {
2177 len = PTR_DIFF(p, pdata);
2178 pad = (len + (align-1)) & ~(align-1);
2180 * offset to the next entry, the caller
2181 * will overwrite it for the last entry
2182 * that's why we always include the padding
2186 * set padding to zero
2189 memset(p, 0, pad - len);
2196 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2197 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2199 SIVAL(p,0,reskey); p += 4;
2200 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2201 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2202 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2203 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2204 SOFF_T(p,0,file_size); p += 8;
2205 SOFF_T(p,0,allocation_size); p += 8;
2206 SIVAL(p,0,mode); p += 4;
2207 q = p; p += 4; /* q is placeholder for name length. */
2208 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2209 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2211 unsigned int ea_size = estimate_ea_size(conn, NULL,
2213 SIVAL(p,0,ea_size); /* Extended attributes */
2216 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2217 SBVAL(p,0,file_index); p += 8;
2218 status = srvstr_push(base_data, flags2, p,
2219 fname, PTR_DIFF(end_data, p),
2220 STR_TERMINATE_ASCII, &len);
2221 if (!NT_STATUS_IS_OK(status)) {
2227 len = PTR_DIFF(p, pdata);
2228 pad = (len + (align-1)) & ~(align-1);
2230 * offset to the next entry, the caller
2231 * will overwrite it for the last entry
2232 * that's why we always include the padding
2236 * set padding to zero
2239 memset(p, 0, pad - len);
2246 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2247 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2248 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2250 SIVAL(p,0,reskey); p += 4;
2251 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2252 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2253 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2254 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2255 SOFF_T(p,0,file_size); p += 8;
2256 SOFF_T(p,0,allocation_size); p += 8;
2257 SIVAL(p,0,mode); p += 4;
2258 q = p; p += 4; /* q is placeholder for name length */
2259 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2260 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2261 } else if (readdir_attr_data &&
2262 readdir_attr_data->type == RDATTR_AAPL) {
2264 * OS X specific SMB2 extension negotiated via
2265 * AAPL create context: return max_access in
2268 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2270 unsigned int ea_size = estimate_ea_size(conn, NULL,
2272 SIVAL(p,0,ea_size); /* Extended attributes */
2276 if (readdir_attr_data &&
2277 readdir_attr_data->type == RDATTR_AAPL) {
2279 * OS X specific SMB2 extension negotiated via
2280 * AAPL create context: return resource fork
2281 * length and compressed FinderInfo in
2284 * According to documentation short_name_len
2285 * should be 0, but on the wire behaviour
2286 * shows its set to 24 by clients.
2290 /* Resourefork length */
2291 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2293 /* Compressed FinderInfo */
2294 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2295 } else if (!was_8_3 && check_mangled_names) {
2296 char mangled_name[13]; /* mangled 8.3 name. */
2297 if (!name_to_8_3(fname,mangled_name,True,
2299 /* Error - mangle failed ! */
2300 memset(mangled_name,'\0',12);
2302 mangled_name[12] = 0;
2303 status = srvstr_push(base_data, flags2,
2304 p+2, mangled_name, 24,
2305 STR_UPPER|STR_UNICODE, &len);
2306 if (!NT_STATUS_IS_OK(status)) {
2311 memset(p + 2 + len,'\0',24 - len);
2315 /* Clear the short name buffer. This is
2316 * IMPORTANT as not doing so will trigger
2317 * a Win2k client bug. JRA.
2324 if (readdir_attr_data &&
2325 readdir_attr_data->type == RDATTR_AAPL) {
2327 * OS X specific SMB2 extension negotiated via
2328 * AAPL create context: return UNIX mode in
2331 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2332 SSVAL(p, 0, aapl_mode);
2338 SBVAL(p,0,file_index); p += 8;
2339 status = srvstr_push(base_data, flags2, p,
2340 fname, PTR_DIFF(end_data, p),
2341 STR_TERMINATE_ASCII, &len);
2342 if (!NT_STATUS_IS_OK(status)) {
2348 len = PTR_DIFF(p, pdata);
2349 pad = (len + (align-1)) & ~(align-1);
2351 * offset to the next entry, the caller
2352 * will overwrite it for the last entry
2353 * that's why we always include the padding
2357 * set padding to zero
2360 memset(p, 0, pad - len);
2367 /* CIFS UNIX Extension. */
2369 case SMB_FIND_FILE_UNIX:
2370 case SMB_FIND_FILE_UNIX_INFO2:
2372 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2374 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2376 if (info_level == SMB_FIND_FILE_UNIX) {
2377 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2378 p = store_file_unix_basic(conn, p,
2379 NULL, &smb_fname->st);
2380 status = srvstr_push(base_data, flags2, p,
2381 fname, PTR_DIFF(end_data, p),
2382 STR_TERMINATE, &len);
2383 if (!NT_STATUS_IS_OK(status)) {
2387 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2388 p = store_file_unix_basic_info2(conn, p,
2389 NULL, &smb_fname->st);
2392 status = srvstr_push(base_data, flags2, p, fname,
2393 PTR_DIFF(end_data, p), 0, &len);
2394 if (!NT_STATUS_IS_OK(status)) {
2397 SIVAL(nameptr, 0, len);
2402 len = PTR_DIFF(p, pdata);
2403 pad = (len + (align-1)) & ~(align-1);
2405 * offset to the next entry, the caller
2406 * will overwrite it for the last entry
2407 * that's why we always include the padding
2411 * set padding to zero
2414 memset(p, 0, pad - len);
2419 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2424 return NT_STATUS_INVALID_LEVEL;
2427 if (PTR_DIFF(p,pdata) > space_remaining) {
2428 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2429 "(wanted %u, had %d)\n",
2430 (unsigned int)PTR_DIFF(p,pdata),
2432 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2435 /* Setup the last entry pointer, as an offset from base_data */
2436 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2437 /* Advance the data pointer to the next slot */
2440 return NT_STATUS_OK;
2443 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2444 connection_struct *conn,
2445 struct dptr_struct *dirptr,
2447 const char *path_mask,
2450 int requires_resume_key,
2458 int space_remaining,
2459 bool *got_exact_match,
2460 int *_last_entry_off,
2461 struct ea_list *name_list,
2462 struct file_id *file_id)
2465 const char *mask = NULL;
2466 long prev_dirpos = 0;
2469 struct smb_filename *smb_fname = NULL;
2470 struct smbd_dirptr_lanman2_state state;
2472 uint64_t last_entry_off = 0;
2474 enum mangled_names_options mangled_names;
2475 bool marshall_with_83_names;
2477 mangled_names = lp_mangled_names(conn->params);
2481 state.info_level = info_level;
2482 if (mangled_names != MANGLED_NAMES_NO) {
2483 state.check_mangled_names = true;
2485 state.has_wild = dptr_has_wild(dirptr);
2486 state.got_exact_match = false;
2488 *got_exact_match = false;
2490 p = strrchr_m(path_mask,'/');
2501 ok = smbd_dirptr_get_entry(ctx,
2507 smbd_dirptr_lanman2_match_fn,
2508 smbd_dirptr_lanman2_mode_fn,
2515 return NT_STATUS_END_OF_FILE;
2518 *got_exact_match = state.got_exact_match;
2520 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2522 status = smbd_marshall_dir_entry(ctx,
2527 marshall_with_83_names,
2528 requires_resume_key,
2539 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2540 DEBUG(1,("Conversion error: illegal character: %s\n",
2541 smb_fname_str_dbg(smb_fname)));
2544 if (file_id != NULL) {
2545 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2549 TALLOC_FREE(smb_fname);
2550 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2551 dptr_SeekDir(dirptr, prev_dirpos);
2554 if (!NT_STATUS_IS_OK(status)) {
2558 *_last_entry_off = last_entry_off;
2559 return NT_STATUS_OK;
2562 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2563 connection_struct *conn,
2564 struct dptr_struct *dirptr,
2566 const char *path_mask,
2569 bool requires_resume_key,
2575 int space_remaining,
2576 bool *got_exact_match,
2577 int *last_entry_off,
2578 struct ea_list *name_list)
2581 const bool do_pad = true;
2583 if (info_level >= 1 && info_level <= 3) {
2584 /* No alignment on earlier info levels. */
2588 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2589 path_mask, dirtype, info_level,
2590 requires_resume_key, dont_descend, ask_sharemode,
2592 ppdata, base_data, end_data,
2595 last_entry_off, name_list, NULL);
2598 /****************************************************************************
2599 Reply to a TRANS2_FINDFIRST.
2600 ****************************************************************************/
2602 static void call_trans2findfirst(connection_struct *conn,
2603 struct smb_request *req,
2604 char **pparams, int total_params,
2605 char **ppdata, int total_data,
2606 unsigned int max_data_bytes)
2608 /* We must be careful here that we don't return more than the
2609 allowed number of data bytes. If this means returning fewer than
2610 maxentries then so be it. We assume that the redirector has
2611 enough room for the fixed number of parameter bytes it has
2613 struct smb_filename *smb_dname = NULL;
2614 char *params = *pparams;
2615 char *pdata = *ppdata;
2619 uint16_t findfirst_flags;
2620 bool close_after_first;
2622 bool requires_resume_key;
2624 char *directory = NULL;
2627 int last_entry_off=0;
2631 bool finished = False;
2632 bool dont_descend = False;
2633 bool out_of_space = False;
2634 int space_remaining;
2635 bool mask_contains_wcard = False;
2636 struct ea_list *ea_list = NULL;
2637 NTSTATUS ntstatus = NT_STATUS_OK;
2638 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2639 struct dptr_struct *dirptr = NULL;
2640 struct smbd_server_connection *sconn = req->sconn;
2641 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2642 ucf_flags_from_smb_request(req);
2643 bool backup_priv = false;
2644 bool as_root = false;
2646 if (total_params < 13) {
2647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2651 dirtype = SVAL(params,0);
2652 maxentries = SVAL(params,2);
2653 findfirst_flags = SVAL(params,4);
2654 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2655 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2656 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2657 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2658 security_token_has_privilege(get_current_nttok(conn),
2661 info_level = SVAL(params,6);
2663 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2664 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2665 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2667 info_level, max_data_bytes));
2670 /* W2K3 seems to treat zero as 1. */
2674 switch (info_level) {
2675 case SMB_FIND_INFO_STANDARD:
2676 case SMB_FIND_EA_SIZE:
2677 case SMB_FIND_EA_LIST:
2678 case SMB_FIND_FILE_DIRECTORY_INFO:
2679 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2680 case SMB_FIND_FILE_NAMES_INFO:
2681 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2682 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2683 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2685 case SMB_FIND_FILE_UNIX:
2686 case SMB_FIND_FILE_UNIX_INFO2:
2687 /* Always use filesystem for UNIX mtime query. */
2688 ask_sharemode = false;
2689 if (!lp_unix_extensions()) {
2690 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2693 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2696 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2700 if (req->posix_pathnames) {
2701 srvstr_get_path_wcard_posix(talloc_tos(),
2709 &mask_contains_wcard);
2711 srvstr_get_path_wcard(talloc_tos(),
2719 &mask_contains_wcard);
2721 if (!NT_STATUS_IS_OK(ntstatus)) {
2722 reply_nterror(req, ntstatus);
2729 ntstatus = filename_convert_with_privilege(talloc_tos(),
2734 &mask_contains_wcard,
2737 ntstatus = filename_convert(talloc_tos(), conn,
2740 &mask_contains_wcard,
2744 if (!NT_STATUS_IS_OK(ntstatus)) {
2745 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2746 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2747 ERRSRV, ERRbadpath);
2750 reply_nterror(req, ntstatus);
2754 mask = smb_dname->original_lcomp;
2756 directory = smb_dname->base_name;
2758 p = strrchr_m(directory,'/');
2760 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2761 if((directory[0] == '.') && (directory[1] == '\0')) {
2762 mask = talloc_strdup(talloc_tos(),"*");
2764 reply_nterror(req, NT_STATUS_NO_MEMORY);
2767 mask_contains_wcard = True;
2773 if (p == NULL || p == directory) {
2774 /* Ensure we don't have a directory name of "". */
2775 directory = talloc_strdup(talloc_tos(), ".");
2777 reply_nterror(req, NT_STATUS_NO_MEMORY);
2780 /* Ensure smb_dname->base_name matches. */
2781 smb_dname->base_name = directory;
2784 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2786 if (info_level == SMB_FIND_EA_LIST) {
2789 if (total_data < 4) {
2790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2794 ea_size = IVAL(pdata,0);
2795 if (ea_size != total_data) {
2796 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2797 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2802 if (!lp_ea_support(SNUM(conn))) {
2803 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2807 /* Pull out the list of names. */
2808 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2815 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2816 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2820 *ppdata = (char *)SMB_REALLOC(
2821 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2822 if(*ppdata == NULL ) {
2823 reply_nterror(req, NT_STATUS_NO_MEMORY);
2827 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2829 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2832 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2833 /* Realloc the params space */
2834 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2835 if (*pparams == NULL) {
2836 reply_nterror(req, NT_STATUS_NO_MEMORY);
2841 /* Save the wildcard match and attribs we are using on this directory -
2842 needed as lanman2 assumes these are being saved between calls */
2844 ntstatus = dptr_create(conn,
2852 mask_contains_wcard,
2856 if (!NT_STATUS_IS_OK(ntstatus)) {
2857 reply_nterror(req, ntstatus);
2862 /* Remember this in case we have
2863 to do a findnext. */
2864 dptr_set_priv(dirptr);
2867 dptr_num = dptr_dnum(dirptr);
2868 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2870 /* Initialize per TRANS2_FIND_FIRST operation data */
2871 dptr_init_search_op(dirptr);
2873 /* We don't need to check for VOL here as this is returned by
2874 a different TRANS2 call. */
2876 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2877 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2878 if (in_list(directory,
2879 lp_dont_descend(talloc_tos(), SNUM(conn)),
2880 conn->case_sensitive)) {
2881 dont_descend = True;
2885 space_remaining = max_data_bytes;
2886 out_of_space = False;
2888 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2889 bool got_exact_match = False;
2891 /* this is a heuristic to avoid seeking the dirptr except when
2892 absolutely necessary. It allows for a filename of about 40 chars */
2893 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2894 out_of_space = True;
2897 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2901 mask,dirtype,info_level,
2902 requires_resume_key,dont_descend,
2907 &last_entry_off, ea_list);
2908 if (NT_STATUS_EQUAL(ntstatus,
2909 NT_STATUS_ILLEGAL_CHARACTER)) {
2911 * Bad character conversion on name. Ignore this
2916 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2917 out_of_space = true;
2919 finished = !NT_STATUS_IS_OK(ntstatus);
2923 if (!finished && !out_of_space)
2927 * As an optimisation if we know we aren't looking
2928 * for a wildcard name (ie. the name matches the wildcard exactly)
2929 * then we can finish on any (first) match.
2930 * This speeds up large directory searches. JRA.
2936 /* Ensure space_remaining never goes -ve. */
2937 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2938 space_remaining = 0;
2939 out_of_space = true;
2941 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2945 /* Check if we can close the dirptr */
2946 if(close_after_first || (finished && close_if_end)) {
2947 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2948 dptr_close(sconn, &dptr_num);
2952 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2953 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2954 * the protocol level is less than NT1. Tested with smbclient. JRA.
2955 * This should fix the OS/2 client bug #2335.
2958 if(numentries == 0) {
2959 dptr_close(sconn, &dptr_num);
2960 if (get_Protocol() < PROTOCOL_NT1) {
2961 reply_force_doserror(req, ERRDOS, ERRnofiles);
2964 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2965 ERRDOS, ERRbadfile);
2970 /* At this point pdata points to numentries directory entries. */
2972 /* Set up the return parameter block */
2973 SSVAL(params,0,dptr_num);
2974 SSVAL(params,2,numentries);
2975 SSVAL(params,4,finished);
2976 SSVAL(params,6,0); /* Never an EA error */
2977 SSVAL(params,8,last_entry_off);
2979 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2982 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2983 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2985 reply_nterror(req, NT_STATUS_NO_MEMORY);
2989 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2990 smb_fn_name(req->cmd),
2991 mask, directory, dirtype, numentries ) );
2994 * Force a name mangle here to ensure that the
2995 * mask as an 8.3 name is top of the mangled cache.
2996 * The reasons for this are subtle. Don't remove
2997 * this code unless you know what you are doing
2998 * (see PR#13758). JRA.
3001 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3002 char mangled_name[13];
3003 name_to_8_3(mask, mangled_name, True, conn->params);
3011 TALLOC_FREE(smb_dname);
3015 /****************************************************************************
3016 Reply to a TRANS2_FINDNEXT.
3017 ****************************************************************************/
3019 static void call_trans2findnext(connection_struct *conn,
3020 struct smb_request *req,
3021 char **pparams, int total_params,
3022 char **ppdata, int total_data,
3023 unsigned int max_data_bytes)
3025 /* We must be careful here that we don't return more than the
3026 allowed number of data bytes. If this means returning fewer than
3027 maxentries then so be it. We assume that the redirector has
3028 enough room for the fixed number of parameter bytes it has
3030 char *params = *pparams;
3031 char *pdata = *ppdata;
3035 uint16_t info_level;
3036 uint32_t resume_key;
3037 uint16_t findnext_flags;
3038 bool close_after_request;
3040 bool requires_resume_key;
3042 bool mask_contains_wcard = False;
3043 char *resume_name = NULL;
3044 const char *mask = NULL;
3045 const char *directory = NULL;
3049 int i, last_entry_off=0;
3050 bool finished = False;
3051 bool dont_descend = False;
3052 bool out_of_space = False;
3053 int space_remaining;
3054 struct ea_list *ea_list = NULL;
3055 NTSTATUS ntstatus = NT_STATUS_OK;
3056 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3057 TALLOC_CTX *ctx = talloc_tos();
3058 struct dptr_struct *dirptr;
3059 struct smbd_server_connection *sconn = req->sconn;
3060 bool backup_priv = false;
3061 bool as_root = false;
3063 if (total_params < 13) {
3064 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3068 dptr_num = SVAL(params,0);
3069 maxentries = SVAL(params,2);
3070 info_level = SVAL(params,4);
3071 resume_key = IVAL(params,6);
3072 findnext_flags = SVAL(params,10);
3073 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3074 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3075 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3076 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3078 if (!continue_bit) {
3079 /* We only need resume_name if continue_bit is zero. */
3080 if (req->posix_pathnames) {
3081 srvstr_get_path_wcard_posix(ctx,
3089 &mask_contains_wcard);
3091 srvstr_get_path_wcard(ctx,
3099 &mask_contains_wcard);
3101 if (!NT_STATUS_IS_OK(ntstatus)) {
3102 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3103 complain (it thinks we're asking for the directory above the shared
3104 path or an invalid name). Catch this as the resume name is only compared, never used in
3105 a file access. JRA. */
3106 srvstr_pull_talloc(ctx, params, req->flags2,
3107 &resume_name, params+12,
3111 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3112 reply_nterror(req, ntstatus);
3118 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3119 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3120 resume_key = %d resume name = %s continue=%d level = %d\n",
3121 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3122 requires_resume_key, resume_key,
3123 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3126 /* W2K3 seems to treat zero as 1. */
3130 switch (info_level) {
3131 case SMB_FIND_INFO_STANDARD:
3132 case SMB_FIND_EA_SIZE:
3133 case SMB_FIND_EA_LIST:
3134 case SMB_FIND_FILE_DIRECTORY_INFO:
3135 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3136 case SMB_FIND_FILE_NAMES_INFO:
3137 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3138 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3139 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3141 case SMB_FIND_FILE_UNIX:
3142 case SMB_FIND_FILE_UNIX_INFO2:
3143 /* Always use filesystem for UNIX mtime query. */
3144 ask_sharemode = false;
3145 if (!lp_unix_extensions()) {
3146 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3151 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3155 if (info_level == SMB_FIND_EA_LIST) {
3158 if (total_data < 4) {
3159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3163 ea_size = IVAL(pdata,0);
3164 if (ea_size != total_data) {
3165 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3166 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3171 if (!lp_ea_support(SNUM(conn))) {
3172 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3176 /* Pull out the list of names. */
3177 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3184 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3189 *ppdata = (char *)SMB_REALLOC(
3190 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3191 if(*ppdata == NULL) {
3192 reply_nterror(req, NT_STATUS_NO_MEMORY);
3197 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3200 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3203 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3204 /* Realloc the params space */
3205 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3206 if(*pparams == NULL ) {
3207 reply_nterror(req, NT_STATUS_NO_MEMORY);
3213 /* Check that the dptr is valid */
3214 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3215 reply_nterror(req, STATUS_NO_MORE_FILES);
3219 directory = dptr_path(sconn, dptr_num);
3221 /* Get the wildcard mask from the dptr */
3222 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3223 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3224 reply_nterror(req, STATUS_NO_MORE_FILES);
3228 /* Get the attr mask from the dptr */
3229 dirtype = dptr_attr(sconn, dptr_num);
3231 backup_priv = dptr_get_priv(dirptr);
3233 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3234 "backup_priv = %d\n",
3235 dptr_num, mask, dirtype,
3237 dptr_TellDir(dirptr),
3240 /* Initialize per TRANS2_FIND_NEXT operation data */
3241 dptr_init_search_op(dirptr);
3243 /* We don't need to check for VOL here as this is returned by
3244 a different TRANS2 call. */
3246 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3247 directory,lp_dont_descend(ctx, SNUM(conn))));
3248 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3249 dont_descend = True;
3252 space_remaining = max_data_bytes;
3253 out_of_space = False;
3261 * Seek to the correct position. We no longer use the resume key but
3262 * depend on the last file name instead.
3265 if(!continue_bit && resume_name && *resume_name) {
3268 long current_pos = 0;
3270 * Remember, name_to_8_3 is called by
3271 * get_lanman2_dir_entry(), so the resume name
3272 * could be mangled. Ensure we check the unmangled name.
3275 if (mangle_is_mangled(resume_name, conn->params)) {
3276 char *new_resume_name = NULL;
3277 mangle_lookup_name_from_8_3(ctx,
3281 if (new_resume_name) {
3282 resume_name = new_resume_name;
3287 * Fix for NT redirector problem triggered by resume key indexes
3288 * changing between directory scans. We now return a resume key of 0
3289 * and instead look for the filename to continue from (also given
3290 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3291 * findfirst/findnext (as is usual) then the directory pointer
3292 * should already be at the correct place.
3295 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3296 } /* end if resume_name && !continue_bit */
3298 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3299 bool got_exact_match = False;
3301 /* this is a heuristic to avoid seeking the dirptr except when
3302 absolutely necessary. It allows for a filename of about 40 chars */
3303 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3304 out_of_space = True;
3307 ntstatus = get_lanman2_dir_entry(ctx,
3311 mask,dirtype,info_level,
3312 requires_resume_key,dont_descend,
3317 &last_entry_off, ea_list);
3318 if (NT_STATUS_EQUAL(ntstatus,
3319 NT_STATUS_ILLEGAL_CHARACTER)) {
3321 * Bad character conversion on name. Ignore this
3326 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3327 out_of_space = true;
3329 finished = !NT_STATUS_IS_OK(ntstatus);
3333 if (!finished && !out_of_space)
3337 * As an optimisation if we know we aren't looking
3338 * for a wildcard name (ie. the name matches the wildcard exactly)
3339 * then we can finish on any (first) match.
3340 * This speeds up large directory searches. JRA.
3346 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3349 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3350 smb_fn_name(req->cmd),
3351 mask, directory, dirtype, numentries ) );
3353 /* Check if we can close the dirptr */
3354 if(close_after_request || (finished && close_if_end)) {
3355 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3356 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3363 /* Set up the return parameter block */
3364 SSVAL(params,0,numentries);
3365 SSVAL(params,2,finished);
3366 SSVAL(params,4,0); /* Never an EA error */
3367 SSVAL(params,6,last_entry_off);
3369 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3375 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3377 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3381 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3383 SMB_ASSERT(extended_info != NULL);
3385 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3386 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3387 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3388 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3389 #ifdef SAMBA_VERSION_REVISION
3390 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3392 extended_info->samba_subversion = 0;
3393 #ifdef SAMBA_VERSION_RC_RELEASE
3394 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3396 #ifdef SAMBA_VERSION_PRE_RELEASE
3397 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3400 #ifdef SAMBA_VERSION_VENDOR_PATCH
3401 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3403 extended_info->samba_gitcommitdate = 0;
3404 #ifdef SAMBA_VERSION_COMMIT_TIME
3405 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3408 memset(extended_info->samba_version_string, 0,
3409 sizeof(extended_info->samba_version_string));
3411 snprintf (extended_info->samba_version_string,
3412 sizeof(extended_info->samba_version_string),
3413 "%s", samba_version_string());
3416 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3417 connection_struct *conn,
3418 TALLOC_CTX *mem_ctx,
3419 uint16_t info_level,
3421 unsigned int max_data_bytes,
3422 size_t *fixed_portion,
3423 struct smb_filename *fname,
3427 char *pdata, *end_data;
3430 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3431 int snum = SNUM(conn);
3432 const char *fstype = lp_fstype(SNUM(conn));
3433 const char *filename = NULL;
3434 const uint64_t bytes_per_sector = 512;
3435 uint32_t additional_flags = 0;
3436 struct smb_filename smb_fname;
3438 NTSTATUS status = NT_STATUS_OK;
3441 if (fname == NULL || fname->base_name == NULL) {
3444 filename = fname->base_name;
3448 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3449 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3450 "info level (0x%x) on IPC$.\n",
3451 (unsigned int)info_level));
3452 return NT_STATUS_ACCESS_DENIED;
3456 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3458 ZERO_STRUCT(smb_fname);
3459 smb_fname.base_name = discard_const_p(char, filename);
3461 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3462 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3463 return map_nt_error_from_unix(errno);
3468 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3469 return NT_STATUS_INVALID_PARAMETER;
3472 *ppdata = (char *)SMB_REALLOC(
3473 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3474 if (*ppdata == NULL) {
3475 return NT_STATUS_NO_MEMORY;
3479 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3480 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3484 switch (info_level) {
3485 case SMB_INFO_ALLOCATION:
3487 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3489 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3491 if (df_ret == (uint64_t)-1) {
3492 return map_nt_error_from_unix(errno);
3495 block_size = lp_block_size(snum);
3496 if (bsize < block_size) {
3497 uint64_t factor = block_size/bsize;
3502 if (bsize > block_size) {
3503 uint64_t factor = bsize/block_size;
3508 sectors_per_unit = bsize/bytes_per_sector;
3510 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3511 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3512 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3515 * For large drives, return max values and not modulo.
3517 dsize = MIN(dsize, UINT32_MAX);
3518 dfree = MIN(dfree, UINT32_MAX);
3520 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3521 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3522 SIVAL(pdata,l1_cUnit,dsize);
3523 SIVAL(pdata,l1_cUnitAvail,dfree);
3524 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3528 case SMB_INFO_VOLUME:
3529 /* Return volume name */
3531 * Add volume serial number - hash of a combination of
3532 * the called hostname and the service name.
3534 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3536 * Win2k3 and previous mess this up by sending a name length
3537 * one byte short. I believe only older clients (OS/2 Win9x) use
3538 * this call so try fixing this by adding a terminating null to
3539 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3541 status = srvstr_push(
3543 pdata+l2_vol_szVolLabel, vname,
3544 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3545 STR_NOALIGN|STR_TERMINATE, &len);
3546 if (!NT_STATUS_IS_OK(status)) {
3549 SCVAL(pdata,l2_vol_cch,len);
3550 data_len = l2_vol_szVolLabel + len;
3551 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3552 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3553 (unsigned)len, vname));
3556 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3557 case SMB_FS_ATTRIBUTE_INFORMATION:
3559 additional_flags = 0;
3560 #if defined(HAVE_SYS_QUOTAS)
3561 additional_flags |= FILE_VOLUME_QUOTAS;
3564 if(lp_nt_acl_support(SNUM(conn))) {
3565 additional_flags |= FILE_PERSISTENT_ACLS;
3568 /* Capabilities are filled in at connection time through STATVFS call */
3569 additional_flags |= conn->fs_capabilities;
3570 additional_flags |= lp_parm_int(conn->params->service,
3571 "share", "fake_fscaps",
3574 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3575 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3576 additional_flags); /* FS ATTRIBUTES */
3578 SIVAL(pdata,4,255); /* Max filename component length */
3579 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3580 and will think we can't do long filenames */
3581 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3582 PTR_DIFF(end_data, pdata+12),
3584 if (!NT_STATUS_IS_OK(status)) {
3588 data_len = 12 + len;
3589 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3590 /* the client only requested a portion of the
3592 data_len = max_data_bytes;
3593 status = STATUS_BUFFER_OVERFLOW;
3595 *fixed_portion = 16;
3598 case SMB_QUERY_FS_LABEL_INFO:
3599 case SMB_FS_LABEL_INFORMATION:
3600 status = srvstr_push(pdata, flags2, pdata+4, vname,
3601 PTR_DIFF(end_data, pdata+4), 0, &len);
3602 if (!NT_STATUS_IS_OK(status)) {
3609 case SMB_QUERY_FS_VOLUME_INFO:
3610 case SMB_FS_VOLUME_INFORMATION:
3613 * Add volume serial number - hash of a combination of
3614 * the called hostname and the service name.
3616 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3617 (str_checksum(get_local_machine_name())<<16));
3619 /* Max label len is 32 characters. */
3620 status = srvstr_push(pdata, flags2, pdata+18, vname,
3621 PTR_DIFF(end_data, pdata+18),
3623 if (!NT_STATUS_IS_OK(status)) {
3626 SIVAL(pdata,12,len);
3629 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3630 (int)strlen(vname),vname,
3631 lp_servicename(talloc_tos(), snum)));
3632 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3633 /* the client only requested a portion of the
3635 data_len = max_data_bytes;
3636 status = STATUS_BUFFER_OVERFLOW;
3638 *fixed_portion = 24;
3641 case SMB_QUERY_FS_SIZE_INFO:
3642 case SMB_FS_SIZE_INFORMATION:
3644 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3646 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3648 if (df_ret == (uint64_t)-1) {
3649 return map_nt_error_from_unix(errno);
3651 block_size = lp_block_size(snum);
3652 if (bsize < block_size) {
3653 uint64_t factor = block_size/bsize;
3658 if (bsize > block_size) {
3659 uint64_t factor = bsize/block_size;
3664 sectors_per_unit = bsize/bytes_per_sector;
3665 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3666 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3667 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3668 SBIG_UINT(pdata,0,dsize);
3669 SBIG_UINT(pdata,8,dfree);
3670 SIVAL(pdata,16,sectors_per_unit);
3671 SIVAL(pdata,20,bytes_per_sector);
3672 *fixed_portion = 24;
3676 case SMB_FS_FULL_SIZE_INFORMATION:
3678 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3680 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3682 if (df_ret == (uint64_t)-1) {
3683 return map_nt_error_from_unix(errno);
3685 block_size = lp_block_size(snum);
3686 if (bsize < block_size) {
3687 uint64_t factor = block_size/bsize;
3692 if (bsize > block_size) {
3693 uint64_t factor = bsize/block_size;
3698 sectors_per_unit = bsize/bytes_per_sector;
3699 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3700 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3701 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3702 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3703 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3704 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3705 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3706 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3707 *fixed_portion = 32;
3711 case SMB_QUERY_FS_DEVICE_INFO:
3712 case SMB_FS_DEVICE_INFORMATION:
3714 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3716 if (!CAN_WRITE(conn)) {
3717 characteristics |= FILE_READ_ONLY_DEVICE;
3720 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3721 SIVAL(pdata,4,characteristics);
3726 #ifdef HAVE_SYS_QUOTAS
3727 case SMB_FS_QUOTA_INFORMATION:
3729 * what we have to send --metze:
3731 * Unknown1: 24 NULL bytes
3732 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3733 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3734 * Quota Flags: 2 byte :
3735 * Unknown3: 6 NULL bytes
3739 * details for Quota Flags:
3741 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3742 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3743 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3744 * 0x0001 Enable Quotas: enable quota for this fs
3748 /* we need to fake up a fsp here,
3749 * because its not send in this call
3752 SMB_NTQUOTA_STRUCT quotas;
3755 ZERO_STRUCT(quotas);
3758 fsp.fnum = FNUM_FIELD_INVALID;
3761 if (get_current_uid(conn) != 0) {
3762 DEBUG(0,("get_user_quota: access_denied "
3763 "service [%s] user [%s]\n",
3764 lp_servicename(talloc_tos(), SNUM(conn)),
3765 conn->session_info->unix_info->unix_name));
3766 return NT_STATUS_ACCESS_DENIED;
3769 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3771 if (!NT_STATUS_IS_OK(status)) {
3772 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3778 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3779 lp_servicename(talloc_tos(), SNUM(conn))));
3781 /* Unknown1 24 NULL bytes*/
3782 SBIG_UINT(pdata,0,(uint64_t)0);
3783 SBIG_UINT(pdata,8,(uint64_t)0);
3784 SBIG_UINT(pdata,16,(uint64_t)0);
3786 /* Default Soft Quota 8 bytes */
3787 SBIG_UINT(pdata,24,quotas.softlim);
3789 /* Default Hard Quota 8 bytes */
3790 SBIG_UINT(pdata,32,quotas.hardlim);
3792 /* Quota flag 2 bytes */
3793 SSVAL(pdata,40,quotas.qflags);
3795 /* Unknown3 6 NULL bytes */
3801 #endif /* HAVE_SYS_QUOTAS */
3802 case SMB_FS_OBJECTID_INFORMATION:
3804 unsigned char objid[16];
3805 struct smb_extended_info extended_info;
3806 memcpy(pdata,create_volume_objectid(conn, objid),16);
3807 samba_extended_info_version (&extended_info);
3808 SIVAL(pdata,16,extended_info.samba_magic);
3809 SIVAL(pdata,20,extended_info.samba_version);
3810 SIVAL(pdata,24,extended_info.samba_subversion);
3811 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3812 memcpy(pdata+36,extended_info.samba_version_string,28);
3817 case SMB_FS_SECTOR_SIZE_INFORMATION:
3821 * These values match a physical Windows Server 2012
3822 * share backed by NTFS atop spinning rust.
3824 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3825 /* logical_bytes_per_sector */
3826 SIVAL(pdata, 0, bytes_per_sector);
3827 /* phys_bytes_per_sector_atomic */
3828 SIVAL(pdata, 4, bytes_per_sector);
3829 /* phys_bytes_per_sector_perf */
3830 SIVAL(pdata, 8, bytes_per_sector);
3831 /* fs_effective_phys_bytes_per_sector_atomic */
3832 SIVAL(pdata, 12, bytes_per_sector);
3834 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3835 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3836 /* byte_off_sector_align */
3837 SIVAL(pdata, 20, 0);
3838 /* byte_off_partition_align */
3839 SIVAL(pdata, 24, 0);
3840 *fixed_portion = 28;
3846 * Query the version and capabilities of the CIFS UNIX extensions
3850 case SMB_QUERY_CIFS_UNIX_INFO:
3852 bool large_write = lp_min_receive_file_size() &&
3853 !srv_is_signing_active(xconn);
3854 bool large_read = !srv_is_signing_active(xconn);
3855 int encrypt_caps = 0;
3857 if (!lp_unix_extensions()) {
3858 return NT_STATUS_INVALID_LEVEL;
3861 switch (conn->encrypt_level) {
3862 case SMB_SIGNING_OFF:
3865 case SMB_SIGNING_DESIRED:
3866 case SMB_SIGNING_IF_REQUIRED:
3867 case SMB_SIGNING_DEFAULT:
3868 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3870 case SMB_SIGNING_REQUIRED:
3871 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3872 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3873 large_write = false;
3879 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3880 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3882 /* We have POSIX ACLs, pathname, encryption,
3883 * large read/write, and locking capability. */
3885 SBIG_UINT(pdata,4,((uint64_t)(
3886 CIFS_UNIX_POSIX_ACLS_CAP|
3887 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3888 CIFS_UNIX_FCNTL_LOCKS_CAP|
3889 CIFS_UNIX_EXTATTR_CAP|
3890 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3892 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3894 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3898 case SMB_QUERY_POSIX_FS_INFO:
3901 vfs_statvfs_struct svfs;
3903 if (!lp_unix_extensions()) {
3904 return NT_STATUS_INVALID_LEVEL;
3907 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3911 SIVAL(pdata,0,svfs.OptimalTransferSize);
3912 SIVAL(pdata,4,svfs.BlockSize);
3913 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3914 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3915 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3916 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3917 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3918 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3919 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3921 } else if (rc == EOPNOTSUPP) {
3922 return NT_STATUS_INVALID_LEVEL;
3923 #endif /* EOPNOTSUPP */
3925 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3926 return NT_STATUS_DOS(ERRSRV, ERRerror);
3931 case SMB_QUERY_POSIX_WHOAMI:
3937 if (!lp_unix_extensions()) {
3938 return NT_STATUS_INVALID_LEVEL;
3941 if (max_data_bytes < 40) {
3942 return NT_STATUS_BUFFER_TOO_SMALL;
3945 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3946 flags |= SMB_WHOAMI_GUEST;
3949 /* NOTE: 8 bytes for UID/GID, irrespective of native
3950 * platform size. This matches
3951 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3953 data_len = 4 /* flags */
3960 + 4 /* pad/reserved */
3961 + (conn->session_info->unix_token->ngroups * 8)
3963 + (conn->session_info->security_token->num_sids *
3967 SIVAL(pdata, 0, flags);
3968 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3970 (uint64_t)conn->session_info->unix_token->uid);
3971 SBIG_UINT(pdata, 16,
3972 (uint64_t)conn->session_info->unix_token->gid);
3975 if (data_len >= max_data_bytes) {
3976 /* Potential overflow, skip the GIDs and SIDs. */
3978 SIVAL(pdata, 24, 0); /* num_groups */
3979 SIVAL(pdata, 28, 0); /* num_sids */
3980 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3981 SIVAL(pdata, 36, 0); /* reserved */
3987 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3988 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3990 /* We walk the SID list twice, but this call is fairly
3991 * infrequent, and I don't expect that it's performance
3992 * sensitive -- jpeach
3994 for (i = 0, sid_bytes = 0;
3995 i < conn->session_info->security_token->num_sids; ++i) {
3996 sid_bytes += ndr_size_dom_sid(
3997 &conn->session_info->security_token->sids[i],
4001 /* SID list byte count */
4002 SIVAL(pdata, 32, sid_bytes);
4004 /* 4 bytes pad/reserved - must be zero */
4005 SIVAL(pdata, 36, 0);
4009 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4010 SBIG_UINT(pdata, data_len,
4011 (uint64_t)conn->session_info->unix_token->groups[i]);
4017 i < conn->session_info->security_token->num_sids; ++i) {
4018 int sid_len = ndr_size_dom_sid(
4019 &conn->session_info->security_token->sids[i],
4022 sid_linearize((uint8_t *)(pdata + data_len),
4024 &conn->session_info->security_token->sids[i]);
4025 data_len += sid_len;
4031 case SMB_MAC_QUERY_FS_INFO:
4033 * Thursby MAC extension... ONLY on NTFS filesystems
4034 * once we do streams then we don't need this
4036 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4038 SIVAL(pdata,84,0x100); /* Don't support mac... */
4043 return NT_STATUS_INVALID_LEVEL;
4046 *ret_data_len = data_len;
4050 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4051 struct smb_request *req,
4053 const DATA_BLOB *qdata)
4056 SMB_NTQUOTA_STRUCT quotas;
4058 ZERO_STRUCT(quotas);
4061 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4062 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4063 lp_servicename(talloc_tos(), SNUM(conn)),
4064 conn->session_info->unix_info->unix_name));
4065 return NT_STATUS_ACCESS_DENIED;
4068 if (!check_fsp_ntquota_handle(conn, req,
4070 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4071 return NT_STATUS_INVALID_HANDLE;
4074 /* note: normally there're 48 bytes,
4075 * but we didn't use the last 6 bytes for now
4078 if (qdata->length < 42) {
4079 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4080 (unsigned int)qdata->length));
4081 return NT_STATUS_INVALID_PARAMETER;
4084 /* unknown_1 24 NULL bytes in pdata*/
4086 /* the soft quotas 8 bytes (uint64_t)*/
4087 quotas.softlim = BVAL(qdata->data,24);
4089 /* the hard quotas 8 bytes (uint64_t)*/
4090 quotas.hardlim = BVAL(qdata->data,32);
4092 /* quota_flags 2 bytes **/
4093 quotas.qflags = SVAL(qdata->data,40);
4095 /* unknown_2 6 NULL bytes follow*/
4097 /* now set the quotas */
4098 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4099 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4100 lp_servicename(talloc_tos(), SNUM(conn))));
4101 status = map_nt_error_from_unix(errno);
4103 status = NT_STATUS_OK;
4108 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4109 struct smb_request *req,
4110 TALLOC_CTX *mem_ctx,
4111 uint16_t info_level,
4113 const DATA_BLOB *pdata)
4115 switch (info_level) {
4116 case SMB_FS_QUOTA_INFORMATION:
4118 return smb_set_fsquota(conn,
4127 return NT_STATUS_INVALID_LEVEL;
4130 /****************************************************************************
4131 Reply to a TRANS2_QFSINFO (query filesystem info).
4132 ****************************************************************************/
4134 static void call_trans2qfsinfo(connection_struct *conn,
4135 struct smb_request *req,
4136 char **pparams, int total_params,
4137 char **ppdata, int total_data,
4138 unsigned int max_data_bytes)
4140 char *params = *pparams;
4141 uint16_t info_level;
4143 size_t fixed_portion;
4146 if (total_params < 2) {
4147 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4151 info_level = SVAL(params,0);
4153 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4154 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4155 DEBUG(0,("call_trans2qfsinfo: encryption required "
4156 "and info level 0x%x sent.\n",
4157 (unsigned int)info_level));
4158 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4163 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4165 status = smbd_do_qfsinfo(req->xconn, conn, req,
4172 if (!NT_STATUS_IS_OK(status)) {
4173 reply_nterror(req, status);
4177 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4180 DEBUG( 4, ( "%s info_level = %d\n",
4181 smb_fn_name(req->cmd), info_level) );
4186 /****************************************************************************
4187 Reply to a TRANS2_SETFSINFO (set filesystem info).
4188 ****************************************************************************/
4190 static void call_trans2setfsinfo(connection_struct *conn,
4191 struct smb_request *req,
4192 char **pparams, int total_params,
4193 char **ppdata, int total_data,
4194 unsigned int max_data_bytes)
4196 struct smbXsrv_connection *xconn = req->xconn;
4197 char *pdata = *ppdata;
4198 char *params = *pparams;
4199 uint16_t info_level;
4201 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4202 lp_servicename(talloc_tos(), SNUM(conn))));
4205 if (total_params < 4) {
4206 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4212 info_level = SVAL(params,2);
4215 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4216 info_level != SMB_SET_CIFS_UNIX_INFO) {
4217 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4218 "info level (0x%x) on IPC$.\n",
4219 (unsigned int)info_level));
4220 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4225 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4226 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4227 DEBUG(0,("call_trans2setfsinfo: encryption required "
4228 "and info level 0x%x sent.\n",
4229 (unsigned int)info_level));
4230 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4235 switch(info_level) {
4236 case SMB_SET_CIFS_UNIX_INFO:
4237 if (!lp_unix_extensions()) {
4238 DEBUG(2,("call_trans2setfsinfo: "
4239 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4240 "unix extensions off\n"));
4242 NT_STATUS_INVALID_LEVEL);
4246 /* There should be 12 bytes of capabilities set. */
4247 if (total_data < 12) {
4250 NT_STATUS_INVALID_PARAMETER);
4253 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4254 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4255 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4256 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4257 /* Just print these values for now. */
4258 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4259 "major = %u, minor = %u cap_low = 0x%x, "
4261 (unsigned int)xconn->
4262 smb1.unix_info.client_major,
4263 (unsigned int)xconn->
4264 smb1.unix_info.client_minor,
4265 (unsigned int)xconn->
4266 smb1.unix_info.client_cap_low,
4267 (unsigned int)xconn->
4268 smb1.unix_info.client_cap_high));
4270 /* Here is where we must switch to posix pathname processing... */
4271 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4272 lp_set_posix_pathnames();
4273 mangle_change_to_posix();
4276 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4277 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4278 /* Client that knows how to do posix locks,
4279 * but not posix open/mkdir operations. Set a
4280 * default type for read/write checks. */
4282 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4287 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4290 size_t param_len = 0;
4291 size_t data_len = total_data;
4293 if (!lp_unix_extensions()) {
4296 NT_STATUS_INVALID_LEVEL);
4300 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4303 NT_STATUS_NOT_SUPPORTED);
4307 if (xconn->smb1.echo_handler.trusted_fde) {
4308 DEBUG( 2,("call_trans2setfsinfo: "
4309 "request transport encryption disabled"
4310 "with 'fork echo handler = yes'\n"));
4313 NT_STATUS_NOT_SUPPORTED);
4317 DEBUG( 4,("call_trans2setfsinfo: "
4318 "request transport encryption.\n"));
4320 status = srv_request_encryption_setup(conn,
4321 (unsigned char **)ppdata,
4323 (unsigned char **)pparams,
4326 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4327 !NT_STATUS_IS_OK(status)) {
4328 reply_nterror(req, status);
4332 send_trans2_replies(conn, req,
4340 if (NT_STATUS_IS_OK(status)) {
4341 /* Server-side transport
4342 * encryption is now *on*. */
4343 status = srv_encryption_start(conn);
4344 if (!NT_STATUS_IS_OK(status)) {
4345 char *reason = talloc_asprintf(talloc_tos(),
4346 "Failure in setting "
4347 "up encrypted transport: %s",
4349 exit_server_cleanly(reason);
4355 case SMB_FS_QUOTA_INFORMATION:
4359 .data = (uint8_t *)pdata,
4360 .length = total_data
4362 files_struct *fsp = NULL;
4363 fsp = file_fsp(req, SVAL(params,0));
4365 status = smb_set_fsquota(conn,
4369 if (!NT_STATUS_IS_OK(status)) {
4370 reply_nterror(req, status);
4376 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4378 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4384 * sending this reply works fine,
4385 * but I'm not sure it's the same
4386 * like windows do...
4389 reply_outbuf(req, 10, 0);
4392 #if defined(HAVE_POSIX_ACLS)
4393 /****************************************************************************
4394 Utility function to count the number of entries in a POSIX acl.
4395 ****************************************************************************/
4397 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4399 unsigned int ace_count = 0;
4400 int entry_id = SMB_ACL_FIRST_ENTRY;
4401 SMB_ACL_ENTRY_T entry;
4403 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4405 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4406 entry_id = SMB_ACL_NEXT_ENTRY;
4413 /****************************************************************************
4414 Utility function to marshall a POSIX acl into wire format.
4415 ****************************************************************************/
4417 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4419 int entry_id = SMB_ACL_FIRST_ENTRY;
4420 SMB_ACL_ENTRY_T entry;
4422 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4423 SMB_ACL_TAG_T tagtype;
4424 SMB_ACL_PERMSET_T permset;
4425 unsigned char perms = 0;
4426 unsigned int own_grp;
4429 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4430 entry_id = SMB_ACL_NEXT_ENTRY;
4433 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4434 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4438 if (sys_acl_get_permset(entry, &permset) == -1) {
4439 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4443 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4444 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4445 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4447 SCVAL(pdata,1,perms);
4450 case SMB_ACL_USER_OBJ:
4451 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4452 own_grp = (unsigned int)pst->st_ex_uid;
4453 SIVAL(pdata,2,own_grp);
4458 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4460 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4463 own_grp = (unsigned int)*puid;
4464 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4465 SIVAL(pdata,2,own_grp);
4469 case SMB_ACL_GROUP_OBJ:
4470 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4471 own_grp = (unsigned int)pst->st_ex_gid;
4472 SIVAL(pdata,2,own_grp);
4477 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4479 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4482 own_grp = (unsigned int)*pgid;
4483 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4484 SIVAL(pdata,2,own_grp);
4489 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4490 SIVAL(pdata,2,0xFFFFFFFF);
4491 SIVAL(pdata,6,0xFFFFFFFF);
4494 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4495 SIVAL(pdata,2,0xFFFFFFFF);
4496 SIVAL(pdata,6,0xFFFFFFFF);
4499 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4502 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4509 /****************************************************************************
4510 Store the FILE_UNIX_BASIC info.
4511 ****************************************************************************/
4513 static char *store_file_unix_basic(connection_struct *conn,
4516 const SMB_STRUCT_STAT *psbuf)
4518 uint64_t file_index = get_FileIndex(conn, psbuf);
4521 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4522 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4524 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4527 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4530 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4531 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4532 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4535 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4539 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4543 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4546 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4547 devno = psbuf->st_ex_rdev;
4549 devno = psbuf->st_ex_dev;
4552 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4556 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4560 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4563 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4567 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4574 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4575 * the chflags(2) (or equivalent) flags.
4577 * XXX: this really should be behind the VFS interface. To do this, we would
4578 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4579 * Each VFS module could then implement its own mapping as appropriate for the
4580 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4582 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4586 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4590 { UF_IMMUTABLE, EXT_IMMUTABLE },
4594 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4598 { UF_HIDDEN, EXT_HIDDEN },
4601 /* Do not remove. We need to guarantee that this array has at least one
4602 * entry to build on HP-UX.
4608 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4609 uint32_t *smb_fflags, uint32_t *smb_fmask)
4613 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4614 *smb_fmask |= info2_flags_map[i].smb_fflag;
4615 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4616 *smb_fflags |= info2_flags_map[i].smb_fflag;
4621 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4622 const uint32_t smb_fflags,
4623 const uint32_t smb_fmask,
4626 uint32_t max_fmask = 0;
4629 *stat_fflags = psbuf->st_ex_flags;
4631 /* For each flags requested in smb_fmask, check the state of the
4632 * corresponding flag in smb_fflags and set or clear the matching
4636 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4637 max_fmask |= info2_flags_map[i].smb_fflag;
4638 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4639 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4640 *stat_fflags |= info2_flags_map[i].stat_fflag;
4642 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4647 /* If smb_fmask is asking to set any bits that are not supported by
4648 * our flag mappings, we should fail.
4650 if ((smb_fmask & max_fmask) != smb_fmask) {
4658 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4659 * of file flags and birth (create) time.
4661 static char *store_file_unix_basic_info2(connection_struct *conn,
4664 const SMB_STRUCT_STAT *psbuf)
4666 uint32_t file_flags = 0;
4667 uint32_t flags_mask = 0;
4669 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4671 /* Create (birth) time 64 bit */
4672 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4675 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4676 SIVAL(pdata, 0, file_flags); /* flags */
4677 SIVAL(pdata, 4, flags_mask); /* mask */
4683 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4684 const struct stream_struct *streams,
4686 unsigned int max_data_bytes,
4687 unsigned int *data_size)
4690 unsigned int ofs = 0;
4692 if (max_data_bytes < 32) {
4693 return NT_STATUS_INFO_LENGTH_MISMATCH;
4696 for (i = 0; i < num_streams; i++) {
4697 unsigned int next_offset;
4699 smb_ucs2_t *namebuf;
4701 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4702 streams[i].name, &namelen) ||
4705 return NT_STATUS_INVALID_PARAMETER;
4709 * name_buf is now null-terminated, we need to marshall as not
4716 * We cannot overflow ...
4718 if ((ofs + 24 + namelen) > max_data_bytes) {
4719 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4721 TALLOC_FREE(namebuf);
4722 return STATUS_BUFFER_OVERFLOW;
4725 SIVAL(data, ofs+4, namelen);
4726 SOFF_T(data, ofs+8, streams[i].size);
4727 SOFF_T(data, ofs+16, streams[i].alloc_size);
4728 memcpy(data+ofs+24, namebuf, namelen);
4729 TALLOC_FREE(namebuf);
4731 next_offset = ofs + 24 + namelen;
4733 if (i == num_streams-1) {
4734 SIVAL(data, ofs, 0);
4737 unsigned int align = ndr_align_size(next_offset, 8);
4739 if ((next_offset + align) > max_data_bytes) {
4740 DEBUG(10, ("refusing to overflow align "
4741 "reply at stream %u\n",
4743 TALLOC_FREE(namebuf);
4744 return STATUS_BUFFER_OVERFLOW;
4747 memset(data+next_offset, 0, align);
4748 next_offset += align;
4750 SIVAL(data, ofs, next_offset - ofs);
4757 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4761 return NT_STATUS_OK;
4764 /****************************************************************************
4765 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4766 ****************************************************************************/
4768 static void call_trans2qpipeinfo(connection_struct *conn,
4769 struct smb_request *req,
4770 unsigned int tran_call,
4771 char **pparams, int total_params,
4772 char **ppdata, int total_data,
4773 unsigned int max_data_bytes)
4775 char *params = *pparams;
4776 char *pdata = *ppdata;
4777 unsigned int data_size = 0;
4778 unsigned int param_size = 2;
4779 uint16_t info_level;
4783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4787 if (total_params < 4) {
4788 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4792 fsp = file_fsp(req, SVAL(params,0));
4793 if (!fsp_is_np(fsp)) {
4794 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4798 info_level = SVAL(params,2);
4800 *pparams = (char *)SMB_REALLOC(*pparams,2);
4801 if (*pparams == NULL) {
4802 reply_nterror(req, NT_STATUS_NO_MEMORY);
4807 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4811 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4812 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4813 if (*ppdata == NULL ) {
4814 reply_nterror(req, NT_STATUS_NO_MEMORY);
4819 switch (info_level) {
4820 case SMB_FILE_STANDARD_INFORMATION:
4822 SOFF_T(pdata,0,4096LL);
4829 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4833 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4839 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4840 TALLOC_CTX *mem_ctx,
4841 uint16_t info_level,
4843 struct smb_filename *smb_fname,
4844 bool delete_pending,
4845 struct timespec write_time_ts,
4846 struct ea_list *ea_list,
4847 int lock_data_count,
4850 unsigned int max_data_bytes,
4851 size_t *fixed_portion,
4853 unsigned int *pdata_size)
4855 char *pdata = *ppdata;
4856 char *dstart, *dend;
4857 unsigned int data_size;
4858 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4859 time_t create_time, mtime, atime, c_time;
4860 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4867 uint64_t file_size = 0;
4869 uint64_t allocation_size = 0;
4870 uint64_t file_index = 0;
4871 uint32_t access_mask = 0;
4874 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4875 return NT_STATUS_INVALID_LEVEL;
4878 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4879 smb_fname_str_dbg(smb_fname),
4881 info_level, max_data_bytes));
4883 mode = dos_mode(conn, smb_fname);
4884 nlink = psbuf->st_ex_nlink;
4886 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4890 if ((nlink > 0) && delete_pending) {
4894 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4895 return NT_STATUS_INVALID_PARAMETER;
4898 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4899 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4900 if (*ppdata == NULL) {
4901 return NT_STATUS_NO_MEMORY;
4905 dend = dstart + data_size - 1;
4907 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4908 update_stat_ex_mtime(psbuf, write_time_ts);
4911 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4912 mtime_ts = psbuf->st_ex_mtime;
4913 atime_ts = psbuf->st_ex_atime;
4914 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4916 if (lp_dos_filetime_resolution(SNUM(conn))) {
4917 dos_filetime_timespec(&create_time_ts);
4918 dos_filetime_timespec(&mtime_ts);
4919 dos_filetime_timespec(&atime_ts);
4920 dos_filetime_timespec(&ctime_ts);
4923 create_time = convert_timespec_to_time_t(create_time_ts);
4924 mtime = convert_timespec_to_time_t(mtime_ts);
4925 atime = convert_timespec_to_time_t(atime_ts);
4926 c_time = convert_timespec_to_time_t(ctime_ts);
4928 p = strrchr_m(smb_fname->base_name,'/');
4930 base_name = smb_fname->base_name;
4934 /* NT expects the name to be in an exact form of the *full*
4935 filename. See the trans2 torture test */
4936 if (ISDOT(base_name)) {
4937 dos_fname = talloc_strdup(mem_ctx, "\\");
4939 return NT_STATUS_NO_MEMORY;
4942 dos_fname = talloc_asprintf(mem_ctx,
4944 smb_fname->base_name);
4946 return NT_STATUS_NO_MEMORY;
4948 if (is_ntfs_stream_smb_fname(smb_fname)) {
4949 dos_fname = talloc_asprintf(dos_fname, "%s",
4950 smb_fname->stream_name);
4952 return NT_STATUS_NO_MEMORY;
4956 string_replace(dos_fname, '/', '\\');
4959 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4962 /* Do we have this path open ? */
4964 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4965 fsp1 = file_find_di_first(conn->sconn, fileid);
4966 if (fsp1 && fsp1->initial_allocation_size) {
4967 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4971 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4972 file_size = get_file_size_stat(psbuf);
4976 pos = fsp->fh->position_information;
4980 access_mask = fsp->access_mask;
4982 /* GENERIC_EXECUTE mapping from Windows */
4983 access_mask = 0x12019F;
4986 /* This should be an index number - looks like
4989 I think this causes us to fail the IFSKIT
4990 BasicFileInformationTest. -tpot */
4991 file_index = get_FileIndex(conn, psbuf);
4995 switch (info_level) {
4996 case SMB_INFO_STANDARD:
4997 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4999 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5000 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5001 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5002 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5003 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5004 SSVAL(pdata,l1_attrFile,mode);
5007 case SMB_INFO_QUERY_EA_SIZE:
5009 unsigned int ea_size =
5010 estimate_ea_size(conn, fsp,
5012 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5014 srv_put_dos_date2(pdata,0,create_time);
5015 srv_put_dos_date2(pdata,4,atime);
5016 srv_put_dos_date2(pdata,8,mtime); /* write time */
5017 SIVAL(pdata,12,(uint32_t)file_size);
5018 SIVAL(pdata,16,(uint32_t)allocation_size);
5019 SSVAL(pdata,20,mode);
5020 SIVAL(pdata,22,ea_size);
5024 case SMB_INFO_IS_NAME_VALID:
5025 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5027 /* os/2 needs this ? really ?*/
5028 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5030 /* This is only reached for qpathinfo */
5034 case SMB_INFO_QUERY_EAS_FROM_LIST:
5036 size_t total_ea_len = 0;
5037 struct ea_list *ea_file_list = NULL;
5038 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5041 get_ea_list_from_file(mem_ctx, conn, fsp,
5043 &total_ea_len, &ea_file_list);
5044 if (!NT_STATUS_IS_OK(status)) {
5048 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5050 if (!ea_list || (total_ea_len > data_size)) {
5052 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5056 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5060 case SMB_INFO_QUERY_ALL_EAS:
5062 /* We have data_size bytes to put EA's into. */
5063 size_t total_ea_len = 0;
5064 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5066 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5068 &total_ea_len, &ea_list);
5069 if (!NT_STATUS_IS_OK(status)) {
5073 if (!ea_list || (total_ea_len > data_size)) {
5075 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5079 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5083 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5085 /* This is FileFullEaInformation - 0xF which maps to
5086 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5088 /* We have data_size bytes to put EA's into. */
5089 size_t total_ea_len = 0;
5090 struct ea_list *ea_file_list = NULL;
5092 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5094 /*TODO: add filtering and index handling */
5097 get_ea_list_from_file(mem_ctx, conn, fsp,
5099 &total_ea_len, &ea_file_list);
5100 if (!NT_STATUS_IS_OK(status)) {
5103 if (!ea_file_list) {
5104 return NT_STATUS_NO_EAS_ON_FILE;
5107 status = fill_ea_chained_buffer(mem_ctx,
5111 conn, ea_file_list);
5112 if (!NT_STATUS_IS_OK(status)) {
5118 case SMB_FILE_BASIC_INFORMATION:
5119 case SMB_QUERY_FILE_BASIC_INFO:
5121 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5122 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5123 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5125 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5129 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5130 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5131 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5132 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5133 SIVAL(pdata,32,mode);
5135 DEBUG(5,("SMB_QFBI - "));
5136 DEBUG(5,("create: %s ", ctime(&create_time)));
5137 DEBUG(5,("access: %s ", ctime(&atime)));
5138 DEBUG(5,("write: %s ", ctime(&mtime)));
5139 DEBUG(5,("change: %s ", ctime(&c_time)));
5140 DEBUG(5,("mode: %x\n", mode));
5141 *fixed_portion = data_size;
5144 case SMB_FILE_STANDARD_INFORMATION:
5145 case SMB_QUERY_FILE_STANDARD_INFO:
5147 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5149 SOFF_T(pdata,0,allocation_size);
5150 SOFF_T(pdata,8,file_size);
5151 SIVAL(pdata,16,nlink);
5152 SCVAL(pdata,20,delete_pending?1:0);
5153 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5154 SSVAL(pdata,22,0); /* Padding. */
5155 *fixed_portion = 24;
5158 case SMB_FILE_EA_INFORMATION:
5159 case SMB_QUERY_FILE_EA_INFO:
5161 unsigned int ea_size =
5162 estimate_ea_size(conn, fsp, smb_fname);
5163 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5166 SIVAL(pdata,0,ea_size);
5170 /* Get the 8.3 name - used if NT SMB was negotiated. */
5171 case SMB_QUERY_FILE_ALT_NAME_INFO:
5172 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5174 char mangled_name[13];
5175 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5176 if (!name_to_8_3(base_name,mangled_name,
5177 True,conn->params)) {
5178 return NT_STATUS_NO_MEMORY;
5180 status = srvstr_push(dstart, flags2,
5181 pdata+4, mangled_name,
5182 PTR_DIFF(dend, pdata+4),
5184 if (!NT_STATUS_IS_OK(status)) {
5187 data_size = 4 + len;
5193 case SMB_QUERY_FILE_NAME_INFO:
5196 this must be *exactly* right for ACLs on mapped drives to work
5198 status = srvstr_push(dstart, flags2,
5200 PTR_DIFF(dend, pdata+4),
5202 if (!NT_STATUS_IS_OK(status)) {
5205 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5206 data_size = 4 + len;
5211 case SMB_FILE_ALLOCATION_INFORMATION:
5212 case SMB_QUERY_FILE_ALLOCATION_INFO:
5213 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5215 SOFF_T(pdata,0,allocation_size);
5218 case SMB_FILE_END_OF_FILE_INFORMATION:
5219 case SMB_QUERY_FILE_END_OF_FILEINFO:
5220 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5222 SOFF_T(pdata,0,file_size);
5225 case SMB_QUERY_FILE_ALL_INFO:
5226 case SMB_FILE_ALL_INFORMATION:
5228 unsigned int ea_size =
5229 estimate_ea_size(conn, fsp, smb_fname);
5230 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5231 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5232 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5233 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5234 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5235 SIVAL(pdata,32,mode);
5236 SIVAL(pdata,36,0); /* padding. */
5238 SOFF_T(pdata,0,allocation_size);
5239 SOFF_T(pdata,8,file_size);
5240 SIVAL(pdata,16,nlink);
5241 SCVAL(pdata,20,delete_pending);
5242 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5245 SIVAL(pdata,0,ea_size);
5246 pdata += 4; /* EA info */
5247 status = srvstr_push(dstart, flags2,
5249 PTR_DIFF(dend, pdata+4),
5251 if (!NT_STATUS_IS_OK(status)) {
5256 data_size = PTR_DIFF(pdata,(*ppdata));
5257 *fixed_portion = 10;
5261 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5263 unsigned int ea_size =
5264 estimate_ea_size(conn, fsp, smb_fname);
5265 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5266 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5267 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5268 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5269 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5270 SIVAL(pdata, 0x20, mode);
5271 SIVAL(pdata, 0x24, 0); /* padding. */
5272 SBVAL(pdata, 0x28, allocation_size);
5273 SBVAL(pdata, 0x30, file_size);
5274 SIVAL(pdata, 0x38, nlink);
5275 SCVAL(pdata, 0x3C, delete_pending);
5276 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5277 SSVAL(pdata, 0x3E, 0); /* padding */
5278 SBVAL(pdata, 0x40, file_index);
5279 SIVAL(pdata, 0x48, ea_size);
5280 SIVAL(pdata, 0x4C, access_mask);
5281 SBVAL(pdata, 0x50, pos);
5282 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5283 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5287 status = srvstr_push(dstart, flags2,
5289 PTR_DIFF(dend, pdata+4),
5291 if (!NT_STATUS_IS_OK(status)) {
5296 data_size = PTR_DIFF(pdata,(*ppdata));
5297 *fixed_portion = 104;
5300 case SMB_FILE_INTERNAL_INFORMATION:
5302 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5303 SBVAL(pdata, 0, file_index);
5308 case SMB_FILE_ACCESS_INFORMATION:
5309 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5310 SIVAL(pdata, 0, access_mask);
5315 case SMB_FILE_NAME_INFORMATION:
5316 /* Pathname with leading '\'. */
5319 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5320 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5321 SIVAL(pdata,0,byte_len);
5322 data_size = 4 + byte_len;
5326 case SMB_FILE_DISPOSITION_INFORMATION:
5327 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5329 SCVAL(pdata,0,delete_pending);
5333 case SMB_FILE_POSITION_INFORMATION:
5334 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5336 SOFF_T(pdata,0,pos);
5340 case SMB_FILE_MODE_INFORMATION:
5341 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5342 SIVAL(pdata,0,mode);
5347 case SMB_FILE_ALIGNMENT_INFORMATION:
5348 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5349 SIVAL(pdata,0,0); /* No alignment needed. */
5355 * NT4 server just returns "invalid query" to this - if we try
5356 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5359 /* The first statement above is false - verified using Thursby
5360 * client against NT4 -- gcolley.
5362 case SMB_QUERY_FILE_STREAM_INFO:
5363 case SMB_FILE_STREAM_INFORMATION: {
5364 unsigned int num_streams = 0;
5365 struct stream_struct *streams = NULL;
5367 DEBUG(10,("smbd_do_qfilepathinfo: "
5368 "SMB_FILE_STREAM_INFORMATION\n"));
5370 if (is_ntfs_stream_smb_fname(smb_fname)) {
5371 return NT_STATUS_INVALID_PARAMETER;
5374 status = vfs_streaminfo(conn,
5381 if (!NT_STATUS_IS_OK(status)) {
5382 DEBUG(10, ("could not get stream info: %s\n",
5383 nt_errstr(status)));
5387 status = marshall_stream_info(num_streams, streams,
5388 pdata, max_data_bytes,
5391 if (!NT_STATUS_IS_OK(status)) {
5392 DEBUG(10, ("marshall_stream_info failed: %s\n",
5393 nt_errstr(status)));
5394 TALLOC_FREE(streams);
5398 TALLOC_FREE(streams);
5400 *fixed_portion = 32;
5404 case SMB_QUERY_COMPRESSION_INFO:
5405 case SMB_FILE_COMPRESSION_INFORMATION:
5406 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5407 SOFF_T(pdata,0,file_size);
5408 SIVAL(pdata,8,0); /* ??? */
5409 SIVAL(pdata,12,0); /* ??? */
5411 *fixed_portion = 16;
5414 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5415 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5416 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5417 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5418 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5419 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5420 SOFF_T(pdata,32,allocation_size);
5421 SOFF_T(pdata,40,file_size);
5422 SIVAL(pdata,48,mode);
5423 SIVAL(pdata,52,0); /* ??? */
5425 *fixed_portion = 56;
5428 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5429 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5430 SIVAL(pdata,0,mode);
5437 * CIFS UNIX Extensions.
5440 case SMB_QUERY_FILE_UNIX_BASIC:
5442 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5443 data_size = PTR_DIFF(pdata,(*ppdata));
5445 DEBUG(4,("smbd_do_qfilepathinfo: "
5446 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5447 dump_data(4, (uint8_t *)(*ppdata), data_size);
5451 case SMB_QUERY_FILE_UNIX_INFO2:
5453 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5454 data_size = PTR_DIFF(pdata,(*ppdata));
5458 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5460 for (i=0; i<100; i++)
5461 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5467 case SMB_QUERY_FILE_UNIX_LINK:
5470 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5473 return NT_STATUS_NO_MEMORY;
5476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5478 if(!S_ISLNK(psbuf->st_ex_mode)) {
5479 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5482 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5484 link_len = SMB_VFS_READLINK(conn,
5487 if (link_len == -1) {
5488 return map_nt_error_from_unix(errno);
5490 buffer[link_len] = 0;
5491 status = srvstr_push(dstart, flags2,
5493 PTR_DIFF(dend, pdata),
5494 STR_TERMINATE, &len);
5495 if (!NT_STATUS_IS_OK(status)) {
5499 data_size = PTR_DIFF(pdata,(*ppdata));
5504 #if defined(HAVE_POSIX_ACLS)
5505 case SMB_QUERY_POSIX_ACL:
5507 SMB_ACL_T file_acl = NULL;
5508 SMB_ACL_T def_acl = NULL;
5509 uint16_t num_file_acls = 0;
5510 uint16_t num_def_acls = 0;
5512 status = refuse_symlink(conn,
5515 if (!NT_STATUS_IS_OK(status)) {
5519 if (fsp && fsp->fh->fd != -1) {
5520 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5524 SMB_VFS_SYS_ACL_GET_FILE(conn,
5526 SMB_ACL_TYPE_ACCESS,
5530 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5531 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5532 "not implemented on "
5533 "filesystem containing %s\n",
5534 smb_fname->base_name));
5535 return NT_STATUS_NOT_IMPLEMENTED;
5538 if (S_ISDIR(psbuf->st_ex_mode)) {
5539 if (fsp && fsp->is_directory) {
5541 SMB_VFS_SYS_ACL_GET_FILE(
5544 SMB_ACL_TYPE_DEFAULT,
5548 SMB_VFS_SYS_ACL_GET_FILE(
5551 SMB_ACL_TYPE_DEFAULT,
5554 def_acl = free_empty_sys_acl(conn, def_acl);
5557 num_file_acls = count_acl_entries(conn, file_acl);
5558 num_def_acls = count_acl_entries(conn, def_acl);
5560 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5561 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5563 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5564 SMB_POSIX_ACL_HEADER_SIZE) ));
5566 TALLOC_FREE(file_acl);
5569 TALLOC_FREE(def_acl);
5571 return NT_STATUS_BUFFER_TOO_SMALL;
5574 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5575 SSVAL(pdata,2,num_file_acls);
5576 SSVAL(pdata,4,num_def_acls);
5577 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5579 TALLOC_FREE(file_acl);
5582 TALLOC_FREE(def_acl);
5584 return NT_STATUS_INTERNAL_ERROR;
5586 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5588 TALLOC_FREE(file_acl);
5591 TALLOC_FREE(def_acl);
5593 return NT_STATUS_INTERNAL_ERROR;
5597 TALLOC_FREE(file_acl);
5600 TALLOC_FREE(def_acl);
5602 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5608 case SMB_QUERY_POSIX_LOCK:
5613 enum brl_type lock_type;
5615 /* We need an open file with a real fd for this. */
5616 if (!fsp || fsp->fh->fd == -1) {
5617 return NT_STATUS_INVALID_LEVEL;
5620 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5621 return NT_STATUS_INVALID_PARAMETER;
5624 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5625 case POSIX_LOCK_TYPE_READ:
5626 lock_type = READ_LOCK;
5628 case POSIX_LOCK_TYPE_WRITE:
5629 lock_type = WRITE_LOCK;
5631 case POSIX_LOCK_TYPE_UNLOCK:
5633 /* There's no point in asking for an unlock... */
5634 return NT_STATUS_INVALID_PARAMETER;
5637 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5638 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5639 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5641 status = query_lock(fsp,
5648 if (ERROR_WAS_LOCK_DENIED(status)) {
5649 /* Here we need to report who has it locked... */
5650 data_size = POSIX_LOCK_DATA_SIZE;
5652 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5653 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5654 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5655 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5656 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5658 } else if (NT_STATUS_IS_OK(status)) {
5659 /* For success we just return a copy of what we sent
5660 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5661 data_size = POSIX_LOCK_DATA_SIZE;
5662 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5663 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5671 return NT_STATUS_INVALID_LEVEL;
5674 *pdata_size = data_size;
5675 return NT_STATUS_OK;
5678 /****************************************************************************
5679 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5680 file name or file id).
5681 ****************************************************************************/
5683 static void call_trans2qfilepathinfo(connection_struct *conn,
5684 struct smb_request *req,
5685 unsigned int tran_call,
5686 char **pparams, int total_params,
5687 char **ppdata, int total_data,
5688 unsigned int max_data_bytes)
5690 char *params = *pparams;
5691 char *pdata = *ppdata;
5692 uint16_t info_level;
5693 unsigned int data_size = 0;
5694 unsigned int param_size = 2;
5695 struct smb_filename *smb_fname = NULL;
5696 bool delete_pending = False;
5697 struct timespec write_time_ts;
5698 files_struct *fsp = NULL;
5699 struct file_id fileid;
5700 struct ea_list *ea_list = NULL;
5701 int lock_data_count = 0;
5702 char *lock_data = NULL;
5703 size_t fixed_portion;
5704 NTSTATUS status = NT_STATUS_OK;
5707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5711 ZERO_STRUCT(write_time_ts);
5713 if (tran_call == TRANSACT2_QFILEINFO) {
5714 if (total_params < 4) {
5715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5720 call_trans2qpipeinfo(conn, req, tran_call,
5721 pparams, total_params,
5727 fsp = file_fsp(req, SVAL(params,0));
5728 info_level = SVAL(params,2);
5730 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5732 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5733 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5737 /* Initial check for valid fsp ptr. */
5738 if (!check_fsp_open(conn, req, fsp)) {
5742 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5743 if (smb_fname == NULL) {
5744 reply_nterror(req, NT_STATUS_NO_MEMORY);
5748 if(fsp->fake_file_handle) {
5750 * This is actually for the QUOTA_FAKE_FILE --metze
5753 /* We know this name is ok, it's already passed the checks. */
5755 } else if(fsp->fh->fd == -1) {
5757 * This is actually a QFILEINFO on a directory
5758 * handle (returned from an NT SMB). NT5.0 seems
5759 * to do this call. JRA.
5762 if (INFO_LEVEL_IS_UNIX(info_level)) {
5763 /* Always do lstat for UNIX calls. */
5764 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5765 DEBUG(3,("call_trans2qfilepathinfo: "
5766 "SMB_VFS_LSTAT of %s failed "
5768 smb_fname_str_dbg(smb_fname),
5771 map_nt_error_from_unix(errno));
5774 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5775 DEBUG(3,("call_trans2qfilepathinfo: "
5776 "SMB_VFS_STAT of %s failed (%s)\n",
5777 smb_fname_str_dbg(smb_fname),
5780 map_nt_error_from_unix(errno));
5784 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5785 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5788 * Original code - this is an open file.
5790 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5791 DEBUG(3, ("fstat of %s failed (%s)\n",
5792 fsp_fnum_dbg(fsp), strerror(errno)));
5794 map_nt_error_from_unix(errno));
5797 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5798 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5804 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5807 if (total_params < 7) {
5808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5812 info_level = SVAL(params,0);
5814 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5816 if (INFO_LEVEL_IS_UNIX(info_level)) {
5817 if (!lp_unix_extensions()) {
5818 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5821 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5822 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5823 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5824 req->posix_pathnames) {
5825 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5829 if (req->posix_pathnames) {
5830 srvstr_get_path_posix(req,
5839 srvstr_get_path(req,
5848 if (!NT_STATUS_IS_OK(status)) {
5849 reply_nterror(req, status);
5853 status = filename_convert(req,
5859 if (!NT_STATUS_IS_OK(status)) {
5860 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5861 reply_botherror(req,
5862 NT_STATUS_PATH_NOT_COVERED,
5863 ERRSRV, ERRbadpath);
5866 reply_nterror(req, status);
5870 /* If this is a stream, check if there is a delete_pending. */
5871 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5872 && is_ntfs_stream_smb_fname(smb_fname)) {
5873 struct smb_filename *smb_fname_base;
5875 /* Create an smb_filename with stream_name == NULL. */
5876 smb_fname_base = synthetic_smb_fname(
5878 smb_fname->base_name,
5882 if (smb_fname_base == NULL) {
5883 reply_nterror(req, NT_STATUS_NO_MEMORY);
5887 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5888 /* Always do lstat for UNIX calls. */
5889 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5890 DEBUG(3,("call_trans2qfilepathinfo: "
5891 "SMB_VFS_LSTAT of %s failed "
5893 smb_fname_str_dbg(smb_fname_base),
5895 TALLOC_FREE(smb_fname_base);
5897 map_nt_error_from_unix(errno));
5901 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5902 DEBUG(3,("call_trans2qfilepathinfo: "
5903 "fileinfo of %s failed "
5905 smb_fname_str_dbg(smb_fname_base),
5907 TALLOC_FREE(smb_fname_base);
5909 map_nt_error_from_unix(errno));
5914 status = file_name_hash(conn,
5915 smb_fname_str_dbg(smb_fname_base),
5917 if (!NT_STATUS_IS_OK(status)) {
5918 TALLOC_FREE(smb_fname_base);
5919 reply_nterror(req, status);
5923 fileid = vfs_file_id_from_sbuf(conn,
5924 &smb_fname_base->st);
5925 TALLOC_FREE(smb_fname_base);
5926 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5927 if (delete_pending) {
5928 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5933 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5934 /* Always do lstat for UNIX calls. */
5935 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5936 DEBUG(3,("call_trans2qfilepathinfo: "
5937 "SMB_VFS_LSTAT of %s failed (%s)\n",
5938 smb_fname_str_dbg(smb_fname),
5941 map_nt_error_from_unix(errno));
5946 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5947 DEBUG(3,("call_trans2qfilepathinfo: "
5948 "SMB_VFS_STAT of %s failed (%s)\n",
5949 smb_fname_str_dbg(smb_fname),
5952 map_nt_error_from_unix(errno));
5957 status = file_name_hash(conn,
5958 smb_fname_str_dbg(smb_fname),
5960 if (!NT_STATUS_IS_OK(status)) {
5961 reply_nterror(req, status);
5965 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5966 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5967 if (delete_pending) {
5968 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5973 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5974 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5976 info_level,tran_call,total_data));
5978 /* Pull out any data sent here before we realloc. */
5979 switch (info_level) {
5980 case SMB_INFO_QUERY_EAS_FROM_LIST:
5982 /* Pull any EA list from the data portion. */
5985 if (total_data < 4) {
5987 req, NT_STATUS_INVALID_PARAMETER);
5990 ea_size = IVAL(pdata,0);
5992 if (total_data > 0 && ea_size != total_data) {
5993 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5994 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5996 req, NT_STATUS_INVALID_PARAMETER);
6000 if (!lp_ea_support(SNUM(conn))) {
6001 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6005 /* Pull out the list of names. */
6006 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6009 req, NT_STATUS_INVALID_PARAMETER);
6015 case SMB_QUERY_POSIX_LOCK:
6017 if (fsp == NULL || fsp->fh->fd == -1) {
6018 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6022 if (total_data != POSIX_LOCK_DATA_SIZE) {
6024 req, NT_STATUS_INVALID_PARAMETER);
6028 /* Copy the lock range data. */
6029 lock_data = (char *)talloc_memdup(
6030 req, pdata, total_data);
6032 reply_nterror(req, NT_STATUS_NO_MEMORY);
6035 lock_data_count = total_data;
6041 *pparams = (char *)SMB_REALLOC(*pparams,2);
6042 if (*pparams == NULL) {
6043 reply_nterror(req, NT_STATUS_NO_MEMORY);
6050 * draft-leach-cifs-v1-spec-02.txt
6051 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6054 * The requested information is placed in the Data portion of the
6055 * transaction response. For the information levels greater than 0x100,
6056 * the transaction response has 1 parameter word which should be
6057 * ignored by the client.
6059 * However Windows only follows this rule for the IS_NAME_VALID call.
6061 switch (info_level) {
6062 case SMB_INFO_IS_NAME_VALID:
6067 if ((info_level & 0xFF00) == 0xFF00) {
6069 * We use levels that start with 0xFF00
6070 * internally to represent SMB2 specific levels
6072 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6076 status = smbd_do_qfilepathinfo(conn, req, info_level,
6078 delete_pending, write_time_ts,
6080 lock_data_count, lock_data,
6081 req->flags2, max_data_bytes,
6083 ppdata, &data_size);
6084 if (!NT_STATUS_IS_OK(status)) {
6085 reply_nterror(req, status);
6088 if (fixed_portion > max_data_bytes) {
6089 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6093 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6099 /****************************************************************************
6100 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6102 ****************************************************************************/
6104 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6105 connection_struct *conn,
6106 struct smb_request *req,
6107 bool overwrite_if_exists,
6108 const struct smb_filename *smb_fname_old,
6109 struct smb_filename *smb_fname_new)
6111 NTSTATUS status = NT_STATUS_OK;
6113 /* source must already exist. */
6114 if (!VALID_STAT(smb_fname_old->st)) {
6115 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6118 if (VALID_STAT(smb_fname_new->st)) {
6119 if (overwrite_if_exists) {
6120 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6121 return NT_STATUS_FILE_IS_A_DIRECTORY;
6123 status = unlink_internals(conn,
6125 FILE_ATTRIBUTE_NORMAL,
6128 if (!NT_STATUS_IS_OK(status)) {
6132 /* Disallow if newname already exists. */
6133 return NT_STATUS_OBJECT_NAME_COLLISION;
6137 /* No links from a directory. */
6138 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6139 return NT_STATUS_FILE_IS_A_DIRECTORY;
6142 /* Setting a hardlink to/from a stream isn't currently supported. */
6143 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6144 is_ntfs_stream_smb_fname(smb_fname_new)) {
6145 return NT_STATUS_INVALID_PARAMETER;
6148 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6149 smb_fname_old->base_name, smb_fname_new->base_name));
6151 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6152 status = map_nt_error_from_unix(errno);
6153 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6154 nt_errstr(status), smb_fname_old->base_name,
6155 smb_fname_new->base_name));
6160 /****************************************************************************
6161 Deal with setting the time from any of the setfilepathinfo functions.
6162 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6163 calling this function.
6164 ****************************************************************************/
6166 NTSTATUS smb_set_file_time(connection_struct *conn,
6168 const struct smb_filename *smb_fname,
6169 struct smb_file_time *ft,
6170 bool setting_write_time)
6172 struct smb_filename smb_fname_base;
6174 FILE_NOTIFY_CHANGE_LAST_ACCESS
6175 |FILE_NOTIFY_CHANGE_LAST_WRITE
6176 |FILE_NOTIFY_CHANGE_CREATION;
6178 if (!VALID_STAT(smb_fname->st)) {
6179 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6182 /* get some defaults (no modifications) if any info is zero or -1. */
6183 if (null_timespec(ft->create_time)) {
6184 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6187 if (null_timespec(ft->atime)) {
6188 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6191 if (null_timespec(ft->mtime)) {
6192 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6195 if (!setting_write_time) {
6196 /* ft->mtime comes from change time, not write time. */
6197 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6200 /* Ensure the resolution is the correct for
6201 * what we can store on this filesystem. */
6203 round_timespec(conn->ts_res, &ft->create_time);
6204 round_timespec(conn->ts_res, &ft->ctime);
6205 round_timespec(conn->ts_res, &ft->atime);
6206 round_timespec(conn->ts_res, &ft->mtime);
6208 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6209 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6210 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6211 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6212 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6213 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6214 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6215 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6217 if (setting_write_time) {
6219 * This was a Windows setfileinfo on an open file.
6220 * NT does this a lot. We also need to
6221 * set the time here, as it can be read by
6222 * FindFirst/FindNext and with the patch for bug #2045
6223 * in smbd/fileio.c it ensures that this timestamp is
6224 * kept sticky even after a write. We save the request
6225 * away and will set it on file close and after a write. JRA.
6228 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6229 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6232 if (fsp->base_fsp) {
6233 set_sticky_write_time_fsp(fsp->base_fsp,
6236 set_sticky_write_time_fsp(fsp, ft->mtime);
6239 set_sticky_write_time_path(
6240 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6245 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6247 /* Always call ntimes on the base, even if a stream was passed in. */
6248 smb_fname_base = *smb_fname;
6249 smb_fname_base.stream_name = NULL;
6251 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6252 return map_nt_error_from_unix(errno);
6255 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6256 smb_fname->base_name);
6257 return NT_STATUS_OK;
6260 /****************************************************************************
6261 Deal with setting the dosmode from any of the setfilepathinfo functions.
6262 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6263 done before calling this function.
6264 ****************************************************************************/
6266 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6267 const struct smb_filename *smb_fname,
6270 struct smb_filename *smb_fname_base;
6273 if (!VALID_STAT(smb_fname->st)) {
6274 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6277 /* Always operate on the base_name, even if a stream was passed in. */
6278 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6279 smb_fname->base_name,
6283 if (smb_fname_base == NULL) {
6284 return NT_STATUS_NO_MEMORY;
6288 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6289 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6291 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6295 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6297 /* check the mode isn't different, before changing it */
6298 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6299 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6300 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6301 (unsigned int)dosmode));
6303 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6305 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6307 smb_fname_str_dbg(smb_fname_base),
6309 status = map_nt_error_from_unix(errno);
6313 status = NT_STATUS_OK;
6315 TALLOC_FREE(smb_fname_base);
6319 /****************************************************************************
6320 Deal with setting the size from any of the setfilepathinfo functions.
6321 ****************************************************************************/
6323 static NTSTATUS smb_set_file_size(connection_struct *conn,
6324 struct smb_request *req,
6326 const struct smb_filename *smb_fname,
6327 const SMB_STRUCT_STAT *psbuf,
6329 bool fail_after_createfile)
6331 NTSTATUS status = NT_STATUS_OK;
6332 struct smb_filename *smb_fname_tmp = NULL;
6333 files_struct *new_fsp = NULL;
6335 if (!VALID_STAT(*psbuf)) {
6336 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6339 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6341 if (size == get_file_size_stat(psbuf)) {
6342 return NT_STATUS_OK;
6345 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6346 smb_fname_str_dbg(smb_fname), (double)size));
6348 if (fsp && fsp->fh->fd != -1) {
6349 /* Handle based call. */
6350 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6351 return NT_STATUS_ACCESS_DENIED;
6354 if (vfs_set_filelen(fsp, size) == -1) {
6355 return map_nt_error_from_unix(errno);
6357 trigger_write_time_update_immediate(fsp);
6358 return NT_STATUS_OK;
6361 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6362 if (smb_fname_tmp == NULL) {
6363 return NT_STATUS_NO_MEMORY;
6366 smb_fname_tmp->st = *psbuf;
6368 status = SMB_VFS_CREATE_FILE(
6371 0, /* root_dir_fid */
6372 smb_fname_tmp, /* fname */
6373 FILE_WRITE_DATA, /* access_mask */
6374 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6376 FILE_OPEN, /* create_disposition*/
6377 0, /* create_options */
6378 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6379 0, /* oplock_request */
6381 0, /* allocation_size */
6382 0, /* private_flags */
6385 &new_fsp, /* result */
6387 NULL, NULL); /* create context */
6389 TALLOC_FREE(smb_fname_tmp);
6391 if (!NT_STATUS_IS_OK(status)) {
6392 /* NB. We check for open_was_deferred in the caller. */
6396 /* See RAW-SFILEINFO-END-OF-FILE */
6397 if (fail_after_createfile) {
6398 close_file(req, new_fsp,NORMAL_CLOSE);
6399 return NT_STATUS_INVALID_LEVEL;
6402 if (vfs_set_filelen(new_fsp, size) == -1) {
6403 status = map_nt_error_from_unix(errno);
6404 close_file(req, new_fsp,NORMAL_CLOSE);
6408 trigger_write_time_update_immediate(new_fsp);
6409 close_file(req, new_fsp,NORMAL_CLOSE);
6410 return NT_STATUS_OK;
6413 /****************************************************************************
6414 Deal with SMB_INFO_SET_EA.
6415 ****************************************************************************/
6417 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6421 const struct smb_filename *smb_fname)
6423 struct ea_list *ea_list = NULL;
6424 TALLOC_CTX *ctx = NULL;
6425 NTSTATUS status = NT_STATUS_OK;
6427 if (total_data < 10) {
6429 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6430 length. They seem to have no effect. Bug #3212. JRA */
6432 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6433 /* We're done. We only get EA info in this call. */
6434 return NT_STATUS_OK;
6437 return NT_STATUS_INVALID_PARAMETER;
6440 if (IVAL(pdata,0) > total_data) {
6441 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6442 IVAL(pdata,0), (unsigned int)total_data));
6443 return NT_STATUS_INVALID_PARAMETER;
6447 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6449 return NT_STATUS_INVALID_PARAMETER;
6452 status = set_ea(conn, fsp, smb_fname, ea_list);
6457 /****************************************************************************
6458 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6459 ****************************************************************************/
6461 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6466 struct ea_list *ea_list = NULL;
6470 return NT_STATUS_INVALID_HANDLE;
6473 if (!lp_ea_support(SNUM(conn))) {
6474 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6475 "EA's not supported.\n",
6476 (unsigned int)total_data));
6477 return NT_STATUS_EAS_NOT_SUPPORTED;
6480 if (total_data < 10) {
6481 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6483 (unsigned int)total_data));
6484 return NT_STATUS_INVALID_PARAMETER;
6487 ea_list = read_nttrans_ea_list(talloc_tos(),
6492 return NT_STATUS_INVALID_PARAMETER;
6495 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6497 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6498 smb_fname_str_dbg(fsp->fsp_name),
6499 nt_errstr(status) ));
6505 /****************************************************************************
6506 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6507 ****************************************************************************/
6509 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6513 struct smb_filename *smb_fname)
6515 NTSTATUS status = NT_STATUS_OK;
6516 bool delete_on_close;
6517 uint32_t dosmode = 0;
6519 if (total_data < 1) {
6520 return NT_STATUS_INVALID_PARAMETER;
6524 return NT_STATUS_INVALID_HANDLE;
6527 delete_on_close = (CVAL(pdata,0) ? True : False);
6528 dosmode = dos_mode(conn, smb_fname);
6530 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6531 "delete_on_close = %u\n",
6532 smb_fname_str_dbg(smb_fname),
6533 (unsigned int)dosmode,
6534 (unsigned int)delete_on_close ));
6536 if (delete_on_close) {
6537 status = can_set_delete_on_close(fsp, dosmode);
6538 if (!NT_STATUS_IS_OK(status)) {
6543 /* The set is across all open files on this dev/inode pair. */
6544 if (!set_delete_on_close(fsp, delete_on_close,
6545 conn->session_info->security_token,
6546 conn->session_info->unix_token)) {
6547 return NT_STATUS_ACCESS_DENIED;
6549 return NT_STATUS_OK;
6552 /****************************************************************************
6553 Deal with SMB_FILE_POSITION_INFORMATION.
6554 ****************************************************************************/
6556 static NTSTATUS smb_file_position_information(connection_struct *conn,
6561 uint64_t position_information;
6563 if (total_data < 8) {
6564 return NT_STATUS_INVALID_PARAMETER;
6568 /* Ignore on pathname based set. */
6569 return NT_STATUS_OK;
6572 position_information = (uint64_t)IVAL(pdata,0);
6573 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6575 DEBUG(10,("smb_file_position_information: Set file position "
6576 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6577 (double)position_information));
6578 fsp->fh->position_information = position_information;
6579 return NT_STATUS_OK;
6582 /****************************************************************************
6583 Deal with SMB_FILE_MODE_INFORMATION.
6584 ****************************************************************************/
6586 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6592 if (total_data < 4) {
6593 return NT_STATUS_INVALID_PARAMETER;
6595 mode = IVAL(pdata,0);
6596 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6597 return NT_STATUS_INVALID_PARAMETER;
6599 return NT_STATUS_OK;
6602 /****************************************************************************
6603 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6604 ****************************************************************************/
6606 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6607 struct smb_request *req,
6610 const struct smb_filename *new_smb_fname)
6612 char *link_target = NULL;
6613 TALLOC_CTX *ctx = talloc_tos();
6615 /* Set a symbolic link. */
6616 /* Don't allow this if follow links is false. */
6618 if (total_data == 0) {
6619 return NT_STATUS_INVALID_PARAMETER;
6622 if (!lp_follow_symlinks(SNUM(conn))) {
6623 return NT_STATUS_ACCESS_DENIED;
6626 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6627 total_data, STR_TERMINATE);
6630 return NT_STATUS_INVALID_PARAMETER;
6633 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6634 new_smb_fname->base_name, link_target ));
6636 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6637 return map_nt_error_from_unix(errno);
6640 return NT_STATUS_OK;
6643 /****************************************************************************
6644 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6645 ****************************************************************************/
6647 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6648 struct smb_request *req,
6649 const char *pdata, int total_data,
6650 struct smb_filename *smb_fname_new)
6652 char *oldname = NULL;
6653 struct smb_filename *smb_fname_old = NULL;
6654 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6655 TALLOC_CTX *ctx = talloc_tos();
6656 NTSTATUS status = NT_STATUS_OK;
6658 /* Set a hard link. */
6659 if (total_data == 0) {
6660 return NT_STATUS_INVALID_PARAMETER;
6663 if (req->posix_pathnames) {
6664 srvstr_get_path_posix(ctx,
6673 srvstr_get_path(ctx,
6682 if (!NT_STATUS_IS_OK(status)) {
6686 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6687 smb_fname_str_dbg(smb_fname_new), oldname));
6689 status = filename_convert(ctx,
6695 if (!NT_STATUS_IS_OK(status)) {
6699 return hardlink_internals(ctx, conn, req, false,
6700 smb_fname_old, smb_fname_new);
6703 /****************************************************************************
6704 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6705 ****************************************************************************/
6707 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6708 struct smb_request *req,
6712 struct smb_filename *smb_fname_src)
6716 char *newname = NULL;
6717 struct smb_filename *smb_fname_dst = NULL;
6718 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6719 ucf_flags_from_smb_request(req);
6720 NTSTATUS status = NT_STATUS_OK;
6721 TALLOC_CTX *ctx = talloc_tos();
6724 return NT_STATUS_INVALID_HANDLE;
6727 if (total_data < 20) {
6728 return NT_STATUS_INVALID_PARAMETER;
6731 overwrite = (CVAL(pdata,0) ? True : False);
6732 len = IVAL(pdata,16);
6734 if (len > (total_data - 20) || (len == 0)) {
6735 return NT_STATUS_INVALID_PARAMETER;
6738 if (req->posix_pathnames) {
6739 srvstr_get_path_posix(ctx,
6748 srvstr_get_path(ctx,
6757 if (!NT_STATUS_IS_OK(status)) {
6761 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6764 status = filename_convert(ctx,
6770 if (!NT_STATUS_IS_OK(status)) {
6774 if (fsp->base_fsp) {
6775 /* newname must be a stream name. */
6776 if (newname[0] != ':') {
6777 return NT_STATUS_NOT_SUPPORTED;
6780 /* Create an smb_fname to call rename_internals_fsp() with. */
6781 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6782 fsp->base_fsp->fsp_name->base_name,
6785 fsp->base_fsp->fsp_name->flags);
6786 if (smb_fname_dst == NULL) {
6787 status = NT_STATUS_NO_MEMORY;
6792 * Set the original last component, since
6793 * rename_internals_fsp() requires it.
6795 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6797 if (smb_fname_dst->original_lcomp == NULL) {
6798 status = NT_STATUS_NO_MEMORY;
6804 DEBUG(10,("smb2_file_rename_information: "
6805 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6806 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6807 smb_fname_str_dbg(smb_fname_dst)));
6808 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6809 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6813 TALLOC_FREE(smb_fname_dst);
6817 static NTSTATUS smb_file_link_information(connection_struct *conn,
6818 struct smb_request *req,
6822 struct smb_filename *smb_fname_src)
6826 char *newname = NULL;
6827 struct smb_filename *smb_fname_dst = NULL;
6828 NTSTATUS status = NT_STATUS_OK;
6829 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6830 ucf_flags_from_smb_request(req);
6831 TALLOC_CTX *ctx = talloc_tos();
6834 return NT_STATUS_INVALID_HANDLE;
6837 if (total_data < 20) {
6838 return NT_STATUS_INVALID_PARAMETER;
6841 overwrite = (CVAL(pdata,0) ? true : false);
6842 len = IVAL(pdata,16);
6844 if (len > (total_data - 20) || (len == 0)) {
6845 return NT_STATUS_INVALID_PARAMETER;
6848 if (req->posix_pathnames) {
6849 srvstr_get_path_posix(ctx,
6858 srvstr_get_path(ctx,
6867 if (!NT_STATUS_IS_OK(status)) {
6871 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6874 status = filename_convert(ctx,
6880 if (!NT_STATUS_IS_OK(status)) {
6884 if (fsp->base_fsp) {
6885 /* No stream names. */
6886 return NT_STATUS_NOT_SUPPORTED;
6889 DEBUG(10,("smb_file_link_information: "
6890 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6891 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6892 smb_fname_str_dbg(smb_fname_dst)));
6893 status = hardlink_internals(ctx,
6900 TALLOC_FREE(smb_fname_dst);
6904 /****************************************************************************
6905 Deal with SMB_FILE_RENAME_INFORMATION.
6906 ****************************************************************************/
6908 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6909 struct smb_request *req,
6913 struct smb_filename *smb_fname_src)
6918 char *newname = NULL;
6919 struct smb_filename *smb_fname_dst = NULL;
6920 bool dest_has_wcard = False;
6921 NTSTATUS status = NT_STATUS_OK;
6923 TALLOC_CTX *ctx = talloc_tos();
6925 if (total_data < 13) {
6926 return NT_STATUS_INVALID_PARAMETER;
6929 overwrite = (CVAL(pdata,0) ? True : False);
6930 root_fid = IVAL(pdata,4);
6931 len = IVAL(pdata,8);
6933 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6934 return NT_STATUS_INVALID_PARAMETER;
6937 if (req->posix_pathnames) {
6938 srvstr_get_path_wcard_posix(ctx,
6948 srvstr_get_path_wcard(ctx,
6958 if (!NT_STATUS_IS_OK(status)) {
6962 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6965 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
6966 status = resolve_dfspath_wcard(ctx, conn,
6968 UCF_COND_ALLOW_WCARD_LCOMP,
6969 !conn->sconn->using_smb2,
6972 if (!NT_STATUS_IS_OK(status)) {
6977 /* Check the new name has no '/' characters. */
6978 if (strchr_m(newname, '/')) {
6979 return NT_STATUS_NOT_SUPPORTED;
6982 if (fsp && fsp->base_fsp) {
6983 /* newname must be a stream name. */
6984 if (newname[0] != ':') {
6985 return NT_STATUS_NOT_SUPPORTED;
6988 /* Create an smb_fname to call rename_internals_fsp() with. */
6989 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6990 fsp->base_fsp->fsp_name->base_name,
6993 fsp->base_fsp->fsp_name->flags);
6994 if (smb_fname_dst == NULL) {
6995 status = NT_STATUS_NO_MEMORY;
7000 * Set the original last component, since
7001 * rename_internals_fsp() requires it.
7003 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7005 if (smb_fname_dst->original_lcomp == NULL) {
7006 status = NT_STATUS_NO_MEMORY;
7012 * Build up an smb_fname_dst based on the filename passed in.
7013 * We basically just strip off the last component, and put on
7014 * the newname instead.
7016 char *base_name = NULL;
7017 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7018 ucf_flags_from_smb_request(req);
7020 if (dest_has_wcard) {
7021 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7024 /* newname must *not* be a stream name. */
7025 if (newname[0] == ':') {
7026 return NT_STATUS_NOT_SUPPORTED;
7030 * Strip off the last component (filename) of the path passed
7033 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7035 return NT_STATUS_NO_MEMORY;
7037 p = strrchr_m(base_name, '/');
7041 base_name = talloc_strdup(ctx, "");
7043 return NT_STATUS_NO_MEMORY;
7046 /* Append the new name. */
7047 base_name = talloc_asprintf_append(base_name,
7051 return NT_STATUS_NO_MEMORY;
7054 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7057 /* If an error we expect this to be
7058 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7060 if (!NT_STATUS_IS_OK(status)) {
7061 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7065 /* Create an smb_fname to call rename_internals_fsp() */
7066 smb_fname_dst = synthetic_smb_fname(ctx,
7070 smb_fname_src->flags);
7071 if (smb_fname_dst == NULL) {
7072 status = NT_STATUS_NO_MEMORY;
7079 DEBUG(10,("smb_file_rename_information: "
7080 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7081 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7082 smb_fname_str_dbg(smb_fname_dst)));
7083 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7086 DEBUG(10,("smb_file_rename_information: "
7087 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7088 smb_fname_str_dbg(smb_fname_src),
7089 smb_fname_str_dbg(smb_fname_dst)));
7090 status = rename_internals(ctx, conn, req, smb_fname_src,
7091 smb_fname_dst, 0, overwrite, false,
7093 FILE_WRITE_ATTRIBUTES);
7096 TALLOC_FREE(smb_fname_dst);
7100 /****************************************************************************
7101 Deal with SMB_SET_POSIX_ACL.
7102 ****************************************************************************/
7104 #if defined(HAVE_POSIX_ACLS)
7105 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7109 const struct smb_filename *smb_fname)
7111 uint16_t posix_acl_version;
7112 uint16_t num_file_acls;
7113 uint16_t num_def_acls;
7114 bool valid_file_acls = True;
7115 bool valid_def_acls = True;
7118 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7119 return NT_STATUS_INVALID_PARAMETER;
7121 posix_acl_version = SVAL(pdata,0);
7122 num_file_acls = SVAL(pdata,2);
7123 num_def_acls = SVAL(pdata,4);
7125 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7126 valid_file_acls = False;
7130 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7131 valid_def_acls = False;
7135 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7136 return NT_STATUS_INVALID_PARAMETER;
7139 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7140 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7141 return NT_STATUS_INVALID_PARAMETER;
7144 status = refuse_symlink(conn, fsp, smb_fname);
7145 if (!NT_STATUS_IS_OK(status)) {
7149 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7150 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7151 (unsigned int)num_file_acls,
7152 (unsigned int)num_def_acls));
7154 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7155 smb_fname, num_file_acls,
7156 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7157 return map_nt_error_from_unix(errno);
7160 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7161 smb_fname, num_def_acls,
7162 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7163 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7164 return map_nt_error_from_unix(errno);
7166 return NT_STATUS_OK;
7170 /****************************************************************************
7171 Deal with SMB_SET_POSIX_LOCK.
7172 ****************************************************************************/
7174 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7175 struct smb_request *req,
7183 bool blocking_lock = False;
7184 enum brl_type lock_type;
7186 NTSTATUS status = NT_STATUS_OK;
7188 if (fsp == NULL || fsp->fh->fd == -1) {
7189 return NT_STATUS_INVALID_HANDLE;
7192 if (total_data != POSIX_LOCK_DATA_SIZE) {
7193 return NT_STATUS_INVALID_PARAMETER;
7196 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7197 case POSIX_LOCK_TYPE_READ:
7198 lock_type = READ_LOCK;
7200 case POSIX_LOCK_TYPE_WRITE:
7201 /* Return the right POSIX-mappable error code for files opened read-only. */
7202 if (!fsp->can_write) {
7203 return NT_STATUS_INVALID_HANDLE;
7205 lock_type = WRITE_LOCK;
7207 case POSIX_LOCK_TYPE_UNLOCK:
7208 lock_type = UNLOCK_LOCK;
7211 return NT_STATUS_INVALID_PARAMETER;
7214 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7215 blocking_lock = False;
7216 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7217 blocking_lock = True;
7219 return NT_STATUS_INVALID_PARAMETER;
7222 if (!lp_blocking_locks(SNUM(conn))) {
7223 blocking_lock = False;
7226 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7227 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7228 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7229 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7230 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7232 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7233 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7235 (unsigned int)lock_type,
7236 (unsigned long long)smblctx,
7240 if (lock_type == UNLOCK_LOCK) {
7241 status = do_unlock(req->sconn->msg_ctx,
7248 uint64_t block_smblctx;
7250 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7261 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7263 * A blocking lock was requested. Package up
7264 * this smb into a queued request and push it
7265 * onto the blocking lock queue.
7267 if(push_blocking_lock_request(br_lck,
7270 -1, /* infinite timeout. */
7278 TALLOC_FREE(br_lck);
7282 TALLOC_FREE(br_lck);
7288 /****************************************************************************
7289 Deal with SMB_SET_FILE_BASIC_INFO.
7290 ****************************************************************************/
7292 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7296 const struct smb_filename *smb_fname)
7298 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7299 struct smb_file_time ft;
7300 uint32_t dosmode = 0;
7301 NTSTATUS status = NT_STATUS_OK;
7305 if (total_data < 36) {
7306 return NT_STATUS_INVALID_PARAMETER;
7309 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7310 if (!NT_STATUS_IS_OK(status)) {
7314 /* Set the attributes */
7315 dosmode = IVAL(pdata,32);
7316 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7317 if (!NT_STATUS_IS_OK(status)) {
7322 ft.create_time = interpret_long_date(pdata);
7325 ft.atime = interpret_long_date(pdata+8);
7328 ft.mtime = interpret_long_date(pdata+16);
7331 ft.ctime = interpret_long_date(pdata+24);
7333 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7334 smb_fname_str_dbg(smb_fname)));
7336 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7340 /****************************************************************************
7341 Deal with SMB_INFO_STANDARD.
7342 ****************************************************************************/
7344 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7348 const struct smb_filename *smb_fname)
7351 struct smb_file_time ft;
7355 if (total_data < 12) {
7356 return NT_STATUS_INVALID_PARAMETER;
7360 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7362 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7364 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7366 DEBUG(10,("smb_set_info_standard: file %s\n",
7367 smb_fname_str_dbg(smb_fname)));
7369 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7370 if (!NT_STATUS_IS_OK(status)) {
7374 return smb_set_file_time(conn,
7381 /****************************************************************************
7382 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7383 ****************************************************************************/
7385 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7386 struct smb_request *req,
7390 struct smb_filename *smb_fname)
7392 uint64_t allocation_size = 0;
7393 NTSTATUS status = NT_STATUS_OK;
7394 files_struct *new_fsp = NULL;
7396 if (!VALID_STAT(smb_fname->st)) {
7397 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7400 if (total_data < 8) {
7401 return NT_STATUS_INVALID_PARAMETER;
7404 allocation_size = (uint64_t)IVAL(pdata,0);
7405 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7406 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7407 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7408 (double)allocation_size));
7410 if (allocation_size) {
7411 allocation_size = smb_roundup(conn, allocation_size);
7414 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7415 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7416 (double)allocation_size));
7418 if (fsp && fsp->fh->fd != -1) {
7419 /* Open file handle. */
7420 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7421 return NT_STATUS_ACCESS_DENIED;
7424 /* Only change if needed. */
7425 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7426 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7427 return map_nt_error_from_unix(errno);
7430 /* But always update the time. */
7432 * This is equivalent to a write. Ensure it's seen immediately
7433 * if there are no pending writes.
7435 trigger_write_time_update_immediate(fsp);
7436 return NT_STATUS_OK;
7439 /* Pathname or stat or directory file. */
7440 status = SMB_VFS_CREATE_FILE(
7443 0, /* root_dir_fid */
7444 smb_fname, /* fname */
7445 FILE_WRITE_DATA, /* access_mask */
7446 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7448 FILE_OPEN, /* create_disposition*/
7449 0, /* create_options */
7450 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7451 0, /* oplock_request */
7453 0, /* allocation_size */
7454 0, /* private_flags */
7457 &new_fsp, /* result */
7459 NULL, NULL); /* create context */
7461 if (!NT_STATUS_IS_OK(status)) {
7462 /* NB. We check for open_was_deferred in the caller. */
7466 /* Only change if needed. */
7467 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7468 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7469 status = map_nt_error_from_unix(errno);
7470 close_file(req, new_fsp, NORMAL_CLOSE);
7475 /* Changing the allocation size should set the last mod time. */
7477 * This is equivalent to a write. Ensure it's seen immediately
7478 * if there are no pending writes.
7480 trigger_write_time_update_immediate(new_fsp);
7481 close_file(req, new_fsp, NORMAL_CLOSE);
7482 return NT_STATUS_OK;
7485 /****************************************************************************
7486 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7487 ****************************************************************************/
7489 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7490 struct smb_request *req,
7494 const struct smb_filename *smb_fname,
7495 bool fail_after_createfile)
7499 if (total_data < 8) {
7500 return NT_STATUS_INVALID_PARAMETER;
7503 size = IVAL(pdata,0);
7504 size |= (((off_t)IVAL(pdata,4)) << 32);
7505 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7506 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7509 return smb_set_file_size(conn, req,
7514 fail_after_createfile);
7517 /****************************************************************************
7518 Allow a UNIX info mknod.
7519 ****************************************************************************/
7521 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7524 const struct smb_filename *smb_fname)
7526 uint32_t file_type = IVAL(pdata,56);
7527 #if defined(HAVE_MAKEDEV)
7528 uint32_t dev_major = IVAL(pdata,60);
7529 uint32_t dev_minor = IVAL(pdata,68);
7531 SMB_DEV_T dev = (SMB_DEV_T)0;
7532 uint32_t raw_unixmode = IVAL(pdata,84);
7536 if (total_data < 100) {
7537 return NT_STATUS_INVALID_PARAMETER;
7540 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7541 PERM_NEW_FILE, &unixmode);
7542 if (!NT_STATUS_IS_OK(status)) {
7546 #if defined(HAVE_MAKEDEV)
7547 dev = makedev(dev_major, dev_minor);
7550 switch (file_type) {
7551 #if defined(S_IFIFO)
7552 case UNIX_TYPE_FIFO:
7553 unixmode |= S_IFIFO;
7556 #if defined(S_IFSOCK)
7557 case UNIX_TYPE_SOCKET:
7558 unixmode |= S_IFSOCK;
7561 #if defined(S_IFCHR)
7562 case UNIX_TYPE_CHARDEV:
7563 unixmode |= S_IFCHR;
7566 #if defined(S_IFBLK)
7567 case UNIX_TYPE_BLKDEV:
7568 unixmode |= S_IFBLK;
7572 return NT_STATUS_INVALID_PARAMETER;
7575 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7576 "%.0f mode 0%o for file %s\n", (double)dev,
7577 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7579 /* Ok - do the mknod. */
7580 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7581 return map_nt_error_from_unix(errno);
7584 /* If any of the other "set" calls fail we
7585 * don't want to end up with a half-constructed mknod.
7588 if (lp_inherit_permissions(SNUM(conn))) {
7590 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7592 return NT_STATUS_NO_MEMORY;
7594 inherit_access_posix_acl(conn, parent, smb_fname,
7596 TALLOC_FREE(parent);
7599 return NT_STATUS_OK;
7602 /****************************************************************************
7603 Deal with SMB_SET_FILE_UNIX_BASIC.
7604 ****************************************************************************/
7606 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7607 struct smb_request *req,
7611 const struct smb_filename *smb_fname)
7613 struct smb_file_time ft;
7614 uint32_t raw_unixmode;
7617 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7618 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7619 NTSTATUS status = NT_STATUS_OK;
7620 bool delete_on_fail = False;
7621 enum perm_type ptype;
7622 files_struct *all_fsps = NULL;
7623 bool modify_mtime = true;
7625 struct smb_filename *smb_fname_tmp = NULL;
7626 SMB_STRUCT_STAT sbuf;
7630 if (total_data < 100) {
7631 return NT_STATUS_INVALID_PARAMETER;
7634 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7635 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7636 size=IVAL(pdata,0); /* first 8 Bytes are size */
7637 size |= (((off_t)IVAL(pdata,4)) << 32);
7640 ft.atime = interpret_long_date(pdata+24); /* access_time */
7641 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7642 set_owner = (uid_t)IVAL(pdata,40);
7643 set_grp = (gid_t)IVAL(pdata,48);
7644 raw_unixmode = IVAL(pdata,84);
7646 if (VALID_STAT(smb_fname->st)) {
7647 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7648 ptype = PERM_EXISTING_DIR;
7650 ptype = PERM_EXISTING_FILE;
7653 ptype = PERM_NEW_FILE;
7656 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7658 if (!NT_STATUS_IS_OK(status)) {
7662 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7663 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7664 smb_fname_str_dbg(smb_fname), (double)size,
7665 (unsigned int)set_owner, (unsigned int)set_grp,
7666 (int)raw_unixmode));
7668 sbuf = smb_fname->st;
7670 if (!VALID_STAT(sbuf)) {
7672 * The only valid use of this is to create character and block
7673 * devices, and named pipes. This is deprecated (IMHO) and
7674 * a new info level should be used for mknod. JRA.
7677 status = smb_unix_mknod(conn,
7681 if (!NT_STATUS_IS_OK(status)) {
7685 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7686 if (smb_fname_tmp == NULL) {
7687 return NT_STATUS_NO_MEMORY;
7690 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7691 status = map_nt_error_from_unix(errno);
7692 TALLOC_FREE(smb_fname_tmp);
7693 SMB_VFS_UNLINK(conn, smb_fname);
7697 sbuf = smb_fname_tmp->st;
7698 smb_fname = smb_fname_tmp;
7700 /* Ensure we don't try and change anything else. */
7701 raw_unixmode = SMB_MODE_NO_CHANGE;
7702 size = get_file_size_stat(&sbuf);
7703 ft.atime = sbuf.st_ex_atime;
7704 ft.mtime = sbuf.st_ex_mtime;
7706 * We continue here as we might want to change the
7709 delete_on_fail = True;
7713 /* Horrible backwards compatibility hack as an old server bug
7714 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7718 size = get_file_size_stat(&sbuf);
7723 * Deal with the UNIX specific mode set.
7726 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7729 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7730 "setting mode 0%o for file %s\n",
7731 (unsigned int)unixmode,
7732 smb_fname_str_dbg(smb_fname)));
7733 if (fsp && fsp->fh->fd != -1) {
7734 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7736 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7739 return map_nt_error_from_unix(errno);
7744 * Deal with the UNIX specific uid set.
7747 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7748 (sbuf.st_ex_uid != set_owner)) {
7751 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7752 "changing owner %u for path %s\n",
7753 (unsigned int)set_owner,
7754 smb_fname_str_dbg(smb_fname)));
7756 if (fsp && fsp->fh->fd != -1) {
7757 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7760 * UNIX extensions calls must always operate
7763 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7764 set_owner, (gid_t)-1);
7768 status = map_nt_error_from_unix(errno);
7769 if (delete_on_fail) {
7770 SMB_VFS_UNLINK(conn, smb_fname);
7777 * Deal with the UNIX specific gid set.
7780 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7781 (sbuf.st_ex_gid != set_grp)) {
7784 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7785 "changing group %u for file %s\n",
7786 (unsigned int)set_owner,
7787 smb_fname_str_dbg(smb_fname)));
7788 if (fsp && fsp->fh->fd != -1) {
7789 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7792 * UNIX extensions calls must always operate
7795 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7799 status = map_nt_error_from_unix(errno);
7800 if (delete_on_fail) {
7801 SMB_VFS_UNLINK(conn, smb_fname);
7807 /* Deal with any size changes. */
7809 status = smb_set_file_size(conn, req,
7815 if (!NT_STATUS_IS_OK(status)) {
7819 /* Deal with any time changes. */
7820 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7821 /* No change, don't cancel anything. */
7825 id = vfs_file_id_from_sbuf(conn, &sbuf);
7826 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7827 all_fsps = file_find_di_next(all_fsps)) {
7829 * We're setting the time explicitly for UNIX.
7830 * Cancel any pending changes over all handles.
7832 all_fsps->update_write_time_on_close = false;
7833 TALLOC_FREE(all_fsps->update_write_time_event);
7837 * Override the "setting_write_time"
7838 * parameter here as it almost does what
7839 * we need. Just remember if we modified
7840 * mtime and send the notify ourselves.
7842 if (null_timespec(ft.mtime)) {
7843 modify_mtime = false;
7846 status = smb_set_file_time(conn,
7852 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7853 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7858 /****************************************************************************
7859 Deal with SMB_SET_FILE_UNIX_INFO2.
7860 ****************************************************************************/
7862 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7863 struct smb_request *req,
7867 const struct smb_filename *smb_fname)
7870 uint32_t smb_fflags;
7873 if (total_data < 116) {
7874 return NT_STATUS_INVALID_PARAMETER;
7877 /* Start by setting all the fields that are common between UNIX_BASIC
7880 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7882 if (!NT_STATUS_IS_OK(status)) {
7886 smb_fflags = IVAL(pdata, 108);
7887 smb_fmask = IVAL(pdata, 112);
7889 /* NB: We should only attempt to alter the file flags if the client
7890 * sends a non-zero mask.
7892 if (smb_fmask != 0) {
7893 int stat_fflags = 0;
7895 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7896 smb_fmask, &stat_fflags)) {
7897 /* Client asked to alter a flag we don't understand. */
7898 return NT_STATUS_INVALID_PARAMETER;
7901 if (fsp && fsp->fh->fd != -1) {
7902 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7903 return NT_STATUS_NOT_SUPPORTED;
7905 if (SMB_VFS_CHFLAGS(conn, smb_fname,
7906 stat_fflags) != 0) {
7907 return map_nt_error_from_unix(errno);
7912 /* XXX: need to add support for changing the create_time here. You
7913 * can do this for paths on Darwin with setattrlist(2). The right way
7914 * to hook this up is probably by extending the VFS utimes interface.
7917 return NT_STATUS_OK;
7920 /****************************************************************************
7921 Create a directory with POSIX semantics.
7922 ****************************************************************************/
7924 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7925 struct smb_request *req,
7928 struct smb_filename *smb_fname,
7929 int *pdata_return_size)
7931 NTSTATUS status = NT_STATUS_OK;
7932 uint32_t raw_unixmode = 0;
7933 uint32_t mod_unixmode = 0;
7934 mode_t unixmode = (mode_t)0;
7935 files_struct *fsp = NULL;
7936 uint16_t info_level_return = 0;
7938 char *pdata = *ppdata;
7940 if (total_data < 18) {
7941 return NT_STATUS_INVALID_PARAMETER;
7944 raw_unixmode = IVAL(pdata,8);
7945 /* Next 4 bytes are not yet defined. */
7947 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7948 PERM_NEW_DIR, &unixmode);
7949 if (!NT_STATUS_IS_OK(status)) {
7953 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7955 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7956 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7958 status = SMB_VFS_CREATE_FILE(
7961 0, /* root_dir_fid */
7962 smb_fname, /* fname */
7963 FILE_READ_ATTRIBUTES, /* access_mask */
7964 FILE_SHARE_NONE, /* share_access */
7965 FILE_CREATE, /* create_disposition*/
7966 FILE_DIRECTORY_FILE, /* create_options */
7967 mod_unixmode, /* file_attributes */
7968 0, /* oplock_request */
7970 0, /* allocation_size */
7971 0, /* private_flags */
7976 NULL, NULL); /* create context */
7978 if (NT_STATUS_IS_OK(status)) {
7979 close_file(req, fsp, NORMAL_CLOSE);
7982 info_level_return = SVAL(pdata,16);
7984 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7985 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7986 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7987 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7989 *pdata_return_size = 12;
7992 /* Realloc the data size */
7993 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7994 if (*ppdata == NULL) {
7995 *pdata_return_size = 0;
7996 return NT_STATUS_NO_MEMORY;
8000 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8001 SSVAL(pdata,2,0); /* No fnum. */
8002 SIVAL(pdata,4,info); /* Was directory created. */
8004 switch (info_level_return) {
8005 case SMB_QUERY_FILE_UNIX_BASIC:
8006 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8007 SSVAL(pdata,10,0); /* Padding. */
8008 store_file_unix_basic(conn, pdata + 12, fsp,
8011 case SMB_QUERY_FILE_UNIX_INFO2:
8012 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8013 SSVAL(pdata,10,0); /* Padding. */
8014 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8018 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8019 SSVAL(pdata,10,0); /* Padding. */
8026 /****************************************************************************
8027 Open/Create a file with POSIX semantics.
8028 ****************************************************************************/
8030 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8031 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8033 static NTSTATUS smb_posix_open(connection_struct *conn,
8034 struct smb_request *req,
8037 struct smb_filename *smb_fname,
8038 int *pdata_return_size)
8040 bool extended_oplock_granted = False;
8041 char *pdata = *ppdata;
8043 uint32_t wire_open_mode = 0;
8044 uint32_t raw_unixmode = 0;
8045 uint32_t mod_unixmode = 0;
8046 uint32_t create_disp = 0;
8047 uint32_t access_mask = 0;
8048 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8049 NTSTATUS status = NT_STATUS_OK;
8050 mode_t unixmode = (mode_t)0;
8051 files_struct *fsp = NULL;
8052 int oplock_request = 0;
8054 uint16_t info_level_return = 0;
8056 if (total_data < 18) {
8057 return NT_STATUS_INVALID_PARAMETER;
8060 flags = IVAL(pdata,0);
8061 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8062 if (oplock_request) {
8063 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8066 wire_open_mode = IVAL(pdata,4);
8068 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8069 return smb_posix_mkdir(conn, req,
8076 switch (wire_open_mode & SMB_ACCMODE) {
8078 access_mask = SMB_O_RDONLY_MAPPING;
8081 access_mask = SMB_O_WRONLY_MAPPING;
8084 access_mask = (SMB_O_RDONLY_MAPPING|
8085 SMB_O_WRONLY_MAPPING);
8088 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8089 (unsigned int)wire_open_mode ));
8090 return NT_STATUS_INVALID_PARAMETER;
8093 wire_open_mode &= ~SMB_ACCMODE;
8095 /* First take care of O_CREAT|O_EXCL interactions. */
8096 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8097 case (SMB_O_CREAT | SMB_O_EXCL):
8098 /* File exists fail. File not exist create. */
8099 create_disp = FILE_CREATE;
8102 /* File exists open. File not exist create. */
8103 create_disp = FILE_OPEN_IF;
8106 /* O_EXCL on its own without O_CREAT is undefined.
8107 We deliberately ignore it as some versions of
8108 Linux CIFSFS can send a bare O_EXCL on the
8109 wire which other filesystems in the kernel
8110 ignore. See bug 9519 for details. */
8115 /* File exists open. File not exist fail. */
8116 create_disp = FILE_OPEN;
8119 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8120 (unsigned int)wire_open_mode ));
8121 return NT_STATUS_INVALID_PARAMETER;
8124 /* Next factor in the effects of O_TRUNC. */
8125 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8127 if (wire_open_mode & SMB_O_TRUNC) {
8128 switch (create_disp) {
8130 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8131 /* Leave create_disp alone as
8132 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8134 /* File exists fail. File not exist create. */
8137 /* SMB_O_CREAT | SMB_O_TRUNC */
8138 /* File exists overwrite. File not exist create. */
8139 create_disp = FILE_OVERWRITE_IF;
8143 /* File exists overwrite. File not exist fail. */
8144 create_disp = FILE_OVERWRITE;
8147 /* Cannot get here. */
8148 smb_panic("smb_posix_open: logic error");
8149 return NT_STATUS_INVALID_PARAMETER;
8153 raw_unixmode = IVAL(pdata,8);
8154 /* Next 4 bytes are not yet defined. */
8156 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8157 (VALID_STAT(smb_fname->st) ?
8158 PERM_EXISTING_FILE : PERM_NEW_FILE),
8161 if (!NT_STATUS_IS_OK(status)) {
8165 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8167 if (wire_open_mode & SMB_O_SYNC) {
8168 create_options |= FILE_WRITE_THROUGH;
8170 if (wire_open_mode & SMB_O_APPEND) {
8171 access_mask |= FILE_APPEND_DATA;
8173 if (wire_open_mode & SMB_O_DIRECT) {
8174 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8177 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8178 VALID_STAT_OF_DIR(smb_fname->st)) {
8179 if (access_mask != SMB_O_RDONLY_MAPPING) {
8180 return NT_STATUS_FILE_IS_A_DIRECTORY;
8182 create_options &= ~FILE_NON_DIRECTORY_FILE;
8183 create_options |= FILE_DIRECTORY_FILE;
8186 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8187 smb_fname_str_dbg(smb_fname),
8188 (unsigned int)wire_open_mode,
8189 (unsigned int)unixmode ));
8191 status = SMB_VFS_CREATE_FILE(
8194 0, /* root_dir_fid */
8195 smb_fname, /* fname */
8196 access_mask, /* access_mask */
8197 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8199 create_disp, /* create_disposition*/
8200 create_options, /* create_options */
8201 mod_unixmode, /* file_attributes */
8202 oplock_request, /* oplock_request */
8204 0, /* allocation_size */
8205 0, /* private_flags */
8210 NULL, NULL); /* create context */
8212 if (!NT_STATUS_IS_OK(status)) {
8216 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8217 extended_oplock_granted = True;
8220 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8221 extended_oplock_granted = True;
8224 info_level_return = SVAL(pdata,16);
8226 /* Allocate the correct return size. */
8228 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8229 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8230 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8231 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8233 *pdata_return_size = 12;
8236 /* Realloc the data size */
8237 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8238 if (*ppdata == NULL) {
8239 close_file(req, fsp, ERROR_CLOSE);
8240 *pdata_return_size = 0;
8241 return NT_STATUS_NO_MEMORY;
8245 if (extended_oplock_granted) {
8246 if (flags & REQUEST_BATCH_OPLOCK) {
8247 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8249 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8251 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8252 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8254 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8257 SSVAL(pdata,2,fsp->fnum);
8258 SIVAL(pdata,4,info); /* Was file created etc. */
8260 switch (info_level_return) {
8261 case SMB_QUERY_FILE_UNIX_BASIC:
8262 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8263 SSVAL(pdata,10,0); /* padding. */
8264 store_file_unix_basic(conn, pdata + 12, fsp,
8267 case SMB_QUERY_FILE_UNIX_INFO2:
8268 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8269 SSVAL(pdata,10,0); /* padding. */
8270 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8274 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8275 SSVAL(pdata,10,0); /* padding. */
8278 return NT_STATUS_OK;
8281 /****************************************************************************
8282 Delete a file with POSIX semantics.
8283 ****************************************************************************/
8285 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8286 struct smb_request *req,
8289 struct smb_filename *smb_fname)
8291 NTSTATUS status = NT_STATUS_OK;
8292 files_struct *fsp = NULL;
8296 int create_options = 0;
8298 struct share_mode_lock *lck = NULL;
8300 if (total_data < 2) {
8301 return NT_STATUS_INVALID_PARAMETER;
8304 flags = SVAL(pdata,0);
8306 if (!VALID_STAT(smb_fname->st)) {
8307 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8310 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8311 !VALID_STAT_OF_DIR(smb_fname->st)) {
8312 return NT_STATUS_NOT_A_DIRECTORY;
8315 DEBUG(10,("smb_posix_unlink: %s %s\n",
8316 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8317 smb_fname_str_dbg(smb_fname)));
8319 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8320 create_options |= FILE_DIRECTORY_FILE;
8323 status = SMB_VFS_CREATE_FILE(
8326 0, /* root_dir_fid */
8327 smb_fname, /* fname */
8328 DELETE_ACCESS, /* access_mask */
8329 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8331 FILE_OPEN, /* create_disposition*/
8332 create_options, /* create_options */
8333 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8334 0, /* oplock_request */
8336 0, /* allocation_size */
8337 0, /* private_flags */
8342 NULL, NULL); /* create context */
8344 if (!NT_STATUS_IS_OK(status)) {
8349 * Don't lie to client. If we can't really delete due to
8350 * non-POSIX opens return SHARING_VIOLATION.
8353 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8355 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8356 "lock for file %s\n", fsp_str_dbg(fsp)));
8357 close_file(req, fsp, NORMAL_CLOSE);
8358 return NT_STATUS_INVALID_PARAMETER;
8362 * See if others still have the file open. If this is the case, then
8363 * don't delete. If all opens are POSIX delete we can set the delete
8364 * on close disposition.
8366 for (i=0; i<lck->data->num_share_modes; i++) {
8367 struct share_mode_entry *e = &lck->data->share_modes[i];
8368 if (is_valid_share_mode_entry(e)) {
8369 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8372 if (share_mode_stale_pid(lck->data, i)) {
8375 /* Fail with sharing violation. */
8377 close_file(req, fsp, NORMAL_CLOSE);
8378 return NT_STATUS_SHARING_VIOLATION;
8383 * Set the delete on close.
8385 status = smb_set_file_disposition_info(conn,
8393 if (!NT_STATUS_IS_OK(status)) {
8394 close_file(req, fsp, NORMAL_CLOSE);
8397 return close_file(req, fsp, NORMAL_CLOSE);
8400 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8401 struct smb_request *req,
8402 TALLOC_CTX *mem_ctx,
8403 uint16_t info_level,
8405 struct smb_filename *smb_fname,
8406 char **ppdata, int total_data,
8409 char *pdata = *ppdata;
8410 NTSTATUS status = NT_STATUS_OK;
8411 int data_return_size = 0;
8415 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8416 return NT_STATUS_INVALID_LEVEL;
8419 if (!CAN_WRITE(conn)) {
8420 /* Allow POSIX opens. The open path will deny
8421 * any non-readonly opens. */
8422 if (info_level != SMB_POSIX_PATH_OPEN) {
8423 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8427 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8428 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8430 info_level, total_data));
8432 switch (info_level) {
8434 case SMB_INFO_STANDARD:
8436 status = smb_set_info_standard(conn,
8444 case SMB_INFO_SET_EA:
8446 status = smb_info_set_ea(conn,
8454 case SMB_SET_FILE_BASIC_INFO:
8455 case SMB_FILE_BASIC_INFORMATION:
8457 status = smb_set_file_basic_info(conn,
8465 case SMB_FILE_ALLOCATION_INFORMATION:
8466 case SMB_SET_FILE_ALLOCATION_INFO:
8468 status = smb_set_file_allocation_info(conn, req,
8476 case SMB_FILE_END_OF_FILE_INFORMATION:
8477 case SMB_SET_FILE_END_OF_FILE_INFO:
8480 * XP/Win7 both fail after the createfile with
8481 * SMB_SET_FILE_END_OF_FILE_INFO but not
8482 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8483 * The level is known here, so pass it down
8487 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8489 status = smb_set_file_end_of_file_info(conn, req,
8498 case SMB_FILE_DISPOSITION_INFORMATION:
8499 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8502 /* JRA - We used to just ignore this on a path ?
8503 * Shouldn't this be invalid level on a pathname
8506 if (tran_call != TRANSACT2_SETFILEINFO) {
8507 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8510 status = smb_set_file_disposition_info(conn,
8518 case SMB_FILE_POSITION_INFORMATION:
8520 status = smb_file_position_information(conn,
8527 case SMB_FILE_FULL_EA_INFORMATION:
8529 status = smb_set_file_full_ea_info(conn,
8536 /* From tridge Samba4 :
8537 * MODE_INFORMATION in setfileinfo (I have no
8538 * idea what "mode information" on a file is - it takes a value of 0,
8539 * 2, 4 or 6. What could it be?).
8542 case SMB_FILE_MODE_INFORMATION:
8544 status = smb_file_mode_information(conn,
8551 * CIFS UNIX extensions.
8554 case SMB_SET_FILE_UNIX_BASIC:
8556 status = smb_set_file_unix_basic(conn, req,
8564 case SMB_SET_FILE_UNIX_INFO2:
8566 status = smb_set_file_unix_info2(conn, req,
8574 case SMB_SET_FILE_UNIX_LINK:
8577 /* We must have a pathname for this. */
8578 return NT_STATUS_INVALID_LEVEL;
8580 status = smb_set_file_unix_link(conn, req, pdata,
8581 total_data, smb_fname);
8585 case SMB_SET_FILE_UNIX_HLINK:
8588 /* We must have a pathname for this. */
8589 return NT_STATUS_INVALID_LEVEL;
8591 status = smb_set_file_unix_hlink(conn, req,
8597 case SMB_FILE_RENAME_INFORMATION:
8599 status = smb_file_rename_information(conn, req,
8605 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8607 /* SMB2 rename information. */
8608 status = smb2_file_rename_information(conn, req,
8614 case SMB_FILE_LINK_INFORMATION:
8616 status = smb_file_link_information(conn, req,
8622 #if defined(HAVE_POSIX_ACLS)
8623 case SMB_SET_POSIX_ACL:
8625 status = smb_set_posix_acl(conn,
8634 case SMB_SET_POSIX_LOCK:
8637 return NT_STATUS_INVALID_LEVEL;
8639 status = smb_set_posix_lock(conn, req,
8640 pdata, total_data, fsp);
8644 case SMB_POSIX_PATH_OPEN:
8647 /* We must have a pathname for this. */
8648 return NT_STATUS_INVALID_LEVEL;
8651 status = smb_posix_open(conn, req,
8659 case SMB_POSIX_PATH_UNLINK:
8662 /* We must have a pathname for this. */
8663 return NT_STATUS_INVALID_LEVEL;
8666 status = smb_posix_unlink(conn, req,
8674 return NT_STATUS_INVALID_LEVEL;
8677 if (!NT_STATUS_IS_OK(status)) {
8681 *ret_data_size = data_return_size;
8682 return NT_STATUS_OK;
8685 /****************************************************************************
8686 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8687 ****************************************************************************/
8689 static void call_trans2setfilepathinfo(connection_struct *conn,
8690 struct smb_request *req,
8691 unsigned int tran_call,
8692 char **pparams, int total_params,
8693 char **ppdata, int total_data,
8694 unsigned int max_data_bytes)
8696 char *params = *pparams;
8697 char *pdata = *ppdata;
8698 uint16_t info_level;
8699 struct smb_filename *smb_fname = NULL;
8700 files_struct *fsp = NULL;
8701 NTSTATUS status = NT_STATUS_OK;
8702 int data_return_size = 0;
8705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8709 if (tran_call == TRANSACT2_SETFILEINFO) {
8710 if (total_params < 4) {
8711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8715 fsp = file_fsp(req, SVAL(params,0));
8716 /* Basic check for non-null fsp. */
8717 if (!check_fsp_open(conn, req, fsp)) {
8720 info_level = SVAL(params,2);
8722 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8723 if (smb_fname == NULL) {
8724 reply_nterror(req, NT_STATUS_NO_MEMORY);
8728 if(fsp->fh->fd == -1) {
8730 * This is actually a SETFILEINFO on a directory
8731 * handle (returned from an NT SMB). NT5.0 seems
8732 * to do this call. JRA.
8734 if (INFO_LEVEL_IS_UNIX(info_level)) {
8735 /* Always do lstat for UNIX calls. */
8736 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8737 DEBUG(3,("call_trans2setfilepathinfo: "
8738 "SMB_VFS_LSTAT of %s failed "
8740 smb_fname_str_dbg(smb_fname),
8742 reply_nterror(req, map_nt_error_from_unix(errno));
8746 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8747 DEBUG(3,("call_trans2setfilepathinfo: "
8748 "fileinfo of %s failed (%s)\n",
8749 smb_fname_str_dbg(smb_fname),
8751 reply_nterror(req, map_nt_error_from_unix(errno));
8755 } else if (fsp->print_file) {
8757 * Doing a DELETE_ON_CLOSE should cancel a print job.
8759 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8760 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8762 DEBUG(3,("call_trans2setfilepathinfo: "
8763 "Cancelling print job (%s)\n",
8767 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8773 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8778 * Original code - this is an open file.
8780 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8781 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8782 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8784 reply_nterror(req, map_nt_error_from_unix(errno));
8790 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8793 if (total_params < 7) {
8794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8798 info_level = SVAL(params,0);
8799 if (req->posix_pathnames) {
8800 srvstr_get_path_posix(req,
8809 srvstr_get_path(req,
8818 if (!NT_STATUS_IS_OK(status)) {
8819 reply_nterror(req, status);
8823 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8824 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8825 info_level == SMB_FILE_RENAME_INFORMATION ||
8826 info_level == SMB_POSIX_PATH_UNLINK) {
8827 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8830 status = filename_convert(req, conn,
8835 if (!NT_STATUS_IS_OK(status)) {
8836 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8837 reply_botherror(req,
8838 NT_STATUS_PATH_NOT_COVERED,
8839 ERRSRV, ERRbadpath);
8842 reply_nterror(req, status);
8846 if (INFO_LEVEL_IS_UNIX(info_level)) {
8848 * For CIFS UNIX extensions the target name may not exist.
8851 /* Always do lstat for UNIX calls. */
8852 SMB_VFS_LSTAT(conn, smb_fname);
8854 } else if (!VALID_STAT(smb_fname->st) &&
8855 SMB_VFS_STAT(conn, smb_fname)) {
8856 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8858 smb_fname_str_dbg(smb_fname),
8860 reply_nterror(req, map_nt_error_from_unix(errno));
8865 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8866 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8868 info_level,total_data));
8870 /* Realloc the parameter size */
8871 *pparams = (char *)SMB_REALLOC(*pparams,2);
8872 if (*pparams == NULL) {
8873 reply_nterror(req, NT_STATUS_NO_MEMORY);
8880 status = smbd_do_setfilepathinfo(conn, req, req,
8886 if (!NT_STATUS_IS_OK(status)) {
8887 if (open_was_deferred(req->xconn, req->mid)) {
8888 /* We have re-scheduled this call. */
8891 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8892 /* We have re-scheduled this call. */
8895 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8896 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8897 ERRSRV, ERRbadpath);
8900 if (info_level == SMB_POSIX_PATH_OPEN) {
8901 reply_openerror(req, status);
8906 * Invalid EA name needs to return 2 param bytes,
8907 * not a zero-length error packet.
8909 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8910 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8913 reply_nterror(req, status);
8918 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8924 /****************************************************************************
8925 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8926 ****************************************************************************/
8928 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8929 char **pparams, int total_params,
8930 char **ppdata, int total_data,
8931 unsigned int max_data_bytes)
8933 struct smb_filename *smb_dname = NULL;
8934 char *params = *pparams;
8935 char *pdata = *ppdata;
8936 char *directory = NULL;
8937 NTSTATUS status = NT_STATUS_OK;
8938 struct ea_list *ea_list = NULL;
8939 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8940 TALLOC_CTX *ctx = talloc_tos();
8942 if (!CAN_WRITE(conn)) {
8943 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8947 if (total_params < 5) {
8948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8952 if (req->posix_pathnames) {
8953 srvstr_get_path_posix(ctx,
8962 srvstr_get_path(ctx,
8971 if (!NT_STATUS_IS_OK(status)) {
8972 reply_nterror(req, status);
8976 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8978 status = filename_convert(ctx,
8985 if (!NT_STATUS_IS_OK(status)) {
8986 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8987 reply_botherror(req,
8988 NT_STATUS_PATH_NOT_COVERED,
8989 ERRSRV, ERRbadpath);
8992 reply_nterror(req, status);
8997 * OS/2 workplace shell seems to send SET_EA requests of "null"
8998 * length (4 bytes containing IVAL 4).
8999 * They seem to have no effect. Bug #3212. JRA.
9002 if (total_data && (total_data != 4)) {
9003 /* Any data in this call is an EA list. */
9004 if (total_data < 10) {
9005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9009 if (IVAL(pdata,0) > total_data) {
9010 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9011 IVAL(pdata,0), (unsigned int)total_data));
9012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9016 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9023 if (!lp_ea_support(SNUM(conn))) {
9024 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9028 /* If total_data == 4 Windows doesn't care what values
9029 * are placed in that field, it just ignores them.
9030 * The System i QNTC IBM SMB client puts bad values here,
9031 * so ignore them. */
9033 status = create_directory(conn, req, smb_dname);
9035 if (!NT_STATUS_IS_OK(status)) {
9036 reply_nterror(req, status);
9040 /* Try and set any given EA. */
9042 status = set_ea(conn, NULL, smb_dname, ea_list);
9043 if (!NT_STATUS_IS_OK(status)) {
9044 reply_nterror(req, status);
9049 /* Realloc the parameter and data sizes */
9050 *pparams = (char *)SMB_REALLOC(*pparams,2);
9051 if(*pparams == NULL) {
9052 reply_nterror(req, NT_STATUS_NO_MEMORY);
9059 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9062 TALLOC_FREE(smb_dname);
9066 /****************************************************************************
9067 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9068 We don't actually do this - we just send a null response.
9069 ****************************************************************************/
9071 static void call_trans2findnotifyfirst(connection_struct *conn,
9072 struct smb_request *req,
9073 char **pparams, int total_params,
9074 char **ppdata, int total_data,
9075 unsigned int max_data_bytes)
9077 char *params = *pparams;
9078 uint16_t info_level;
9080 if (total_params < 6) {
9081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9085 info_level = SVAL(params,4);
9086 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9088 switch (info_level) {
9093 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9097 /* Realloc the parameter and data sizes */
9098 *pparams = (char *)SMB_REALLOC(*pparams,6);
9099 if (*pparams == NULL) {
9100 reply_nterror(req, NT_STATUS_NO_MEMORY);
9105 SSVAL(params,0,fnf_handle);
9106 SSVAL(params,2,0); /* No changes */
9107 SSVAL(params,4,0); /* No EA errors */
9114 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9119 /****************************************************************************
9120 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9121 changes). Currently this does nothing.
9122 ****************************************************************************/
9124 static void call_trans2findnotifynext(connection_struct *conn,
9125 struct smb_request *req,
9126 char **pparams, int total_params,
9127 char **ppdata, int total_data,
9128 unsigned int max_data_bytes)
9130 char *params = *pparams;
9132 DEBUG(3,("call_trans2findnotifynext\n"));
9134 /* Realloc the parameter and data sizes */
9135 *pparams = (char *)SMB_REALLOC(*pparams,4);
9136 if (*pparams == NULL) {
9137 reply_nterror(req, NT_STATUS_NO_MEMORY);
9142 SSVAL(params,0,0); /* No changes */
9143 SSVAL(params,2,0); /* No EA errors */
9145 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9150 /****************************************************************************
9151 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9152 ****************************************************************************/
9154 static void call_trans2getdfsreferral(connection_struct *conn,
9155 struct smb_request *req,
9156 char **pparams, int total_params,
9157 char **ppdata, int total_data,
9158 unsigned int max_data_bytes)
9160 char *params = *pparams;
9161 char *pathname = NULL;
9163 int max_referral_level;
9164 NTSTATUS status = NT_STATUS_OK;
9165 TALLOC_CTX *ctx = talloc_tos();
9167 DEBUG(10,("call_trans2getdfsreferral\n"));
9169 if (total_params < 3) {
9170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9174 max_referral_level = SVAL(params,0);
9176 if(!lp_host_msdfs()) {
9177 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9181 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9182 total_params - 2, STR_TERMINATE);
9184 reply_nterror(req, NT_STATUS_NOT_FOUND);
9187 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9188 ppdata,&status)) < 0) {
9189 reply_nterror(req, status);
9193 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9194 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9195 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9200 #define LMCAT_SPL 0x53
9201 #define LMFUNC_GETJOBID 0x60
9203 /****************************************************************************
9204 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9205 ****************************************************************************/
9207 static void call_trans2ioctl(connection_struct *conn,
9208 struct smb_request *req,
9209 char **pparams, int total_params,
9210 char **ppdata, int total_data,
9211 unsigned int max_data_bytes)
9213 char *pdata = *ppdata;
9214 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9218 /* check for an invalid fid before proceeding */
9221 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9225 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9226 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9227 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9228 if (*ppdata == NULL) {
9229 reply_nterror(req, NT_STATUS_NO_MEMORY);
9234 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9235 CAN ACCEPT THIS IN UNICODE. JRA. */
9238 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9240 status = srvstr_push(pdata, req->flags2, pdata + 2,
9241 lp_netbios_name(), 15,
9242 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9243 if (!NT_STATUS_IS_OK(status)) {
9244 reply_nterror(req, status);
9247 status = srvstr_push(pdata, req->flags2, pdata+18,
9248 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9249 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9250 if (!NT_STATUS_IS_OK(status)) {
9251 reply_nterror(req, status);
9254 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9259 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9260 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9263 /****************************************************************************
9264 Reply to a SMBfindclose (stop trans2 directory search).
9265 ****************************************************************************/
9267 void reply_findclose(struct smb_request *req)
9270 struct smbd_server_connection *sconn = req->sconn;
9272 START_PROFILE(SMBfindclose);
9275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9276 END_PROFILE(SMBfindclose);
9280 dptr_num = SVALS(req->vwv+0, 0);
9282 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9284 dptr_close(sconn, &dptr_num);
9286 reply_outbuf(req, 0, 0);
9288 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9290 END_PROFILE(SMBfindclose);
9294 /****************************************************************************
9295 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9296 ****************************************************************************/
9298 void reply_findnclose(struct smb_request *req)
9302 START_PROFILE(SMBfindnclose);
9305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9306 END_PROFILE(SMBfindnclose);
9310 dptr_num = SVAL(req->vwv+0, 0);
9312 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9314 /* We never give out valid handles for a
9315 findnotifyfirst - so any dptr_num is ok here.
9318 reply_outbuf(req, 0, 0);
9320 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9322 END_PROFILE(SMBfindnclose);
9326 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9327 struct trans_state *state)
9329 if (get_Protocol() >= PROTOCOL_NT1) {
9330 req->flags2 |= 0x40; /* IS_LONG_NAME */
9331 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9334 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9335 if (state->call != TRANSACT2_QFSINFO &&
9336 state->call != TRANSACT2_SETFSINFO) {
9337 DEBUG(0,("handle_trans2: encryption required "
9339 (unsigned int)state->call));
9340 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9345 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9347 /* Now we must call the relevant TRANS2 function */
9348 switch(state->call) {
9349 case TRANSACT2_OPEN:
9351 START_PROFILE(Trans2_open);
9352 call_trans2open(conn, req,
9353 &state->param, state->total_param,
9354 &state->data, state->total_data,
9355 state->max_data_return);
9356 END_PROFILE(Trans2_open);
9360 case TRANSACT2_FINDFIRST:
9362 START_PROFILE(Trans2_findfirst);
9363 call_trans2findfirst(conn, req,
9364 &state->param, state->total_param,
9365 &state->data, state->total_data,
9366 state->max_data_return);
9367 END_PROFILE(Trans2_findfirst);
9371 case TRANSACT2_FINDNEXT:
9373 START_PROFILE(Trans2_findnext);
9374 call_trans2findnext(conn, req,
9375 &state->param, state->total_param,
9376 &state->data, state->total_data,
9377 state->max_data_return);
9378 END_PROFILE(Trans2_findnext);
9382 case TRANSACT2_QFSINFO:
9384 START_PROFILE(Trans2_qfsinfo);
9385 call_trans2qfsinfo(conn, req,
9386 &state->param, state->total_param,
9387 &state->data, state->total_data,
9388 state->max_data_return);
9389 END_PROFILE(Trans2_qfsinfo);
9393 case TRANSACT2_SETFSINFO:
9395 START_PROFILE(Trans2_setfsinfo);
9396 call_trans2setfsinfo(conn, req,
9397 &state->param, state->total_param,
9398 &state->data, state->total_data,
9399 state->max_data_return);
9400 END_PROFILE(Trans2_setfsinfo);
9404 case TRANSACT2_QPATHINFO:
9405 case TRANSACT2_QFILEINFO:
9407 START_PROFILE(Trans2_qpathinfo);
9408 call_trans2qfilepathinfo(conn, req, state->call,
9409 &state->param, state->total_param,
9410 &state->data, state->total_data,
9411 state->max_data_return);
9412 END_PROFILE(Trans2_qpathinfo);
9416 case TRANSACT2_SETPATHINFO:
9417 case TRANSACT2_SETFILEINFO:
9419 START_PROFILE(Trans2_setpathinfo);
9420 call_trans2setfilepathinfo(conn, req, state->call,
9421 &state->param, state->total_param,
9422 &state->data, state->total_data,
9423 state->max_data_return);
9424 END_PROFILE(Trans2_setpathinfo);
9428 case TRANSACT2_FINDNOTIFYFIRST:
9430 START_PROFILE(Trans2_findnotifyfirst);
9431 call_trans2findnotifyfirst(conn, req,
9432 &state->param, state->total_param,
9433 &state->data, state->total_data,
9434 state->max_data_return);
9435 END_PROFILE(Trans2_findnotifyfirst);
9439 case TRANSACT2_FINDNOTIFYNEXT:
9441 START_PROFILE(Trans2_findnotifynext);
9442 call_trans2findnotifynext(conn, req,
9443 &state->param, state->total_param,
9444 &state->data, state->total_data,
9445 state->max_data_return);
9446 END_PROFILE(Trans2_findnotifynext);
9450 case TRANSACT2_MKDIR:
9452 START_PROFILE(Trans2_mkdir);
9453 call_trans2mkdir(conn, req,
9454 &state->param, state->total_param,
9455 &state->data, state->total_data,
9456 state->max_data_return);
9457 END_PROFILE(Trans2_mkdir);
9461 case TRANSACT2_GET_DFS_REFERRAL:
9463 START_PROFILE(Trans2_get_dfs_referral);
9464 call_trans2getdfsreferral(conn, req,
9465 &state->param, state->total_param,
9466 &state->data, state->total_data,
9467 state->max_data_return);
9468 END_PROFILE(Trans2_get_dfs_referral);
9472 case TRANSACT2_IOCTL:
9474 START_PROFILE(Trans2_ioctl);
9475 call_trans2ioctl(conn, req,
9476 &state->param, state->total_param,
9477 &state->data, state->total_data,
9478 state->max_data_return);
9479 END_PROFILE(Trans2_ioctl);
9484 /* Error in request */
9485 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9486 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9490 /****************************************************************************
9491 Reply to a SMBtrans2.
9492 ****************************************************************************/
9494 void reply_trans2(struct smb_request *req)
9496 connection_struct *conn = req->conn;
9501 unsigned int tran_call;
9502 struct trans_state *state;
9505 START_PROFILE(SMBtrans2);
9507 if (req->wct < 14) {
9508 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9509 END_PROFILE(SMBtrans2);
9513 dsoff = SVAL(req->vwv+12, 0);
9514 dscnt = SVAL(req->vwv+11, 0);
9515 psoff = SVAL(req->vwv+10, 0);
9516 pscnt = SVAL(req->vwv+9, 0);
9517 tran_call = SVAL(req->vwv+14, 0);
9519 result = allow_new_trans(conn->pending_trans, req->mid);
9520 if (!NT_STATUS_IS_OK(result)) {
9521 DEBUG(2, ("Got invalid trans2 request: %s\n",
9522 nt_errstr(result)));
9523 reply_nterror(req, result);
9524 END_PROFILE(SMBtrans2);
9529 switch (tran_call) {
9530 /* List the allowed trans2 calls on IPC$ */
9531 case TRANSACT2_OPEN:
9532 case TRANSACT2_GET_DFS_REFERRAL:
9533 case TRANSACT2_QFILEINFO:
9534 case TRANSACT2_QFSINFO:
9535 case TRANSACT2_SETFSINFO:
9538 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9539 END_PROFILE(SMBtrans2);
9544 if ((state = talloc(conn, struct trans_state)) == NULL) {
9545 DEBUG(0, ("talloc failed\n"));
9546 reply_nterror(req, NT_STATUS_NO_MEMORY);
9547 END_PROFILE(SMBtrans2);
9551 state->cmd = SMBtrans2;
9553 state->mid = req->mid;
9554 state->vuid = req->vuid;
9555 state->setup_count = SVAL(req->vwv+13, 0);
9556 state->setup = NULL;
9557 state->total_param = SVAL(req->vwv+0, 0);
9558 state->param = NULL;
9559 state->total_data = SVAL(req->vwv+1, 0);
9561 state->max_param_return = SVAL(req->vwv+2, 0);
9562 state->max_data_return = SVAL(req->vwv+3, 0);
9563 state->max_setup_return = SVAL(req->vwv+4, 0);
9564 state->close_on_completion = BITSETW(req->vwv+5, 0);
9565 state->one_way = BITSETW(req->vwv+5, 1);
9567 state->call = tran_call;
9569 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9570 is so as a sanity check */
9571 if (state->setup_count != 1) {
9573 * Need to have rc=0 for ioctl to get job id for OS/2.
9574 * Network printing will fail if function is not successful.
9575 * Similar function in reply.c will be used if protocol
9576 * is LANMAN1.0 instead of LM1.2X002.
9577 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9578 * outbuf doesn't have to be set(only job id is used).
9580 if ( (state->setup_count == 4)
9581 && (tran_call == TRANSACT2_IOCTL)
9582 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9583 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9584 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9586 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9587 DEBUG(2,("Transaction is %d\n",tran_call));
9589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9590 END_PROFILE(SMBtrans2);
9595 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9598 if (state->total_data) {
9600 if (trans_oob(state->total_data, 0, dscnt)
9601 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9605 /* Can't use talloc here, the core routines do realloc on the
9606 * params and data. */
9607 state->data = (char *)SMB_MALLOC(state->total_data);
9608 if (state->data == NULL) {
9609 DEBUG(0,("reply_trans2: data malloc fail for %u "
9610 "bytes !\n", (unsigned int)state->total_data));
9612 reply_nterror(req, NT_STATUS_NO_MEMORY);
9613 END_PROFILE(SMBtrans2);
9617 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9620 if (state->total_param) {
9622 if (trans_oob(state->total_param, 0, pscnt)
9623 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9627 /* Can't use talloc here, the core routines do realloc on the
9628 * params and data. */
9629 state->param = (char *)SMB_MALLOC(state->total_param);
9630 if (state->param == NULL) {
9631 DEBUG(0,("reply_trans: param malloc fail for %u "
9632 "bytes !\n", (unsigned int)state->total_param));
9633 SAFE_FREE(state->data);
9635 reply_nterror(req, NT_STATUS_NO_MEMORY);
9636 END_PROFILE(SMBtrans2);
9640 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9643 state->received_data = dscnt;
9644 state->received_param = pscnt;
9646 if ((state->received_param == state->total_param) &&
9647 (state->received_data == state->total_data)) {
9649 handle_trans2(conn, req, state);
9651 SAFE_FREE(state->data);
9652 SAFE_FREE(state->param);
9654 END_PROFILE(SMBtrans2);
9658 DLIST_ADD(conn->pending_trans, state);
9660 /* We need to send an interim response then receive the rest
9661 of the parameter/data bytes */
9662 reply_outbuf(req, 0, 0);
9663 show_msg((char *)req->outbuf);
9664 END_PROFILE(SMBtrans2);
9669 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9670 SAFE_FREE(state->data);
9671 SAFE_FREE(state->param);
9673 END_PROFILE(SMBtrans2);
9674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9678 /****************************************************************************
9679 Reply to a SMBtranss2
9680 ****************************************************************************/
9682 void reply_transs2(struct smb_request *req)
9684 connection_struct *conn = req->conn;
9685 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9686 struct trans_state *state;
9688 START_PROFILE(SMBtranss2);
9690 show_msg((const char *)req->inbuf);
9692 /* Windows clients expect all replies to
9693 a transact secondary (SMBtranss2 0x33)
9694 to have a command code of transact
9695 (SMBtrans2 0x32). See bug #8989
9696 and also [MS-CIFS] section 2.2.4.47.2
9699 req->cmd = SMBtrans2;
9702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9703 END_PROFILE(SMBtranss2);
9707 for (state = conn->pending_trans; state != NULL;
9708 state = state->next) {
9709 if (state->mid == req->mid) {
9714 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9716 END_PROFILE(SMBtranss2);
9720 /* Revise state->total_param and state->total_data in case they have
9721 changed downwards */
9723 if (SVAL(req->vwv+0, 0) < state->total_param)
9724 state->total_param = SVAL(req->vwv+0, 0);
9725 if (SVAL(req->vwv+1, 0) < state->total_data)
9726 state->total_data = SVAL(req->vwv+1, 0);
9728 pcnt = SVAL(req->vwv+2, 0);
9729 poff = SVAL(req->vwv+3, 0);
9730 pdisp = SVAL(req->vwv+4, 0);
9732 dcnt = SVAL(req->vwv+5, 0);
9733 doff = SVAL(req->vwv+6, 0);
9734 ddisp = SVAL(req->vwv+7, 0);
9736 state->received_param += pcnt;
9737 state->received_data += dcnt;
9739 if ((state->received_data > state->total_data) ||
9740 (state->received_param > state->total_param))
9744 if (trans_oob(state->total_param, pdisp, pcnt)
9745 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9748 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9752 if (trans_oob(state->total_data, ddisp, dcnt)
9753 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9756 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9759 if ((state->received_param < state->total_param) ||
9760 (state->received_data < state->total_data)) {
9761 END_PROFILE(SMBtranss2);
9765 handle_trans2(conn, req, state);
9767 DLIST_REMOVE(conn->pending_trans, state);
9768 SAFE_FREE(state->data);
9769 SAFE_FREE(state->param);
9772 END_PROFILE(SMBtranss2);
9777 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9778 DLIST_REMOVE(conn->pending_trans, state);
9779 SAFE_FREE(state->data);
9780 SAFE_FREE(state->param);
9782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9783 END_PROFILE(SMBtranss2);