2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
41 #include "lib/util_ea.h"
42 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
55 const SMB_STRUCT_STAT *psbuf);
57 /****************************************************************************
58 Check if an open file handle or smb_fname is a symlink.
59 ****************************************************************************/
61 static NTSTATUS refuse_symlink(connection_struct *conn,
62 const files_struct *fsp,
63 const struct smb_filename *smb_fname)
66 const SMB_STRUCT_STAT *pst = NULL;
69 pst = &fsp->fsp_name->st;
74 if (!VALID_STAT(*pst)) {
75 int ret = vfs_stat_smb_basename(conn,
78 if (ret == -1 && errno != ENOENT) {
79 return map_nt_error_from_unix(errno);
80 } else if (ret == -1) {
81 /* it's not a symlink.. */
87 if (S_ISLNK(pst->st_ex_mode)) {
88 return NT_STATUS_ACCESS_DENIED;
93 NTSTATUS check_access_fsp(const struct files_struct *fsp,
96 if (!(fsp->access_mask & access_mask)) {
97 return NT_STATUS_ACCESS_DENIED;
102 /********************************************************************
103 The canonical "check access" based on object handle or path function.
104 ********************************************************************/
106 NTSTATUS check_access(connection_struct *conn,
108 const struct smb_filename *smb_fname,
109 uint32_t access_mask)
114 status = check_access_fsp(fsp, access_mask);
116 status = smbd_check_access_rights(conn, smb_fname,
123 /********************************************************************
124 Roundup a value to the nearest allocation roundup size boundary.
125 Only do this for Windows clients.
126 ********************************************************************/
128 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
130 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
132 /* Only roundup for Windows clients. */
133 enum remote_arch_types ra_type = get_remote_arch();
134 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
135 val = SMB_ROUNDUP(val,rval);
140 /********************************************************************
141 Create a 64 bit FileIndex. If the file is on the same device as
142 the root of the share, just return the 64-bit inode. If it isn't,
143 mangle as we used to do.
144 ********************************************************************/
146 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
149 if (conn->sconn->aapl_zero_file_id) {
152 if (conn->base_share_dev == psbuf->st_ex_dev) {
153 return (uint64_t)psbuf->st_ex_ino;
155 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
156 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
161 /********************************************************************
162 Globally (for this connection / multi-channel) disable file-ID
163 calculation. This is required to be global because it serves
164 Macs in AAPL mode, which is globally set.
165 ********************************************************************/
166 void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
168 sconn->aapl_zero_file_id = true;
171 /****************************************************************************
172 Utility functions for dealing with extended attributes.
173 ****************************************************************************/
175 /****************************************************************************
176 Refuse to allow clients to overwrite our private xattrs.
177 ****************************************************************************/
179 bool samba_private_attr_name(const char *unix_ea_name)
181 static const char * const prohibited_ea_names[] = {
182 SAMBA_POSIX_INHERITANCE_EA_NAME,
183 SAMBA_XATTR_DOS_ATTRIB,
191 for (i = 0; prohibited_ea_names[i]; i++) {
192 if (strequal( prohibited_ea_names[i], unix_ea_name))
195 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
196 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
202 /****************************************************************************
203 Get one EA value. Fill in a struct ea_struct.
204 ****************************************************************************/
206 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
207 connection_struct *conn,
209 const struct smb_filename *smb_fname,
211 struct ea_struct *pea)
213 /* Get the value of this xattr. Max size is 64k. */
214 size_t attr_size = 256;
220 val = talloc_realloc(mem_ctx, val, char, attr_size);
222 return NT_STATUS_NO_MEMORY;
225 if (fsp && fsp->fh->fd != -1) {
226 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
228 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
229 ea_name, val, attr_size);
232 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
238 return map_nt_error_from_unix(errno);
241 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
242 dump_data(10, (uint8_t *)val, sizeret);
245 if (strnequal(ea_name, "user.", 5)) {
246 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
248 pea->name = talloc_strdup(mem_ctx, ea_name);
250 if (pea->name == NULL) {
252 return NT_STATUS_NO_MEMORY;
254 pea->value.data = (unsigned char *)val;
255 pea->value.length = (size_t)sizeret;
259 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
260 connection_struct *conn,
262 const struct smb_filename *smb_fname,
267 /* Get a list of all xattrs. Max namesize is 64k. */
268 size_t ea_namelist_size = 1024;
269 char *ea_namelist = smallbuf;
270 char *to_free = NULL;
275 ssize_t sizeret = -1;
283 status = refuse_symlink(conn, fsp, smb_fname);
284 if (!NT_STATUS_IS_OK(status)) {
286 * Just return no EA's on a symlink.
291 if (fsp && fsp->fh->fd != -1) {
292 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
295 sizeret = SMB_VFS_LISTXATTR(conn,
301 if ((sizeret == -1) && (errno == ERANGE)) {
302 ea_namelist_size = 65536;
303 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
304 if (ea_namelist == NULL) {
305 return NT_STATUS_NO_MEMORY;
307 to_free = ea_namelist;
309 if (fsp && fsp->fh->fd != -1) {
310 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
313 sizeret = SMB_VFS_LISTXATTR(conn,
321 status = map_nt_error_from_unix(errno);
322 TALLOC_FREE(to_free);
326 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
329 TALLOC_FREE(to_free);
334 * Ensure the result is 0-terminated
337 if (ea_namelist[sizeret-1] != '\0') {
338 TALLOC_FREE(to_free);
339 return NT_STATUS_INTERNAL_ERROR;
347 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
351 *pnum_names = num_names;
353 if (pnames == NULL) {
354 TALLOC_FREE(to_free);
358 names = talloc_array(mem_ctx, char *, num_names);
360 DEBUG(0, ("talloc failed\n"));
361 TALLOC_FREE(to_free);
362 return NT_STATUS_NO_MEMORY;
365 if (ea_namelist == smallbuf) {
366 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
367 if (ea_namelist == NULL) {
369 return NT_STATUS_NO_MEMORY;
372 talloc_steal(names, ea_namelist);
374 ea_namelist = talloc_realloc(names, ea_namelist, char,
376 if (ea_namelist == NULL) {
378 return NT_STATUS_NO_MEMORY;
384 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
385 names[num_names++] = p;
393 /****************************************************************************
394 Return a linked list of the total EA's. Plus the total size
395 ****************************************************************************/
397 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
398 connection_struct *conn,
400 const struct smb_filename *smb_fname,
401 size_t *pea_total_len,
402 struct ea_list **ea_list)
404 /* Get a list of all xattrs. Max namesize is 64k. */
407 struct ea_list *ea_list_head = NULL;
408 bool posix_pathnames = false;
414 if (!lp_ea_support(SNUM(conn))) {
420 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
422 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
425 status = get_ea_names_from_file(talloc_tos(),
432 if (!NT_STATUS_IS_OK(status)) {
436 if (num_names == 0) {
440 for (i=0; i<num_names; i++) {
441 struct ea_list *listp;
444 if (strnequal(names[i], "system.", 7)
445 || samba_private_attr_name(names[i]))
449 * Filter out any underlying POSIX EA names
450 * that a Windows client can't handle.
452 if (!posix_pathnames &&
453 is_invalid_windows_ea_name(names[i])) {
457 listp = talloc(mem_ctx, struct ea_list);
459 return NT_STATUS_NO_MEMORY;
462 status = get_ea_value(listp,
469 if (!NT_STATUS_IS_OK(status)) {
474 if (listp->ea.value.length == 0) {
476 * We can never return a zero length EA.
477 * Windows reports the EA's as corrupted.
483 push_ascii_fstring(dos_ea_name, listp->ea.name);
486 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
488 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
489 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
490 (unsigned int)listp->ea.value.length));
492 DLIST_ADD_END(ea_list_head, listp);
496 /* Add on 4 for total length. */
497 if (*pea_total_len) {
501 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
502 (unsigned int)*pea_total_len));
504 *ea_list = ea_list_head;
508 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
509 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
514 if (!lp_ea_support(SNUM(conn))) {
518 if (is_ntfs_stream_smb_fname(smb_fname)) {
519 return NT_STATUS_INVALID_PARAMETER;
522 return get_ea_list_from_file_path(mem_ctx,
530 /****************************************************************************
531 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
533 ****************************************************************************/
535 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
536 connection_struct *conn, struct ea_list *ea_list)
538 unsigned int ret_data_size = 4;
541 SMB_ASSERT(total_data_size >= 4);
543 if (!lp_ea_support(SNUM(conn))) {
548 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
551 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
552 dos_namelen = strlen(dos_ea_name);
553 if (dos_namelen > 255 || dos_namelen == 0) {
556 if (ea_list->ea.value.length > 65535) {
559 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
563 /* We know we have room. */
564 SCVAL(p,0,ea_list->ea.flags);
565 SCVAL(p,1,dos_namelen);
566 SSVAL(p,2,ea_list->ea.value.length);
567 strlcpy(p+4, dos_ea_name, dos_namelen+1);
568 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
570 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
571 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
574 ret_data_size = PTR_DIFF(p, pdata);
575 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
576 SIVAL(pdata,0,ret_data_size);
577 return ret_data_size;
580 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
582 unsigned int total_data_size,
583 unsigned int *ret_data_size,
584 connection_struct *conn,
585 struct ea_list *ea_list)
587 uint8_t *p = (uint8_t *)pdata;
588 uint8_t *last_start = NULL;
589 bool do_store_data = (pdata != NULL);
593 if (!lp_ea_support(SNUM(conn))) {
594 return NT_STATUS_NO_EAS_ON_FILE;
597 for (; ea_list; ea_list = ea_list->next) {
603 if (last_start != NULL && do_store_data) {
604 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
608 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
609 dos_namelen = strlen(dos_ea_name);
610 if (dos_namelen > 255 || dos_namelen == 0) {
611 return NT_STATUS_INTERNAL_ERROR;
613 if (ea_list->ea.value.length > 65535) {
614 return NT_STATUS_INTERNAL_ERROR;
617 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
620 pad = (4 - (this_size % 4)) % 4;
625 if (this_size > total_data_size) {
626 return NT_STATUS_INFO_LENGTH_MISMATCH;
629 /* We know we have room. */
630 SIVAL(p, 0x00, 0); /* next offset */
631 SCVAL(p, 0x04, ea_list->ea.flags);
632 SCVAL(p, 0x05, dos_namelen);
633 SSVAL(p, 0x06, ea_list->ea.value.length);
634 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
635 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
637 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
641 total_data_size -= this_size;
647 *ret_data_size = PTR_DIFF(p, pdata);
648 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
652 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
654 size_t total_ea_len = 0;
656 struct ea_list *ea_list = NULL;
658 if (!lp_ea_support(SNUM(conn))) {
661 mem_ctx = talloc_stackframe();
663 /* If this is a stream fsp, then we need to instead find the
664 * estimated ea len from the main file, not the stream
665 * (streams cannot have EAs), but the estimate isn't just 0 in
667 if (is_ntfs_stream_smb_fname(smb_fname)) {
670 (void)get_ea_list_from_file_path(mem_ctx,
676 if(conn->sconn->using_smb2) {
678 unsigned int ret_data_size;
680 * We're going to be using fill_ea_chained_buffer() to
681 * marshall EA's - this size is significantly larger
682 * than the SMB1 buffer. Re-calculate the size without
685 status = fill_ea_chained_buffer(mem_ctx,
691 if (!NT_STATUS_IS_OK(status)) {
694 total_ea_len = ret_data_size;
696 TALLOC_FREE(mem_ctx);
700 /****************************************************************************
701 Ensure the EA name is case insensitive by matching any existing EA name.
702 ****************************************************************************/
704 static void canonicalize_ea_name(connection_struct *conn,
706 const struct smb_filename *smb_fname,
707 fstring unix_ea_name)
710 TALLOC_CTX *mem_ctx = talloc_tos();
711 struct ea_list *ea_list;
712 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
718 if (!NT_STATUS_IS_OK(status)) {
722 for (; ea_list; ea_list = ea_list->next) {
723 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
724 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
725 &unix_ea_name[5], ea_list->ea.name));
726 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
732 /****************************************************************************
733 Set or delete an extended attribute.
734 ****************************************************************************/
736 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
737 const struct smb_filename *smb_fname, struct ea_list *ea_list)
740 bool posix_pathnames = false;
742 if (!lp_ea_support(SNUM(conn))) {
743 return NT_STATUS_EAS_NOT_SUPPORTED;
748 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
750 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
753 status = refuse_symlink(conn, fsp, smb_fname);
754 if (!NT_STATUS_IS_OK(status)) {
758 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
759 if (!NT_STATUS_IS_OK(status)) {
763 /* Setting EAs on streams isn't supported. */
764 if (is_ntfs_stream_smb_fname(smb_fname)) {
765 return NT_STATUS_INVALID_PARAMETER;
769 * Filter out invalid Windows EA names - before
770 * we set *any* of them.
773 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
774 return STATUS_INVALID_EA_NAME;
777 for (;ea_list; ea_list = ea_list->next) {
779 fstring unix_ea_name;
781 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
782 fstrcat(unix_ea_name, ea_list->ea.name);
784 canonicalize_ea_name(conn,
789 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
791 if (samba_private_attr_name(unix_ea_name)) {
792 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
793 return NT_STATUS_ACCESS_DENIED;
796 if (ea_list->ea.value.length == 0) {
797 /* Remove the attribute. */
798 if (fsp && (fsp->fh->fd != -1)) {
799 DEBUG(10,("set_ea: deleting ea name %s on "
800 "file %s by file descriptor.\n",
801 unix_ea_name, fsp_str_dbg(fsp)));
802 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
804 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
805 unix_ea_name, smb_fname->base_name));
806 ret = SMB_VFS_REMOVEXATTR(conn,
811 /* Removing a non existent attribute always succeeds. */
812 if (ret == -1 && errno == ENOATTR) {
813 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
819 if (fsp && (fsp->fh->fd != -1)) {
820 DEBUG(10,("set_ea: setting ea name %s on file "
821 "%s by file descriptor.\n",
822 unix_ea_name, fsp_str_dbg(fsp)));
823 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
824 ea_list->ea.value.data, ea_list->ea.value.length, 0);
826 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
827 unix_ea_name, smb_fname->base_name));
828 ret = SMB_VFS_SETXATTR(conn,
831 ea_list->ea.value.data,
832 ea_list->ea.value.length,
839 if (errno == ENOTSUP) {
840 return NT_STATUS_EAS_NOT_SUPPORTED;
843 return map_nt_error_from_unix(errno);
849 /****************************************************************************
850 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
851 ****************************************************************************/
853 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
855 struct ea_list *ea_list_head = NULL;
856 size_t converted_size, offset = 0;
858 while (offset + 2 < data_size) {
859 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
860 unsigned int namelen = CVAL(pdata,offset);
862 offset++; /* Go past the namelen byte. */
864 /* integer wrap paranioa. */
865 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
866 (offset > data_size) || (namelen > data_size) ||
867 (offset + namelen >= data_size)) {
870 /* Ensure the name is null terminated. */
871 if (pdata[offset + namelen] != '\0') {
874 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
876 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
877 "failed: %s", strerror(errno)));
883 offset += (namelen + 1); /* Go past the name + terminating zero. */
884 DLIST_ADD_END(ea_list_head, eal);
885 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
891 /****************************************************************************
892 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
893 ****************************************************************************/
895 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
897 struct ea_list *ea_list_head = NULL;
899 size_t bytes_used = 0;
901 while (offset < data_size) {
902 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
908 DLIST_ADD_END(ea_list_head, eal);
909 offset += bytes_used;
915 /****************************************************************************
916 Count the total EA size needed.
917 ****************************************************************************/
919 static size_t ea_list_size(struct ea_list *ealist)
922 struct ea_list *listp;
925 for (listp = ealist; listp; listp = listp->next) {
926 push_ascii_fstring(dos_ea_name, listp->ea.name);
927 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
929 /* Add on 4 for total length. */
937 /****************************************************************************
938 Return a union of EA's from a file list and a list of names.
939 The TALLOC context for the two lists *MUST* be identical as we steal
940 memory from one list to add to another. JRA.
941 ****************************************************************************/
943 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
945 struct ea_list *nlistp, *flistp;
947 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
948 for (flistp = file_list; flistp; flistp = flistp->next) {
949 if (strequal(nlistp->ea.name, flistp->ea.name)) {
955 /* Copy the data from this entry. */
956 nlistp->ea.flags = flistp->ea.flags;
957 nlistp->ea.value = flistp->ea.value;
960 nlistp->ea.flags = 0;
961 ZERO_STRUCT(nlistp->ea.value);
965 *total_ea_len = ea_list_size(name_list);
969 /****************************************************************************
970 Send the required number of replies back.
971 We assume all fields other than the data fields are
972 set correctly for the type of call.
973 HACK ! Always assumes smb_setup field is zero.
974 ****************************************************************************/
976 void send_trans2_replies(connection_struct *conn,
977 struct smb_request *req,
985 /* As we are using a protocol > LANMAN1 then the max_send
986 variable must have been set in the sessetupX call.
987 This takes precedence over the max_xmit field in the
988 global struct. These different max_xmit variables should
989 be merged as this is now too confusing */
991 int data_to_send = datasize;
992 int params_to_send = paramsize;
994 const char *pp = params;
995 const char *pd = pdata;
996 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
997 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
998 int data_alignment_offset = 0;
999 bool overflow = False;
1000 struct smbXsrv_connection *xconn = req->xconn;
1001 int max_send = xconn->smb1.sessions.max_send;
1003 /* Modify the data_to_send and datasize and set the error if
1004 we're trying to send more than max_data_bytes. We still send
1005 the part of the packet(s) that fit. Strange, but needed
1008 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1009 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1010 max_data_bytes, datasize ));
1011 datasize = data_to_send = max_data_bytes;
1015 /* If there genuinely are no parameters or data to send just send the empty packet */
1017 if(params_to_send == 0 && data_to_send == 0) {
1018 reply_outbuf(req, 10, 0);
1019 if (NT_STATUS_V(status)) {
1022 ntstatus_to_dos(status, &eclass, &ecode);
1023 error_packet_set((char *)req->outbuf,
1024 eclass, ecode, status,
1027 show_msg((char *)req->outbuf);
1028 if (!srv_send_smb(xconn,
1029 (char *)req->outbuf,
1030 true, req->seqnum+1,
1031 IS_CONN_ENCRYPTED(conn),
1033 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1035 TALLOC_FREE(req->outbuf);
1039 /* When sending params and data ensure that both are nicely aligned */
1040 /* Only do this alignment when there is also data to send - else
1041 can cause NT redirector problems. */
1043 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1044 data_alignment_offset = 4 - (params_to_send % 4);
1046 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1047 /* The alignment_offset is to align the param bytes on an even byte
1048 boundary. NT 4.0 Beta needs this to work correctly. */
1050 useable_space = max_send - (smb_size
1053 + data_alignment_offset);
1055 if (useable_space < 0) {
1056 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1057 "= %d!!!", useable_space));
1058 exit_server_cleanly("send_trans2_replies: Not enough space");
1061 while (params_to_send || data_to_send) {
1062 /* Calculate whether we will totally or partially fill this packet */
1064 total_sent_thistime = params_to_send + data_to_send;
1066 /* We can never send more than useable_space */
1068 * Note that 'useable_space' does not include the alignment offsets,
1069 * but we must include the alignment offsets in the calculation of
1070 * the length of the data we send over the wire, as the alignment offsets
1071 * are sent here. Fix from Marc_Jacobsen@hp.com.
1074 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1076 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1077 + data_alignment_offset);
1079 /* Set total params and data to be sent */
1080 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1081 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1083 /* Calculate how many parameters and data we can fit into
1084 * this packet. Parameters get precedence
1087 params_sent_thistime = MIN(params_to_send,useable_space);
1088 data_sent_thistime = useable_space - params_sent_thistime;
1089 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1091 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1093 /* smb_proff is the offset from the start of the SMB header to the
1094 parameter bytes, however the first 4 bytes of outbuf are
1095 the Netbios over TCP header. Thus use smb_base() to subtract
1096 them from the calculation */
1098 SSVAL(req->outbuf,smb_proff,
1099 ((smb_buf(req->outbuf)+alignment_offset)
1100 - smb_base(req->outbuf)));
1102 if(params_sent_thistime == 0)
1103 SSVAL(req->outbuf,smb_prdisp,0);
1105 /* Absolute displacement of param bytes sent in this packet */
1106 SSVAL(req->outbuf,smb_prdisp,pp - params);
1108 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1109 if(data_sent_thistime == 0) {
1110 SSVAL(req->outbuf,smb_droff,0);
1111 SSVAL(req->outbuf,smb_drdisp, 0);
1113 /* The offset of the data bytes is the offset of the
1114 parameter bytes plus the number of parameters being sent this time */
1115 SSVAL(req->outbuf, smb_droff,
1116 ((smb_buf(req->outbuf)+alignment_offset)
1117 - smb_base(req->outbuf))
1118 + params_sent_thistime + data_alignment_offset);
1119 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1122 /* Initialize the padding for alignment */
1124 if (alignment_offset != 0) {
1125 memset(smb_buf(req->outbuf), 0, alignment_offset);
1128 /* Copy the param bytes into the packet */
1130 if(params_sent_thistime) {
1131 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1132 params_sent_thistime);
1135 /* Copy in the data bytes */
1136 if(data_sent_thistime) {
1137 if (data_alignment_offset != 0) {
1138 memset((smb_buf(req->outbuf)+alignment_offset+
1139 params_sent_thistime), 0,
1140 data_alignment_offset);
1142 memcpy(smb_buf(req->outbuf)+alignment_offset
1143 +params_sent_thistime+data_alignment_offset,
1144 pd,data_sent_thistime);
1147 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1148 params_sent_thistime, data_sent_thistime, useable_space));
1149 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1150 params_to_send, data_to_send, paramsize, datasize));
1153 error_packet_set((char *)req->outbuf,
1154 ERRDOS,ERRbufferoverflow,
1155 STATUS_BUFFER_OVERFLOW,
1157 } else if (NT_STATUS_V(status)) {
1160 ntstatus_to_dos(status, &eclass, &ecode);
1161 error_packet_set((char *)req->outbuf,
1162 eclass, ecode, status,
1166 /* Send the packet */
1167 show_msg((char *)req->outbuf);
1168 if (!srv_send_smb(xconn,
1169 (char *)req->outbuf,
1170 true, req->seqnum+1,
1171 IS_CONN_ENCRYPTED(conn),
1173 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1175 TALLOC_FREE(req->outbuf);
1177 pp += params_sent_thistime;
1178 pd += data_sent_thistime;
1180 params_to_send -= params_sent_thistime;
1181 data_to_send -= data_sent_thistime;
1184 if(params_to_send < 0 || data_to_send < 0) {
1185 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1186 params_to_send, data_to_send));
1194 /****************************************************************************
1195 Reply to a TRANSACT2_OPEN.
1196 ****************************************************************************/
1198 static void call_trans2open(connection_struct *conn,
1199 struct smb_request *req,
1200 char **pparams, int total_params,
1201 char **ppdata, int total_data,
1202 unsigned int max_data_bytes)
1204 struct smb_filename *smb_fname = NULL;
1205 char *params = *pparams;
1206 char *pdata = *ppdata;
1209 bool oplock_request;
1211 bool return_additional_info;
1220 int fattr=0,mtime=0;
1221 SMB_INO_T inode = 0;
1224 struct ea_list *ea_list = NULL;
1227 uint32_t access_mask;
1228 uint32_t share_mode;
1229 uint32_t create_disposition;
1230 uint32_t create_options = 0;
1231 uint32_t private_flags = 0;
1232 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1233 TALLOC_CTX *ctx = talloc_tos();
1236 * Ensure we have enough parameters to perform the operation.
1239 if (total_params < 29) {
1240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1244 flags = SVAL(params, 0);
1245 deny_mode = SVAL(params, 2);
1246 open_attr = SVAL(params,6);
1247 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1248 if (oplock_request) {
1249 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1253 return_additional_info = BITSETW(params,0);
1254 open_sattr = SVAL(params, 4);
1255 open_time = make_unix_date3(params+8);
1257 open_ofun = SVAL(params,12);
1258 open_size = IVAL(params,14);
1259 pname = ¶ms[28];
1262 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1266 if (req->posix_pathnames) {
1267 srvstr_get_path_posix(ctx,
1276 srvstr_get_path(ctx,
1285 if (!NT_STATUS_IS_OK(status)) {
1286 reply_nterror(req, status);
1290 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1291 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1292 (unsigned int)open_ofun, open_size));
1294 status = filename_convert(ctx,
1301 if (!NT_STATUS_IS_OK(status)) {
1302 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1303 reply_botherror(req,
1304 NT_STATUS_PATH_NOT_COVERED,
1305 ERRSRV, ERRbadpath);
1308 reply_nterror(req, status);
1312 if (open_ofun == 0) {
1313 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1317 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1319 &access_mask, &share_mode,
1320 &create_disposition,
1323 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1327 /* Any data in this call is an EA list. */
1328 if (total_data && (total_data != 4)) {
1329 if (total_data < 10) {
1330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1334 if (IVAL(pdata,0) > total_data) {
1335 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1336 IVAL(pdata,0), (unsigned int)total_data));
1337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1341 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1348 if (!lp_ea_support(SNUM(conn))) {
1349 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1353 if (!req->posix_pathnames &&
1354 ea_list_has_invalid_name(ea_list)) {
1356 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1357 if(*pparams == NULL ) {
1358 reply_nterror(req, NT_STATUS_NO_MEMORY);
1362 memset(params, '\0', param_len);
1363 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1364 params, param_len, NULL, 0, max_data_bytes);
1369 status = SMB_VFS_CREATE_FILE(
1372 0, /* root_dir_fid */
1373 smb_fname, /* fname */
1374 access_mask, /* access_mask */
1375 share_mode, /* share_access */
1376 create_disposition, /* create_disposition*/
1377 create_options, /* create_options */
1378 open_attr, /* file_attributes */
1379 oplock_request, /* oplock_request */
1381 open_size, /* allocation_size */
1384 ea_list, /* ea_list */
1386 &smb_action, /* psbuf */
1387 NULL, NULL); /* create context */
1389 if (!NT_STATUS_IS_OK(status)) {
1390 if (open_was_deferred(req->xconn, req->mid)) {
1391 /* We have re-scheduled this call. */
1394 reply_openerror(req, status);
1398 size = get_file_size_stat(&smb_fname->st);
1399 fattr = dos_mode(conn, smb_fname);
1400 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1401 inode = smb_fname->st.st_ex_ino;
1402 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1403 close_file(req, fsp, ERROR_CLOSE);
1404 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1408 /* Realloc the size of parameters and data we will return */
1409 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1410 if(*pparams == NULL ) {
1411 reply_nterror(req, NT_STATUS_NO_MEMORY);
1416 SSVAL(params,0,fsp->fnum);
1417 SSVAL(params,2,fattr);
1418 srv_put_dos_date2(params,4, mtime);
1419 SIVAL(params,8, (uint32_t)size);
1420 SSVAL(params,12,deny_mode);
1421 SSVAL(params,14,0); /* open_type - file or directory. */
1422 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1424 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1425 smb_action |= EXTENDED_OPLOCK_GRANTED;
1428 SSVAL(params,18,smb_action);
1431 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1433 SIVAL(params,20,inode);
1434 SSVAL(params,24,0); /* Padding. */
1436 uint32_t ea_size = estimate_ea_size(conn, fsp,
1438 SIVAL(params, 26, ea_size);
1440 SIVAL(params, 26, 0);
1443 /* Send the required number of replies */
1444 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1446 TALLOC_FREE(smb_fname);
1449 /*********************************************************
1450 Routine to check if a given string matches exactly.
1451 as a special case a mask of "." does NOT match. That
1452 is required for correct wildcard semantics
1453 Case can be significant or not.
1454 **********************************************************/
1456 static bool exact_match(bool has_wild,
1457 bool case_sensitive,
1461 if (mask[0] == '.' && mask[1] == 0) {
1469 if (case_sensitive) {
1470 return strcmp(str,mask)==0;
1472 return strcasecmp_m(str,mask) == 0;
1476 /****************************************************************************
1477 Return the filetype for UNIX extensions.
1478 ****************************************************************************/
1480 static uint32_t unix_filetype(mode_t mode)
1483 return UNIX_TYPE_FILE;
1484 else if(S_ISDIR(mode))
1485 return UNIX_TYPE_DIR;
1487 else if(S_ISLNK(mode))
1488 return UNIX_TYPE_SYMLINK;
1491 else if(S_ISCHR(mode))
1492 return UNIX_TYPE_CHARDEV;
1495 else if(S_ISBLK(mode))
1496 return UNIX_TYPE_BLKDEV;
1499 else if(S_ISFIFO(mode))
1500 return UNIX_TYPE_FIFO;
1503 else if(S_ISSOCK(mode))
1504 return UNIX_TYPE_SOCKET;
1507 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1508 return UNIX_TYPE_UNKNOWN;
1511 /****************************************************************************
1512 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1513 ****************************************************************************/
1515 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1517 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1518 const SMB_STRUCT_STAT *psbuf,
1520 enum perm_type ptype,
1525 if (perms == SMB_MODE_NO_CHANGE) {
1526 if (!VALID_STAT(*psbuf)) {
1527 return NT_STATUS_INVALID_PARAMETER;
1529 *ret_perms = psbuf->st_ex_mode;
1530 return NT_STATUS_OK;
1534 ret = wire_perms_to_unix(perms);
1536 if (ptype == PERM_NEW_FILE) {
1538 * "create mask"/"force create mode" are
1539 * only applied to new files, not existing ones.
1541 ret &= lp_create_mask(SNUM(conn));
1542 /* Add in force bits */
1543 ret |= lp_force_create_mode(SNUM(conn));
1544 } else if (ptype == PERM_NEW_DIR) {
1546 * "directory mask"/"force directory mode" are
1547 * only applied to new directories, not existing ones.
1549 ret &= lp_directory_mask(SNUM(conn));
1550 /* Add in force bits */
1551 ret |= lp_force_directory_mode(SNUM(conn));
1555 return NT_STATUS_OK;
1558 /****************************************************************************
1559 Needed to show the msdfs symlinks as directories. Modifies psbuf
1560 to be a directory if it's a msdfs link.
1561 ****************************************************************************/
1563 static bool check_msdfs_link(connection_struct *conn,
1564 struct smb_filename *smb_fname)
1566 int saved_errno = errno;
1567 if(lp_host_msdfs() &&
1568 lp_msdfs_root(SNUM(conn)) &&
1569 is_msdfs_link(conn, smb_fname)) {
1571 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1573 smb_fname->base_name));
1574 smb_fname->st.st_ex_mode =
1575 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1576 errno = saved_errno;
1579 errno = saved_errno;
1584 /****************************************************************************
1585 Get a level dependent lanman2 dir entry.
1586 ****************************************************************************/
1588 struct smbd_dirptr_lanman2_state {
1589 connection_struct *conn;
1590 uint32_t info_level;
1591 bool check_mangled_names;
1593 bool got_exact_match;
1596 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1602 struct smbd_dirptr_lanman2_state *state =
1603 (struct smbd_dirptr_lanman2_state *)private_data;
1605 char mangled_name[13]; /* mangled 8.3 name. */
1609 /* Mangle fname if it's an illegal name. */
1610 if (mangle_must_mangle(dname, state->conn->params)) {
1612 * Slow path - ensure we can push the original name as UCS2. If
1613 * not, then just don't return this name.
1617 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1618 uint8_t *tmp = talloc_array(talloc_tos(),
1622 status = srvstr_push(NULL,
1623 FLAGS2_UNICODE_STRINGS,
1632 if (!NT_STATUS_IS_OK(status)) {
1636 ok = name_to_8_3(dname, mangled_name,
1637 true, state->conn->params);
1641 fname = mangled_name;
1646 got_match = exact_match(state->has_wild,
1647 state->conn->case_sensitive,
1649 state->got_exact_match = got_match;
1651 got_match = mask_match(fname, mask,
1652 state->conn->case_sensitive);
1655 if(!got_match && state->check_mangled_names &&
1656 !mangle_is_8_3(fname, false, state->conn->params)) {
1658 * It turns out that NT matches wildcards against
1659 * both long *and* short names. This may explain some
1660 * of the wildcard wierdness from old DOS clients
1661 * that some people have been seeing.... JRA.
1663 /* Force the mangling into 8.3. */
1664 ok = name_to_8_3(fname, mangled_name,
1665 false, state->conn->params);
1670 got_match = exact_match(state->has_wild,
1671 state->conn->case_sensitive,
1672 mangled_name, mask);
1673 state->got_exact_match = got_match;
1675 got_match = mask_match(mangled_name, mask,
1676 state->conn->case_sensitive);
1684 *_fname = talloc_strdup(ctx, fname);
1685 if (*_fname == NULL) {
1692 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1694 struct smb_filename *smb_fname,
1698 struct smbd_dirptr_lanman2_state *state =
1699 (struct smbd_dirptr_lanman2_state *)private_data;
1700 bool ms_dfs_link = false;
1703 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1704 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1705 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1706 "Couldn't lstat [%s] (%s)\n",
1707 smb_fname_str_dbg(smb_fname),
1711 } else if (!VALID_STAT(smb_fname->st) &&
1712 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1713 /* Needed to show the msdfs symlinks as
1716 ms_dfs_link = check_msdfs_link(state->conn,
1719 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1720 "Couldn't stat [%s] (%s)\n",
1721 smb_fname_str_dbg(smb_fname),
1728 mode = dos_mode_msdfs(state->conn, smb_fname);
1729 } else if (get_dosmode) {
1730 mode = dos_mode(state->conn, smb_fname);
1737 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1738 connection_struct *conn,
1740 uint32_t info_level,
1741 struct ea_list *name_list,
1742 bool check_mangled_names,
1743 bool requires_resume_key,
1746 const struct smb_filename *smb_fname,
1747 int space_remaining,
1753 uint64_t *last_entry_off)
1755 char *p, *q, *pdata = *ppdata;
1757 uint64_t file_size = 0;
1758 uint64_t allocation_size = 0;
1759 uint64_t file_index = 0;
1761 struct timespec mdate_ts = {0};
1762 struct timespec adate_ts = {0};
1763 struct timespec cdate_ts = {0};
1764 struct timespec create_date_ts = {0};
1765 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1767 char *last_entry_ptr;
1772 struct readdir_attr_data *readdir_attr_data = NULL;
1774 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1775 file_size = get_file_size_stat(&smb_fname->st);
1777 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1779 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1780 if (!NT_STATUS_IS_OK(status)) {
1781 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1786 file_index = get_FileIndex(conn, &smb_fname->st);
1788 mdate_ts = smb_fname->st.st_ex_mtime;
1789 adate_ts = smb_fname->st.st_ex_atime;
1790 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1791 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1793 if (lp_dos_filetime_resolution(SNUM(conn))) {
1794 dos_filetime_timespec(&create_date_ts);
1795 dos_filetime_timespec(&mdate_ts);
1796 dos_filetime_timespec(&adate_ts);
1797 dos_filetime_timespec(&cdate_ts);
1800 create_date = convert_timespec_to_time_t(create_date_ts);
1801 mdate = convert_timespec_to_time_t(mdate_ts);
1802 adate = convert_timespec_to_time_t(adate_ts);
1804 /* align the record */
1805 SMB_ASSERT(align >= 1);
1807 off = (int)PTR_DIFF(pdata, base_data);
1808 pad = (off + (align-1)) & ~(align-1);
1811 if (pad && pad > space_remaining) {
1812 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1813 "for padding (wanted %u, had %d)\n",
1816 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1820 /* initialize padding to 0 */
1822 memset(pdata, 0, pad);
1824 space_remaining -= pad;
1826 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1836 switch (info_level) {
1837 case SMB_FIND_INFO_STANDARD:
1838 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1839 if(requires_resume_key) {
1843 srv_put_dos_date2(p,0,create_date);
1844 srv_put_dos_date2(p,4,adate);
1845 srv_put_dos_date2(p,8,mdate);
1846 SIVAL(p,12,(uint32_t)file_size);
1847 SIVAL(p,16,(uint32_t)allocation_size);
1851 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1852 p += ucs2_align(base_data, p, 0);
1854 status = srvstr_push(base_data, flags2, p,
1855 fname, PTR_DIFF(end_data, p),
1856 STR_TERMINATE, &len);
1857 if (!NT_STATUS_IS_OK(status)) {
1860 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1862 SCVAL(nameptr, -1, len - 2);
1864 SCVAL(nameptr, -1, 0);
1868 SCVAL(nameptr, -1, len - 1);
1870 SCVAL(nameptr, -1, 0);
1876 case SMB_FIND_EA_SIZE:
1877 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1878 if (requires_resume_key) {
1882 srv_put_dos_date2(p,0,create_date);
1883 srv_put_dos_date2(p,4,adate);
1884 srv_put_dos_date2(p,8,mdate);
1885 SIVAL(p,12,(uint32_t)file_size);
1886 SIVAL(p,16,(uint32_t)allocation_size);
1889 unsigned int ea_size = estimate_ea_size(conn, NULL,
1891 SIVAL(p,22,ea_size); /* Extended attributes */
1895 status = srvstr_push(base_data, flags2,
1896 p, fname, PTR_DIFF(end_data, p),
1897 STR_TERMINATE | STR_NOALIGN, &len);
1898 if (!NT_STATUS_IS_OK(status)) {
1901 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1914 SCVAL(nameptr,0,len);
1916 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1919 case SMB_FIND_EA_LIST:
1921 struct ea_list *file_list = NULL;
1924 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1926 return NT_STATUS_INVALID_PARAMETER;
1928 if (requires_resume_key) {
1932 srv_put_dos_date2(p,0,create_date);
1933 srv_put_dos_date2(p,4,adate);
1934 srv_put_dos_date2(p,8,mdate);
1935 SIVAL(p,12,(uint32_t)file_size);
1936 SIVAL(p,16,(uint32_t)allocation_size);
1938 p += 22; /* p now points to the EA area. */
1940 status = get_ea_list_from_file(ctx, conn, NULL,
1942 &ea_len, &file_list);
1943 if (!NT_STATUS_IS_OK(status)) {
1946 name_list = ea_list_union(name_list, file_list, &ea_len);
1948 /* We need to determine if this entry will fit in the space available. */
1949 /* Max string size is 255 bytes. */
1950 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1951 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1952 "(wanted %u, had %d)\n",
1953 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1955 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1958 /* Push the ea_data followed by the name. */
1959 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1961 status = srvstr_push(base_data, flags2,
1962 p + 1, fname, PTR_DIFF(end_data, p+1),
1963 STR_TERMINATE | STR_NOALIGN, &len);
1964 if (!NT_STATUS_IS_OK(status)) {
1967 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1980 SCVAL(nameptr,0,len);
1982 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1986 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1987 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1988 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1990 SIVAL(p,0,reskey); p += 4;
1991 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1992 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1993 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1994 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1995 SOFF_T(p,0,file_size); p += 8;
1996 SOFF_T(p,0,allocation_size); p += 8;
1997 SIVAL(p,0,mode); p += 4;
1998 q = p; p += 4; /* q is placeholder for name length. */
1999 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2000 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2002 unsigned int ea_size = estimate_ea_size(conn, NULL,
2004 SIVAL(p,0,ea_size); /* Extended attributes */
2007 /* Clear the short name buffer. This is
2008 * IMPORTANT as not doing so will trigger
2009 * a Win2k client bug. JRA.
2011 if (!was_8_3 && check_mangled_names) {
2012 char mangled_name[13]; /* mangled 8.3 name. */
2013 if (!name_to_8_3(fname,mangled_name,True,
2015 /* Error - mangle failed ! */
2016 memset(mangled_name,'\0',12);
2018 mangled_name[12] = 0;
2019 status = srvstr_push(base_data, flags2,
2020 p+2, mangled_name, 24,
2021 STR_UPPER|STR_UNICODE, &len);
2022 if (!NT_STATUS_IS_OK(status)) {
2026 memset(p + 2 + len,'\0',24 - len);
2033 status = srvstr_push(base_data, flags2, p,
2034 fname, PTR_DIFF(end_data, p),
2035 STR_TERMINATE_ASCII, &len);
2036 if (!NT_STATUS_IS_OK(status)) {
2042 len = PTR_DIFF(p, pdata);
2043 pad = (len + (align-1)) & ~(align-1);
2045 * offset to the next entry, the caller
2046 * will overwrite it for the last entry
2047 * that's why we always include the padding
2051 * set padding to zero
2054 memset(p, 0, pad - len);
2061 case SMB_FIND_FILE_DIRECTORY_INFO:
2062 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2064 SIVAL(p,0,reskey); p += 4;
2065 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2066 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2067 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2068 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2069 SOFF_T(p,0,file_size); p += 8;
2070 SOFF_T(p,0,allocation_size); p += 8;
2071 SIVAL(p,0,mode); p += 4;
2072 status = srvstr_push(base_data, flags2,
2073 p + 4, fname, PTR_DIFF(end_data, p+4),
2074 STR_TERMINATE_ASCII, &len);
2075 if (!NT_STATUS_IS_OK(status)) {
2081 len = PTR_DIFF(p, pdata);
2082 pad = (len + (align-1)) & ~(align-1);
2084 * offset to the next entry, the caller
2085 * will overwrite it for the last entry
2086 * that's why we always include the padding
2090 * set padding to zero
2093 memset(p, 0, pad - len);
2100 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2101 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2103 SIVAL(p,0,reskey); p += 4;
2104 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2105 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2106 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2107 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2108 SOFF_T(p,0,file_size); p += 8;
2109 SOFF_T(p,0,allocation_size); p += 8;
2110 SIVAL(p,0,mode); p += 4;
2111 q = p; p += 4; /* q is placeholder for name length. */
2113 unsigned int ea_size = estimate_ea_size(conn, NULL,
2115 SIVAL(p,0,ea_size); /* Extended attributes */
2118 status = srvstr_push(base_data, flags2, p,
2119 fname, PTR_DIFF(end_data, p),
2120 STR_TERMINATE_ASCII, &len);
2121 if (!NT_STATUS_IS_OK(status)) {
2127 len = PTR_DIFF(p, pdata);
2128 pad = (len + (align-1)) & ~(align-1);
2130 * offset to the next entry, the caller
2131 * will overwrite it for the last entry
2132 * that's why we always include the padding
2136 * set padding to zero
2139 memset(p, 0, pad - len);
2146 case SMB_FIND_FILE_NAMES_INFO:
2147 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2149 SIVAL(p,0,reskey); p += 4;
2151 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2152 acl on a dir (tridge) */
2153 status = srvstr_push(base_data, flags2, p,
2154 fname, PTR_DIFF(end_data, p),
2155 STR_TERMINATE_ASCII, &len);
2156 if (!NT_STATUS_IS_OK(status)) {
2162 len = PTR_DIFF(p, pdata);
2163 pad = (len + (align-1)) & ~(align-1);
2165 * offset to the next entry, the caller
2166 * will overwrite it for the last entry
2167 * that's why we always include the padding
2171 * set padding to zero
2174 memset(p, 0, pad - len);
2181 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2182 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2184 SIVAL(p,0,reskey); p += 4;
2185 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2186 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2187 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2188 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2189 SOFF_T(p,0,file_size); p += 8;
2190 SOFF_T(p,0,allocation_size); p += 8;
2191 SIVAL(p,0,mode); p += 4;
2192 q = p; p += 4; /* q is placeholder for name length. */
2193 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2194 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2196 unsigned int ea_size = estimate_ea_size(conn, NULL,
2198 SIVAL(p,0,ea_size); /* Extended attributes */
2201 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2202 SBVAL(p,0,file_index); p += 8;
2203 status = srvstr_push(base_data, flags2, p,
2204 fname, PTR_DIFF(end_data, p),
2205 STR_TERMINATE_ASCII, &len);
2206 if (!NT_STATUS_IS_OK(status)) {
2212 len = PTR_DIFF(p, pdata);
2213 pad = (len + (align-1)) & ~(align-1);
2215 * offset to the next entry, the caller
2216 * will overwrite it for the last entry
2217 * that's why we always include the padding
2221 * set padding to zero
2224 memset(p, 0, pad - len);
2231 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2232 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2233 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2235 SIVAL(p,0,reskey); p += 4;
2236 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2237 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2238 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2239 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2240 SOFF_T(p,0,file_size); p += 8;
2241 SOFF_T(p,0,allocation_size); p += 8;
2242 SIVAL(p,0,mode); p += 4;
2243 q = p; p += 4; /* q is placeholder for name length */
2244 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2245 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2246 } else if (readdir_attr_data &&
2247 readdir_attr_data->type == RDATTR_AAPL) {
2249 * OS X specific SMB2 extension negotiated via
2250 * AAPL create context: return max_access in
2253 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2255 unsigned int ea_size = estimate_ea_size(conn, NULL,
2257 SIVAL(p,0,ea_size); /* Extended attributes */
2261 if (readdir_attr_data &&
2262 readdir_attr_data->type == RDATTR_AAPL) {
2264 * OS X specific SMB2 extension negotiated via
2265 * AAPL create context: return resource fork
2266 * length and compressed FinderInfo in
2269 * According to documentation short_name_len
2270 * should be 0, but on the wire behaviour
2271 * shows its set to 24 by clients.
2275 /* Resourefork length */
2276 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2278 /* Compressed FinderInfo */
2279 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2280 } else if (!was_8_3 && check_mangled_names) {
2281 char mangled_name[13]; /* mangled 8.3 name. */
2282 if (!name_to_8_3(fname,mangled_name,True,
2284 /* Error - mangle failed ! */
2285 memset(mangled_name,'\0',12);
2287 mangled_name[12] = 0;
2288 status = srvstr_push(base_data, flags2,
2289 p+2, mangled_name, 24,
2290 STR_UPPER|STR_UNICODE, &len);
2291 if (!NT_STATUS_IS_OK(status)) {
2296 memset(p + 2 + len,'\0',24 - len);
2300 /* Clear the short name buffer. This is
2301 * IMPORTANT as not doing so will trigger
2302 * a Win2k client bug. JRA.
2309 if (readdir_attr_data &&
2310 readdir_attr_data->type == RDATTR_AAPL) {
2312 * OS X specific SMB2 extension negotiated via
2313 * AAPL create context: return UNIX mode in
2316 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2317 SSVAL(p, 0, aapl_mode);
2323 SBVAL(p,0,file_index); p += 8;
2324 status = srvstr_push(base_data, flags2, p,
2325 fname, PTR_DIFF(end_data, p),
2326 STR_TERMINATE_ASCII, &len);
2327 if (!NT_STATUS_IS_OK(status)) {
2333 len = PTR_DIFF(p, pdata);
2334 pad = (len + (align-1)) & ~(align-1);
2336 * offset to the next entry, the caller
2337 * will overwrite it for the last entry
2338 * that's why we always include the padding
2342 * set padding to zero
2345 memset(p, 0, pad - len);
2352 /* CIFS UNIX Extension. */
2354 case SMB_FIND_FILE_UNIX:
2355 case SMB_FIND_FILE_UNIX_INFO2:
2357 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2359 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2361 if (info_level == SMB_FIND_FILE_UNIX) {
2362 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2363 p = store_file_unix_basic(conn, p,
2364 NULL, &smb_fname->st);
2365 status = srvstr_push(base_data, flags2, p,
2366 fname, PTR_DIFF(end_data, p),
2367 STR_TERMINATE, &len);
2368 if (!NT_STATUS_IS_OK(status)) {
2372 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2373 p = store_file_unix_basic_info2(conn, p,
2374 NULL, &smb_fname->st);
2377 status = srvstr_push(base_data, flags2, p, fname,
2378 PTR_DIFF(end_data, p), 0, &len);
2379 if (!NT_STATUS_IS_OK(status)) {
2382 SIVAL(nameptr, 0, len);
2387 len = PTR_DIFF(p, pdata);
2388 pad = (len + (align-1)) & ~(align-1);
2390 * offset to the next entry, the caller
2391 * will overwrite it for the last entry
2392 * that's why we always include the padding
2396 * set padding to zero
2399 memset(p, 0, pad - len);
2404 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2409 return NT_STATUS_INVALID_LEVEL;
2412 if (PTR_DIFF(p,pdata) > space_remaining) {
2413 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2414 "(wanted %u, had %d)\n",
2415 (unsigned int)PTR_DIFF(p,pdata),
2417 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2420 /* Setup the last entry pointer, as an offset from base_data */
2421 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2422 /* Advance the data pointer to the next slot */
2425 return NT_STATUS_OK;
2428 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2429 connection_struct *conn,
2430 struct dptr_struct *dirptr,
2432 const char *path_mask,
2435 int requires_resume_key,
2444 int space_remaining,
2445 struct smb_filename **_smb_fname,
2446 bool *got_exact_match,
2447 int *_last_entry_off,
2448 struct ea_list *name_list,
2449 struct file_id *file_id)
2452 const char *mask = NULL;
2453 long prev_dirpos = 0;
2456 struct smb_filename *smb_fname = NULL;
2457 struct smbd_dirptr_lanman2_state state;
2459 uint64_t last_entry_off = 0;
2461 enum mangled_names_options mangled_names;
2462 bool marshall_with_83_names;
2464 mangled_names = lp_mangled_names(conn->params);
2468 state.info_level = info_level;
2469 if (mangled_names != MANGLED_NAMES_NO) {
2470 state.check_mangled_names = true;
2472 state.has_wild = dptr_has_wild(dirptr);
2473 state.got_exact_match = false;
2475 *got_exact_match = false;
2477 p = strrchr_m(path_mask,'/');
2488 ok = smbd_dirptr_get_entry(ctx,
2495 smbd_dirptr_lanman2_match_fn,
2496 smbd_dirptr_lanman2_mode_fn,
2503 return NT_STATUS_END_OF_FILE;
2506 *got_exact_match = state.got_exact_match;
2508 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2510 status = smbd_marshall_dir_entry(ctx,
2515 marshall_with_83_names,
2516 requires_resume_key,
2527 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2528 DEBUG(1,("Conversion error: illegal character: %s\n",
2529 smb_fname_str_dbg(smb_fname)));
2532 if (file_id != NULL) {
2533 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2536 if (!NT_STATUS_IS_OK(status) &&
2537 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2539 TALLOC_FREE(smb_fname);
2544 if (_smb_fname != NULL) {
2545 struct smb_filename *name = NULL;
2547 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2549 TALLOC_FREE(smb_fname);
2551 return NT_STATUS_NO_MEMORY;
2556 TALLOC_FREE(smb_fname);
2559 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2560 dptr_SeekDir(dirptr, prev_dirpos);
2564 *_last_entry_off = last_entry_off;
2565 return NT_STATUS_OK;
2568 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2569 connection_struct *conn,
2570 struct dptr_struct *dirptr,
2572 const char *path_mask,
2575 bool requires_resume_key,
2581 int space_remaining,
2582 bool *got_exact_match,
2583 int *last_entry_off,
2584 struct ea_list *name_list)
2587 const bool do_pad = true;
2589 if (info_level >= 1 && info_level <= 3) {
2590 /* No alignment on earlier info levels. */
2594 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2595 path_mask, dirtype, info_level,
2596 requires_resume_key, dont_descend, ask_sharemode,
2597 true, align, do_pad,
2598 ppdata, base_data, end_data,
2602 last_entry_off, name_list, NULL);
2605 /****************************************************************************
2606 Reply to a TRANS2_FINDFIRST.
2607 ****************************************************************************/
2609 static void call_trans2findfirst(connection_struct *conn,
2610 struct smb_request *req,
2611 char **pparams, int total_params,
2612 char **ppdata, int total_data,
2613 unsigned int max_data_bytes)
2615 /* We must be careful here that we don't return more than the
2616 allowed number of data bytes. If this means returning fewer than
2617 maxentries then so be it. We assume that the redirector has
2618 enough room for the fixed number of parameter bytes it has
2620 struct smb_filename *smb_dname = NULL;
2621 char *params = *pparams;
2622 char *pdata = *ppdata;
2626 uint16_t findfirst_flags;
2627 bool close_after_first;
2629 bool requires_resume_key;
2631 char *directory = NULL;
2634 int last_entry_off=0;
2638 bool finished = False;
2639 bool dont_descend = False;
2640 bool out_of_space = False;
2641 int space_remaining;
2642 bool mask_contains_wcard = False;
2643 struct ea_list *ea_list = NULL;
2644 NTSTATUS ntstatus = NT_STATUS_OK;
2645 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2646 struct dptr_struct *dirptr = NULL;
2647 struct smbd_server_connection *sconn = req->sconn;
2648 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2649 ucf_flags_from_smb_request(req);
2650 bool backup_priv = false;
2651 bool as_root = false;
2653 if (total_params < 13) {
2654 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2658 dirtype = SVAL(params,0);
2659 maxentries = SVAL(params,2);
2660 findfirst_flags = SVAL(params,4);
2661 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2662 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2663 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2664 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2665 security_token_has_privilege(get_current_nttok(conn),
2668 info_level = SVAL(params,6);
2670 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2671 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2672 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2674 info_level, max_data_bytes));
2677 /* W2K3 seems to treat zero as 1. */
2681 switch (info_level) {
2682 case SMB_FIND_INFO_STANDARD:
2683 case SMB_FIND_EA_SIZE:
2684 case SMB_FIND_EA_LIST:
2685 case SMB_FIND_FILE_DIRECTORY_INFO:
2686 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2687 case SMB_FIND_FILE_NAMES_INFO:
2688 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2689 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2690 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2692 case SMB_FIND_FILE_UNIX:
2693 case SMB_FIND_FILE_UNIX_INFO2:
2694 /* Always use filesystem for UNIX mtime query. */
2695 ask_sharemode = false;
2696 if (!lp_unix_extensions()) {
2697 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2700 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2703 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2707 if (req->posix_pathnames) {
2708 srvstr_get_path_wcard_posix(talloc_tos(),
2716 &mask_contains_wcard);
2718 srvstr_get_path_wcard(talloc_tos(),
2726 &mask_contains_wcard);
2728 if (!NT_STATUS_IS_OK(ntstatus)) {
2729 reply_nterror(req, ntstatus);
2736 ntstatus = filename_convert_with_privilege(talloc_tos(),
2741 &mask_contains_wcard,
2744 ntstatus = filename_convert(talloc_tos(), conn,
2748 &mask_contains_wcard,
2752 if (!NT_STATUS_IS_OK(ntstatus)) {
2753 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2754 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2755 ERRSRV, ERRbadpath);
2758 reply_nterror(req, ntstatus);
2762 mask = smb_dname->original_lcomp;
2764 directory = smb_dname->base_name;
2766 p = strrchr_m(directory,'/');
2768 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2769 if((directory[0] == '.') && (directory[1] == '\0')) {
2770 mask = talloc_strdup(talloc_tos(),"*");
2772 reply_nterror(req, NT_STATUS_NO_MEMORY);
2775 mask_contains_wcard = True;
2781 if (p == NULL || p == directory) {
2782 /* Ensure we don't have a directory name of "". */
2783 directory = talloc_strdup(talloc_tos(), ".");
2785 reply_nterror(req, NT_STATUS_NO_MEMORY);
2788 /* Ensure smb_dname->base_name matches. */
2789 smb_dname->base_name = directory;
2792 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2794 if (info_level == SMB_FIND_EA_LIST) {
2797 if (total_data < 4) {
2798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2802 ea_size = IVAL(pdata,0);
2803 if (ea_size != total_data) {
2804 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2805 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2806 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2810 if (!lp_ea_support(SNUM(conn))) {
2811 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2815 /* Pull out the list of names. */
2816 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2823 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2828 *ppdata = (char *)SMB_REALLOC(
2829 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2830 if(*ppdata == NULL ) {
2831 reply_nterror(req, NT_STATUS_NO_MEMORY);
2835 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2837 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2840 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2841 /* Realloc the params space */
2842 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2843 if (*pparams == NULL) {
2844 reply_nterror(req, NT_STATUS_NO_MEMORY);
2849 /* Save the wildcard match and attribs we are using on this directory -
2850 needed as lanman2 assumes these are being saved between calls */
2852 ntstatus = dptr_create(conn,
2860 mask_contains_wcard,
2864 if (!NT_STATUS_IS_OK(ntstatus)) {
2865 reply_nterror(req, ntstatus);
2870 /* Remember this in case we have
2871 to do a findnext. */
2872 dptr_set_priv(dirptr);
2875 dptr_num = dptr_dnum(dirptr);
2876 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2878 /* We don't need to check for VOL here as this is returned by
2879 a different TRANS2 call. */
2881 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2882 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2883 if (in_list(directory,
2884 lp_dont_descend(talloc_tos(), SNUM(conn)),
2885 conn->case_sensitive)) {
2886 dont_descend = True;
2890 space_remaining = max_data_bytes;
2891 out_of_space = False;
2893 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2894 bool got_exact_match = False;
2896 /* this is a heuristic to avoid seeking the dirptr except when
2897 absolutely necessary. It allows for a filename of about 40 chars */
2898 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2899 out_of_space = True;
2902 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2906 mask,dirtype,info_level,
2907 requires_resume_key,dont_descend,
2912 &last_entry_off, ea_list);
2913 if (NT_STATUS_EQUAL(ntstatus,
2914 NT_STATUS_ILLEGAL_CHARACTER)) {
2916 * Bad character conversion on name. Ignore this
2921 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2922 out_of_space = true;
2924 finished = !NT_STATUS_IS_OK(ntstatus);
2928 if (!finished && !out_of_space)
2932 * As an optimisation if we know we aren't looking
2933 * for a wildcard name (ie. the name matches the wildcard exactly)
2934 * then we can finish on any (first) match.
2935 * This speeds up large directory searches. JRA.
2941 /* Ensure space_remaining never goes -ve. */
2942 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2943 space_remaining = 0;
2944 out_of_space = true;
2946 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2950 /* Check if we can close the dirptr */
2951 if(close_after_first || (finished && close_if_end)) {
2952 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2953 dptr_close(sconn, &dptr_num);
2957 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2958 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2959 * the protocol level is less than NT1. Tested with smbclient. JRA.
2960 * This should fix the OS/2 client bug #2335.
2963 if(numentries == 0) {
2964 dptr_close(sconn, &dptr_num);
2965 if (get_Protocol() < PROTOCOL_NT1) {
2966 reply_force_doserror(req, ERRDOS, ERRnofiles);
2969 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2970 ERRDOS, ERRbadfile);
2975 /* At this point pdata points to numentries directory entries. */
2977 /* Set up the return parameter block */
2978 SSVAL(params,0,dptr_num);
2979 SSVAL(params,2,numentries);
2980 SSVAL(params,4,finished);
2981 SSVAL(params,6,0); /* Never an EA error */
2982 SSVAL(params,8,last_entry_off);
2984 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2987 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2988 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2990 reply_nterror(req, NT_STATUS_NO_MEMORY);
2994 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2995 smb_fn_name(req->cmd),
2996 mask, directory, dirtype, numentries ) );
2999 * Force a name mangle here to ensure that the
3000 * mask as an 8.3 name is top of the mangled cache.
3001 * The reasons for this are subtle. Don't remove
3002 * this code unless you know what you are doing
3003 * (see PR#13758). JRA.
3006 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3007 char mangled_name[13];
3008 name_to_8_3(mask, mangled_name, True, conn->params);
3016 TALLOC_FREE(smb_dname);
3020 /****************************************************************************
3021 Reply to a TRANS2_FINDNEXT.
3022 ****************************************************************************/
3024 static void call_trans2findnext(connection_struct *conn,
3025 struct smb_request *req,
3026 char **pparams, int total_params,
3027 char **ppdata, int total_data,
3028 unsigned int max_data_bytes)
3030 /* We must be careful here that we don't return more than the
3031 allowed number of data bytes. If this means returning fewer than
3032 maxentries then so be it. We assume that the redirector has
3033 enough room for the fixed number of parameter bytes it has
3035 char *params = *pparams;
3036 char *pdata = *ppdata;
3040 uint16_t info_level;
3041 uint32_t resume_key;
3042 uint16_t findnext_flags;
3043 bool close_after_request;
3045 bool requires_resume_key;
3047 bool mask_contains_wcard = False;
3048 char *resume_name = NULL;
3049 const char *mask = NULL;
3050 const char *directory = NULL;
3054 int i, last_entry_off=0;
3055 bool finished = False;
3056 bool dont_descend = False;
3057 bool out_of_space = False;
3058 int space_remaining;
3059 struct ea_list *ea_list = NULL;
3060 NTSTATUS ntstatus = NT_STATUS_OK;
3061 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3062 TALLOC_CTX *ctx = talloc_tos();
3063 struct dptr_struct *dirptr;
3064 struct smbd_server_connection *sconn = req->sconn;
3065 bool backup_priv = false;
3066 bool as_root = false;
3068 if (total_params < 13) {
3069 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3073 dptr_num = SVAL(params,0);
3074 maxentries = SVAL(params,2);
3075 info_level = SVAL(params,4);
3076 resume_key = IVAL(params,6);
3077 findnext_flags = SVAL(params,10);
3078 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3079 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3080 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3081 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3083 if (!continue_bit) {
3084 /* We only need resume_name if continue_bit is zero. */
3085 if (req->posix_pathnames) {
3086 srvstr_get_path_wcard_posix(ctx,
3094 &mask_contains_wcard);
3096 srvstr_get_path_wcard(ctx,
3104 &mask_contains_wcard);
3106 if (!NT_STATUS_IS_OK(ntstatus)) {
3107 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3108 complain (it thinks we're asking for the directory above the shared
3109 path or an invalid name). Catch this as the resume name is only compared, never used in
3110 a file access. JRA. */
3111 srvstr_pull_talloc(ctx, params, req->flags2,
3112 &resume_name, params+12,
3116 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3117 reply_nterror(req, ntstatus);
3123 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3124 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3125 resume_key = %d resume name = %s continue=%d level = %d\n",
3126 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3127 requires_resume_key, resume_key,
3128 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3131 /* W2K3 seems to treat zero as 1. */
3135 switch (info_level) {
3136 case SMB_FIND_INFO_STANDARD:
3137 case SMB_FIND_EA_SIZE:
3138 case SMB_FIND_EA_LIST:
3139 case SMB_FIND_FILE_DIRECTORY_INFO:
3140 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3141 case SMB_FIND_FILE_NAMES_INFO:
3142 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3143 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3144 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3146 case SMB_FIND_FILE_UNIX:
3147 case SMB_FIND_FILE_UNIX_INFO2:
3148 /* Always use filesystem for UNIX mtime query. */
3149 ask_sharemode = false;
3150 if (!lp_unix_extensions()) {
3151 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3156 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3160 if (info_level == SMB_FIND_EA_LIST) {
3163 if (total_data < 4) {
3164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3168 ea_size = IVAL(pdata,0);
3169 if (ea_size != total_data) {
3170 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3171 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3176 if (!lp_ea_support(SNUM(conn))) {
3177 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3181 /* Pull out the list of names. */
3182 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3189 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3194 *ppdata = (char *)SMB_REALLOC(
3195 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3196 if(*ppdata == NULL) {
3197 reply_nterror(req, NT_STATUS_NO_MEMORY);
3202 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3205 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3208 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3209 /* Realloc the params space */
3210 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3211 if(*pparams == NULL ) {
3212 reply_nterror(req, NT_STATUS_NO_MEMORY);
3218 /* Check that the dptr is valid */
3219 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3220 reply_nterror(req, STATUS_NO_MORE_FILES);
3224 directory = dptr_path(sconn, dptr_num);
3226 /* Get the wildcard mask from the dptr */
3227 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3228 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3229 reply_nterror(req, STATUS_NO_MORE_FILES);
3233 /* Get the attr mask from the dptr */
3234 dirtype = dptr_attr(sconn, dptr_num);
3236 backup_priv = dptr_get_priv(dirptr);
3238 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3239 "backup_priv = %d\n",
3240 dptr_num, mask, dirtype,
3242 dptr_TellDir(dirptr),
3245 /* We don't need to check for VOL here as this is returned by
3246 a different TRANS2 call. */
3248 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3249 directory,lp_dont_descend(ctx, SNUM(conn))));
3250 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3251 dont_descend = True;
3254 space_remaining = max_data_bytes;
3255 out_of_space = False;
3263 * Seek to the correct position. We no longer use the resume key but
3264 * depend on the last file name instead.
3267 if(!continue_bit && resume_name && *resume_name) {
3270 long current_pos = 0;
3272 * Remember, name_to_8_3 is called by
3273 * get_lanman2_dir_entry(), so the resume name
3274 * could be mangled. Ensure we check the unmangled name.
3277 if (mangle_is_mangled(resume_name, conn->params)) {
3278 char *new_resume_name = NULL;
3279 mangle_lookup_name_from_8_3(ctx,
3283 if (new_resume_name) {
3284 resume_name = new_resume_name;
3289 * Fix for NT redirector problem triggered by resume key indexes
3290 * changing between directory scans. We now return a resume key of 0
3291 * and instead look for the filename to continue from (also given
3292 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3293 * findfirst/findnext (as is usual) then the directory pointer
3294 * should already be at the correct place.
3297 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3298 } /* end if resume_name && !continue_bit */
3300 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3301 bool got_exact_match = False;
3303 /* this is a heuristic to avoid seeking the dirptr except when
3304 absolutely necessary. It allows for a filename of about 40 chars */
3305 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3306 out_of_space = True;
3309 ntstatus = get_lanman2_dir_entry(ctx,
3313 mask,dirtype,info_level,
3314 requires_resume_key,dont_descend,
3319 &last_entry_off, ea_list);
3320 if (NT_STATUS_EQUAL(ntstatus,
3321 NT_STATUS_ILLEGAL_CHARACTER)) {
3323 * Bad character conversion on name. Ignore this
3328 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3329 out_of_space = true;
3331 finished = !NT_STATUS_IS_OK(ntstatus);
3335 if (!finished && !out_of_space)
3339 * As an optimisation if we know we aren't looking
3340 * for a wildcard name (ie. the name matches the wildcard exactly)
3341 * then we can finish on any (first) match.
3342 * This speeds up large directory searches. JRA.
3348 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3351 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3352 smb_fn_name(req->cmd),
3353 mask, directory, dirtype, numentries ) );
3355 /* Check if we can close the dirptr */
3356 if(close_after_request || (finished && close_if_end)) {
3357 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3358 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3365 /* Set up the return parameter block */
3366 SSVAL(params,0,numentries);
3367 SSVAL(params,2,finished);
3368 SSVAL(params,4,0); /* Never an EA error */
3369 SSVAL(params,6,last_entry_off);
3371 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3377 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3379 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3383 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3385 SMB_ASSERT(extended_info != NULL);
3387 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3388 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3389 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3390 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3391 #ifdef SAMBA_VERSION_REVISION
3392 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3394 extended_info->samba_subversion = 0;
3395 #ifdef SAMBA_VERSION_RC_RELEASE
3396 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3398 #ifdef SAMBA_VERSION_PRE_RELEASE
3399 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3402 #ifdef SAMBA_VERSION_VENDOR_PATCH
3403 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3405 extended_info->samba_gitcommitdate = 0;
3406 #ifdef SAMBA_VERSION_COMMIT_TIME
3407 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3410 memset(extended_info->samba_version_string, 0,
3411 sizeof(extended_info->samba_version_string));
3413 snprintf (extended_info->samba_version_string,
3414 sizeof(extended_info->samba_version_string),
3415 "%s", samba_version_string());
3418 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3419 connection_struct *conn,
3420 TALLOC_CTX *mem_ctx,
3421 uint16_t info_level,
3423 unsigned int max_data_bytes,
3424 size_t *fixed_portion,
3425 struct smb_filename *fname,
3429 char *pdata, *end_data;
3432 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3433 int snum = SNUM(conn);
3434 const char *fstype = lp_fstype(SNUM(conn));
3435 const char *filename = NULL;
3436 const uint64_t bytes_per_sector = 512;
3437 uint32_t additional_flags = 0;
3438 struct smb_filename smb_fname;
3440 NTSTATUS status = NT_STATUS_OK;
3443 if (fname == NULL || fname->base_name == NULL) {
3446 filename = fname->base_name;
3450 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3451 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3452 "info level (0x%x) on IPC$.\n",
3453 (unsigned int)info_level));
3454 return NT_STATUS_ACCESS_DENIED;
3458 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3460 ZERO_STRUCT(smb_fname);
3461 smb_fname.base_name = discard_const_p(char, filename);
3463 if(info_level != SMB_FS_QUOTA_INFORMATION
3464 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3465 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3466 return map_nt_error_from_unix(errno);
3471 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3472 return NT_STATUS_INVALID_PARAMETER;
3475 *ppdata = (char *)SMB_REALLOC(
3476 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3477 if (*ppdata == NULL) {
3478 return NT_STATUS_NO_MEMORY;
3482 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3483 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3487 switch (info_level) {
3488 case SMB_INFO_ALLOCATION:
3490 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3492 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3494 if (df_ret == (uint64_t)-1) {
3495 return map_nt_error_from_unix(errno);
3498 block_size = lp_block_size(snum);
3499 if (bsize < block_size) {
3500 uint64_t factor = block_size/bsize;
3505 if (bsize > block_size) {
3506 uint64_t factor = bsize/block_size;
3511 sectors_per_unit = bsize/bytes_per_sector;
3513 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3514 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3515 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3518 * For large drives, return max values and not modulo.
3520 dsize = MIN(dsize, UINT32_MAX);
3521 dfree = MIN(dfree, UINT32_MAX);
3523 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3524 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3525 SIVAL(pdata,l1_cUnit,dsize);
3526 SIVAL(pdata,l1_cUnitAvail,dfree);
3527 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3531 case SMB_INFO_VOLUME:
3532 /* Return volume name */
3534 * Add volume serial number - hash of a combination of
3535 * the called hostname and the service name.
3537 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3539 * Win2k3 and previous mess this up by sending a name length
3540 * one byte short. I believe only older clients (OS/2 Win9x) use
3541 * this call so try fixing this by adding a terminating null to
3542 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3544 status = srvstr_push(
3546 pdata+l2_vol_szVolLabel, vname,
3547 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3548 STR_NOALIGN|STR_TERMINATE, &len);
3549 if (!NT_STATUS_IS_OK(status)) {
3552 SCVAL(pdata,l2_vol_cch,len);
3553 data_len = l2_vol_szVolLabel + len;
3554 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3555 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3556 (unsigned)len, vname));
3559 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3560 case SMB_FS_ATTRIBUTE_INFORMATION:
3562 additional_flags = 0;
3563 #if defined(HAVE_SYS_QUOTAS)
3564 additional_flags |= FILE_VOLUME_QUOTAS;
3567 if(lp_nt_acl_support(SNUM(conn))) {
3568 additional_flags |= FILE_PERSISTENT_ACLS;
3571 /* Capabilities are filled in at connection time through STATVFS call */
3572 additional_flags |= conn->fs_capabilities;
3573 additional_flags |= lp_parm_int(conn->params->service,
3574 "share", "fake_fscaps",
3577 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3578 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3579 additional_flags); /* FS ATTRIBUTES */
3581 SIVAL(pdata,4,255); /* Max filename component length */
3582 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3583 and will think we can't do long filenames */
3584 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3585 PTR_DIFF(end_data, pdata+12),
3587 if (!NT_STATUS_IS_OK(status)) {
3591 data_len = 12 + len;
3592 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3593 /* the client only requested a portion of the
3595 data_len = max_data_bytes;
3596 status = STATUS_BUFFER_OVERFLOW;
3598 *fixed_portion = 16;
3601 case SMB_QUERY_FS_LABEL_INFO:
3602 case SMB_FS_LABEL_INFORMATION:
3603 status = srvstr_push(pdata, flags2, pdata+4, vname,
3604 PTR_DIFF(end_data, pdata+4), 0, &len);
3605 if (!NT_STATUS_IS_OK(status)) {
3612 case SMB_QUERY_FS_VOLUME_INFO:
3613 case SMB_FS_VOLUME_INFORMATION:
3616 * Add volume serial number - hash of a combination of
3617 * the called hostname and the service name.
3619 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3620 (str_checksum(get_local_machine_name())<<16));
3622 /* Max label len is 32 characters. */
3623 status = srvstr_push(pdata, flags2, pdata+18, vname,
3624 PTR_DIFF(end_data, pdata+18),
3626 if (!NT_STATUS_IS_OK(status)) {
3629 SIVAL(pdata,12,len);
3632 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3633 (int)strlen(vname),vname,
3634 lp_servicename(talloc_tos(), snum)));
3635 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3636 /* the client only requested a portion of the
3638 data_len = max_data_bytes;
3639 status = STATUS_BUFFER_OVERFLOW;
3641 *fixed_portion = 24;
3644 case SMB_QUERY_FS_SIZE_INFO:
3645 case SMB_FS_SIZE_INFORMATION:
3647 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3649 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3651 if (df_ret == (uint64_t)-1) {
3652 return map_nt_error_from_unix(errno);
3654 block_size = lp_block_size(snum);
3655 if (bsize < block_size) {
3656 uint64_t factor = block_size/bsize;
3661 if (bsize > block_size) {
3662 uint64_t factor = bsize/block_size;
3667 sectors_per_unit = bsize/bytes_per_sector;
3668 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3669 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3670 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3671 SBIG_UINT(pdata,0,dsize);
3672 SBIG_UINT(pdata,8,dfree);
3673 SIVAL(pdata,16,sectors_per_unit);
3674 SIVAL(pdata,20,bytes_per_sector);
3675 *fixed_portion = 24;
3679 case SMB_FS_FULL_SIZE_INFORMATION:
3681 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3683 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3685 if (df_ret == (uint64_t)-1) {
3686 return map_nt_error_from_unix(errno);
3688 block_size = lp_block_size(snum);
3689 if (bsize < block_size) {
3690 uint64_t factor = block_size/bsize;
3695 if (bsize > block_size) {
3696 uint64_t factor = bsize/block_size;
3701 sectors_per_unit = bsize/bytes_per_sector;
3702 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3703 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3704 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3705 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3706 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3707 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3708 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3709 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3710 *fixed_portion = 32;
3714 case SMB_QUERY_FS_DEVICE_INFO:
3715 case SMB_FS_DEVICE_INFORMATION:
3717 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3719 if (!CAN_WRITE(conn)) {
3720 characteristics |= FILE_READ_ONLY_DEVICE;
3723 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3724 SIVAL(pdata,4,characteristics);
3729 #ifdef HAVE_SYS_QUOTAS
3730 case SMB_FS_QUOTA_INFORMATION:
3732 * what we have to send --metze:
3734 * Unknown1: 24 NULL bytes
3735 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3736 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3737 * Quota Flags: 2 byte :
3738 * Unknown3: 6 NULL bytes
3742 * details for Quota Flags:
3744 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3745 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3746 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3747 * 0x0001 Enable Quotas: enable quota for this fs
3751 /* we need to fake up a fsp here,
3752 * because its not send in this call
3755 SMB_NTQUOTA_STRUCT quotas;
3758 ZERO_STRUCT(quotas);
3761 fsp.fnum = FNUM_FIELD_INVALID;
3764 if (get_current_uid(conn) != 0) {
3765 DEBUG(0,("get_user_quota: access_denied "
3766 "service [%s] user [%s]\n",
3767 lp_servicename(talloc_tos(), SNUM(conn)),
3768 conn->session_info->unix_info->unix_name));
3769 return NT_STATUS_ACCESS_DENIED;
3772 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3774 if (!NT_STATUS_IS_OK(status)) {
3775 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3781 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3782 lp_servicename(talloc_tos(), SNUM(conn))));
3784 /* Unknown1 24 NULL bytes*/
3785 SBIG_UINT(pdata,0,(uint64_t)0);
3786 SBIG_UINT(pdata,8,(uint64_t)0);
3787 SBIG_UINT(pdata,16,(uint64_t)0);
3789 /* Default Soft Quota 8 bytes */
3790 SBIG_UINT(pdata,24,quotas.softlim);
3792 /* Default Hard Quota 8 bytes */
3793 SBIG_UINT(pdata,32,quotas.hardlim);
3795 /* Quota flag 2 bytes */
3796 SSVAL(pdata,40,quotas.qflags);
3798 /* Unknown3 6 NULL bytes */
3804 #endif /* HAVE_SYS_QUOTAS */
3805 case SMB_FS_OBJECTID_INFORMATION:
3807 unsigned char objid[16];
3808 struct smb_extended_info extended_info;
3809 memcpy(pdata,create_volume_objectid(conn, objid),16);
3810 samba_extended_info_version (&extended_info);
3811 SIVAL(pdata,16,extended_info.samba_magic);
3812 SIVAL(pdata,20,extended_info.samba_version);
3813 SIVAL(pdata,24,extended_info.samba_subversion);
3814 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3815 memcpy(pdata+36,extended_info.samba_version_string,28);
3820 case SMB_FS_SECTOR_SIZE_INFORMATION:
3824 * These values match a physical Windows Server 2012
3825 * share backed by NTFS atop spinning rust.
3827 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3828 /* logical_bytes_per_sector */
3829 SIVAL(pdata, 0, bytes_per_sector);
3830 /* phys_bytes_per_sector_atomic */
3831 SIVAL(pdata, 4, bytes_per_sector);
3832 /* phys_bytes_per_sector_perf */
3833 SIVAL(pdata, 8, bytes_per_sector);
3834 /* fs_effective_phys_bytes_per_sector_atomic */
3835 SIVAL(pdata, 12, bytes_per_sector);
3837 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3838 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3839 /* byte_off_sector_align */
3840 SIVAL(pdata, 20, 0);
3841 /* byte_off_partition_align */
3842 SIVAL(pdata, 24, 0);
3843 *fixed_portion = 28;
3849 * Query the version and capabilities of the CIFS UNIX extensions
3853 case SMB_QUERY_CIFS_UNIX_INFO:
3855 bool large_write = lp_min_receive_file_size() &&
3856 !srv_is_signing_active(xconn);
3857 bool large_read = !srv_is_signing_active(xconn);
3858 int encrypt_caps = 0;
3860 if (!lp_unix_extensions()) {
3861 return NT_STATUS_INVALID_LEVEL;
3864 switch (conn->encrypt_level) {
3865 case SMB_SIGNING_OFF:
3868 case SMB_SIGNING_DESIRED:
3869 case SMB_SIGNING_IF_REQUIRED:
3870 case SMB_SIGNING_DEFAULT:
3871 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3873 case SMB_SIGNING_REQUIRED:
3874 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3875 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3876 large_write = false;
3882 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3883 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3885 /* We have POSIX ACLs, pathname, encryption,
3886 * large read/write, and locking capability. */
3888 SBIG_UINT(pdata,4,((uint64_t)(
3889 CIFS_UNIX_POSIX_ACLS_CAP|
3890 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3891 CIFS_UNIX_FCNTL_LOCKS_CAP|
3892 CIFS_UNIX_EXTATTR_CAP|
3893 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3895 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3897 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3901 case SMB_QUERY_POSIX_FS_INFO:
3904 vfs_statvfs_struct svfs;
3906 if (!lp_unix_extensions()) {
3907 return NT_STATUS_INVALID_LEVEL;
3910 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3914 SIVAL(pdata,0,svfs.OptimalTransferSize);
3915 SIVAL(pdata,4,svfs.BlockSize);
3916 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3917 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3918 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3919 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3920 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3921 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3922 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3924 } else if (rc == EOPNOTSUPP) {
3925 return NT_STATUS_INVALID_LEVEL;
3926 #endif /* EOPNOTSUPP */
3928 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3929 return NT_STATUS_DOS(ERRSRV, ERRerror);
3934 case SMB_QUERY_POSIX_WHOAMI:
3940 if (!lp_unix_extensions()) {
3941 return NT_STATUS_INVALID_LEVEL;
3944 if (max_data_bytes < 40) {
3945 return NT_STATUS_BUFFER_TOO_SMALL;
3948 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3949 flags |= SMB_WHOAMI_GUEST;
3952 /* NOTE: 8 bytes for UID/GID, irrespective of native
3953 * platform size. This matches
3954 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3956 data_len = 4 /* flags */
3963 + 4 /* pad/reserved */
3964 + (conn->session_info->unix_token->ngroups * 8)
3966 + (conn->session_info->security_token->num_sids *
3970 SIVAL(pdata, 0, flags);
3971 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3973 (uint64_t)conn->session_info->unix_token->uid);
3974 SBIG_UINT(pdata, 16,
3975 (uint64_t)conn->session_info->unix_token->gid);
3978 if (data_len >= max_data_bytes) {
3979 /* Potential overflow, skip the GIDs and SIDs. */
3981 SIVAL(pdata, 24, 0); /* num_groups */
3982 SIVAL(pdata, 28, 0); /* num_sids */
3983 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3984 SIVAL(pdata, 36, 0); /* reserved */
3990 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3991 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3993 /* We walk the SID list twice, but this call is fairly
3994 * infrequent, and I don't expect that it's performance
3995 * sensitive -- jpeach
3997 for (i = 0, sid_bytes = 0;
3998 i < conn->session_info->security_token->num_sids; ++i) {
3999 sid_bytes += ndr_size_dom_sid(
4000 &conn->session_info->security_token->sids[i],
4004 /* SID list byte count */
4005 SIVAL(pdata, 32, sid_bytes);
4007 /* 4 bytes pad/reserved - must be zero */
4008 SIVAL(pdata, 36, 0);
4012 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4013 SBIG_UINT(pdata, data_len,
4014 (uint64_t)conn->session_info->unix_token->groups[i]);
4020 i < conn->session_info->security_token->num_sids; ++i) {
4021 int sid_len = ndr_size_dom_sid(
4022 &conn->session_info->security_token->sids[i],
4025 sid_linearize((uint8_t *)(pdata + data_len),
4027 &conn->session_info->security_token->sids[i]);
4028 data_len += sid_len;
4034 case SMB_MAC_QUERY_FS_INFO:
4036 * Thursby MAC extension... ONLY on NTFS filesystems
4037 * once we do streams then we don't need this
4039 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4041 SIVAL(pdata,84,0x100); /* Don't support mac... */
4047 return NT_STATUS_INVALID_LEVEL;
4050 *ret_data_len = data_len;
4054 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4055 struct smb_request *req,
4057 const DATA_BLOB *qdata)
4060 SMB_NTQUOTA_STRUCT quotas;
4062 ZERO_STRUCT(quotas);
4065 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4066 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4067 lp_servicename(talloc_tos(), SNUM(conn)),
4068 conn->session_info->unix_info->unix_name));
4069 return NT_STATUS_ACCESS_DENIED;
4072 if (!check_fsp_ntquota_handle(conn, req,
4074 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4075 return NT_STATUS_INVALID_HANDLE;
4078 /* note: normally there're 48 bytes,
4079 * but we didn't use the last 6 bytes for now
4082 if (qdata->length < 42) {
4083 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4084 (unsigned int)qdata->length));
4085 return NT_STATUS_INVALID_PARAMETER;
4088 /* unknown_1 24 NULL bytes in pdata*/
4090 /* the soft quotas 8 bytes (uint64_t)*/
4091 quotas.softlim = BVAL(qdata->data,24);
4093 /* the hard quotas 8 bytes (uint64_t)*/
4094 quotas.hardlim = BVAL(qdata->data,32);
4096 /* quota_flags 2 bytes **/
4097 quotas.qflags = SVAL(qdata->data,40);
4099 /* unknown_2 6 NULL bytes follow*/
4101 /* now set the quotas */
4102 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4103 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4104 lp_servicename(talloc_tos(), SNUM(conn))));
4105 status = map_nt_error_from_unix(errno);
4107 status = NT_STATUS_OK;
4112 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4113 struct smb_request *req,
4114 TALLOC_CTX *mem_ctx,
4115 uint16_t info_level,
4117 const DATA_BLOB *pdata)
4119 switch (info_level) {
4120 case SMB_FS_QUOTA_INFORMATION:
4122 return smb_set_fsquota(conn,
4131 return NT_STATUS_INVALID_LEVEL;
4134 /****************************************************************************
4135 Reply to a TRANS2_QFSINFO (query filesystem info).
4136 ****************************************************************************/
4138 static void call_trans2qfsinfo(connection_struct *conn,
4139 struct smb_request *req,
4140 char **pparams, int total_params,
4141 char **ppdata, int total_data,
4142 unsigned int max_data_bytes)
4144 char *params = *pparams;
4145 uint16_t info_level;
4147 size_t fixed_portion;
4150 if (total_params < 2) {
4151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4155 info_level = SVAL(params,0);
4157 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4158 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4159 DEBUG(0,("call_trans2qfsinfo: encryption required "
4160 "and info level 0x%x sent.\n",
4161 (unsigned int)info_level));
4162 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4167 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4169 status = smbd_do_qfsinfo(req->xconn, conn, req,
4176 if (!NT_STATUS_IS_OK(status)) {
4177 reply_nterror(req, status);
4181 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4184 DEBUG( 4, ( "%s info_level = %d\n",
4185 smb_fn_name(req->cmd), info_level) );
4190 /****************************************************************************
4191 Reply to a TRANS2_SETFSINFO (set filesystem info).
4192 ****************************************************************************/
4194 static void call_trans2setfsinfo(connection_struct *conn,
4195 struct smb_request *req,
4196 char **pparams, int total_params,
4197 char **ppdata, int total_data,
4198 unsigned int max_data_bytes)
4200 struct smbXsrv_connection *xconn = req->xconn;
4201 char *pdata = *ppdata;
4202 char *params = *pparams;
4203 uint16_t info_level;
4205 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4206 lp_servicename(talloc_tos(), SNUM(conn))));
4209 if (total_params < 4) {
4210 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4216 info_level = SVAL(params,2);
4219 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4220 info_level != SMB_SET_CIFS_UNIX_INFO) {
4221 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4222 "info level (0x%x) on IPC$.\n",
4223 (unsigned int)info_level));
4224 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4229 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4230 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4231 DEBUG(0,("call_trans2setfsinfo: encryption required "
4232 "and info level 0x%x sent.\n",
4233 (unsigned int)info_level));
4234 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4239 switch(info_level) {
4240 case SMB_SET_CIFS_UNIX_INFO:
4241 if (!lp_unix_extensions()) {
4242 DEBUG(2,("call_trans2setfsinfo: "
4243 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4244 "unix extensions off\n"));
4246 NT_STATUS_INVALID_LEVEL);
4250 /* There should be 12 bytes of capabilities set. */
4251 if (total_data < 12) {
4254 NT_STATUS_INVALID_PARAMETER);
4257 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4258 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4259 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4260 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4261 /* Just print these values for now. */
4262 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4263 "major = %u, minor = %u cap_low = 0x%x, "
4265 (unsigned int)xconn->
4266 smb1.unix_info.client_major,
4267 (unsigned int)xconn->
4268 smb1.unix_info.client_minor,
4269 (unsigned int)xconn->
4270 smb1.unix_info.client_cap_low,
4271 (unsigned int)xconn->
4272 smb1.unix_info.client_cap_high));
4274 /* Here is where we must switch to posix pathname processing... */
4275 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4276 lp_set_posix_pathnames();
4277 mangle_change_to_posix();
4280 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4281 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4282 /* Client that knows how to do posix locks,
4283 * but not posix open/mkdir operations. Set a
4284 * default type for read/write checks. */
4286 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4291 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4294 size_t param_len = 0;
4295 size_t data_len = total_data;
4297 if (!lp_unix_extensions()) {
4300 NT_STATUS_INVALID_LEVEL);
4304 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4307 NT_STATUS_NOT_SUPPORTED);
4311 if (xconn->smb1.echo_handler.trusted_fde) {
4312 DEBUG( 2,("call_trans2setfsinfo: "
4313 "request transport encryption disabled"
4314 "with 'fork echo handler = yes'\n"));
4317 NT_STATUS_NOT_SUPPORTED);
4321 DEBUG( 4,("call_trans2setfsinfo: "
4322 "request transport encryption.\n"));
4324 status = srv_request_encryption_setup(conn,
4325 (unsigned char **)ppdata,
4327 (unsigned char **)pparams,
4330 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4331 !NT_STATUS_IS_OK(status)) {
4332 reply_nterror(req, status);
4336 send_trans2_replies(conn, req,
4344 if (NT_STATUS_IS_OK(status)) {
4345 /* Server-side transport
4346 * encryption is now *on*. */
4347 status = srv_encryption_start(conn);
4348 if (!NT_STATUS_IS_OK(status)) {
4349 char *reason = talloc_asprintf(talloc_tos(),
4350 "Failure in setting "
4351 "up encrypted transport: %s",
4353 exit_server_cleanly(reason);
4359 case SMB_FS_QUOTA_INFORMATION:
4363 .data = (uint8_t *)pdata,
4364 .length = total_data
4366 files_struct *fsp = NULL;
4367 fsp = file_fsp(req, SVAL(params,0));
4369 status = smb_set_fsquota(conn,
4373 if (!NT_STATUS_IS_OK(status)) {
4374 reply_nterror(req, status);
4380 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4382 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4388 * sending this reply works fine,
4389 * but I'm not sure it's the same
4390 * like windows do...
4393 reply_outbuf(req, 10, 0);
4396 #if defined(HAVE_POSIX_ACLS)
4397 /****************************************************************************
4398 Utility function to count the number of entries in a POSIX acl.
4399 ****************************************************************************/
4401 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4403 unsigned int ace_count = 0;
4404 int entry_id = SMB_ACL_FIRST_ENTRY;
4405 SMB_ACL_ENTRY_T entry;
4407 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4409 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4410 entry_id = SMB_ACL_NEXT_ENTRY;
4417 /****************************************************************************
4418 Utility function to marshall a POSIX acl into wire format.
4419 ****************************************************************************/
4421 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4423 int entry_id = SMB_ACL_FIRST_ENTRY;
4424 SMB_ACL_ENTRY_T entry;
4426 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4427 SMB_ACL_TAG_T tagtype;
4428 SMB_ACL_PERMSET_T permset;
4429 unsigned char perms = 0;
4430 unsigned int own_grp;
4433 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4434 entry_id = SMB_ACL_NEXT_ENTRY;
4437 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4438 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4442 if (sys_acl_get_permset(entry, &permset) == -1) {
4443 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4447 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4448 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4449 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4451 SCVAL(pdata,1,perms);
4454 case SMB_ACL_USER_OBJ:
4455 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4456 own_grp = (unsigned int)pst->st_ex_uid;
4457 SIVAL(pdata,2,own_grp);
4462 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4464 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4467 own_grp = (unsigned int)*puid;
4468 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4469 SIVAL(pdata,2,own_grp);
4473 case SMB_ACL_GROUP_OBJ:
4474 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4475 own_grp = (unsigned int)pst->st_ex_gid;
4476 SIVAL(pdata,2,own_grp);
4481 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4483 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4486 own_grp = (unsigned int)*pgid;
4487 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4488 SIVAL(pdata,2,own_grp);
4493 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4494 SIVAL(pdata,2,0xFFFFFFFF);
4495 SIVAL(pdata,6,0xFFFFFFFF);
4498 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4499 SIVAL(pdata,2,0xFFFFFFFF);
4500 SIVAL(pdata,6,0xFFFFFFFF);
4503 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4506 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4513 /****************************************************************************
4514 Store the FILE_UNIX_BASIC info.
4515 ****************************************************************************/
4517 static char *store_file_unix_basic(connection_struct *conn,
4520 const SMB_STRUCT_STAT *psbuf)
4522 uint64_t file_index = get_FileIndex(conn, psbuf);
4525 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4526 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4528 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4531 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4534 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4535 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4536 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4539 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4543 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4547 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4550 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4551 devno = psbuf->st_ex_rdev;
4553 devno = psbuf->st_ex_dev;
4556 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4560 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4564 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4567 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4571 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4578 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4579 * the chflags(2) (or equivalent) flags.
4581 * XXX: this really should be behind the VFS interface. To do this, we would
4582 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4583 * Each VFS module could then implement its own mapping as appropriate for the
4584 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4586 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4590 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4594 { UF_IMMUTABLE, EXT_IMMUTABLE },
4598 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4602 { UF_HIDDEN, EXT_HIDDEN },
4605 /* Do not remove. We need to guarantee that this array has at least one
4606 * entry to build on HP-UX.
4612 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4613 uint32_t *smb_fflags, uint32_t *smb_fmask)
4617 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4618 *smb_fmask |= info2_flags_map[i].smb_fflag;
4619 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4620 *smb_fflags |= info2_flags_map[i].smb_fflag;
4625 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4626 const uint32_t smb_fflags,
4627 const uint32_t smb_fmask,
4630 uint32_t max_fmask = 0;
4633 *stat_fflags = psbuf->st_ex_flags;
4635 /* For each flags requested in smb_fmask, check the state of the
4636 * corresponding flag in smb_fflags and set or clear the matching
4640 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4641 max_fmask |= info2_flags_map[i].smb_fflag;
4642 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4643 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4644 *stat_fflags |= info2_flags_map[i].stat_fflag;
4646 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4651 /* If smb_fmask is asking to set any bits that are not supported by
4652 * our flag mappings, we should fail.
4654 if ((smb_fmask & max_fmask) != smb_fmask) {
4662 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4663 * of file flags and birth (create) time.
4665 static char *store_file_unix_basic_info2(connection_struct *conn,
4668 const SMB_STRUCT_STAT *psbuf)
4670 uint32_t file_flags = 0;
4671 uint32_t flags_mask = 0;
4673 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4675 /* Create (birth) time 64 bit */
4676 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4679 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4680 SIVAL(pdata, 0, file_flags); /* flags */
4681 SIVAL(pdata, 4, flags_mask); /* mask */
4687 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4688 const struct stream_struct *streams,
4690 unsigned int max_data_bytes,
4691 unsigned int *data_size)
4694 unsigned int ofs = 0;
4696 if (max_data_bytes < 32) {
4697 return NT_STATUS_INFO_LENGTH_MISMATCH;
4700 for (i = 0; i < num_streams; i++) {
4701 unsigned int next_offset;
4703 smb_ucs2_t *namebuf;
4705 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4706 streams[i].name, &namelen) ||
4709 return NT_STATUS_INVALID_PARAMETER;
4713 * name_buf is now null-terminated, we need to marshall as not
4720 * We cannot overflow ...
4722 if ((ofs + 24 + namelen) > max_data_bytes) {
4723 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4725 TALLOC_FREE(namebuf);
4726 return STATUS_BUFFER_OVERFLOW;
4729 SIVAL(data, ofs+4, namelen);
4730 SOFF_T(data, ofs+8, streams[i].size);
4731 SOFF_T(data, ofs+16, streams[i].alloc_size);
4732 memcpy(data+ofs+24, namebuf, namelen);
4733 TALLOC_FREE(namebuf);
4735 next_offset = ofs + 24 + namelen;
4737 if (i == num_streams-1) {
4738 SIVAL(data, ofs, 0);
4741 unsigned int align = ndr_align_size(next_offset, 8);
4743 if ((next_offset + align) > max_data_bytes) {
4744 DEBUG(10, ("refusing to overflow align "
4745 "reply at stream %u\n",
4747 TALLOC_FREE(namebuf);
4748 return STATUS_BUFFER_OVERFLOW;
4751 memset(data+next_offset, 0, align);
4752 next_offset += align;
4754 SIVAL(data, ofs, next_offset - ofs);
4761 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4765 return NT_STATUS_OK;
4768 /****************************************************************************
4769 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4770 ****************************************************************************/
4772 static void call_trans2qpipeinfo(connection_struct *conn,
4773 struct smb_request *req,
4774 unsigned int tran_call,
4775 char **pparams, int total_params,
4776 char **ppdata, int total_data,
4777 unsigned int max_data_bytes)
4779 char *params = *pparams;
4780 char *pdata = *ppdata;
4781 unsigned int data_size = 0;
4782 unsigned int param_size = 2;
4783 uint16_t info_level;
4787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4791 if (total_params < 4) {
4792 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4796 fsp = file_fsp(req, SVAL(params,0));
4797 if (!fsp_is_np(fsp)) {
4798 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4802 info_level = SVAL(params,2);
4804 *pparams = (char *)SMB_REALLOC(*pparams,2);
4805 if (*pparams == NULL) {
4806 reply_nterror(req, NT_STATUS_NO_MEMORY);
4811 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4815 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4816 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4817 if (*ppdata == NULL ) {
4818 reply_nterror(req, NT_STATUS_NO_MEMORY);
4823 switch (info_level) {
4824 case SMB_FILE_STANDARD_INFORMATION:
4826 SOFF_T(pdata,0,4096LL);
4833 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4837 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4843 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4844 TALLOC_CTX *mem_ctx,
4845 uint16_t info_level,
4847 struct smb_filename *smb_fname,
4848 bool delete_pending,
4849 struct timespec write_time_ts,
4850 struct ea_list *ea_list,
4851 int lock_data_count,
4854 unsigned int max_data_bytes,
4855 size_t *fixed_portion,
4857 unsigned int *pdata_size)
4859 char *pdata = *ppdata;
4860 char *dstart, *dend;
4861 unsigned int data_size;
4862 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4863 time_t create_time, mtime, atime, c_time;
4864 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4871 uint64_t file_size = 0;
4873 uint64_t allocation_size = 0;
4874 uint64_t file_index = 0;
4875 uint32_t access_mask = 0;
4878 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4879 return NT_STATUS_INVALID_LEVEL;
4882 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4883 smb_fname_str_dbg(smb_fname),
4885 info_level, max_data_bytes));
4887 mode = dos_mode(conn, smb_fname);
4888 nlink = psbuf->st_ex_nlink;
4890 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4894 if ((nlink > 0) && delete_pending) {
4898 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4899 return NT_STATUS_INVALID_PARAMETER;
4902 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4903 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4904 if (*ppdata == NULL) {
4905 return NT_STATUS_NO_MEMORY;
4909 dend = dstart + data_size - 1;
4911 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4912 update_stat_ex_mtime(psbuf, write_time_ts);
4915 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4916 mtime_ts = psbuf->st_ex_mtime;
4917 atime_ts = psbuf->st_ex_atime;
4918 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4920 if (lp_dos_filetime_resolution(SNUM(conn))) {
4921 dos_filetime_timespec(&create_time_ts);
4922 dos_filetime_timespec(&mtime_ts);
4923 dos_filetime_timespec(&atime_ts);
4924 dos_filetime_timespec(&ctime_ts);
4927 create_time = convert_timespec_to_time_t(create_time_ts);
4928 mtime = convert_timespec_to_time_t(mtime_ts);
4929 atime = convert_timespec_to_time_t(atime_ts);
4930 c_time = convert_timespec_to_time_t(ctime_ts);
4932 p = strrchr_m(smb_fname->base_name,'/');
4934 base_name = smb_fname->base_name;
4938 /* NT expects the name to be in an exact form of the *full*
4939 filename. See the trans2 torture test */
4940 if (ISDOT(base_name)) {
4941 dos_fname = talloc_strdup(mem_ctx, "\\");
4943 return NT_STATUS_NO_MEMORY;
4946 dos_fname = talloc_asprintf(mem_ctx,
4948 smb_fname->base_name);
4950 return NT_STATUS_NO_MEMORY;
4952 if (is_ntfs_stream_smb_fname(smb_fname)) {
4953 dos_fname = talloc_asprintf(dos_fname, "%s",
4954 smb_fname->stream_name);
4956 return NT_STATUS_NO_MEMORY;
4960 string_replace(dos_fname, '/', '\\');
4963 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4966 /* Do we have this path open ? */
4968 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4969 fsp1 = file_find_di_first(conn->sconn, fileid);
4970 if (fsp1 && fsp1->initial_allocation_size) {
4971 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4975 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4976 file_size = get_file_size_stat(psbuf);
4980 pos = fsp->fh->position_information;
4984 access_mask = fsp->access_mask;
4986 /* GENERIC_EXECUTE mapping from Windows */
4987 access_mask = 0x12019F;
4990 /* This should be an index number - looks like
4993 I think this causes us to fail the IFSKIT
4994 BasicFileInformationTest. -tpot */
4995 file_index = get_FileIndex(conn, psbuf);
4999 switch (info_level) {
5000 case SMB_INFO_STANDARD:
5001 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5003 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5004 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5005 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5006 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5007 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5008 SSVAL(pdata,l1_attrFile,mode);
5011 case SMB_INFO_QUERY_EA_SIZE:
5013 unsigned int ea_size =
5014 estimate_ea_size(conn, fsp,
5016 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5018 srv_put_dos_date2(pdata,0,create_time);
5019 srv_put_dos_date2(pdata,4,atime);
5020 srv_put_dos_date2(pdata,8,mtime); /* write time */
5021 SIVAL(pdata,12,(uint32_t)file_size);
5022 SIVAL(pdata,16,(uint32_t)allocation_size);
5023 SSVAL(pdata,20,mode);
5024 SIVAL(pdata,22,ea_size);
5028 case SMB_INFO_IS_NAME_VALID:
5029 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5031 /* os/2 needs this ? really ?*/
5032 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5034 /* This is only reached for qpathinfo */
5038 case SMB_INFO_QUERY_EAS_FROM_LIST:
5040 size_t total_ea_len = 0;
5041 struct ea_list *ea_file_list = NULL;
5042 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5045 get_ea_list_from_file(mem_ctx, conn, fsp,
5047 &total_ea_len, &ea_file_list);
5048 if (!NT_STATUS_IS_OK(status)) {
5052 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5054 if (!ea_list || (total_ea_len > data_size)) {
5056 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5060 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5064 case SMB_INFO_QUERY_ALL_EAS:
5066 /* We have data_size bytes to put EA's into. */
5067 size_t total_ea_len = 0;
5068 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5070 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5072 &total_ea_len, &ea_list);
5073 if (!NT_STATUS_IS_OK(status)) {
5077 if (!ea_list || (total_ea_len > data_size)) {
5079 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5083 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5087 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5089 /* This is FileFullEaInformation - 0xF which maps to
5090 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5092 /* We have data_size bytes to put EA's into. */
5093 size_t total_ea_len = 0;
5094 struct ea_list *ea_file_list = NULL;
5096 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5098 /*TODO: add filtering and index handling */
5101 get_ea_list_from_file(mem_ctx, conn, fsp,
5103 &total_ea_len, &ea_file_list);
5104 if (!NT_STATUS_IS_OK(status)) {
5107 if (!ea_file_list) {
5108 return NT_STATUS_NO_EAS_ON_FILE;
5111 status = fill_ea_chained_buffer(mem_ctx,
5115 conn, ea_file_list);
5116 if (!NT_STATUS_IS_OK(status)) {
5122 case SMB_FILE_BASIC_INFORMATION:
5123 case SMB_QUERY_FILE_BASIC_INFO:
5125 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5126 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5127 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5129 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5133 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5134 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5135 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5136 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5137 SIVAL(pdata,32,mode);
5139 DEBUG(5,("SMB_QFBI - "));
5140 DEBUG(5,("create: %s ", ctime(&create_time)));
5141 DEBUG(5,("access: %s ", ctime(&atime)));
5142 DEBUG(5,("write: %s ", ctime(&mtime)));
5143 DEBUG(5,("change: %s ", ctime(&c_time)));
5144 DEBUG(5,("mode: %x\n", mode));
5145 *fixed_portion = data_size;
5148 case SMB_FILE_STANDARD_INFORMATION:
5149 case SMB_QUERY_FILE_STANDARD_INFO:
5151 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5153 SOFF_T(pdata,0,allocation_size);
5154 SOFF_T(pdata,8,file_size);
5155 SIVAL(pdata,16,nlink);
5156 SCVAL(pdata,20,delete_pending?1:0);
5157 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5158 SSVAL(pdata,22,0); /* Padding. */
5159 *fixed_portion = 24;
5162 case SMB_FILE_EA_INFORMATION:
5163 case SMB_QUERY_FILE_EA_INFO:
5165 unsigned int ea_size =
5166 estimate_ea_size(conn, fsp, smb_fname);
5167 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5170 SIVAL(pdata,0,ea_size);
5174 /* Get the 8.3 name - used if NT SMB was negotiated. */
5175 case SMB_QUERY_FILE_ALT_NAME_INFO:
5176 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5178 char mangled_name[13];
5179 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5180 if (!name_to_8_3(base_name,mangled_name,
5181 True,conn->params)) {
5182 return NT_STATUS_NO_MEMORY;
5184 status = srvstr_push(dstart, flags2,
5185 pdata+4, mangled_name,
5186 PTR_DIFF(dend, pdata+4),
5188 if (!NT_STATUS_IS_OK(status)) {
5191 data_size = 4 + len;
5197 case SMB_QUERY_FILE_NAME_INFO:
5200 this must be *exactly* right for ACLs on mapped drives to work
5202 status = srvstr_push(dstart, flags2,
5204 PTR_DIFF(dend, pdata+4),
5206 if (!NT_STATUS_IS_OK(status)) {
5209 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5210 data_size = 4 + len;
5215 case SMB_FILE_ALLOCATION_INFORMATION:
5216 case SMB_QUERY_FILE_ALLOCATION_INFO:
5217 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5219 SOFF_T(pdata,0,allocation_size);
5222 case SMB_FILE_END_OF_FILE_INFORMATION:
5223 case SMB_QUERY_FILE_END_OF_FILEINFO:
5224 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5226 SOFF_T(pdata,0,file_size);
5229 case SMB_QUERY_FILE_ALL_INFO:
5230 case SMB_FILE_ALL_INFORMATION:
5232 unsigned int ea_size =
5233 estimate_ea_size(conn, fsp, smb_fname);
5234 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5235 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5236 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5237 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5238 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5239 SIVAL(pdata,32,mode);
5240 SIVAL(pdata,36,0); /* padding. */
5242 SOFF_T(pdata,0,allocation_size);
5243 SOFF_T(pdata,8,file_size);
5244 SIVAL(pdata,16,nlink);
5245 SCVAL(pdata,20,delete_pending);
5246 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5249 SIVAL(pdata,0,ea_size);
5250 pdata += 4; /* EA info */
5251 status = srvstr_push(dstart, flags2,
5253 PTR_DIFF(dend, pdata+4),
5255 if (!NT_STATUS_IS_OK(status)) {
5260 data_size = PTR_DIFF(pdata,(*ppdata));
5261 *fixed_portion = 10;
5265 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5267 unsigned int ea_size =
5268 estimate_ea_size(conn, fsp, smb_fname);
5269 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5270 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5271 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5272 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5273 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5274 SIVAL(pdata, 0x20, mode);
5275 SIVAL(pdata, 0x24, 0); /* padding. */
5276 SBVAL(pdata, 0x28, allocation_size);
5277 SBVAL(pdata, 0x30, file_size);
5278 SIVAL(pdata, 0x38, nlink);
5279 SCVAL(pdata, 0x3C, delete_pending);
5280 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5281 SSVAL(pdata, 0x3E, 0); /* padding */
5282 SBVAL(pdata, 0x40, file_index);
5283 SIVAL(pdata, 0x48, ea_size);
5284 SIVAL(pdata, 0x4C, access_mask);
5285 SBVAL(pdata, 0x50, pos);
5286 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5287 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5291 status = srvstr_push(dstart, flags2,
5293 PTR_DIFF(dend, pdata+4),
5295 if (!NT_STATUS_IS_OK(status)) {
5300 data_size = PTR_DIFF(pdata,(*ppdata));
5301 *fixed_portion = 104;
5304 case SMB_FILE_INTERNAL_INFORMATION:
5306 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5307 SBVAL(pdata, 0, file_index);
5312 case SMB_FILE_ACCESS_INFORMATION:
5313 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5314 SIVAL(pdata, 0, access_mask);
5319 case SMB_FILE_NAME_INFORMATION:
5320 /* Pathname with leading '\'. */
5323 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5324 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5325 SIVAL(pdata,0,byte_len);
5326 data_size = 4 + byte_len;
5330 case SMB_FILE_DISPOSITION_INFORMATION:
5331 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5333 SCVAL(pdata,0,delete_pending);
5337 case SMB_FILE_POSITION_INFORMATION:
5338 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5340 SOFF_T(pdata,0,pos);
5344 case SMB_FILE_MODE_INFORMATION:
5345 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5346 SIVAL(pdata,0,mode);
5351 case SMB_FILE_ALIGNMENT_INFORMATION:
5352 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5353 SIVAL(pdata,0,0); /* No alignment needed. */
5359 * NT4 server just returns "invalid query" to this - if we try
5360 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5363 /* The first statement above is false - verified using Thursby
5364 * client against NT4 -- gcolley.
5366 case SMB_QUERY_FILE_STREAM_INFO:
5367 case SMB_FILE_STREAM_INFORMATION: {
5368 unsigned int num_streams = 0;
5369 struct stream_struct *streams = NULL;
5371 DEBUG(10,("smbd_do_qfilepathinfo: "
5372 "SMB_FILE_STREAM_INFORMATION\n"));
5374 if (is_ntfs_stream_smb_fname(smb_fname)) {
5375 return NT_STATUS_INVALID_PARAMETER;
5378 status = vfs_streaminfo(conn,
5385 if (!NT_STATUS_IS_OK(status)) {
5386 DEBUG(10, ("could not get stream info: %s\n",
5387 nt_errstr(status)));
5391 status = marshall_stream_info(num_streams, streams,
5392 pdata, max_data_bytes,
5395 if (!NT_STATUS_IS_OK(status)) {
5396 DEBUG(10, ("marshall_stream_info failed: %s\n",
5397 nt_errstr(status)));
5398 TALLOC_FREE(streams);
5402 TALLOC_FREE(streams);
5404 *fixed_portion = 32;
5408 case SMB_QUERY_COMPRESSION_INFO:
5409 case SMB_FILE_COMPRESSION_INFORMATION:
5410 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5411 SOFF_T(pdata,0,file_size);
5412 SIVAL(pdata,8,0); /* ??? */
5413 SIVAL(pdata,12,0); /* ??? */
5415 *fixed_portion = 16;
5418 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5419 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5420 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5421 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5422 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5423 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5424 SOFF_T(pdata,32,allocation_size);
5425 SOFF_T(pdata,40,file_size);
5426 SIVAL(pdata,48,mode);
5427 SIVAL(pdata,52,0); /* ??? */
5429 *fixed_portion = 56;
5432 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5433 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5434 SIVAL(pdata,0,mode);
5441 * CIFS UNIX Extensions.
5444 case SMB_QUERY_FILE_UNIX_BASIC:
5446 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5447 data_size = PTR_DIFF(pdata,(*ppdata));
5449 DEBUG(4,("smbd_do_qfilepathinfo: "
5450 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5451 dump_data(4, (uint8_t *)(*ppdata), data_size);
5455 case SMB_QUERY_FILE_UNIX_INFO2:
5457 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5458 data_size = PTR_DIFF(pdata,(*ppdata));
5462 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5464 for (i=0; i<100; i++)
5465 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5471 case SMB_QUERY_FILE_UNIX_LINK:
5474 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5477 return NT_STATUS_NO_MEMORY;
5480 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5482 if(!S_ISLNK(psbuf->st_ex_mode)) {
5483 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5486 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5488 link_len = SMB_VFS_READLINK(conn,
5491 if (link_len == -1) {
5492 return map_nt_error_from_unix(errno);
5494 buffer[link_len] = 0;
5495 status = srvstr_push(dstart, flags2,
5497 PTR_DIFF(dend, pdata),
5498 STR_TERMINATE, &len);
5499 if (!NT_STATUS_IS_OK(status)) {
5503 data_size = PTR_DIFF(pdata,(*ppdata));
5508 #if defined(HAVE_POSIX_ACLS)
5509 case SMB_QUERY_POSIX_ACL:
5511 SMB_ACL_T file_acl = NULL;
5512 SMB_ACL_T def_acl = NULL;
5513 uint16_t num_file_acls = 0;
5514 uint16_t num_def_acls = 0;
5516 status = refuse_symlink(conn,
5519 if (!NT_STATUS_IS_OK(status)) {
5523 if (fsp && fsp->fh->fd != -1) {
5524 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5528 SMB_VFS_SYS_ACL_GET_FILE(conn,
5530 SMB_ACL_TYPE_ACCESS,
5534 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5535 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5536 "not implemented on "
5537 "filesystem containing %s\n",
5538 smb_fname->base_name));
5539 return NT_STATUS_NOT_IMPLEMENTED;
5542 if (S_ISDIR(psbuf->st_ex_mode)) {
5543 if (fsp && fsp->is_directory) {
5545 SMB_VFS_SYS_ACL_GET_FILE(
5548 SMB_ACL_TYPE_DEFAULT,
5552 SMB_VFS_SYS_ACL_GET_FILE(
5555 SMB_ACL_TYPE_DEFAULT,
5558 def_acl = free_empty_sys_acl(conn, def_acl);
5561 num_file_acls = count_acl_entries(conn, file_acl);
5562 num_def_acls = count_acl_entries(conn, def_acl);
5564 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5565 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5567 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5568 SMB_POSIX_ACL_HEADER_SIZE) ));
5570 TALLOC_FREE(file_acl);
5573 TALLOC_FREE(def_acl);
5575 return NT_STATUS_BUFFER_TOO_SMALL;
5578 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5579 SSVAL(pdata,2,num_file_acls);
5580 SSVAL(pdata,4,num_def_acls);
5581 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5583 TALLOC_FREE(file_acl);
5586 TALLOC_FREE(def_acl);
5588 return NT_STATUS_INTERNAL_ERROR;
5590 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5592 TALLOC_FREE(file_acl);
5595 TALLOC_FREE(def_acl);
5597 return NT_STATUS_INTERNAL_ERROR;
5601 TALLOC_FREE(file_acl);
5604 TALLOC_FREE(def_acl);
5606 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5612 case SMB_QUERY_POSIX_LOCK:
5617 enum brl_type lock_type;
5619 /* We need an open file with a real fd for this. */
5620 if (!fsp || fsp->fh->fd == -1) {
5621 return NT_STATUS_INVALID_LEVEL;
5624 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5625 return NT_STATUS_INVALID_PARAMETER;
5628 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5629 case POSIX_LOCK_TYPE_READ:
5630 lock_type = READ_LOCK;
5632 case POSIX_LOCK_TYPE_WRITE:
5633 lock_type = WRITE_LOCK;
5635 case POSIX_LOCK_TYPE_UNLOCK:
5637 /* There's no point in asking for an unlock... */
5638 return NT_STATUS_INVALID_PARAMETER;
5641 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5642 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5643 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5645 status = query_lock(fsp,
5652 if (ERROR_WAS_LOCK_DENIED(status)) {
5653 /* Here we need to report who has it locked... */
5654 data_size = POSIX_LOCK_DATA_SIZE;
5656 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5657 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5658 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5659 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5660 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5662 } else if (NT_STATUS_IS_OK(status)) {
5663 /* For success we just return a copy of what we sent
5664 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5665 data_size = POSIX_LOCK_DATA_SIZE;
5666 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5667 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5675 return NT_STATUS_INVALID_LEVEL;
5678 *pdata_size = data_size;
5679 return NT_STATUS_OK;
5682 /****************************************************************************
5683 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5684 file name or file id).
5685 ****************************************************************************/
5687 static void call_trans2qfilepathinfo(connection_struct *conn,
5688 struct smb_request *req,
5689 unsigned int tran_call,
5690 char **pparams, int total_params,
5691 char **ppdata, int total_data,
5692 unsigned int max_data_bytes)
5694 char *params = *pparams;
5695 char *pdata = *ppdata;
5696 uint16_t info_level;
5697 unsigned int data_size = 0;
5698 unsigned int param_size = 2;
5699 struct smb_filename *smb_fname = NULL;
5700 bool delete_pending = False;
5701 struct timespec write_time_ts;
5702 files_struct *fsp = NULL;
5703 struct file_id fileid;
5704 struct ea_list *ea_list = NULL;
5705 int lock_data_count = 0;
5706 char *lock_data = NULL;
5707 size_t fixed_portion;
5708 NTSTATUS status = NT_STATUS_OK;
5711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5715 ZERO_STRUCT(write_time_ts);
5717 if (tran_call == TRANSACT2_QFILEINFO) {
5718 if (total_params < 4) {
5719 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5724 call_trans2qpipeinfo(conn, req, tran_call,
5725 pparams, total_params,
5731 fsp = file_fsp(req, SVAL(params,0));
5732 info_level = SVAL(params,2);
5734 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5736 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5737 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5741 /* Initial check for valid fsp ptr. */
5742 if (!check_fsp_open(conn, req, fsp)) {
5746 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5747 if (smb_fname == NULL) {
5748 reply_nterror(req, NT_STATUS_NO_MEMORY);
5752 if(fsp->fake_file_handle) {
5754 * This is actually for the QUOTA_FAKE_FILE --metze
5757 /* We know this name is ok, it's already passed the checks. */
5759 } else if(fsp->fh->fd == -1) {
5761 * This is actually a QFILEINFO on a directory
5762 * handle (returned from an NT SMB). NT5.0 seems
5763 * to do this call. JRA.
5766 if (INFO_LEVEL_IS_UNIX(info_level)) {
5767 /* Always do lstat for UNIX calls. */
5768 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5769 DEBUG(3,("call_trans2qfilepathinfo: "
5770 "SMB_VFS_LSTAT of %s failed "
5772 smb_fname_str_dbg(smb_fname),
5775 map_nt_error_from_unix(errno));
5778 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5779 DEBUG(3,("call_trans2qfilepathinfo: "
5780 "SMB_VFS_STAT of %s failed (%s)\n",
5781 smb_fname_str_dbg(smb_fname),
5784 map_nt_error_from_unix(errno));
5788 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5789 fileid = vfs_file_id_from_sbuf(
5790 conn, &smb_fname->st);
5791 get_file_infos(fileid, fsp->name_hash,
5797 * Original code - this is an open file.
5799 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5800 DEBUG(3, ("fstat of %s failed (%s)\n",
5801 fsp_fnum_dbg(fsp), strerror(errno)));
5803 map_nt_error_from_unix(errno));
5806 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5807 fileid = vfs_file_id_from_sbuf(
5808 conn, &smb_fname->st);
5809 get_file_infos(fileid, fsp->name_hash,
5818 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5821 if (total_params < 7) {
5822 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5826 info_level = SVAL(params,0);
5828 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5830 if (INFO_LEVEL_IS_UNIX(info_level)) {
5831 if (!lp_unix_extensions()) {
5832 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5835 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5836 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5837 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5838 req->posix_pathnames) {
5839 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5843 if (req->posix_pathnames) {
5844 srvstr_get_path_posix(req,
5853 srvstr_get_path(req,
5862 if (!NT_STATUS_IS_OK(status)) {
5863 reply_nterror(req, status);
5867 status = filename_convert(req,
5874 if (!NT_STATUS_IS_OK(status)) {
5875 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5876 reply_botherror(req,
5877 NT_STATUS_PATH_NOT_COVERED,
5878 ERRSRV, ERRbadpath);
5881 reply_nterror(req, status);
5885 /* If this is a stream, check if there is a delete_pending. */
5886 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5887 && is_ntfs_stream_smb_fname(smb_fname)) {
5888 struct smb_filename *smb_fname_base;
5890 /* Create an smb_filename with stream_name == NULL. */
5891 smb_fname_base = synthetic_smb_fname(
5893 smb_fname->base_name,
5897 if (smb_fname_base == NULL) {
5898 reply_nterror(req, NT_STATUS_NO_MEMORY);
5902 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5903 /* Always do lstat for UNIX calls. */
5904 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5905 DEBUG(3,("call_trans2qfilepathinfo: "
5906 "SMB_VFS_LSTAT of %s failed "
5908 smb_fname_str_dbg(smb_fname_base),
5910 TALLOC_FREE(smb_fname_base);
5912 map_nt_error_from_unix(errno));
5916 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5917 DEBUG(3,("call_trans2qfilepathinfo: "
5918 "fileinfo of %s failed "
5920 smb_fname_str_dbg(smb_fname_base),
5922 TALLOC_FREE(smb_fname_base);
5924 map_nt_error_from_unix(errno));
5929 status = file_name_hash(conn,
5930 smb_fname_str_dbg(smb_fname_base),
5932 if (!NT_STATUS_IS_OK(status)) {
5933 TALLOC_FREE(smb_fname_base);
5934 reply_nterror(req, status);
5938 fileid = vfs_file_id_from_sbuf(conn,
5939 &smb_fname_base->st);
5940 TALLOC_FREE(smb_fname_base);
5941 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5942 if (delete_pending) {
5943 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5948 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5949 /* Always do lstat for UNIX calls. */
5950 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5951 DEBUG(3,("call_trans2qfilepathinfo: "
5952 "SMB_VFS_LSTAT of %s failed (%s)\n",
5953 smb_fname_str_dbg(smb_fname),
5956 map_nt_error_from_unix(errno));
5961 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5962 DEBUG(3,("call_trans2qfilepathinfo: "
5963 "SMB_VFS_STAT of %s failed (%s)\n",
5964 smb_fname_str_dbg(smb_fname),
5967 map_nt_error_from_unix(errno));
5972 status = file_name_hash(conn,
5973 smb_fname_str_dbg(smb_fname),
5975 if (!NT_STATUS_IS_OK(status)) {
5976 reply_nterror(req, status);
5980 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5981 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5982 get_file_infos(fileid, name_hash, &delete_pending,
5986 if (delete_pending) {
5987 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5992 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5993 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5995 info_level,tran_call,total_data));
5997 /* Pull out any data sent here before we realloc. */
5998 switch (info_level) {
5999 case SMB_INFO_QUERY_EAS_FROM_LIST:
6001 /* Pull any EA list from the data portion. */
6004 if (total_data < 4) {
6006 req, NT_STATUS_INVALID_PARAMETER);
6009 ea_size = IVAL(pdata,0);
6011 if (total_data > 0 && ea_size != total_data) {
6012 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6013 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6015 req, NT_STATUS_INVALID_PARAMETER);
6019 if (!lp_ea_support(SNUM(conn))) {
6020 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6024 /* Pull out the list of names. */
6025 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6028 req, NT_STATUS_INVALID_PARAMETER);
6034 case SMB_QUERY_POSIX_LOCK:
6036 if (fsp == NULL || fsp->fh->fd == -1) {
6037 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6041 if (total_data != POSIX_LOCK_DATA_SIZE) {
6043 req, NT_STATUS_INVALID_PARAMETER);
6047 /* Copy the lock range data. */
6048 lock_data = (char *)talloc_memdup(
6049 req, pdata, total_data);
6051 reply_nterror(req, NT_STATUS_NO_MEMORY);
6054 lock_data_count = total_data;
6060 *pparams = (char *)SMB_REALLOC(*pparams,2);
6061 if (*pparams == NULL) {
6062 reply_nterror(req, NT_STATUS_NO_MEMORY);
6069 * draft-leach-cifs-v1-spec-02.txt
6070 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6073 * The requested information is placed in the Data portion of the
6074 * transaction response. For the information levels greater than 0x100,
6075 * the transaction response has 1 parameter word which should be
6076 * ignored by the client.
6078 * However Windows only follows this rule for the IS_NAME_VALID call.
6080 switch (info_level) {
6081 case SMB_INFO_IS_NAME_VALID:
6086 if ((info_level & 0xFF00) == 0xFF00) {
6088 * We use levels that start with 0xFF00
6089 * internally to represent SMB2 specific levels
6091 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6095 status = smbd_do_qfilepathinfo(conn, req, info_level,
6097 delete_pending, write_time_ts,
6099 lock_data_count, lock_data,
6100 req->flags2, max_data_bytes,
6102 ppdata, &data_size);
6103 if (!NT_STATUS_IS_OK(status)) {
6104 reply_nterror(req, status);
6107 if (fixed_portion > max_data_bytes) {
6108 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6112 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6118 /****************************************************************************
6119 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6121 ****************************************************************************/
6123 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6124 connection_struct *conn,
6125 struct smb_request *req,
6126 bool overwrite_if_exists,
6127 const struct smb_filename *smb_fname_old,
6128 struct smb_filename *smb_fname_new)
6130 NTSTATUS status = NT_STATUS_OK;
6132 /* source must already exist. */
6133 if (!VALID_STAT(smb_fname_old->st)) {
6134 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6137 if (VALID_STAT(smb_fname_new->st)) {
6138 if (overwrite_if_exists) {
6139 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6140 return NT_STATUS_FILE_IS_A_DIRECTORY;
6142 status = unlink_internals(conn,
6144 FILE_ATTRIBUTE_NORMAL,
6147 if (!NT_STATUS_IS_OK(status)) {
6151 /* Disallow if newname already exists. */
6152 return NT_STATUS_OBJECT_NAME_COLLISION;
6156 /* No links from a directory. */
6157 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6158 return NT_STATUS_FILE_IS_A_DIRECTORY;
6161 /* Setting a hardlink to/from a stream isn't currently supported. */
6162 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6163 is_ntfs_stream_smb_fname(smb_fname_new)) {
6164 return NT_STATUS_INVALID_PARAMETER;
6167 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6168 smb_fname_old->base_name, smb_fname_new->base_name));
6170 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6171 status = map_nt_error_from_unix(errno);
6172 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6173 nt_errstr(status), smb_fname_old->base_name,
6174 smb_fname_new->base_name));
6179 /****************************************************************************
6180 Deal with setting the time from any of the setfilepathinfo functions.
6181 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6182 calling this function.
6183 ****************************************************************************/
6185 NTSTATUS smb_set_file_time(connection_struct *conn,
6187 const struct smb_filename *smb_fname,
6188 struct smb_file_time *ft,
6189 bool setting_write_time)
6191 struct smb_filename smb_fname_base;
6193 FILE_NOTIFY_CHANGE_LAST_ACCESS
6194 |FILE_NOTIFY_CHANGE_LAST_WRITE
6195 |FILE_NOTIFY_CHANGE_CREATION;
6197 if (!VALID_STAT(smb_fname->st)) {
6198 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6201 /* get some defaults (no modifications) if any info is zero or -1. */
6202 if (null_timespec(ft->create_time)) {
6203 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6206 if (null_timespec(ft->atime)) {
6207 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6210 if (null_timespec(ft->mtime)) {
6211 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6214 if (!setting_write_time) {
6215 /* ft->mtime comes from change time, not write time. */
6216 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6219 /* Ensure the resolution is the correct for
6220 * what we can store on this filesystem. */
6222 round_timespec(conn->ts_res, &ft->create_time);
6223 round_timespec(conn->ts_res, &ft->ctime);
6224 round_timespec(conn->ts_res, &ft->atime);
6225 round_timespec(conn->ts_res, &ft->mtime);
6227 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6228 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6229 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6230 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6231 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6232 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6233 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6234 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6236 if (setting_write_time) {
6238 * This was a Windows setfileinfo on an open file.
6239 * NT does this a lot. We also need to
6240 * set the time here, as it can be read by
6241 * FindFirst/FindNext and with the patch for bug #2045
6242 * in smbd/fileio.c it ensures that this timestamp is
6243 * kept sticky even after a write. We save the request
6244 * away and will set it on file close and after a write. JRA.
6247 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6248 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6251 if (fsp->base_fsp) {
6252 set_sticky_write_time_fsp(fsp->base_fsp,
6255 set_sticky_write_time_fsp(fsp, ft->mtime);
6258 set_sticky_write_time_path(
6259 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6264 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6266 /* Always call ntimes on the base, even if a stream was passed in. */
6267 smb_fname_base = *smb_fname;
6268 smb_fname_base.stream_name = NULL;
6270 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6271 return map_nt_error_from_unix(errno);
6274 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6275 smb_fname->base_name);
6276 return NT_STATUS_OK;
6279 /****************************************************************************
6280 Deal with setting the dosmode from any of the setfilepathinfo functions.
6281 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6282 done before calling this function.
6283 ****************************************************************************/
6285 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6286 const struct smb_filename *smb_fname,
6289 struct smb_filename *smb_fname_base;
6292 if (!VALID_STAT(smb_fname->st)) {
6293 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6296 /* Always operate on the base_name, even if a stream was passed in. */
6297 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6298 smb_fname->base_name,
6302 if (smb_fname_base == NULL) {
6303 return NT_STATUS_NO_MEMORY;
6307 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6308 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6310 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6314 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6316 /* check the mode isn't different, before changing it */
6317 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6318 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6319 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6320 (unsigned int)dosmode));
6322 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6324 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6326 smb_fname_str_dbg(smb_fname_base),
6328 status = map_nt_error_from_unix(errno);
6332 status = NT_STATUS_OK;
6334 TALLOC_FREE(smb_fname_base);
6338 /****************************************************************************
6339 Deal with setting the size from any of the setfilepathinfo functions.
6340 ****************************************************************************/
6342 static NTSTATUS smb_set_file_size(connection_struct *conn,
6343 struct smb_request *req,
6345 const struct smb_filename *smb_fname,
6346 const SMB_STRUCT_STAT *psbuf,
6348 bool fail_after_createfile)
6350 NTSTATUS status = NT_STATUS_OK;
6351 struct smb_filename *smb_fname_tmp = NULL;
6352 files_struct *new_fsp = NULL;
6354 if (!VALID_STAT(*psbuf)) {
6355 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6358 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6360 get_file_size_stat(psbuf));
6362 if (size == get_file_size_stat(psbuf)) {
6363 return NT_STATUS_OK;
6366 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6367 smb_fname_str_dbg(smb_fname), (double)size));
6369 if (fsp && fsp->fh->fd != -1) {
6370 /* Handle based call. */
6371 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6372 return NT_STATUS_ACCESS_DENIED;
6375 if (vfs_set_filelen(fsp, size) == -1) {
6376 return map_nt_error_from_unix(errno);
6378 trigger_write_time_update_immediate(fsp);
6379 return NT_STATUS_OK;
6382 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6383 if (smb_fname_tmp == NULL) {
6384 return NT_STATUS_NO_MEMORY;
6387 smb_fname_tmp->st = *psbuf;
6389 status = SMB_VFS_CREATE_FILE(
6392 0, /* root_dir_fid */
6393 smb_fname_tmp, /* fname */
6394 FILE_WRITE_DATA, /* access_mask */
6395 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6397 FILE_OPEN, /* create_disposition*/
6398 0, /* create_options */
6399 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6400 0, /* oplock_request */
6402 0, /* allocation_size */
6403 0, /* private_flags */
6406 &new_fsp, /* result */
6408 NULL, NULL); /* create context */
6410 TALLOC_FREE(smb_fname_tmp);
6412 if (!NT_STATUS_IS_OK(status)) {
6413 /* NB. We check for open_was_deferred in the caller. */
6417 /* See RAW-SFILEINFO-END-OF-FILE */
6418 if (fail_after_createfile) {
6419 close_file(req, new_fsp,NORMAL_CLOSE);
6420 return NT_STATUS_INVALID_LEVEL;
6423 if (vfs_set_filelen(new_fsp, size) == -1) {
6424 status = map_nt_error_from_unix(errno);
6425 close_file(req, new_fsp,NORMAL_CLOSE);
6429 trigger_write_time_update_immediate(new_fsp);
6430 close_file(req, new_fsp,NORMAL_CLOSE);
6431 return NT_STATUS_OK;
6434 /****************************************************************************
6435 Deal with SMB_INFO_SET_EA.
6436 ****************************************************************************/
6438 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6442 const struct smb_filename *smb_fname)
6444 struct ea_list *ea_list = NULL;
6445 TALLOC_CTX *ctx = NULL;
6446 NTSTATUS status = NT_STATUS_OK;
6448 if (total_data < 10) {
6450 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6451 length. They seem to have no effect. Bug #3212. JRA */
6453 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6454 /* We're done. We only get EA info in this call. */
6455 return NT_STATUS_OK;
6458 return NT_STATUS_INVALID_PARAMETER;
6461 if (IVAL(pdata,0) > total_data) {
6462 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6463 IVAL(pdata,0), (unsigned int)total_data));
6464 return NT_STATUS_INVALID_PARAMETER;
6468 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6470 return NT_STATUS_INVALID_PARAMETER;
6473 status = set_ea(conn, fsp, smb_fname, ea_list);
6478 /****************************************************************************
6479 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6480 ****************************************************************************/
6482 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6487 struct ea_list *ea_list = NULL;
6491 return NT_STATUS_INVALID_HANDLE;
6494 if (!lp_ea_support(SNUM(conn))) {
6495 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6496 "EA's not supported.\n",
6497 (unsigned int)total_data));
6498 return NT_STATUS_EAS_NOT_SUPPORTED;
6501 if (total_data < 10) {
6502 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6504 (unsigned int)total_data));
6505 return NT_STATUS_INVALID_PARAMETER;
6508 ea_list = read_nttrans_ea_list(talloc_tos(),
6513 return NT_STATUS_INVALID_PARAMETER;
6516 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6518 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6519 smb_fname_str_dbg(fsp->fsp_name),
6520 nt_errstr(status) ));
6526 /****************************************************************************
6527 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6528 ****************************************************************************/
6530 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6534 struct smb_filename *smb_fname)
6536 NTSTATUS status = NT_STATUS_OK;
6537 bool delete_on_close;
6538 uint32_t dosmode = 0;
6540 if (total_data < 1) {
6541 return NT_STATUS_INVALID_PARAMETER;
6545 return NT_STATUS_INVALID_HANDLE;
6548 delete_on_close = (CVAL(pdata,0) ? True : False);
6549 dosmode = dos_mode(conn, smb_fname);
6551 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6552 "delete_on_close = %u\n",
6553 smb_fname_str_dbg(smb_fname),
6554 (unsigned int)dosmode,
6555 (unsigned int)delete_on_close ));
6557 if (delete_on_close) {
6558 status = can_set_delete_on_close(fsp, dosmode);
6559 if (!NT_STATUS_IS_OK(status)) {
6564 /* The set is across all open files on this dev/inode pair. */
6565 if (!set_delete_on_close(fsp, delete_on_close,
6566 conn->session_info->security_token,
6567 conn->session_info->unix_token)) {
6568 return NT_STATUS_ACCESS_DENIED;
6570 return NT_STATUS_OK;
6573 /****************************************************************************
6574 Deal with SMB_FILE_POSITION_INFORMATION.
6575 ****************************************************************************/
6577 static NTSTATUS smb_file_position_information(connection_struct *conn,
6582 uint64_t position_information;
6584 if (total_data < 8) {
6585 return NT_STATUS_INVALID_PARAMETER;
6589 /* Ignore on pathname based set. */
6590 return NT_STATUS_OK;
6593 position_information = (uint64_t)IVAL(pdata,0);
6594 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6596 DEBUG(10,("smb_file_position_information: Set file position "
6597 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6598 (double)position_information));
6599 fsp->fh->position_information = position_information;
6600 return NT_STATUS_OK;
6603 /****************************************************************************
6604 Deal with SMB_FILE_MODE_INFORMATION.
6605 ****************************************************************************/
6607 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6613 if (total_data < 4) {
6614 return NT_STATUS_INVALID_PARAMETER;
6616 mode = IVAL(pdata,0);
6617 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6618 return NT_STATUS_INVALID_PARAMETER;
6620 return NT_STATUS_OK;
6623 /****************************************************************************
6624 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6625 ****************************************************************************/
6627 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6628 struct smb_request *req,
6631 const struct smb_filename *new_smb_fname)
6633 char *link_target = NULL;
6634 TALLOC_CTX *ctx = talloc_tos();
6636 /* Set a symbolic link. */
6637 /* Don't allow this if follow links is false. */
6639 if (total_data == 0) {
6640 return NT_STATUS_INVALID_PARAMETER;
6643 if (!lp_follow_symlinks(SNUM(conn))) {
6644 return NT_STATUS_ACCESS_DENIED;
6647 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6648 total_data, STR_TERMINATE);
6651 return NT_STATUS_INVALID_PARAMETER;
6654 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6655 new_smb_fname->base_name, link_target ));
6657 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6658 return map_nt_error_from_unix(errno);
6661 return NT_STATUS_OK;
6664 /****************************************************************************
6665 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6666 ****************************************************************************/
6668 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6669 struct smb_request *req,
6670 const char *pdata, int total_data,
6671 struct smb_filename *smb_fname_new)
6673 char *oldname = NULL;
6674 struct smb_filename *smb_fname_old = NULL;
6675 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6676 TALLOC_CTX *ctx = talloc_tos();
6677 NTSTATUS status = NT_STATUS_OK;
6679 /* Set a hard link. */
6680 if (total_data == 0) {
6681 return NT_STATUS_INVALID_PARAMETER;
6684 if (req->posix_pathnames) {
6685 srvstr_get_path_posix(ctx,
6694 srvstr_get_path(ctx,
6703 if (!NT_STATUS_IS_OK(status)) {
6707 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6708 smb_fname_str_dbg(smb_fname_new), oldname));
6710 status = filename_convert(ctx,
6717 if (!NT_STATUS_IS_OK(status)) {
6721 return hardlink_internals(ctx, conn, req, false,
6722 smb_fname_old, smb_fname_new);
6725 /****************************************************************************
6726 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6727 ****************************************************************************/
6729 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6730 struct smb_request *req,
6734 struct smb_filename *smb_fname_src)
6738 char *newname = NULL;
6739 struct smb_filename *smb_fname_dst = NULL;
6740 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6741 ucf_flags_from_smb_request(req);
6742 NTSTATUS status = NT_STATUS_OK;
6743 TALLOC_CTX *ctx = talloc_tos();
6746 return NT_STATUS_INVALID_HANDLE;
6749 if (total_data < 20) {
6750 return NT_STATUS_INVALID_PARAMETER;
6753 overwrite = (CVAL(pdata,0) ? True : False);
6754 len = IVAL(pdata,16);
6756 if (len > (total_data - 20) || (len == 0)) {
6757 return NT_STATUS_INVALID_PARAMETER;
6760 if (req->posix_pathnames) {
6761 srvstr_get_path_posix(ctx,
6770 srvstr_get_path(ctx,
6779 if (!NT_STATUS_IS_OK(status)) {
6783 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6786 status = filename_convert(ctx,
6793 if (!NT_STATUS_IS_OK(status)) {
6797 if (fsp->base_fsp) {
6798 /* newname must be a stream name. */
6799 if (newname[0] != ':') {
6800 return NT_STATUS_NOT_SUPPORTED;
6803 /* Create an smb_fname to call rename_internals_fsp() with. */
6804 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6805 fsp->base_fsp->fsp_name->base_name,
6808 fsp->base_fsp->fsp_name->flags);
6809 if (smb_fname_dst == NULL) {
6810 status = NT_STATUS_NO_MEMORY;
6815 * Set the original last component, since
6816 * rename_internals_fsp() requires it.
6818 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6820 if (smb_fname_dst->original_lcomp == NULL) {
6821 status = NT_STATUS_NO_MEMORY;
6827 DEBUG(10,("smb2_file_rename_information: "
6828 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6829 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6830 smb_fname_str_dbg(smb_fname_dst)));
6831 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6832 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6836 TALLOC_FREE(smb_fname_dst);
6840 static NTSTATUS smb_file_link_information(connection_struct *conn,
6841 struct smb_request *req,
6845 struct smb_filename *smb_fname_src)
6849 char *newname = NULL;
6850 struct smb_filename *smb_fname_dst = NULL;
6851 NTSTATUS status = NT_STATUS_OK;
6852 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6853 ucf_flags_from_smb_request(req);
6854 TALLOC_CTX *ctx = talloc_tos();
6857 return NT_STATUS_INVALID_HANDLE;
6860 if (total_data < 20) {
6861 return NT_STATUS_INVALID_PARAMETER;
6864 overwrite = (CVAL(pdata,0) ? true : false);
6865 len = IVAL(pdata,16);
6867 if (len > (total_data - 20) || (len == 0)) {
6868 return NT_STATUS_INVALID_PARAMETER;
6871 if (req->posix_pathnames) {
6872 srvstr_get_path_posix(ctx,
6881 srvstr_get_path(ctx,
6890 if (!NT_STATUS_IS_OK(status)) {
6894 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6897 status = filename_convert(ctx,
6904 if (!NT_STATUS_IS_OK(status)) {
6908 if (fsp->base_fsp) {
6909 /* No stream names. */
6910 return NT_STATUS_NOT_SUPPORTED;
6913 DEBUG(10,("smb_file_link_information: "
6914 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6915 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6916 smb_fname_str_dbg(smb_fname_dst)));
6917 status = hardlink_internals(ctx,
6924 TALLOC_FREE(smb_fname_dst);
6928 /****************************************************************************
6929 Deal with SMB_FILE_RENAME_INFORMATION.
6930 ****************************************************************************/
6932 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6933 struct smb_request *req,
6937 struct smb_filename *smb_fname_src)
6942 char *newname = NULL;
6943 struct smb_filename *smb_fname_dst = NULL;
6944 bool dest_has_wcard = False;
6945 NTSTATUS status = NT_STATUS_OK;
6947 TALLOC_CTX *ctx = talloc_tos();
6949 if (total_data < 13) {
6950 return NT_STATUS_INVALID_PARAMETER;
6953 overwrite = (CVAL(pdata,0) ? True : False);
6954 root_fid = IVAL(pdata,4);
6955 len = IVAL(pdata,8);
6957 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6958 return NT_STATUS_INVALID_PARAMETER;
6961 if (req->posix_pathnames) {
6962 srvstr_get_path_wcard_posix(ctx,
6972 srvstr_get_path_wcard(ctx,
6982 if (!NT_STATUS_IS_OK(status)) {
6986 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6989 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
6990 status = resolve_dfspath_wcard(ctx, conn,
6992 UCF_COND_ALLOW_WCARD_LCOMP,
6993 !conn->sconn->using_smb2,
6996 if (!NT_STATUS_IS_OK(status)) {
7001 /* Check the new name has no '/' characters. */
7002 if (strchr_m(newname, '/')) {
7003 return NT_STATUS_NOT_SUPPORTED;
7006 if (fsp && fsp->base_fsp) {
7007 /* newname must be a stream name. */
7008 if (newname[0] != ':') {
7009 return NT_STATUS_NOT_SUPPORTED;
7012 /* Create an smb_fname to call rename_internals_fsp() with. */
7013 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7014 fsp->base_fsp->fsp_name->base_name,
7017 fsp->base_fsp->fsp_name->flags);
7018 if (smb_fname_dst == NULL) {
7019 status = NT_STATUS_NO_MEMORY;
7024 * Set the original last component, since
7025 * rename_internals_fsp() requires it.
7027 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7029 if (smb_fname_dst->original_lcomp == NULL) {
7030 status = NT_STATUS_NO_MEMORY;
7036 * Build up an smb_fname_dst based on the filename passed in.
7037 * We basically just strip off the last component, and put on
7038 * the newname instead.
7040 char *base_name = NULL;
7041 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7042 ucf_flags_from_smb_request(req);
7044 if (dest_has_wcard) {
7045 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7048 /* newname must *not* be a stream name. */
7049 if (newname[0] == ':') {
7050 return NT_STATUS_NOT_SUPPORTED;
7054 * Strip off the last component (filename) of the path passed
7057 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7059 return NT_STATUS_NO_MEMORY;
7061 p = strrchr_m(base_name, '/');
7065 base_name = talloc_strdup(ctx, "");
7067 return NT_STATUS_NO_MEMORY;
7070 /* Append the new name. */
7071 base_name = talloc_asprintf_append(base_name,
7075 return NT_STATUS_NO_MEMORY;
7078 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7081 /* If an error we expect this to be
7082 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7084 if (!NT_STATUS_IS_OK(status)) {
7085 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7089 /* Create an smb_fname to call rename_internals_fsp() */
7090 smb_fname_dst = synthetic_smb_fname(ctx,
7094 smb_fname_src->flags);
7095 if (smb_fname_dst == NULL) {
7096 status = NT_STATUS_NO_MEMORY;
7103 DEBUG(10,("smb_file_rename_information: "
7104 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7105 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7106 smb_fname_str_dbg(smb_fname_dst)));
7107 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7110 DEBUG(10,("smb_file_rename_information: "
7111 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7112 smb_fname_str_dbg(smb_fname_src),
7113 smb_fname_str_dbg(smb_fname_dst)));
7114 status = rename_internals(ctx, conn, req, smb_fname_src,
7115 smb_fname_dst, 0, overwrite, false,
7117 FILE_WRITE_ATTRIBUTES);
7120 TALLOC_FREE(smb_fname_dst);
7124 /****************************************************************************
7125 Deal with SMB_SET_POSIX_ACL.
7126 ****************************************************************************/
7128 #if defined(HAVE_POSIX_ACLS)
7129 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7133 const struct smb_filename *smb_fname)
7135 uint16_t posix_acl_version;
7136 uint16_t num_file_acls;
7137 uint16_t num_def_acls;
7138 bool valid_file_acls = True;
7139 bool valid_def_acls = True;
7142 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7143 return NT_STATUS_INVALID_PARAMETER;
7145 posix_acl_version = SVAL(pdata,0);
7146 num_file_acls = SVAL(pdata,2);
7147 num_def_acls = SVAL(pdata,4);
7149 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7150 valid_file_acls = False;
7154 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7155 valid_def_acls = False;
7159 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7160 return NT_STATUS_INVALID_PARAMETER;
7163 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7164 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7165 return NT_STATUS_INVALID_PARAMETER;
7168 status = refuse_symlink(conn, fsp, smb_fname);
7169 if (!NT_STATUS_IS_OK(status)) {
7173 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7174 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7175 (unsigned int)num_file_acls,
7176 (unsigned int)num_def_acls));
7178 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7179 smb_fname, num_file_acls,
7180 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7181 return map_nt_error_from_unix(errno);
7184 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7185 smb_fname, num_def_acls,
7186 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7187 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7188 return map_nt_error_from_unix(errno);
7190 return NT_STATUS_OK;
7194 /****************************************************************************
7195 Deal with SMB_SET_POSIX_LOCK.
7196 ****************************************************************************/
7198 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7199 struct smb_request *req,
7207 bool blocking_lock = False;
7208 enum brl_type lock_type;
7210 NTSTATUS status = NT_STATUS_OK;
7212 if (fsp == NULL || fsp->fh->fd == -1) {
7213 return NT_STATUS_INVALID_HANDLE;
7216 if (total_data != POSIX_LOCK_DATA_SIZE) {
7217 return NT_STATUS_INVALID_PARAMETER;
7220 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7221 case POSIX_LOCK_TYPE_READ:
7222 lock_type = READ_LOCK;
7224 case POSIX_LOCK_TYPE_WRITE:
7225 /* Return the right POSIX-mappable error code for files opened read-only. */
7226 if (!fsp->can_write) {
7227 return NT_STATUS_INVALID_HANDLE;
7229 lock_type = WRITE_LOCK;
7231 case POSIX_LOCK_TYPE_UNLOCK:
7232 lock_type = UNLOCK_LOCK;
7235 return NT_STATUS_INVALID_PARAMETER;
7238 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7239 blocking_lock = False;
7240 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7241 blocking_lock = True;
7243 return NT_STATUS_INVALID_PARAMETER;
7246 if (!lp_blocking_locks(SNUM(conn))) {
7247 blocking_lock = False;
7250 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7251 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7252 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7253 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7254 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7256 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7257 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7259 (unsigned int)lock_type,
7260 (unsigned long long)smblctx,
7264 if (lock_type == UNLOCK_LOCK) {
7265 status = do_unlock(req->sconn->msg_ctx,
7272 uint64_t block_smblctx;
7274 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7285 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7287 * A blocking lock was requested. Package up
7288 * this smb into a queued request and push it
7289 * onto the blocking lock queue.
7291 if(push_blocking_lock_request(br_lck,
7294 -1, /* infinite timeout. */
7302 TALLOC_FREE(br_lck);
7306 TALLOC_FREE(br_lck);
7312 /****************************************************************************
7313 Deal with SMB_SET_FILE_BASIC_INFO.
7314 ****************************************************************************/
7316 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7320 const struct smb_filename *smb_fname)
7322 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7323 struct smb_file_time ft;
7324 uint32_t dosmode = 0;
7325 NTSTATUS status = NT_STATUS_OK;
7329 if (total_data < 36) {
7330 return NT_STATUS_INVALID_PARAMETER;
7333 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7334 if (!NT_STATUS_IS_OK(status)) {
7338 /* Set the attributes */
7339 dosmode = IVAL(pdata,32);
7340 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7341 if (!NT_STATUS_IS_OK(status)) {
7346 ft.create_time = interpret_long_date(pdata);
7349 ft.atime = interpret_long_date(pdata+8);
7352 ft.mtime = interpret_long_date(pdata+16);
7355 ft.ctime = interpret_long_date(pdata+24);
7357 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7358 smb_fname_str_dbg(smb_fname)));
7360 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7364 /****************************************************************************
7365 Deal with SMB_INFO_STANDARD.
7366 ****************************************************************************/
7368 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7372 const struct smb_filename *smb_fname)
7375 struct smb_file_time ft;
7379 if (total_data < 12) {
7380 return NT_STATUS_INVALID_PARAMETER;
7384 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7386 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7388 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7390 DEBUG(10,("smb_set_info_standard: file %s\n",
7391 smb_fname_str_dbg(smb_fname)));
7393 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7394 if (!NT_STATUS_IS_OK(status)) {
7398 return smb_set_file_time(conn,
7405 /****************************************************************************
7406 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7407 ****************************************************************************/
7409 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7410 struct smb_request *req,
7414 struct smb_filename *smb_fname)
7416 uint64_t allocation_size = 0;
7417 NTSTATUS status = NT_STATUS_OK;
7418 files_struct *new_fsp = NULL;
7420 if (!VALID_STAT(smb_fname->st)) {
7421 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7424 if (total_data < 8) {
7425 return NT_STATUS_INVALID_PARAMETER;
7428 allocation_size = (uint64_t)IVAL(pdata,0);
7429 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7430 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7431 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7432 (double)allocation_size));
7434 if (allocation_size) {
7435 allocation_size = smb_roundup(conn, allocation_size);
7438 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7439 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7440 (double)allocation_size));
7442 if (fsp && fsp->fh->fd != -1) {
7443 /* Open file handle. */
7444 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7445 return NT_STATUS_ACCESS_DENIED;
7448 /* Only change if needed. */
7449 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7450 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7451 return map_nt_error_from_unix(errno);
7454 /* But always update the time. */
7456 * This is equivalent to a write. Ensure it's seen immediately
7457 * if there are no pending writes.
7459 trigger_write_time_update_immediate(fsp);
7460 return NT_STATUS_OK;
7463 /* Pathname or stat or directory file. */
7464 status = SMB_VFS_CREATE_FILE(
7467 0, /* root_dir_fid */
7468 smb_fname, /* fname */
7469 FILE_WRITE_DATA, /* access_mask */
7470 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7472 FILE_OPEN, /* create_disposition*/
7473 0, /* create_options */
7474 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7475 0, /* oplock_request */
7477 0, /* allocation_size */
7478 0, /* private_flags */
7481 &new_fsp, /* result */
7483 NULL, NULL); /* create context */
7485 if (!NT_STATUS_IS_OK(status)) {
7486 /* NB. We check for open_was_deferred in the caller. */
7490 /* Only change if needed. */
7491 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7492 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7493 status = map_nt_error_from_unix(errno);
7494 close_file(req, new_fsp, NORMAL_CLOSE);
7499 /* Changing the allocation size should set the last mod time. */
7501 * This is equivalent to a write. Ensure it's seen immediately
7502 * if there are no pending writes.
7504 trigger_write_time_update_immediate(new_fsp);
7505 close_file(req, new_fsp, NORMAL_CLOSE);
7506 return NT_STATUS_OK;
7509 /****************************************************************************
7510 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7511 ****************************************************************************/
7513 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7514 struct smb_request *req,
7518 const struct smb_filename *smb_fname,
7519 bool fail_after_createfile)
7523 if (total_data < 8) {
7524 return NT_STATUS_INVALID_PARAMETER;
7527 size = IVAL(pdata,0);
7528 size |= (((off_t)IVAL(pdata,4)) << 32);
7529 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7530 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7533 return smb_set_file_size(conn, req,
7538 fail_after_createfile);
7541 /****************************************************************************
7542 Allow a UNIX info mknod.
7543 ****************************************************************************/
7545 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7548 const struct smb_filename *smb_fname)
7550 uint32_t file_type = IVAL(pdata,56);
7551 #if defined(HAVE_MAKEDEV)
7552 uint32_t dev_major = IVAL(pdata,60);
7553 uint32_t dev_minor = IVAL(pdata,68);
7555 SMB_DEV_T dev = (SMB_DEV_T)0;
7556 uint32_t raw_unixmode = IVAL(pdata,84);
7560 if (total_data < 100) {
7561 return NT_STATUS_INVALID_PARAMETER;
7564 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7565 PERM_NEW_FILE, &unixmode);
7566 if (!NT_STATUS_IS_OK(status)) {
7570 #if defined(HAVE_MAKEDEV)
7571 dev = makedev(dev_major, dev_minor);
7574 switch (file_type) {
7575 #if defined(S_IFIFO)
7576 case UNIX_TYPE_FIFO:
7577 unixmode |= S_IFIFO;
7580 #if defined(S_IFSOCK)
7581 case UNIX_TYPE_SOCKET:
7582 unixmode |= S_IFSOCK;
7585 #if defined(S_IFCHR)
7586 case UNIX_TYPE_CHARDEV:
7587 unixmode |= S_IFCHR;
7590 #if defined(S_IFBLK)
7591 case UNIX_TYPE_BLKDEV:
7592 unixmode |= S_IFBLK;
7596 return NT_STATUS_INVALID_PARAMETER;
7599 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7600 "%.0f mode 0%o for file %s\n", (double)dev,
7601 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7603 /* Ok - do the mknod. */
7604 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7605 return map_nt_error_from_unix(errno);
7608 /* If any of the other "set" calls fail we
7609 * don't want to end up with a half-constructed mknod.
7612 if (lp_inherit_permissions(SNUM(conn))) {
7614 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7616 return NT_STATUS_NO_MEMORY;
7618 inherit_access_posix_acl(conn, parent, smb_fname,
7620 TALLOC_FREE(parent);
7623 return NT_STATUS_OK;
7626 /****************************************************************************
7627 Deal with SMB_SET_FILE_UNIX_BASIC.
7628 ****************************************************************************/
7630 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7631 struct smb_request *req,
7635 const struct smb_filename *smb_fname)
7637 struct smb_file_time ft;
7638 uint32_t raw_unixmode;
7641 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7642 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7643 NTSTATUS status = NT_STATUS_OK;
7644 bool delete_on_fail = False;
7645 enum perm_type ptype;
7646 files_struct *all_fsps = NULL;
7647 bool modify_mtime = true;
7649 struct smb_filename *smb_fname_tmp = NULL;
7650 SMB_STRUCT_STAT sbuf;
7654 if (total_data < 100) {
7655 return NT_STATUS_INVALID_PARAMETER;
7658 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7659 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7660 size=IVAL(pdata,0); /* first 8 Bytes are size */
7661 size |= (((off_t)IVAL(pdata,4)) << 32);
7664 ft.atime = interpret_long_date(pdata+24); /* access_time */
7665 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7666 set_owner = (uid_t)IVAL(pdata,40);
7667 set_grp = (gid_t)IVAL(pdata,48);
7668 raw_unixmode = IVAL(pdata,84);
7670 if (VALID_STAT(smb_fname->st)) {
7671 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7672 ptype = PERM_EXISTING_DIR;
7674 ptype = PERM_EXISTING_FILE;
7677 ptype = PERM_NEW_FILE;
7680 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7682 if (!NT_STATUS_IS_OK(status)) {
7686 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7687 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7688 smb_fname_str_dbg(smb_fname), (double)size,
7689 (unsigned int)set_owner, (unsigned int)set_grp,
7690 (int)raw_unixmode));
7692 sbuf = smb_fname->st;
7694 if (!VALID_STAT(sbuf)) {
7696 * The only valid use of this is to create character and block
7697 * devices, and named pipes. This is deprecated (IMHO) and
7698 * a new info level should be used for mknod. JRA.
7701 status = smb_unix_mknod(conn,
7705 if (!NT_STATUS_IS_OK(status)) {
7709 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7710 if (smb_fname_tmp == NULL) {
7711 return NT_STATUS_NO_MEMORY;
7714 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7715 status = map_nt_error_from_unix(errno);
7716 TALLOC_FREE(smb_fname_tmp);
7717 SMB_VFS_UNLINK(conn, smb_fname);
7721 sbuf = smb_fname_tmp->st;
7722 smb_fname = smb_fname_tmp;
7724 /* Ensure we don't try and change anything else. */
7725 raw_unixmode = SMB_MODE_NO_CHANGE;
7726 size = get_file_size_stat(&sbuf);
7727 ft.atime = sbuf.st_ex_atime;
7728 ft.mtime = sbuf.st_ex_mtime;
7730 * We continue here as we might want to change the
7733 delete_on_fail = True;
7737 /* Horrible backwards compatibility hack as an old server bug
7738 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7742 size = get_file_size_stat(&sbuf);
7747 * Deal with the UNIX specific mode set.
7750 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7753 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7754 "setting mode 0%o for file %s\n",
7755 (unsigned int)unixmode,
7756 smb_fname_str_dbg(smb_fname)));
7757 if (fsp && fsp->fh->fd != -1) {
7758 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7760 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7763 return map_nt_error_from_unix(errno);
7768 * Deal with the UNIX specific uid set.
7771 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7772 (sbuf.st_ex_uid != set_owner)) {
7775 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7776 "changing owner %u for path %s\n",
7777 (unsigned int)set_owner,
7778 smb_fname_str_dbg(smb_fname)));
7780 if (fsp && fsp->fh->fd != -1) {
7781 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7784 * UNIX extensions calls must always operate
7787 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7788 set_owner, (gid_t)-1);
7792 status = map_nt_error_from_unix(errno);
7793 if (delete_on_fail) {
7794 SMB_VFS_UNLINK(conn, smb_fname);
7801 * Deal with the UNIX specific gid set.
7804 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7805 (sbuf.st_ex_gid != set_grp)) {
7808 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7809 "changing group %u for file %s\n",
7810 (unsigned int)set_grp,
7811 smb_fname_str_dbg(smb_fname)));
7812 if (fsp && fsp->fh->fd != -1) {
7813 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
7816 * UNIX extensions calls must always operate
7819 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7823 status = map_nt_error_from_unix(errno);
7824 if (delete_on_fail) {
7825 SMB_VFS_UNLINK(conn, smb_fname);
7831 /* Deal with any size changes. */
7833 status = smb_set_file_size(conn, req,
7839 if (!NT_STATUS_IS_OK(status)) {
7843 /* Deal with any time changes. */
7844 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7845 /* No change, don't cancel anything. */
7849 id = vfs_file_id_from_sbuf(conn, &sbuf);
7850 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7851 all_fsps = file_find_di_next(all_fsps)) {
7853 * We're setting the time explicitly for UNIX.
7854 * Cancel any pending changes over all handles.
7856 all_fsps->update_write_time_on_close = false;
7857 TALLOC_FREE(all_fsps->update_write_time_event);
7861 * Override the "setting_write_time"
7862 * parameter here as it almost does what
7863 * we need. Just remember if we modified
7864 * mtime and send the notify ourselves.
7866 if (null_timespec(ft.mtime)) {
7867 modify_mtime = false;
7870 status = smb_set_file_time(conn,
7876 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7877 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7882 /****************************************************************************
7883 Deal with SMB_SET_FILE_UNIX_INFO2.
7884 ****************************************************************************/
7886 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7887 struct smb_request *req,
7891 const struct smb_filename *smb_fname)
7894 uint32_t smb_fflags;
7897 if (total_data < 116) {
7898 return NT_STATUS_INVALID_PARAMETER;
7901 /* Start by setting all the fields that are common between UNIX_BASIC
7904 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7906 if (!NT_STATUS_IS_OK(status)) {
7910 smb_fflags = IVAL(pdata, 108);
7911 smb_fmask = IVAL(pdata, 112);
7913 /* NB: We should only attempt to alter the file flags if the client
7914 * sends a non-zero mask.
7916 if (smb_fmask != 0) {
7917 int stat_fflags = 0;
7919 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7920 smb_fmask, &stat_fflags)) {
7921 /* Client asked to alter a flag we don't understand. */
7922 return NT_STATUS_INVALID_PARAMETER;
7925 if (fsp && fsp->fh->fd != -1) {
7926 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7927 return NT_STATUS_NOT_SUPPORTED;
7929 if (SMB_VFS_CHFLAGS(conn, smb_fname,
7930 stat_fflags) != 0) {
7931 return map_nt_error_from_unix(errno);
7936 /* XXX: need to add support for changing the create_time here. You
7937 * can do this for paths on Darwin with setattrlist(2). The right way
7938 * to hook this up is probably by extending the VFS utimes interface.
7941 return NT_STATUS_OK;
7944 /****************************************************************************
7945 Create a directory with POSIX semantics.
7946 ****************************************************************************/
7948 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7949 struct smb_request *req,
7952 struct smb_filename *smb_fname,
7953 int *pdata_return_size)
7955 NTSTATUS status = NT_STATUS_OK;
7956 uint32_t raw_unixmode = 0;
7957 uint32_t mod_unixmode = 0;
7958 mode_t unixmode = (mode_t)0;
7959 files_struct *fsp = NULL;
7960 uint16_t info_level_return = 0;
7962 char *pdata = *ppdata;
7964 if (total_data < 18) {
7965 return NT_STATUS_INVALID_PARAMETER;
7968 raw_unixmode = IVAL(pdata,8);
7969 /* Next 4 bytes are not yet defined. */
7971 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7972 PERM_NEW_DIR, &unixmode);
7973 if (!NT_STATUS_IS_OK(status)) {
7977 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7979 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7980 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7982 status = SMB_VFS_CREATE_FILE(
7985 0, /* root_dir_fid */
7986 smb_fname, /* fname */
7987 FILE_READ_ATTRIBUTES, /* access_mask */
7988 FILE_SHARE_NONE, /* share_access */
7989 FILE_CREATE, /* create_disposition*/
7990 FILE_DIRECTORY_FILE, /* create_options */
7991 mod_unixmode, /* file_attributes */
7992 0, /* oplock_request */
7994 0, /* allocation_size */
7995 0, /* private_flags */
8000 NULL, NULL); /* create context */
8002 if (NT_STATUS_IS_OK(status)) {
8003 close_file(req, fsp, NORMAL_CLOSE);
8006 info_level_return = SVAL(pdata,16);
8008 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8009 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8010 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8011 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8013 *pdata_return_size = 12;
8016 /* Realloc the data size */
8017 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8018 if (*ppdata == NULL) {
8019 *pdata_return_size = 0;
8020 return NT_STATUS_NO_MEMORY;
8024 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8025 SSVAL(pdata,2,0); /* No fnum. */
8026 SIVAL(pdata,4,info); /* Was directory created. */
8028 switch (info_level_return) {
8029 case SMB_QUERY_FILE_UNIX_BASIC:
8030 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8031 SSVAL(pdata,10,0); /* Padding. */
8032 store_file_unix_basic(conn, pdata + 12, fsp,
8035 case SMB_QUERY_FILE_UNIX_INFO2:
8036 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8037 SSVAL(pdata,10,0); /* Padding. */
8038 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8042 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8043 SSVAL(pdata,10,0); /* Padding. */
8050 /****************************************************************************
8051 Open/Create a file with POSIX semantics.
8052 ****************************************************************************/
8054 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8055 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8057 static NTSTATUS smb_posix_open(connection_struct *conn,
8058 struct smb_request *req,
8061 struct smb_filename *smb_fname,
8062 int *pdata_return_size)
8064 bool extended_oplock_granted = False;
8065 char *pdata = *ppdata;
8067 uint32_t wire_open_mode = 0;
8068 uint32_t raw_unixmode = 0;
8069 uint32_t mod_unixmode = 0;
8070 uint32_t create_disp = 0;
8071 uint32_t access_mask = 0;
8072 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8073 NTSTATUS status = NT_STATUS_OK;
8074 mode_t unixmode = (mode_t)0;
8075 files_struct *fsp = NULL;
8076 int oplock_request = 0;
8078 uint16_t info_level_return = 0;
8080 if (total_data < 18) {
8081 return NT_STATUS_INVALID_PARAMETER;
8084 flags = IVAL(pdata,0);
8085 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8086 if (oplock_request) {
8087 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8090 wire_open_mode = IVAL(pdata,4);
8092 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8093 return smb_posix_mkdir(conn, req,
8100 switch (wire_open_mode & SMB_ACCMODE) {
8102 access_mask = SMB_O_RDONLY_MAPPING;
8105 access_mask = SMB_O_WRONLY_MAPPING;
8108 access_mask = (SMB_O_RDONLY_MAPPING|
8109 SMB_O_WRONLY_MAPPING);
8112 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8113 (unsigned int)wire_open_mode ));
8114 return NT_STATUS_INVALID_PARAMETER;
8117 wire_open_mode &= ~SMB_ACCMODE;
8119 /* First take care of O_CREAT|O_EXCL interactions. */
8120 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8121 case (SMB_O_CREAT | SMB_O_EXCL):
8122 /* File exists fail. File not exist create. */
8123 create_disp = FILE_CREATE;
8126 /* File exists open. File not exist create. */
8127 create_disp = FILE_OPEN_IF;
8130 /* O_EXCL on its own without O_CREAT is undefined.
8131 We deliberately ignore it as some versions of
8132 Linux CIFSFS can send a bare O_EXCL on the
8133 wire which other filesystems in the kernel
8134 ignore. See bug 9519 for details. */
8139 /* File exists open. File not exist fail. */
8140 create_disp = FILE_OPEN;
8143 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8144 (unsigned int)wire_open_mode ));
8145 return NT_STATUS_INVALID_PARAMETER;
8148 /* Next factor in the effects of O_TRUNC. */
8149 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8151 if (wire_open_mode & SMB_O_TRUNC) {
8152 switch (create_disp) {
8154 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8155 /* Leave create_disp alone as
8156 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8158 /* File exists fail. File not exist create. */
8161 /* SMB_O_CREAT | SMB_O_TRUNC */
8162 /* File exists overwrite. File not exist create. */
8163 create_disp = FILE_OVERWRITE_IF;
8167 /* File exists overwrite. File not exist fail. */
8168 create_disp = FILE_OVERWRITE;
8171 /* Cannot get here. */
8172 smb_panic("smb_posix_open: logic error");
8173 return NT_STATUS_INVALID_PARAMETER;
8177 raw_unixmode = IVAL(pdata,8);
8178 /* Next 4 bytes are not yet defined. */
8180 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8181 (VALID_STAT(smb_fname->st) ?
8182 PERM_EXISTING_FILE : PERM_NEW_FILE),
8185 if (!NT_STATUS_IS_OK(status)) {
8189 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8191 if (wire_open_mode & SMB_O_SYNC) {
8192 create_options |= FILE_WRITE_THROUGH;
8194 if (wire_open_mode & SMB_O_APPEND) {
8195 access_mask |= FILE_APPEND_DATA;
8197 if (wire_open_mode & SMB_O_DIRECT) {
8198 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8201 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8202 VALID_STAT_OF_DIR(smb_fname->st)) {
8203 if (access_mask != SMB_O_RDONLY_MAPPING) {
8204 return NT_STATUS_FILE_IS_A_DIRECTORY;
8206 create_options &= ~FILE_NON_DIRECTORY_FILE;
8207 create_options |= FILE_DIRECTORY_FILE;
8210 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8211 smb_fname_str_dbg(smb_fname),
8212 (unsigned int)wire_open_mode,
8213 (unsigned int)unixmode ));
8215 status = SMB_VFS_CREATE_FILE(
8218 0, /* root_dir_fid */
8219 smb_fname, /* fname */
8220 access_mask, /* access_mask */
8221 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8223 create_disp, /* create_disposition*/
8224 create_options, /* create_options */
8225 mod_unixmode, /* file_attributes */
8226 oplock_request, /* oplock_request */
8228 0, /* allocation_size */
8229 0, /* private_flags */
8234 NULL, NULL); /* create context */
8236 if (!NT_STATUS_IS_OK(status)) {
8240 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8241 extended_oplock_granted = True;
8244 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8245 extended_oplock_granted = True;
8248 info_level_return = SVAL(pdata,16);
8250 /* Allocate the correct return size. */
8252 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8253 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8254 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8255 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8257 *pdata_return_size = 12;
8260 /* Realloc the data size */
8261 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8262 if (*ppdata == NULL) {
8263 close_file(req, fsp, ERROR_CLOSE);
8264 *pdata_return_size = 0;
8265 return NT_STATUS_NO_MEMORY;
8269 if (extended_oplock_granted) {
8270 if (flags & REQUEST_BATCH_OPLOCK) {
8271 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8273 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8275 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8276 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8278 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8281 SSVAL(pdata,2,fsp->fnum);
8282 SIVAL(pdata,4,info); /* Was file created etc. */
8284 switch (info_level_return) {
8285 case SMB_QUERY_FILE_UNIX_BASIC:
8286 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8287 SSVAL(pdata,10,0); /* padding. */
8288 store_file_unix_basic(conn, pdata + 12, fsp,
8291 case SMB_QUERY_FILE_UNIX_INFO2:
8292 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8293 SSVAL(pdata,10,0); /* padding. */
8294 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8298 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8299 SSVAL(pdata,10,0); /* padding. */
8302 return NT_STATUS_OK;
8305 /****************************************************************************
8306 Delete a file with POSIX semantics.
8307 ****************************************************************************/
8309 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8310 struct smb_request *req,
8313 struct smb_filename *smb_fname)
8315 struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
8316 NTSTATUS status = NT_STATUS_OK;
8317 files_struct *fsp = NULL;
8321 int create_options = 0;
8322 struct share_mode_lock *lck = NULL;
8323 bool other_nonposix_opens;
8325 if (total_data < 2) {
8326 return NT_STATUS_INVALID_PARAMETER;
8329 flags = SVAL(pdata,0);
8331 if (!VALID_STAT(smb_fname->st)) {
8332 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8335 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8336 !VALID_STAT_OF_DIR(smb_fname->st)) {
8337 return NT_STATUS_NOT_A_DIRECTORY;
8340 DEBUG(10,("smb_posix_unlink: %s %s\n",
8341 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8342 smb_fname_str_dbg(smb_fname)));
8344 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8345 create_options |= FILE_DIRECTORY_FILE;
8348 status = SMB_VFS_CREATE_FILE(
8351 0, /* root_dir_fid */
8352 smb_fname, /* fname */
8353 DELETE_ACCESS, /* access_mask */
8354 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8356 FILE_OPEN, /* create_disposition*/
8357 create_options, /* create_options */
8358 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8359 0, /* oplock_request */
8361 0, /* allocation_size */
8362 0, /* private_flags */
8367 NULL, NULL); /* create context */
8369 if (!NT_STATUS_IS_OK(status)) {
8374 * Don't lie to client. If we can't really delete due to
8375 * non-POSIX opens return SHARING_VIOLATION.
8378 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8380 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8381 "lock for file %s\n", fsp_str_dbg(fsp)));
8382 close_file(req, fsp, NORMAL_CLOSE);
8383 return NT_STATUS_INVALID_PARAMETER;
8386 other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
8387 if (other_nonposix_opens) {
8388 /* Fail with sharing violation. */
8390 close_file(req, fsp, NORMAL_CLOSE);
8391 return NT_STATUS_SHARING_VIOLATION;
8395 * Set the delete on close.
8397 status = smb_set_file_disposition_info(conn,
8405 if (!NT_STATUS_IS_OK(status)) {
8406 close_file(req, fsp, NORMAL_CLOSE);
8409 return close_file(req, fsp, NORMAL_CLOSE);
8412 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8413 struct smb_request *req,
8414 TALLOC_CTX *mem_ctx,
8415 uint16_t info_level,
8417 struct smb_filename *smb_fname,
8418 char **ppdata, int total_data,
8421 char *pdata = *ppdata;
8422 NTSTATUS status = NT_STATUS_OK;
8423 int data_return_size = 0;
8427 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8428 return NT_STATUS_INVALID_LEVEL;
8431 if (!CAN_WRITE(conn)) {
8432 /* Allow POSIX opens. The open path will deny
8433 * any non-readonly opens. */
8434 if (info_level != SMB_POSIX_PATH_OPEN) {
8435 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8439 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8440 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8442 info_level, total_data));
8444 switch (info_level) {
8446 case SMB_INFO_STANDARD:
8448 status = smb_set_info_standard(conn,
8456 case SMB_INFO_SET_EA:
8458 status = smb_info_set_ea(conn,
8466 case SMB_SET_FILE_BASIC_INFO:
8467 case SMB_FILE_BASIC_INFORMATION:
8469 status = smb_set_file_basic_info(conn,
8477 case SMB_FILE_ALLOCATION_INFORMATION:
8478 case SMB_SET_FILE_ALLOCATION_INFO:
8480 status = smb_set_file_allocation_info(conn, req,
8488 case SMB_FILE_END_OF_FILE_INFORMATION:
8489 case SMB_SET_FILE_END_OF_FILE_INFO:
8492 * XP/Win7 both fail after the createfile with
8493 * SMB_SET_FILE_END_OF_FILE_INFO but not
8494 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8495 * The level is known here, so pass it down
8499 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8501 status = smb_set_file_end_of_file_info(conn, req,
8510 case SMB_FILE_DISPOSITION_INFORMATION:
8511 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8514 /* JRA - We used to just ignore this on a path ?
8515 * Shouldn't this be invalid level on a pathname
8518 if (tran_call != TRANSACT2_SETFILEINFO) {
8519 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8522 status = smb_set_file_disposition_info(conn,
8530 case SMB_FILE_POSITION_INFORMATION:
8532 status = smb_file_position_information(conn,
8539 case SMB_FILE_FULL_EA_INFORMATION:
8541 status = smb_set_file_full_ea_info(conn,
8548 /* From tridge Samba4 :
8549 * MODE_INFORMATION in setfileinfo (I have no
8550 * idea what "mode information" on a file is - it takes a value of 0,
8551 * 2, 4 or 6. What could it be?).
8554 case SMB_FILE_MODE_INFORMATION:
8556 status = smb_file_mode_information(conn,
8562 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8563 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8564 case SMB_FILE_SHORT_NAME_INFORMATION:
8565 return NT_STATUS_NOT_SUPPORTED;
8568 * CIFS UNIX extensions.
8571 case SMB_SET_FILE_UNIX_BASIC:
8573 status = smb_set_file_unix_basic(conn, req,
8581 case SMB_SET_FILE_UNIX_INFO2:
8583 status = smb_set_file_unix_info2(conn, req,
8591 case SMB_SET_FILE_UNIX_LINK:
8594 /* We must have a pathname for this. */
8595 return NT_STATUS_INVALID_LEVEL;
8597 status = smb_set_file_unix_link(conn, req, pdata,
8598 total_data, smb_fname);
8602 case SMB_SET_FILE_UNIX_HLINK:
8605 /* We must have a pathname for this. */
8606 return NT_STATUS_INVALID_LEVEL;
8608 status = smb_set_file_unix_hlink(conn, req,
8614 case SMB_FILE_RENAME_INFORMATION:
8616 status = smb_file_rename_information(conn, req,
8622 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8624 /* SMB2 rename information. */
8625 status = smb2_file_rename_information(conn, req,
8631 case SMB_FILE_LINK_INFORMATION:
8633 status = smb_file_link_information(conn, req,
8639 #if defined(HAVE_POSIX_ACLS)
8640 case SMB_SET_POSIX_ACL:
8642 status = smb_set_posix_acl(conn,
8651 case SMB_SET_POSIX_LOCK:
8654 return NT_STATUS_INVALID_LEVEL;
8656 status = smb_set_posix_lock(conn, req,
8657 pdata, total_data, fsp);
8661 case SMB_POSIX_PATH_OPEN:
8664 /* We must have a pathname for this. */
8665 return NT_STATUS_INVALID_LEVEL;
8668 status = smb_posix_open(conn, req,
8676 case SMB_POSIX_PATH_UNLINK:
8679 /* We must have a pathname for this. */
8680 return NT_STATUS_INVALID_LEVEL;
8683 status = smb_posix_unlink(conn, req,
8691 return NT_STATUS_INVALID_LEVEL;
8694 if (!NT_STATUS_IS_OK(status)) {
8698 *ret_data_size = data_return_size;
8699 return NT_STATUS_OK;
8702 /****************************************************************************
8703 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8704 ****************************************************************************/
8706 static void call_trans2setfilepathinfo(connection_struct *conn,
8707 struct smb_request *req,
8708 unsigned int tran_call,
8709 char **pparams, int total_params,
8710 char **ppdata, int total_data,
8711 unsigned int max_data_bytes)
8713 char *params = *pparams;
8714 char *pdata = *ppdata;
8715 uint16_t info_level;
8716 struct smb_filename *smb_fname = NULL;
8717 files_struct *fsp = NULL;
8718 NTSTATUS status = NT_STATUS_OK;
8719 int data_return_size = 0;
8722 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8726 if (tran_call == TRANSACT2_SETFILEINFO) {
8727 if (total_params < 4) {
8728 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8732 fsp = file_fsp(req, SVAL(params,0));
8733 /* Basic check for non-null fsp. */
8734 if (!check_fsp_open(conn, req, fsp)) {
8737 info_level = SVAL(params,2);
8739 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8740 if (smb_fname == NULL) {
8741 reply_nterror(req, NT_STATUS_NO_MEMORY);
8745 if(fsp->fh->fd == -1) {
8747 * This is actually a SETFILEINFO on a directory
8748 * handle (returned from an NT SMB). NT5.0 seems
8749 * to do this call. JRA.
8751 if (INFO_LEVEL_IS_UNIX(info_level)) {
8752 /* Always do lstat for UNIX calls. */
8753 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8754 DEBUG(3,("call_trans2setfilepathinfo: "
8755 "SMB_VFS_LSTAT of %s failed "
8757 smb_fname_str_dbg(smb_fname),
8759 reply_nterror(req, map_nt_error_from_unix(errno));
8763 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8764 DEBUG(3,("call_trans2setfilepathinfo: "
8765 "fileinfo of %s failed (%s)\n",
8766 smb_fname_str_dbg(smb_fname),
8768 reply_nterror(req, map_nt_error_from_unix(errno));
8772 } else if (fsp->print_file) {
8774 * Doing a DELETE_ON_CLOSE should cancel a print job.
8776 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8777 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8779 DEBUG(3,("call_trans2setfilepathinfo: "
8780 "Cancelling print job (%s)\n",
8784 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8790 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8795 * Original code - this is an open file.
8797 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8798 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8799 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8801 reply_nterror(req, map_nt_error_from_unix(errno));
8807 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8810 if (total_params < 7) {
8811 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8815 info_level = SVAL(params,0);
8816 if (req->posix_pathnames) {
8817 srvstr_get_path_posix(req,
8826 srvstr_get_path(req,
8835 if (!NT_STATUS_IS_OK(status)) {
8836 reply_nterror(req, status);
8840 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8841 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8842 info_level == SMB_FILE_RENAME_INFORMATION ||
8843 info_level == SMB_POSIX_PATH_UNLINK) {
8844 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8847 status = filename_convert(req, conn,
8853 if (!NT_STATUS_IS_OK(status)) {
8854 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8855 reply_botherror(req,
8856 NT_STATUS_PATH_NOT_COVERED,
8857 ERRSRV, ERRbadpath);
8860 reply_nterror(req, status);
8864 if (INFO_LEVEL_IS_UNIX(info_level)) {
8866 * For CIFS UNIX extensions the target name may not exist.
8869 /* Always do lstat for UNIX calls. */
8870 SMB_VFS_LSTAT(conn, smb_fname);
8872 } else if (!VALID_STAT(smb_fname->st) &&
8873 SMB_VFS_STAT(conn, smb_fname)) {
8874 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8876 smb_fname_str_dbg(smb_fname),
8878 reply_nterror(req, map_nt_error_from_unix(errno));
8883 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8884 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8886 info_level,total_data));
8888 /* Realloc the parameter size */
8889 *pparams = (char *)SMB_REALLOC(*pparams,2);
8890 if (*pparams == NULL) {
8891 reply_nterror(req, NT_STATUS_NO_MEMORY);
8898 status = smbd_do_setfilepathinfo(conn, req, req,
8904 if (!NT_STATUS_IS_OK(status)) {
8905 if (open_was_deferred(req->xconn, req->mid)) {
8906 /* We have re-scheduled this call. */
8909 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8910 /* We have re-scheduled this call. */
8913 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8914 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8915 ERRSRV, ERRbadpath);
8918 if (info_level == SMB_POSIX_PATH_OPEN) {
8919 reply_openerror(req, status);
8924 * Invalid EA name needs to return 2 param bytes,
8925 * not a zero-length error packet.
8927 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8928 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8931 reply_nterror(req, status);
8936 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8942 /****************************************************************************
8943 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8944 ****************************************************************************/
8946 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8947 char **pparams, int total_params,
8948 char **ppdata, int total_data,
8949 unsigned int max_data_bytes)
8951 struct smb_filename *smb_dname = NULL;
8952 char *params = *pparams;
8953 char *pdata = *ppdata;
8954 char *directory = NULL;
8955 NTSTATUS status = NT_STATUS_OK;
8956 struct ea_list *ea_list = NULL;
8957 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8958 TALLOC_CTX *ctx = talloc_tos();
8960 if (!CAN_WRITE(conn)) {
8961 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8965 if (total_params < 5) {
8966 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8970 if (req->posix_pathnames) {
8971 srvstr_get_path_posix(ctx,
8980 srvstr_get_path(ctx,
8989 if (!NT_STATUS_IS_OK(status)) {
8990 reply_nterror(req, status);
8994 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8996 status = filename_convert(ctx,
9004 if (!NT_STATUS_IS_OK(status)) {
9005 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9006 reply_botherror(req,
9007 NT_STATUS_PATH_NOT_COVERED,
9008 ERRSRV, ERRbadpath);
9011 reply_nterror(req, status);
9016 * OS/2 workplace shell seems to send SET_EA requests of "null"
9017 * length (4 bytes containing IVAL 4).
9018 * They seem to have no effect. Bug #3212. JRA.
9021 if (total_data && (total_data != 4)) {
9022 /* Any data in this call is an EA list. */
9023 if (total_data < 10) {
9024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9028 if (IVAL(pdata,0) > total_data) {
9029 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9030 IVAL(pdata,0), (unsigned int)total_data));
9031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9035 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9038 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9042 if (!lp_ea_support(SNUM(conn))) {
9043 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9047 /* If total_data == 4 Windows doesn't care what values
9048 * are placed in that field, it just ignores them.
9049 * The System i QNTC IBM SMB client puts bad values here,
9050 * so ignore them. */
9052 status = create_directory(conn, req, smb_dname);
9054 if (!NT_STATUS_IS_OK(status)) {
9055 reply_nterror(req, status);
9059 /* Try and set any given EA. */
9061 status = set_ea(conn, NULL, smb_dname, ea_list);
9062 if (!NT_STATUS_IS_OK(status)) {
9063 reply_nterror(req, status);
9068 /* Realloc the parameter and data sizes */
9069 *pparams = (char *)SMB_REALLOC(*pparams,2);
9070 if(*pparams == NULL) {
9071 reply_nterror(req, NT_STATUS_NO_MEMORY);
9078 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9081 TALLOC_FREE(smb_dname);
9085 /****************************************************************************
9086 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9087 We don't actually do this - we just send a null response.
9088 ****************************************************************************/
9090 static void call_trans2findnotifyfirst(connection_struct *conn,
9091 struct smb_request *req,
9092 char **pparams, int total_params,
9093 char **ppdata, int total_data,
9094 unsigned int max_data_bytes)
9096 char *params = *pparams;
9097 uint16_t info_level;
9099 if (total_params < 6) {
9100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9104 info_level = SVAL(params,4);
9105 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9107 switch (info_level) {
9112 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9116 /* Realloc the parameter and data sizes */
9117 *pparams = (char *)SMB_REALLOC(*pparams,6);
9118 if (*pparams == NULL) {
9119 reply_nterror(req, NT_STATUS_NO_MEMORY);
9124 SSVAL(params,0,fnf_handle);
9125 SSVAL(params,2,0); /* No changes */
9126 SSVAL(params,4,0); /* No EA errors */
9133 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9138 /****************************************************************************
9139 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9140 changes). Currently this does nothing.
9141 ****************************************************************************/
9143 static void call_trans2findnotifynext(connection_struct *conn,
9144 struct smb_request *req,
9145 char **pparams, int total_params,
9146 char **ppdata, int total_data,
9147 unsigned int max_data_bytes)
9149 char *params = *pparams;
9151 DEBUG(3,("call_trans2findnotifynext\n"));
9153 /* Realloc the parameter and data sizes */
9154 *pparams = (char *)SMB_REALLOC(*pparams,4);
9155 if (*pparams == NULL) {
9156 reply_nterror(req, NT_STATUS_NO_MEMORY);
9161 SSVAL(params,0,0); /* No changes */
9162 SSVAL(params,2,0); /* No EA errors */
9164 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9169 /****************************************************************************
9170 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9171 ****************************************************************************/
9173 static void call_trans2getdfsreferral(connection_struct *conn,
9174 struct smb_request *req,
9175 char **pparams, int total_params,
9176 char **ppdata, int total_data,
9177 unsigned int max_data_bytes)
9179 char *params = *pparams;
9180 char *pathname = NULL;
9182 int max_referral_level;
9183 NTSTATUS status = NT_STATUS_OK;
9184 TALLOC_CTX *ctx = talloc_tos();
9186 DEBUG(10,("call_trans2getdfsreferral\n"));
9188 if (total_params < 3) {
9189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9193 max_referral_level = SVAL(params,0);
9195 if(!lp_host_msdfs()) {
9196 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9200 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9201 total_params - 2, STR_TERMINATE);
9203 reply_nterror(req, NT_STATUS_NOT_FOUND);
9206 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9207 ppdata,&status)) < 0) {
9208 reply_nterror(req, status);
9212 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9213 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9214 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9219 #define LMCAT_SPL 0x53
9220 #define LMFUNC_GETJOBID 0x60
9222 /****************************************************************************
9223 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9224 ****************************************************************************/
9226 static void call_trans2ioctl(connection_struct *conn,
9227 struct smb_request *req,
9228 char **pparams, int total_params,
9229 char **ppdata, int total_data,
9230 unsigned int max_data_bytes)
9232 char *pdata = *ppdata;
9233 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9237 /* check for an invalid fid before proceeding */
9240 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9244 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9245 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9246 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9247 if (*ppdata == NULL) {
9248 reply_nterror(req, NT_STATUS_NO_MEMORY);
9253 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9254 CAN ACCEPT THIS IN UNICODE. JRA. */
9257 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9259 status = srvstr_push(pdata, req->flags2, pdata + 2,
9260 lp_netbios_name(), 15,
9261 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9262 if (!NT_STATUS_IS_OK(status)) {
9263 reply_nterror(req, status);
9266 status = srvstr_push(pdata, req->flags2, pdata+18,
9267 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9268 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9269 if (!NT_STATUS_IS_OK(status)) {
9270 reply_nterror(req, status);
9273 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9278 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9279 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9282 /****************************************************************************
9283 Reply to a SMBfindclose (stop trans2 directory search).
9284 ****************************************************************************/
9286 void reply_findclose(struct smb_request *req)
9289 struct smbd_server_connection *sconn = req->sconn;
9291 START_PROFILE(SMBfindclose);
9294 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9295 END_PROFILE(SMBfindclose);
9299 dptr_num = SVALS(req->vwv+0, 0);
9301 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9303 dptr_close(sconn, &dptr_num);
9305 reply_outbuf(req, 0, 0);
9307 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9309 END_PROFILE(SMBfindclose);
9313 /****************************************************************************
9314 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9315 ****************************************************************************/
9317 void reply_findnclose(struct smb_request *req)
9321 START_PROFILE(SMBfindnclose);
9324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9325 END_PROFILE(SMBfindnclose);
9329 dptr_num = SVAL(req->vwv+0, 0);
9331 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9333 /* We never give out valid handles for a
9334 findnotifyfirst - so any dptr_num is ok here.
9337 reply_outbuf(req, 0, 0);
9339 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9341 END_PROFILE(SMBfindnclose);
9345 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9346 struct trans_state *state)
9348 if (get_Protocol() >= PROTOCOL_NT1) {
9349 req->flags2 |= 0x40; /* IS_LONG_NAME */
9350 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9353 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9354 if (state->call != TRANSACT2_QFSINFO &&
9355 state->call != TRANSACT2_SETFSINFO) {
9356 DEBUG(0,("handle_trans2: encryption required "
9358 (unsigned int)state->call));
9359 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9364 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9366 /* Now we must call the relevant TRANS2 function */
9367 switch(state->call) {
9368 case TRANSACT2_OPEN:
9370 START_PROFILE(Trans2_open);
9371 call_trans2open(conn, req,
9372 &state->param, state->total_param,
9373 &state->data, state->total_data,
9374 state->max_data_return);
9375 END_PROFILE(Trans2_open);
9379 case TRANSACT2_FINDFIRST:
9381 START_PROFILE(Trans2_findfirst);
9382 call_trans2findfirst(conn, req,
9383 &state->param, state->total_param,
9384 &state->data, state->total_data,
9385 state->max_data_return);
9386 END_PROFILE(Trans2_findfirst);
9390 case TRANSACT2_FINDNEXT:
9392 START_PROFILE(Trans2_findnext);
9393 call_trans2findnext(conn, req,
9394 &state->param, state->total_param,
9395 &state->data, state->total_data,
9396 state->max_data_return);
9397 END_PROFILE(Trans2_findnext);
9401 case TRANSACT2_QFSINFO:
9403 START_PROFILE(Trans2_qfsinfo);
9404 call_trans2qfsinfo(conn, req,
9405 &state->param, state->total_param,
9406 &state->data, state->total_data,
9407 state->max_data_return);
9408 END_PROFILE(Trans2_qfsinfo);
9412 case TRANSACT2_SETFSINFO:
9414 START_PROFILE(Trans2_setfsinfo);
9415 call_trans2setfsinfo(conn, req,
9416 &state->param, state->total_param,
9417 &state->data, state->total_data,
9418 state->max_data_return);
9419 END_PROFILE(Trans2_setfsinfo);
9423 case TRANSACT2_QPATHINFO:
9424 case TRANSACT2_QFILEINFO:
9426 START_PROFILE(Trans2_qpathinfo);
9427 call_trans2qfilepathinfo(conn, req, state->call,
9428 &state->param, state->total_param,
9429 &state->data, state->total_data,
9430 state->max_data_return);
9431 END_PROFILE(Trans2_qpathinfo);
9435 case TRANSACT2_SETPATHINFO:
9436 case TRANSACT2_SETFILEINFO:
9438 START_PROFILE(Trans2_setpathinfo);
9439 call_trans2setfilepathinfo(conn, req, state->call,
9440 &state->param, state->total_param,
9441 &state->data, state->total_data,
9442 state->max_data_return);
9443 END_PROFILE(Trans2_setpathinfo);
9447 case TRANSACT2_FINDNOTIFYFIRST:
9449 START_PROFILE(Trans2_findnotifyfirst);
9450 call_trans2findnotifyfirst(conn, req,
9451 &state->param, state->total_param,
9452 &state->data, state->total_data,
9453 state->max_data_return);
9454 END_PROFILE(Trans2_findnotifyfirst);
9458 case TRANSACT2_FINDNOTIFYNEXT:
9460 START_PROFILE(Trans2_findnotifynext);
9461 call_trans2findnotifynext(conn, req,
9462 &state->param, state->total_param,
9463 &state->data, state->total_data,
9464 state->max_data_return);
9465 END_PROFILE(Trans2_findnotifynext);
9469 case TRANSACT2_MKDIR:
9471 START_PROFILE(Trans2_mkdir);
9472 call_trans2mkdir(conn, req,
9473 &state->param, state->total_param,
9474 &state->data, state->total_data,
9475 state->max_data_return);
9476 END_PROFILE(Trans2_mkdir);
9480 case TRANSACT2_GET_DFS_REFERRAL:
9482 START_PROFILE(Trans2_get_dfs_referral);
9483 call_trans2getdfsreferral(conn, req,
9484 &state->param, state->total_param,
9485 &state->data, state->total_data,
9486 state->max_data_return);
9487 END_PROFILE(Trans2_get_dfs_referral);
9491 case TRANSACT2_IOCTL:
9493 START_PROFILE(Trans2_ioctl);
9494 call_trans2ioctl(conn, req,
9495 &state->param, state->total_param,
9496 &state->data, state->total_data,
9497 state->max_data_return);
9498 END_PROFILE(Trans2_ioctl);
9503 /* Error in request */
9504 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9505 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9509 /****************************************************************************
9510 Reply to a SMBtrans2.
9511 ****************************************************************************/
9513 void reply_trans2(struct smb_request *req)
9515 connection_struct *conn = req->conn;
9520 unsigned int tran_call;
9521 struct trans_state *state;
9524 START_PROFILE(SMBtrans2);
9526 if (req->wct < 14) {
9527 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9528 END_PROFILE(SMBtrans2);
9532 dsoff = SVAL(req->vwv+12, 0);
9533 dscnt = SVAL(req->vwv+11, 0);
9534 psoff = SVAL(req->vwv+10, 0);
9535 pscnt = SVAL(req->vwv+9, 0);
9536 tran_call = SVAL(req->vwv+14, 0);
9538 result = allow_new_trans(conn->pending_trans, req->mid);
9539 if (!NT_STATUS_IS_OK(result)) {
9540 DEBUG(2, ("Got invalid trans2 request: %s\n",
9541 nt_errstr(result)));
9542 reply_nterror(req, result);
9543 END_PROFILE(SMBtrans2);
9548 switch (tran_call) {
9549 /* List the allowed trans2 calls on IPC$ */
9550 case TRANSACT2_OPEN:
9551 case TRANSACT2_GET_DFS_REFERRAL:
9552 case TRANSACT2_QFILEINFO:
9553 case TRANSACT2_QFSINFO:
9554 case TRANSACT2_SETFSINFO:
9557 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9558 END_PROFILE(SMBtrans2);
9563 if ((state = talloc(conn, struct trans_state)) == NULL) {
9564 DEBUG(0, ("talloc failed\n"));
9565 reply_nterror(req, NT_STATUS_NO_MEMORY);
9566 END_PROFILE(SMBtrans2);
9570 state->cmd = SMBtrans2;
9572 state->mid = req->mid;
9573 state->vuid = req->vuid;
9574 state->setup_count = SVAL(req->vwv+13, 0);
9575 state->setup = NULL;
9576 state->total_param = SVAL(req->vwv+0, 0);
9577 state->param = NULL;
9578 state->total_data = SVAL(req->vwv+1, 0);
9580 state->max_param_return = SVAL(req->vwv+2, 0);
9581 state->max_data_return = SVAL(req->vwv+3, 0);
9582 state->max_setup_return = SVAL(req->vwv+4, 0);
9583 state->close_on_completion = BITSETW(req->vwv+5, 0);
9584 state->one_way = BITSETW(req->vwv+5, 1);
9586 state->call = tran_call;
9588 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9589 is so as a sanity check */
9590 if (state->setup_count != 1) {
9592 * Need to have rc=0 for ioctl to get job id for OS/2.
9593 * Network printing will fail if function is not successful.
9594 * Similar function in reply.c will be used if protocol
9595 * is LANMAN1.0 instead of LM1.2X002.
9596 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9597 * outbuf doesn't have to be set(only job id is used).
9599 if ( (state->setup_count == 4)
9600 && (tran_call == TRANSACT2_IOCTL)
9601 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9602 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9603 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9605 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9606 DEBUG(2,("Transaction is %d\n",tran_call));
9608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9609 END_PROFILE(SMBtrans2);
9614 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9617 if (state->total_data) {
9619 if (trans_oob(state->total_data, 0, dscnt)
9620 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9624 /* Can't use talloc here, the core routines do realloc on the
9625 * params and data. */
9626 state->data = (char *)SMB_MALLOC(state->total_data);
9627 if (state->data == NULL) {
9628 DEBUG(0,("reply_trans2: data malloc fail for %u "
9629 "bytes !\n", (unsigned int)state->total_data));
9631 reply_nterror(req, NT_STATUS_NO_MEMORY);
9632 END_PROFILE(SMBtrans2);
9636 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9639 if (state->total_param) {
9641 if (trans_oob(state->total_param, 0, pscnt)
9642 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9646 /* Can't use talloc here, the core routines do realloc on the
9647 * params and data. */
9648 state->param = (char *)SMB_MALLOC(state->total_param);
9649 if (state->param == NULL) {
9650 DEBUG(0,("reply_trans: param malloc fail for %u "
9651 "bytes !\n", (unsigned int)state->total_param));
9652 SAFE_FREE(state->data);
9654 reply_nterror(req, NT_STATUS_NO_MEMORY);
9655 END_PROFILE(SMBtrans2);
9659 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9662 state->received_data = dscnt;
9663 state->received_param = pscnt;
9665 if ((state->received_param == state->total_param) &&
9666 (state->received_data == state->total_data)) {
9668 handle_trans2(conn, req, state);
9670 SAFE_FREE(state->data);
9671 SAFE_FREE(state->param);
9673 END_PROFILE(SMBtrans2);
9677 DLIST_ADD(conn->pending_trans, state);
9679 /* We need to send an interim response then receive the rest
9680 of the parameter/data bytes */
9681 reply_outbuf(req, 0, 0);
9682 show_msg((char *)req->outbuf);
9683 END_PROFILE(SMBtrans2);
9688 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9689 SAFE_FREE(state->data);
9690 SAFE_FREE(state->param);
9692 END_PROFILE(SMBtrans2);
9693 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9697 /****************************************************************************
9698 Reply to a SMBtranss2
9699 ****************************************************************************/
9701 void reply_transs2(struct smb_request *req)
9703 connection_struct *conn = req->conn;
9704 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9705 struct trans_state *state;
9707 START_PROFILE(SMBtranss2);
9709 show_msg((const char *)req->inbuf);
9711 /* Windows clients expect all replies to
9712 a transact secondary (SMBtranss2 0x33)
9713 to have a command code of transact
9714 (SMBtrans2 0x32). See bug #8989
9715 and also [MS-CIFS] section 2.2.4.47.2
9718 req->cmd = SMBtrans2;
9721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9722 END_PROFILE(SMBtranss2);
9726 for (state = conn->pending_trans; state != NULL;
9727 state = state->next) {
9728 if (state->mid == req->mid) {
9733 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9734 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9735 END_PROFILE(SMBtranss2);
9739 /* Revise state->total_param and state->total_data in case they have
9740 changed downwards */
9742 if (SVAL(req->vwv+0, 0) < state->total_param)
9743 state->total_param = SVAL(req->vwv+0, 0);
9744 if (SVAL(req->vwv+1, 0) < state->total_data)
9745 state->total_data = SVAL(req->vwv+1, 0);
9747 pcnt = SVAL(req->vwv+2, 0);
9748 poff = SVAL(req->vwv+3, 0);
9749 pdisp = SVAL(req->vwv+4, 0);
9751 dcnt = SVAL(req->vwv+5, 0);
9752 doff = SVAL(req->vwv+6, 0);
9753 ddisp = SVAL(req->vwv+7, 0);
9755 state->received_param += pcnt;
9756 state->received_data += dcnt;
9758 if ((state->received_data > state->total_data) ||
9759 (state->received_param > state->total_param))
9763 if (trans_oob(state->total_param, pdisp, pcnt)
9764 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9767 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9771 if (trans_oob(state->total_data, ddisp, dcnt)
9772 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9775 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9778 if ((state->received_param < state->total_param) ||
9779 (state->received_data < state->total_data)) {
9780 END_PROFILE(SMBtranss2);
9784 handle_trans2(conn, req, state);
9786 DLIST_REMOVE(conn->pending_trans, state);
9787 SAFE_FREE(state->data);
9788 SAFE_FREE(state->param);
9791 END_PROFILE(SMBtranss2);
9796 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9797 DLIST_REMOVE(conn->pending_trans, state);
9798 SAFE_FREE(state->data);
9799 SAFE_FREE(state->param);
9801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9802 END_PROFILE(SMBtranss2);