2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
55 const SMB_STRUCT_STAT *psbuf);
57 /****************************************************************************
58 Check if an open file handle or smb_fname is a symlink.
59 ****************************************************************************/
61 static NTSTATUS refuse_symlink(connection_struct *conn,
62 const files_struct *fsp,
63 const struct smb_filename *smb_fname)
66 const SMB_STRUCT_STAT *pst = NULL;
69 pst = &fsp->fsp_name->st;
74 if (!VALID_STAT(*pst)) {
75 int ret = vfs_stat_smb_basename(conn,
78 if (ret == -1 && errno != ENOENT) {
79 return map_nt_error_from_unix(errno);
80 } else if (ret == -1) {
81 /* it's not a symlink.. */
87 if (S_ISLNK(pst->st_ex_mode)) {
88 return NT_STATUS_ACCESS_DENIED;
93 NTSTATUS check_access_fsp(const struct files_struct *fsp,
96 if (!(fsp->access_mask & access_mask)) {
97 return NT_STATUS_ACCESS_DENIED;
102 /********************************************************************
103 The canonical "check access" based on object handle or path function.
104 ********************************************************************/
106 NTSTATUS check_access(connection_struct *conn,
108 const struct smb_filename *smb_fname,
109 uint32_t access_mask)
114 status = check_access_fsp(fsp, access_mask);
116 status = smbd_check_access_rights(conn, smb_fname,
123 /********************************************************************
124 Roundup a value to the nearest allocation roundup size boundary.
125 Only do this for Windows clients.
126 ********************************************************************/
128 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
130 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
132 /* Only roundup for Windows clients. */
133 enum remote_arch_types ra_type = get_remote_arch();
134 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
135 val = SMB_ROUNDUP(val,rval);
140 /********************************************************************
141 Create a 64 bit FileIndex. If the file is on the same device as
142 the root of the share, just return the 64-bit inode. If it isn't,
143 mangle as we used to do.
144 ********************************************************************/
146 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
149 if (conn->sconn->aapl_zero_file_id) {
152 if (conn->base_share_dev == psbuf->st_ex_dev) {
153 return (uint64_t)psbuf->st_ex_ino;
155 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
156 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
161 /********************************************************************
162 Globally (for this connection / multi-channel) disable file-ID
163 calculation. This is required to be global because it serves
164 Macs in AAPL mode, which is globally set.
165 ********************************************************************/
166 void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
168 sconn->aapl_zero_file_id = true;
171 /****************************************************************************
172 Utility functions for dealing with extended attributes.
173 ****************************************************************************/
175 /****************************************************************************
176 Refuse to allow clients to overwrite our private xattrs.
177 ****************************************************************************/
179 bool samba_private_attr_name(const char *unix_ea_name)
181 static const char * const prohibited_ea_names[] = {
182 SAMBA_POSIX_INHERITANCE_EA_NAME,
183 SAMBA_XATTR_DOS_ATTRIB,
191 for (i = 0; prohibited_ea_names[i]; i++) {
192 if (strequal( prohibited_ea_names[i], unix_ea_name))
195 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
196 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
202 /****************************************************************************
203 Get one EA value. Fill in a struct ea_struct.
204 ****************************************************************************/
206 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
207 connection_struct *conn,
209 const struct smb_filename *smb_fname,
211 struct ea_struct *pea)
213 /* Get the value of this xattr. Max size is 64k. */
214 size_t attr_size = 256;
220 val = talloc_realloc(mem_ctx, val, char, attr_size);
222 return NT_STATUS_NO_MEMORY;
225 if (fsp && fsp->fh->fd != -1) {
226 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
228 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
229 ea_name, val, attr_size);
232 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
238 return map_nt_error_from_unix(errno);
241 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
242 dump_data(10, (uint8_t *)val, sizeret);
245 if (strnequal(ea_name, "user.", 5)) {
246 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
248 pea->name = talloc_strdup(mem_ctx, ea_name);
250 if (pea->name == NULL) {
252 return NT_STATUS_NO_MEMORY;
254 pea->value.data = (unsigned char *)val;
255 pea->value.length = (size_t)sizeret;
259 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
260 connection_struct *conn,
262 const struct smb_filename *smb_fname,
267 /* Get a list of all xattrs. Max namesize is 64k. */
268 size_t ea_namelist_size = 1024;
269 char *ea_namelist = smallbuf;
270 char *to_free = NULL;
275 ssize_t sizeret = -1;
283 status = refuse_symlink(conn, fsp, smb_fname);
284 if (!NT_STATUS_IS_OK(status)) {
286 * Just return no EA's on a symlink.
291 if (fsp && fsp->fh->fd != -1) {
292 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
295 sizeret = SMB_VFS_LISTXATTR(conn,
301 if ((sizeret == -1) && (errno == ERANGE)) {
302 ea_namelist_size = 65536;
303 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
304 if (ea_namelist == NULL) {
305 return NT_STATUS_NO_MEMORY;
307 to_free = ea_namelist;
309 if (fsp && fsp->fh->fd != -1) {
310 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
313 sizeret = SMB_VFS_LISTXATTR(conn,
321 status = map_nt_error_from_unix(errno);
322 TALLOC_FREE(to_free);
326 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
329 TALLOC_FREE(to_free);
334 * Ensure the result is 0-terminated
337 if (ea_namelist[sizeret-1] != '\0') {
338 TALLOC_FREE(to_free);
339 return NT_STATUS_INTERNAL_ERROR;
347 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
351 *pnum_names = num_names;
353 if (pnames == NULL) {
354 TALLOC_FREE(to_free);
358 names = talloc_array(mem_ctx, char *, num_names);
360 DEBUG(0, ("talloc failed\n"));
361 TALLOC_FREE(to_free);
362 return NT_STATUS_NO_MEMORY;
365 if (ea_namelist == smallbuf) {
366 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
367 if (ea_namelist == NULL) {
369 return NT_STATUS_NO_MEMORY;
372 talloc_steal(names, ea_namelist);
374 ea_namelist = talloc_realloc(names, ea_namelist, char,
376 if (ea_namelist == NULL) {
378 return NT_STATUS_NO_MEMORY;
384 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
385 names[num_names++] = p;
393 /****************************************************************************
394 Return a linked list of the total EA's. Plus the total size
395 ****************************************************************************/
397 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
398 connection_struct *conn,
400 const struct smb_filename *smb_fname,
401 size_t *pea_total_len,
402 struct ea_list **ea_list)
404 /* Get a list of all xattrs. Max namesize is 64k. */
407 struct ea_list *ea_list_head = NULL;
408 bool posix_pathnames = false;
414 if (!lp_ea_support(SNUM(conn))) {
420 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
422 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
425 status = get_ea_names_from_file(talloc_tos(),
432 if (!NT_STATUS_IS_OK(status)) {
436 if (num_names == 0) {
440 for (i=0; i<num_names; i++) {
441 struct ea_list *listp;
444 if (strnequal(names[i], "system.", 7)
445 || samba_private_attr_name(names[i]))
449 * Filter out any underlying POSIX EA names
450 * that a Windows client can't handle.
452 if (!posix_pathnames &&
453 is_invalid_windows_ea_name(names[i])) {
457 listp = talloc(mem_ctx, struct ea_list);
459 return NT_STATUS_NO_MEMORY;
462 status = get_ea_value(listp,
469 if (!NT_STATUS_IS_OK(status)) {
474 if (listp->ea.value.length == 0) {
476 * We can never return a zero length EA.
477 * Windows reports the EA's as corrupted.
483 push_ascii_fstring(dos_ea_name, listp->ea.name);
486 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
488 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
489 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
490 (unsigned int)listp->ea.value.length));
492 DLIST_ADD_END(ea_list_head, listp);
496 /* Add on 4 for total length. */
497 if (*pea_total_len) {
501 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
502 (unsigned int)*pea_total_len));
504 *ea_list = ea_list_head;
508 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
509 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
514 if (!lp_ea_support(SNUM(conn))) {
518 if (is_ntfs_stream_smb_fname(smb_fname)) {
519 return NT_STATUS_INVALID_PARAMETER;
522 return get_ea_list_from_file_path(mem_ctx,
530 /****************************************************************************
531 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
533 ****************************************************************************/
535 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
536 connection_struct *conn, struct ea_list *ea_list)
538 unsigned int ret_data_size = 4;
541 SMB_ASSERT(total_data_size >= 4);
543 if (!lp_ea_support(SNUM(conn))) {
548 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
551 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
552 dos_namelen = strlen(dos_ea_name);
553 if (dos_namelen > 255 || dos_namelen == 0) {
556 if (ea_list->ea.value.length > 65535) {
559 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
563 /* We know we have room. */
564 SCVAL(p,0,ea_list->ea.flags);
565 SCVAL(p,1,dos_namelen);
566 SSVAL(p,2,ea_list->ea.value.length);
567 strlcpy(p+4, dos_ea_name, dos_namelen+1);
568 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
570 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
571 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
574 ret_data_size = PTR_DIFF(p, pdata);
575 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
576 SIVAL(pdata,0,ret_data_size);
577 return ret_data_size;
580 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
582 unsigned int total_data_size,
583 unsigned int *ret_data_size,
584 connection_struct *conn,
585 struct ea_list *ea_list)
587 uint8_t *p = (uint8_t *)pdata;
588 uint8_t *last_start = NULL;
589 bool do_store_data = (pdata != NULL);
593 if (!lp_ea_support(SNUM(conn))) {
594 return NT_STATUS_NO_EAS_ON_FILE;
597 for (; ea_list; ea_list = ea_list->next) {
603 if (last_start != NULL && do_store_data) {
604 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
608 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
609 dos_namelen = strlen(dos_ea_name);
610 if (dos_namelen > 255 || dos_namelen == 0) {
611 return NT_STATUS_INTERNAL_ERROR;
613 if (ea_list->ea.value.length > 65535) {
614 return NT_STATUS_INTERNAL_ERROR;
617 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
620 pad = (4 - (this_size % 4)) % 4;
625 if (this_size > total_data_size) {
626 return NT_STATUS_INFO_LENGTH_MISMATCH;
629 /* We know we have room. */
630 SIVAL(p, 0x00, 0); /* next offset */
631 SCVAL(p, 0x04, ea_list->ea.flags);
632 SCVAL(p, 0x05, dos_namelen);
633 SSVAL(p, 0x06, ea_list->ea.value.length);
634 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
635 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
637 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
641 total_data_size -= this_size;
647 *ret_data_size = PTR_DIFF(p, pdata);
648 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
652 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
654 size_t total_ea_len = 0;
656 struct ea_list *ea_list = NULL;
658 if (!lp_ea_support(SNUM(conn))) {
661 mem_ctx = talloc_stackframe();
663 /* If this is a stream fsp, then we need to instead find the
664 * estimated ea len from the main file, not the stream
665 * (streams cannot have EAs), but the estimate isn't just 0 in
667 if (is_ntfs_stream_smb_fname(smb_fname)) {
670 (void)get_ea_list_from_file_path(mem_ctx,
676 if(conn->sconn->using_smb2) {
678 unsigned int ret_data_size;
680 * We're going to be using fill_ea_chained_buffer() to
681 * marshall EA's - this size is significantly larger
682 * than the SMB1 buffer. Re-calculate the size without
685 status = fill_ea_chained_buffer(mem_ctx,
691 if (!NT_STATUS_IS_OK(status)) {
694 total_ea_len = ret_data_size;
696 TALLOC_FREE(mem_ctx);
700 /****************************************************************************
701 Ensure the EA name is case insensitive by matching any existing EA name.
702 ****************************************************************************/
704 static void canonicalize_ea_name(connection_struct *conn,
706 const struct smb_filename *smb_fname,
707 fstring unix_ea_name)
710 TALLOC_CTX *mem_ctx = talloc_tos();
711 struct ea_list *ea_list;
712 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
718 if (!NT_STATUS_IS_OK(status)) {
722 for (; ea_list; ea_list = ea_list->next) {
723 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
724 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
725 &unix_ea_name[5], ea_list->ea.name));
726 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
732 /****************************************************************************
733 Set or delete an extended attribute.
734 ****************************************************************************/
736 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
737 const struct smb_filename *smb_fname, struct ea_list *ea_list)
740 bool posix_pathnames = false;
742 if (!lp_ea_support(SNUM(conn))) {
743 return NT_STATUS_EAS_NOT_SUPPORTED;
748 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
750 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
753 status = refuse_symlink(conn, fsp, smb_fname);
754 if (!NT_STATUS_IS_OK(status)) {
758 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
759 if (!NT_STATUS_IS_OK(status)) {
763 /* Setting EAs on streams isn't supported. */
764 if (is_ntfs_stream_smb_fname(smb_fname)) {
765 return NT_STATUS_INVALID_PARAMETER;
769 * Filter out invalid Windows EA names - before
770 * we set *any* of them.
773 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
774 return STATUS_INVALID_EA_NAME;
777 for (;ea_list; ea_list = ea_list->next) {
779 fstring unix_ea_name;
781 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
782 fstrcat(unix_ea_name, ea_list->ea.name);
784 canonicalize_ea_name(conn,
789 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
791 if (samba_private_attr_name(unix_ea_name)) {
792 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
793 return NT_STATUS_ACCESS_DENIED;
796 if (ea_list->ea.value.length == 0) {
797 /* Remove the attribute. */
798 if (fsp && (fsp->fh->fd != -1)) {
799 DEBUG(10,("set_ea: deleting ea name %s on "
800 "file %s by file descriptor.\n",
801 unix_ea_name, fsp_str_dbg(fsp)));
802 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
804 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
805 unix_ea_name, smb_fname->base_name));
806 ret = SMB_VFS_REMOVEXATTR(conn,
811 /* Removing a non existent attribute always succeeds. */
812 if (ret == -1 && errno == ENOATTR) {
813 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
819 if (fsp && (fsp->fh->fd != -1)) {
820 DEBUG(10,("set_ea: setting ea name %s on file "
821 "%s by file descriptor.\n",
822 unix_ea_name, fsp_str_dbg(fsp)));
823 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
824 ea_list->ea.value.data, ea_list->ea.value.length, 0);
826 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
827 unix_ea_name, smb_fname->base_name));
828 ret = SMB_VFS_SETXATTR(conn,
831 ea_list->ea.value.data,
832 ea_list->ea.value.length,
839 if (errno == ENOTSUP) {
840 return NT_STATUS_EAS_NOT_SUPPORTED;
843 return map_nt_error_from_unix(errno);
849 /****************************************************************************
850 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
851 ****************************************************************************/
853 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
855 struct ea_list *ea_list_head = NULL;
856 size_t converted_size, offset = 0;
858 while (offset + 2 < data_size) {
859 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
860 unsigned int namelen = CVAL(pdata,offset);
862 offset++; /* Go past the namelen byte. */
864 /* integer wrap paranioa. */
865 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
866 (offset > data_size) || (namelen > data_size) ||
867 (offset + namelen >= data_size)) {
870 /* Ensure the name is null terminated. */
871 if (pdata[offset + namelen] != '\0') {
874 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
876 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
877 "failed: %s", strerror(errno)));
883 offset += (namelen + 1); /* Go past the name + terminating zero. */
884 DLIST_ADD_END(ea_list_head, eal);
885 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
891 /****************************************************************************
892 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
893 ****************************************************************************/
895 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
897 struct ea_list *ea_list_head = NULL;
899 size_t bytes_used = 0;
901 while (offset < data_size) {
902 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
908 DLIST_ADD_END(ea_list_head, eal);
909 offset += bytes_used;
915 /****************************************************************************
916 Count the total EA size needed.
917 ****************************************************************************/
919 static size_t ea_list_size(struct ea_list *ealist)
922 struct ea_list *listp;
925 for (listp = ealist; listp; listp = listp->next) {
926 push_ascii_fstring(dos_ea_name, listp->ea.name);
927 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
929 /* Add on 4 for total length. */
937 /****************************************************************************
938 Return a union of EA's from a file list and a list of names.
939 The TALLOC context for the two lists *MUST* be identical as we steal
940 memory from one list to add to another. JRA.
941 ****************************************************************************/
943 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
945 struct ea_list *nlistp, *flistp;
947 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
948 for (flistp = file_list; flistp; flistp = flistp->next) {
949 if (strequal(nlistp->ea.name, flistp->ea.name)) {
955 /* Copy the data from this entry. */
956 nlistp->ea.flags = flistp->ea.flags;
957 nlistp->ea.value = flistp->ea.value;
960 nlistp->ea.flags = 0;
961 ZERO_STRUCT(nlistp->ea.value);
965 *total_ea_len = ea_list_size(name_list);
969 /****************************************************************************
970 Send the required number of replies back.
971 We assume all fields other than the data fields are
972 set correctly for the type of call.
973 HACK ! Always assumes smb_setup field is zero.
974 ****************************************************************************/
976 void send_trans2_replies(connection_struct *conn,
977 struct smb_request *req,
985 /* As we are using a protocol > LANMAN1 then the max_send
986 variable must have been set in the sessetupX call.
987 This takes precedence over the max_xmit field in the
988 global struct. These different max_xmit variables should
989 be merged as this is now too confusing */
991 int data_to_send = datasize;
992 int params_to_send = paramsize;
994 const char *pp = params;
995 const char *pd = pdata;
996 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
997 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
998 int data_alignment_offset = 0;
999 bool overflow = False;
1000 struct smbXsrv_connection *xconn = req->xconn;
1001 int max_send = xconn->smb1.sessions.max_send;
1003 /* Modify the data_to_send and datasize and set the error if
1004 we're trying to send more than max_data_bytes. We still send
1005 the part of the packet(s) that fit. Strange, but needed
1008 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1009 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1010 max_data_bytes, datasize ));
1011 datasize = data_to_send = max_data_bytes;
1015 /* If there genuinely are no parameters or data to send just send the empty packet */
1017 if(params_to_send == 0 && data_to_send == 0) {
1018 reply_outbuf(req, 10, 0);
1019 if (NT_STATUS_V(status)) {
1022 ntstatus_to_dos(status, &eclass, &ecode);
1023 error_packet_set((char *)req->outbuf,
1024 eclass, ecode, status,
1027 show_msg((char *)req->outbuf);
1028 if (!srv_send_smb(xconn,
1029 (char *)req->outbuf,
1030 true, req->seqnum+1,
1031 IS_CONN_ENCRYPTED(conn),
1033 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1035 TALLOC_FREE(req->outbuf);
1039 /* When sending params and data ensure that both are nicely aligned */
1040 /* Only do this alignment when there is also data to send - else
1041 can cause NT redirector problems. */
1043 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1044 data_alignment_offset = 4 - (params_to_send % 4);
1046 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1047 /* The alignment_offset is to align the param bytes on an even byte
1048 boundary. NT 4.0 Beta needs this to work correctly. */
1050 useable_space = max_send - (smb_size
1053 + data_alignment_offset);
1055 if (useable_space < 0) {
1056 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1057 "= %d!!!", useable_space));
1058 exit_server_cleanly("send_trans2_replies: Not enough space");
1061 while (params_to_send || data_to_send) {
1062 /* Calculate whether we will totally or partially fill this packet */
1064 total_sent_thistime = params_to_send + data_to_send;
1066 /* We can never send more than useable_space */
1068 * Note that 'useable_space' does not include the alignment offsets,
1069 * but we must include the alignment offsets in the calculation of
1070 * the length of the data we send over the wire, as the alignment offsets
1071 * are sent here. Fix from Marc_Jacobsen@hp.com.
1074 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1076 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1077 + data_alignment_offset);
1079 /* Set total params and data to be sent */
1080 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1081 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1083 /* Calculate how many parameters and data we can fit into
1084 * this packet. Parameters get precedence
1087 params_sent_thistime = MIN(params_to_send,useable_space);
1088 data_sent_thistime = useable_space - params_sent_thistime;
1089 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1091 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1093 /* smb_proff is the offset from the start of the SMB header to the
1094 parameter bytes, however the first 4 bytes of outbuf are
1095 the Netbios over TCP header. Thus use smb_base() to subtract
1096 them from the calculation */
1098 SSVAL(req->outbuf,smb_proff,
1099 ((smb_buf(req->outbuf)+alignment_offset)
1100 - smb_base(req->outbuf)));
1102 if(params_sent_thistime == 0)
1103 SSVAL(req->outbuf,smb_prdisp,0);
1105 /* Absolute displacement of param bytes sent in this packet */
1106 SSVAL(req->outbuf,smb_prdisp,pp - params);
1108 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1109 if(data_sent_thistime == 0) {
1110 SSVAL(req->outbuf,smb_droff,0);
1111 SSVAL(req->outbuf,smb_drdisp, 0);
1113 /* The offset of the data bytes is the offset of the
1114 parameter bytes plus the number of parameters being sent this time */
1115 SSVAL(req->outbuf, smb_droff,
1116 ((smb_buf(req->outbuf)+alignment_offset)
1117 - smb_base(req->outbuf))
1118 + params_sent_thistime + data_alignment_offset);
1119 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1122 /* Initialize the padding for alignment */
1124 if (alignment_offset != 0) {
1125 memset(smb_buf(req->outbuf), 0, alignment_offset);
1128 /* Copy the param bytes into the packet */
1130 if(params_sent_thistime) {
1131 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1132 params_sent_thistime);
1135 /* Copy in the data bytes */
1136 if(data_sent_thistime) {
1137 if (data_alignment_offset != 0) {
1138 memset((smb_buf(req->outbuf)+alignment_offset+
1139 params_sent_thistime), 0,
1140 data_alignment_offset);
1142 memcpy(smb_buf(req->outbuf)+alignment_offset
1143 +params_sent_thistime+data_alignment_offset,
1144 pd,data_sent_thistime);
1147 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1148 params_sent_thistime, data_sent_thistime, useable_space));
1149 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1150 params_to_send, data_to_send, paramsize, datasize));
1153 error_packet_set((char *)req->outbuf,
1154 ERRDOS,ERRbufferoverflow,
1155 STATUS_BUFFER_OVERFLOW,
1157 } else if (NT_STATUS_V(status)) {
1160 ntstatus_to_dos(status, &eclass, &ecode);
1161 error_packet_set((char *)req->outbuf,
1162 eclass, ecode, status,
1166 /* Send the packet */
1167 show_msg((char *)req->outbuf);
1168 if (!srv_send_smb(xconn,
1169 (char *)req->outbuf,
1170 true, req->seqnum+1,
1171 IS_CONN_ENCRYPTED(conn),
1173 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1175 TALLOC_FREE(req->outbuf);
1177 pp += params_sent_thistime;
1178 pd += data_sent_thistime;
1180 params_to_send -= params_sent_thistime;
1181 data_to_send -= data_sent_thistime;
1184 if(params_to_send < 0 || data_to_send < 0) {
1185 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1186 params_to_send, data_to_send));
1194 /****************************************************************************
1195 Reply to a TRANSACT2_OPEN.
1196 ****************************************************************************/
1198 static void call_trans2open(connection_struct *conn,
1199 struct smb_request *req,
1200 char **pparams, int total_params,
1201 char **ppdata, int total_data,
1202 unsigned int max_data_bytes)
1204 struct smb_filename *smb_fname = NULL;
1205 char *params = *pparams;
1206 char *pdata = *ppdata;
1209 bool oplock_request;
1211 bool return_additional_info;
1220 int fattr=0,mtime=0;
1221 SMB_INO_T inode = 0;
1224 struct ea_list *ea_list = NULL;
1227 uint32_t access_mask;
1228 uint32_t share_mode;
1229 uint32_t create_disposition;
1230 uint32_t create_options = 0;
1231 uint32_t private_flags = 0;
1232 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1233 TALLOC_CTX *ctx = talloc_tos();
1236 * Ensure we have enough parameters to perform the operation.
1239 if (total_params < 29) {
1240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1244 flags = SVAL(params, 0);
1245 deny_mode = SVAL(params, 2);
1246 open_attr = SVAL(params,6);
1247 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1248 if (oplock_request) {
1249 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1253 return_additional_info = BITSETW(params,0);
1254 open_sattr = SVAL(params, 4);
1255 open_time = make_unix_date3(params+8);
1257 open_ofun = SVAL(params,12);
1258 open_size = IVAL(params,14);
1259 pname = ¶ms[28];
1262 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1266 if (req->posix_pathnames) {
1267 srvstr_get_path_posix(ctx,
1276 srvstr_get_path(ctx,
1285 if (!NT_STATUS_IS_OK(status)) {
1286 reply_nterror(req, status);
1290 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1291 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1292 (unsigned int)open_ofun, open_size));
1294 status = filename_convert(ctx,
1300 if (!NT_STATUS_IS_OK(status)) {
1301 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1302 reply_botherror(req,
1303 NT_STATUS_PATH_NOT_COVERED,
1304 ERRSRV, ERRbadpath);
1307 reply_nterror(req, status);
1311 if (open_ofun == 0) {
1312 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1316 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1318 &access_mask, &share_mode,
1319 &create_disposition,
1322 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1326 /* Any data in this call is an EA list. */
1327 if (total_data && (total_data != 4)) {
1328 if (total_data < 10) {
1329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1333 if (IVAL(pdata,0) > total_data) {
1334 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1335 IVAL(pdata,0), (unsigned int)total_data));
1336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1340 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1347 if (!lp_ea_support(SNUM(conn))) {
1348 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1352 if (!req->posix_pathnames &&
1353 ea_list_has_invalid_name(ea_list)) {
1355 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1356 if(*pparams == NULL ) {
1357 reply_nterror(req, NT_STATUS_NO_MEMORY);
1361 memset(params, '\0', param_len);
1362 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1363 params, param_len, NULL, 0, max_data_bytes);
1368 status = SMB_VFS_CREATE_FILE(
1371 0, /* root_dir_fid */
1372 smb_fname, /* fname */
1373 access_mask, /* access_mask */
1374 share_mode, /* share_access */
1375 create_disposition, /* create_disposition*/
1376 create_options, /* create_options */
1377 open_attr, /* file_attributes */
1378 oplock_request, /* oplock_request */
1380 open_size, /* allocation_size */
1383 ea_list, /* ea_list */
1385 &smb_action, /* psbuf */
1386 NULL, NULL); /* create context */
1388 if (!NT_STATUS_IS_OK(status)) {
1389 if (open_was_deferred(req->xconn, req->mid)) {
1390 /* We have re-scheduled this call. */
1393 reply_openerror(req, status);
1397 size = get_file_size_stat(&smb_fname->st);
1398 fattr = dos_mode(conn, smb_fname);
1399 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1400 inode = smb_fname->st.st_ex_ino;
1401 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1402 close_file(req, fsp, ERROR_CLOSE);
1403 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1407 /* Realloc the size of parameters and data we will return */
1408 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1409 if(*pparams == NULL ) {
1410 reply_nterror(req, NT_STATUS_NO_MEMORY);
1415 SSVAL(params,0,fsp->fnum);
1416 SSVAL(params,2,fattr);
1417 srv_put_dos_date2(params,4, mtime);
1418 SIVAL(params,8, (uint32_t)size);
1419 SSVAL(params,12,deny_mode);
1420 SSVAL(params,14,0); /* open_type - file or directory. */
1421 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1423 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1424 smb_action |= EXTENDED_OPLOCK_GRANTED;
1427 SSVAL(params,18,smb_action);
1430 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1432 SIVAL(params,20,inode);
1433 SSVAL(params,24,0); /* Padding. */
1435 uint32_t ea_size = estimate_ea_size(conn, fsp,
1437 SIVAL(params, 26, ea_size);
1439 SIVAL(params, 26, 0);
1442 /* Send the required number of replies */
1443 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1445 TALLOC_FREE(smb_fname);
1448 /*********************************************************
1449 Routine to check if a given string matches exactly.
1450 as a special case a mask of "." does NOT match. That
1451 is required for correct wildcard semantics
1452 Case can be significant or not.
1453 **********************************************************/
1455 static bool exact_match(bool has_wild,
1456 bool case_sensitive,
1460 if (mask[0] == '.' && mask[1] == 0) {
1468 if (case_sensitive) {
1469 return strcmp(str,mask)==0;
1471 return strcasecmp_m(str,mask) == 0;
1475 /****************************************************************************
1476 Return the filetype for UNIX extensions.
1477 ****************************************************************************/
1479 static uint32_t unix_filetype(mode_t mode)
1482 return UNIX_TYPE_FILE;
1483 else if(S_ISDIR(mode))
1484 return UNIX_TYPE_DIR;
1486 else if(S_ISLNK(mode))
1487 return UNIX_TYPE_SYMLINK;
1490 else if(S_ISCHR(mode))
1491 return UNIX_TYPE_CHARDEV;
1494 else if(S_ISBLK(mode))
1495 return UNIX_TYPE_BLKDEV;
1498 else if(S_ISFIFO(mode))
1499 return UNIX_TYPE_FIFO;
1502 else if(S_ISSOCK(mode))
1503 return UNIX_TYPE_SOCKET;
1506 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1507 return UNIX_TYPE_UNKNOWN;
1510 /****************************************************************************
1511 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1512 ****************************************************************************/
1514 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1516 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1517 const SMB_STRUCT_STAT *psbuf,
1519 enum perm_type ptype,
1524 if (perms == SMB_MODE_NO_CHANGE) {
1525 if (!VALID_STAT(*psbuf)) {
1526 return NT_STATUS_INVALID_PARAMETER;
1528 *ret_perms = psbuf->st_ex_mode;
1529 return NT_STATUS_OK;
1533 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1534 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1535 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1536 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1537 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1538 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1539 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1540 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1541 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1543 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1546 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1549 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1552 if (ptype == PERM_NEW_FILE) {
1554 * "create mask"/"force create mode" are
1555 * only applied to new files, not existing ones.
1557 ret &= lp_create_mask(SNUM(conn));
1558 /* Add in force bits */
1559 ret |= lp_force_create_mode(SNUM(conn));
1560 } else if (ptype == PERM_NEW_DIR) {
1562 * "directory mask"/"force directory mode" are
1563 * only applied to new directories, not existing ones.
1565 ret &= lp_directory_mask(SNUM(conn));
1566 /* Add in force bits */
1567 ret |= lp_force_directory_mode(SNUM(conn));
1571 return NT_STATUS_OK;
1574 /****************************************************************************
1575 Needed to show the msdfs symlinks as directories. Modifies psbuf
1576 to be a directory if it's a msdfs link.
1577 ****************************************************************************/
1579 static bool check_msdfs_link(connection_struct *conn,
1580 struct smb_filename *smb_fname)
1582 int saved_errno = errno;
1583 if(lp_host_msdfs() &&
1584 lp_msdfs_root(SNUM(conn)) &&
1585 is_msdfs_link(conn, smb_fname)) {
1587 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1589 smb_fname->base_name));
1590 smb_fname->st.st_ex_mode =
1591 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1592 errno = saved_errno;
1595 errno = saved_errno;
1600 /****************************************************************************
1601 Get a level dependent lanman2 dir entry.
1602 ****************************************************************************/
1604 struct smbd_dirptr_lanman2_state {
1605 connection_struct *conn;
1606 uint32_t info_level;
1607 bool check_mangled_names;
1609 bool got_exact_match;
1612 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1618 struct smbd_dirptr_lanman2_state *state =
1619 (struct smbd_dirptr_lanman2_state *)private_data;
1621 char mangled_name[13]; /* mangled 8.3 name. */
1625 /* Mangle fname if it's an illegal name. */
1626 if (mangle_must_mangle(dname, state->conn->params)) {
1628 * Slow path - ensure we can push the original name as UCS2. If
1629 * not, then just don't return this name.
1633 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1634 uint8_t *tmp = talloc_array(talloc_tos(),
1638 status = srvstr_push(NULL,
1639 FLAGS2_UNICODE_STRINGS,
1648 if (!NT_STATUS_IS_OK(status)) {
1652 ok = name_to_8_3(dname, mangled_name,
1653 true, state->conn->params);
1657 fname = mangled_name;
1662 got_match = exact_match(state->has_wild,
1663 state->conn->case_sensitive,
1665 state->got_exact_match = got_match;
1667 got_match = mask_match(fname, mask,
1668 state->conn->case_sensitive);
1671 if(!got_match && state->check_mangled_names &&
1672 !mangle_is_8_3(fname, false, state->conn->params)) {
1674 * It turns out that NT matches wildcards against
1675 * both long *and* short names. This may explain some
1676 * of the wildcard wierdness from old DOS clients
1677 * that some people have been seeing.... JRA.
1679 /* Force the mangling into 8.3. */
1680 ok = name_to_8_3(fname, mangled_name,
1681 false, state->conn->params);
1686 got_match = exact_match(state->has_wild,
1687 state->conn->case_sensitive,
1688 mangled_name, mask);
1689 state->got_exact_match = got_match;
1691 got_match = mask_match(mangled_name, mask,
1692 state->conn->case_sensitive);
1700 *_fname = talloc_strdup(ctx, fname);
1701 if (*_fname == NULL) {
1708 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1710 struct smb_filename *smb_fname,
1713 struct smbd_dirptr_lanman2_state *state =
1714 (struct smbd_dirptr_lanman2_state *)private_data;
1715 bool ms_dfs_link = false;
1718 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1719 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1720 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1721 "Couldn't lstat [%s] (%s)\n",
1722 smb_fname_str_dbg(smb_fname),
1726 } else if (!VALID_STAT(smb_fname->st) &&
1727 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1728 /* Needed to show the msdfs symlinks as
1731 ms_dfs_link = check_msdfs_link(state->conn,
1734 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1735 "Couldn't stat [%s] (%s)\n",
1736 smb_fname_str_dbg(smb_fname),
1743 mode = dos_mode_msdfs(state->conn, smb_fname);
1745 mode = dos_mode(state->conn, smb_fname);
1752 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1753 connection_struct *conn,
1755 uint32_t info_level,
1756 struct ea_list *name_list,
1757 bool check_mangled_names,
1758 bool requires_resume_key,
1761 const struct smb_filename *smb_fname,
1762 int space_remaining,
1768 uint64_t *last_entry_off)
1770 char *p, *q, *pdata = *ppdata;
1772 uint64_t file_size = 0;
1773 uint64_t allocation_size = 0;
1774 uint64_t file_index = 0;
1776 struct timespec mdate_ts = {0};
1777 struct timespec adate_ts = {0};
1778 struct timespec cdate_ts = {0};
1779 struct timespec create_date_ts = {0};
1780 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1782 char *last_entry_ptr;
1787 struct readdir_attr_data *readdir_attr_data = NULL;
1789 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1790 file_size = get_file_size_stat(&smb_fname->st);
1792 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1794 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1801 file_index = get_FileIndex(conn, &smb_fname->st);
1803 mdate_ts = smb_fname->st.st_ex_mtime;
1804 adate_ts = smb_fname->st.st_ex_atime;
1805 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1806 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1808 if (lp_dos_filetime_resolution(SNUM(conn))) {
1809 dos_filetime_timespec(&create_date_ts);
1810 dos_filetime_timespec(&mdate_ts);
1811 dos_filetime_timespec(&adate_ts);
1812 dos_filetime_timespec(&cdate_ts);
1815 create_date = convert_timespec_to_time_t(create_date_ts);
1816 mdate = convert_timespec_to_time_t(mdate_ts);
1817 adate = convert_timespec_to_time_t(adate_ts);
1819 /* align the record */
1820 SMB_ASSERT(align >= 1);
1822 off = (int)PTR_DIFF(pdata, base_data);
1823 pad = (off + (align-1)) & ~(align-1);
1826 if (pad && pad > space_remaining) {
1827 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1828 "for padding (wanted %u, had %d)\n",
1831 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1835 /* initialize padding to 0 */
1837 memset(pdata, 0, pad);
1839 space_remaining -= pad;
1841 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1851 switch (info_level) {
1852 case SMB_FIND_INFO_STANDARD:
1853 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1854 if(requires_resume_key) {
1858 srv_put_dos_date2(p,0,create_date);
1859 srv_put_dos_date2(p,4,adate);
1860 srv_put_dos_date2(p,8,mdate);
1861 SIVAL(p,12,(uint32_t)file_size);
1862 SIVAL(p,16,(uint32_t)allocation_size);
1866 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1867 p += ucs2_align(base_data, p, 0);
1869 status = srvstr_push(base_data, flags2, p,
1870 fname, PTR_DIFF(end_data, p),
1871 STR_TERMINATE, &len);
1872 if (!NT_STATUS_IS_OK(status)) {
1875 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1877 SCVAL(nameptr, -1, len - 2);
1879 SCVAL(nameptr, -1, 0);
1883 SCVAL(nameptr, -1, len - 1);
1885 SCVAL(nameptr, -1, 0);
1891 case SMB_FIND_EA_SIZE:
1892 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1893 if (requires_resume_key) {
1897 srv_put_dos_date2(p,0,create_date);
1898 srv_put_dos_date2(p,4,adate);
1899 srv_put_dos_date2(p,8,mdate);
1900 SIVAL(p,12,(uint32_t)file_size);
1901 SIVAL(p,16,(uint32_t)allocation_size);
1904 unsigned int ea_size = estimate_ea_size(conn, NULL,
1906 SIVAL(p,22,ea_size); /* Extended attributes */
1910 status = srvstr_push(base_data, flags2,
1911 p, fname, PTR_DIFF(end_data, p),
1912 STR_TERMINATE | STR_NOALIGN, &len);
1913 if (!NT_STATUS_IS_OK(status)) {
1916 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1929 SCVAL(nameptr,0,len);
1931 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1934 case SMB_FIND_EA_LIST:
1936 struct ea_list *file_list = NULL;
1939 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1941 return NT_STATUS_INVALID_PARAMETER;
1943 if (requires_resume_key) {
1947 srv_put_dos_date2(p,0,create_date);
1948 srv_put_dos_date2(p,4,adate);
1949 srv_put_dos_date2(p,8,mdate);
1950 SIVAL(p,12,(uint32_t)file_size);
1951 SIVAL(p,16,(uint32_t)allocation_size);
1953 p += 22; /* p now points to the EA area. */
1955 status = get_ea_list_from_file(ctx, conn, NULL,
1957 &ea_len, &file_list);
1958 if (!NT_STATUS_IS_OK(status)) {
1961 name_list = ea_list_union(name_list, file_list, &ea_len);
1963 /* We need to determine if this entry will fit in the space available. */
1964 /* Max string size is 255 bytes. */
1965 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1966 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1967 "(wanted %u, had %d)\n",
1968 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1970 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1973 /* Push the ea_data followed by the name. */
1974 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1976 status = srvstr_push(base_data, flags2,
1977 p + 1, fname, PTR_DIFF(end_data, p+1),
1978 STR_TERMINATE | STR_NOALIGN, &len);
1979 if (!NT_STATUS_IS_OK(status)) {
1982 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1995 SCVAL(nameptr,0,len);
1997 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2001 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2002 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2003 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2005 SIVAL(p,0,reskey); p += 4;
2006 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2007 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2008 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2009 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2010 SOFF_T(p,0,file_size); p += 8;
2011 SOFF_T(p,0,allocation_size); p += 8;
2012 SIVAL(p,0,mode); p += 4;
2013 q = p; p += 4; /* q is placeholder for name length. */
2014 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2015 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2017 unsigned int ea_size = estimate_ea_size(conn, NULL,
2019 SIVAL(p,0,ea_size); /* Extended attributes */
2022 /* Clear the short name buffer. This is
2023 * IMPORTANT as not doing so will trigger
2024 * a Win2k client bug. JRA.
2026 if (!was_8_3 && check_mangled_names) {
2027 char mangled_name[13]; /* mangled 8.3 name. */
2028 if (!name_to_8_3(fname,mangled_name,True,
2030 /* Error - mangle failed ! */
2031 memset(mangled_name,'\0',12);
2033 mangled_name[12] = 0;
2034 status = srvstr_push(base_data, flags2,
2035 p+2, mangled_name, 24,
2036 STR_UPPER|STR_UNICODE, &len);
2037 if (!NT_STATUS_IS_OK(status)) {
2041 memset(p + 2 + len,'\0',24 - len);
2048 status = srvstr_push(base_data, flags2, p,
2049 fname, PTR_DIFF(end_data, p),
2050 STR_TERMINATE_ASCII, &len);
2051 if (!NT_STATUS_IS_OK(status)) {
2057 len = PTR_DIFF(p, pdata);
2058 pad = (len + (align-1)) & ~(align-1);
2060 * offset to the next entry, the caller
2061 * will overwrite it for the last entry
2062 * that's why we always include the padding
2066 * set padding to zero
2069 memset(p, 0, pad - len);
2076 case SMB_FIND_FILE_DIRECTORY_INFO:
2077 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2079 SIVAL(p,0,reskey); p += 4;
2080 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2081 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2082 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2083 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2084 SOFF_T(p,0,file_size); p += 8;
2085 SOFF_T(p,0,allocation_size); p += 8;
2086 SIVAL(p,0,mode); p += 4;
2087 status = srvstr_push(base_data, flags2,
2088 p + 4, fname, PTR_DIFF(end_data, p+4),
2089 STR_TERMINATE_ASCII, &len);
2090 if (!NT_STATUS_IS_OK(status)) {
2096 len = PTR_DIFF(p, pdata);
2097 pad = (len + (align-1)) & ~(align-1);
2099 * offset to the next entry, the caller
2100 * will overwrite it for the last entry
2101 * that's why we always include the padding
2105 * set padding to zero
2108 memset(p, 0, pad - len);
2115 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2116 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2118 SIVAL(p,0,reskey); p += 4;
2119 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2120 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2121 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2122 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2123 SOFF_T(p,0,file_size); p += 8;
2124 SOFF_T(p,0,allocation_size); p += 8;
2125 SIVAL(p,0,mode); p += 4;
2126 q = p; p += 4; /* q is placeholder for name length. */
2128 unsigned int ea_size = estimate_ea_size(conn, NULL,
2130 SIVAL(p,0,ea_size); /* Extended attributes */
2133 status = srvstr_push(base_data, flags2, p,
2134 fname, PTR_DIFF(end_data, p),
2135 STR_TERMINATE_ASCII, &len);
2136 if (!NT_STATUS_IS_OK(status)) {
2142 len = PTR_DIFF(p, pdata);
2143 pad = (len + (align-1)) & ~(align-1);
2145 * offset to the next entry, the caller
2146 * will overwrite it for the last entry
2147 * that's why we always include the padding
2151 * set padding to zero
2154 memset(p, 0, pad - len);
2161 case SMB_FIND_FILE_NAMES_INFO:
2162 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2164 SIVAL(p,0,reskey); p += 4;
2166 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2167 acl on a dir (tridge) */
2168 status = srvstr_push(base_data, flags2, p,
2169 fname, PTR_DIFF(end_data, p),
2170 STR_TERMINATE_ASCII, &len);
2171 if (!NT_STATUS_IS_OK(status)) {
2177 len = PTR_DIFF(p, pdata);
2178 pad = (len + (align-1)) & ~(align-1);
2180 * offset to the next entry, the caller
2181 * will overwrite it for the last entry
2182 * that's why we always include the padding
2186 * set padding to zero
2189 memset(p, 0, pad - len);
2196 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2197 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2199 SIVAL(p,0,reskey); p += 4;
2200 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2201 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2202 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2203 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2204 SOFF_T(p,0,file_size); p += 8;
2205 SOFF_T(p,0,allocation_size); p += 8;
2206 SIVAL(p,0,mode); p += 4;
2207 q = p; p += 4; /* q is placeholder for name length. */
2208 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2209 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2211 unsigned int ea_size = estimate_ea_size(conn, NULL,
2213 SIVAL(p,0,ea_size); /* Extended attributes */
2216 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2217 SBVAL(p,0,file_index); p += 8;
2218 status = srvstr_push(base_data, flags2, p,
2219 fname, PTR_DIFF(end_data, p),
2220 STR_TERMINATE_ASCII, &len);
2221 if (!NT_STATUS_IS_OK(status)) {
2227 len = PTR_DIFF(p, pdata);
2228 pad = (len + (align-1)) & ~(align-1);
2230 * offset to the next entry, the caller
2231 * will overwrite it for the last entry
2232 * that's why we always include the padding
2236 * set padding to zero
2239 memset(p, 0, pad - len);
2246 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2247 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2248 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2250 SIVAL(p,0,reskey); p += 4;
2251 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2252 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2253 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2254 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2255 SOFF_T(p,0,file_size); p += 8;
2256 SOFF_T(p,0,allocation_size); p += 8;
2257 SIVAL(p,0,mode); p += 4;
2258 q = p; p += 4; /* q is placeholder for name length */
2259 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2260 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2261 } else if (readdir_attr_data &&
2262 readdir_attr_data->type == RDATTR_AAPL) {
2264 * OS X specific SMB2 extension negotiated via
2265 * AAPL create context: return max_access in
2268 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2270 unsigned int ea_size = estimate_ea_size(conn, NULL,
2272 SIVAL(p,0,ea_size); /* Extended attributes */
2276 if (readdir_attr_data &&
2277 readdir_attr_data->type == RDATTR_AAPL) {
2279 * OS X specific SMB2 extension negotiated via
2280 * AAPL create context: return resource fork
2281 * length and compressed FinderInfo in
2284 * According to documentation short_name_len
2285 * should be 0, but on the wire behaviour
2286 * shows its set to 24 by clients.
2290 /* Resourefork length */
2291 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2293 /* Compressed FinderInfo */
2294 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2295 } else if (!was_8_3 && check_mangled_names) {
2296 char mangled_name[13]; /* mangled 8.3 name. */
2297 if (!name_to_8_3(fname,mangled_name,True,
2299 /* Error - mangle failed ! */
2300 memset(mangled_name,'\0',12);
2302 mangled_name[12] = 0;
2303 status = srvstr_push(base_data, flags2,
2304 p+2, mangled_name, 24,
2305 STR_UPPER|STR_UNICODE, &len);
2306 if (!NT_STATUS_IS_OK(status)) {
2311 memset(p + 2 + len,'\0',24 - len);
2315 /* Clear the short name buffer. This is
2316 * IMPORTANT as not doing so will trigger
2317 * a Win2k client bug. JRA.
2324 if (readdir_attr_data &&
2325 readdir_attr_data->type == RDATTR_AAPL) {
2327 * OS X specific SMB2 extension negotiated via
2328 * AAPL create context: return UNIX mode in
2331 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2332 SSVAL(p, 0, aapl_mode);
2338 SBVAL(p,0,file_index); p += 8;
2339 status = srvstr_push(base_data, flags2, p,
2340 fname, PTR_DIFF(end_data, p),
2341 STR_TERMINATE_ASCII, &len);
2342 if (!NT_STATUS_IS_OK(status)) {
2348 len = PTR_DIFF(p, pdata);
2349 pad = (len + (align-1)) & ~(align-1);
2351 * offset to the next entry, the caller
2352 * will overwrite it for the last entry
2353 * that's why we always include the padding
2357 * set padding to zero
2360 memset(p, 0, pad - len);
2367 /* CIFS UNIX Extension. */
2369 case SMB_FIND_FILE_UNIX:
2370 case SMB_FIND_FILE_UNIX_INFO2:
2372 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2374 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2376 if (info_level == SMB_FIND_FILE_UNIX) {
2377 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2378 p = store_file_unix_basic(conn, p,
2379 NULL, &smb_fname->st);
2380 status = srvstr_push(base_data, flags2, p,
2381 fname, PTR_DIFF(end_data, p),
2382 STR_TERMINATE, &len);
2383 if (!NT_STATUS_IS_OK(status)) {
2387 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2388 p = store_file_unix_basic_info2(conn, p,
2389 NULL, &smb_fname->st);
2392 status = srvstr_push(base_data, flags2, p, fname,
2393 PTR_DIFF(end_data, p), 0, &len);
2394 if (!NT_STATUS_IS_OK(status)) {
2397 SIVAL(nameptr, 0, len);
2402 len = PTR_DIFF(p, pdata);
2403 pad = (len + (align-1)) & ~(align-1);
2405 * offset to the next entry, the caller
2406 * will overwrite it for the last entry
2407 * that's why we always include the padding
2411 * set padding to zero
2414 memset(p, 0, pad - len);
2419 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2424 return NT_STATUS_INVALID_LEVEL;
2427 if (PTR_DIFF(p,pdata) > space_remaining) {
2428 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2429 "(wanted %u, had %d)\n",
2430 (unsigned int)PTR_DIFF(p,pdata),
2432 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2435 /* Setup the last entry pointer, as an offset from base_data */
2436 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2437 /* Advance the data pointer to the next slot */
2440 return NT_STATUS_OK;
2443 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2444 connection_struct *conn,
2445 struct dptr_struct *dirptr,
2447 const char *path_mask,
2450 int requires_resume_key,
2458 int space_remaining,
2459 bool *got_exact_match,
2460 int *_last_entry_off,
2461 struct ea_list *name_list,
2462 struct file_id *file_id)
2465 const char *mask = NULL;
2466 long prev_dirpos = 0;
2469 struct smb_filename *smb_fname = NULL;
2470 struct smbd_dirptr_lanman2_state state;
2472 uint64_t last_entry_off = 0;
2474 enum mangled_names_options mangled_names;
2475 bool marshall_with_83_names;
2477 mangled_names = lp_mangled_names(conn->params);
2481 state.info_level = info_level;
2482 if (mangled_names != MANGLED_NAMES_NO) {
2483 state.check_mangled_names = true;
2485 state.has_wild = dptr_has_wild(dirptr);
2486 state.got_exact_match = false;
2488 *got_exact_match = false;
2490 p = strrchr_m(path_mask,'/');
2501 ok = smbd_dirptr_get_entry(ctx,
2507 smbd_dirptr_lanman2_match_fn,
2508 smbd_dirptr_lanman2_mode_fn,
2515 return NT_STATUS_END_OF_FILE;
2518 *got_exact_match = state.got_exact_match;
2520 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2522 status = smbd_marshall_dir_entry(ctx,
2527 marshall_with_83_names,
2528 requires_resume_key,
2539 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2540 DEBUG(1,("Conversion error: illegal character: %s\n",
2541 smb_fname_str_dbg(smb_fname)));
2544 if (file_id != NULL) {
2545 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2549 TALLOC_FREE(smb_fname);
2550 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2551 dptr_SeekDir(dirptr, prev_dirpos);
2554 if (!NT_STATUS_IS_OK(status)) {
2558 *_last_entry_off = last_entry_off;
2559 return NT_STATUS_OK;
2562 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2563 connection_struct *conn,
2564 struct dptr_struct *dirptr,
2566 const char *path_mask,
2569 bool requires_resume_key,
2575 int space_remaining,
2576 bool *got_exact_match,
2577 int *last_entry_off,
2578 struct ea_list *name_list)
2581 const bool do_pad = true;
2583 if (info_level >= 1 && info_level <= 3) {
2584 /* No alignment on earlier info levels. */
2588 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2589 path_mask, dirtype, info_level,
2590 requires_resume_key, dont_descend, ask_sharemode,
2592 ppdata, base_data, end_data,
2595 last_entry_off, name_list, NULL);
2598 /****************************************************************************
2599 Reply to a TRANS2_FINDFIRST.
2600 ****************************************************************************/
2602 static void call_trans2findfirst(connection_struct *conn,
2603 struct smb_request *req,
2604 char **pparams, int total_params,
2605 char **ppdata, int total_data,
2606 unsigned int max_data_bytes)
2608 /* We must be careful here that we don't return more than the
2609 allowed number of data bytes. If this means returning fewer than
2610 maxentries then so be it. We assume that the redirector has
2611 enough room for the fixed number of parameter bytes it has
2613 struct smb_filename *smb_dname = NULL;
2614 char *params = *pparams;
2615 char *pdata = *ppdata;
2619 uint16_t findfirst_flags;
2620 bool close_after_first;
2622 bool requires_resume_key;
2624 char *directory = NULL;
2627 int last_entry_off=0;
2631 bool finished = False;
2632 bool dont_descend = False;
2633 bool out_of_space = False;
2634 int space_remaining;
2635 bool mask_contains_wcard = False;
2636 struct ea_list *ea_list = NULL;
2637 NTSTATUS ntstatus = NT_STATUS_OK;
2638 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2639 struct dptr_struct *dirptr = NULL;
2640 struct smbd_server_connection *sconn = req->sconn;
2641 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2642 ucf_flags_from_smb_request(req);
2643 bool backup_priv = false;
2644 bool as_root = false;
2646 if (total_params < 13) {
2647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2651 dirtype = SVAL(params,0);
2652 maxentries = SVAL(params,2);
2653 findfirst_flags = SVAL(params,4);
2654 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2655 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2656 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2657 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2658 security_token_has_privilege(get_current_nttok(conn),
2661 info_level = SVAL(params,6);
2663 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2664 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2665 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2667 info_level, max_data_bytes));
2670 /* W2K3 seems to treat zero as 1. */
2674 switch (info_level) {
2675 case SMB_FIND_INFO_STANDARD:
2676 case SMB_FIND_EA_SIZE:
2677 case SMB_FIND_EA_LIST:
2678 case SMB_FIND_FILE_DIRECTORY_INFO:
2679 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2680 case SMB_FIND_FILE_NAMES_INFO:
2681 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2682 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2683 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2685 case SMB_FIND_FILE_UNIX:
2686 case SMB_FIND_FILE_UNIX_INFO2:
2687 /* Always use filesystem for UNIX mtime query. */
2688 ask_sharemode = false;
2689 if (!lp_unix_extensions()) {
2690 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2693 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2696 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2700 if (req->posix_pathnames) {
2701 srvstr_get_path_wcard_posix(talloc_tos(),
2709 &mask_contains_wcard);
2711 srvstr_get_path_wcard(talloc_tos(),
2719 &mask_contains_wcard);
2721 if (!NT_STATUS_IS_OK(ntstatus)) {
2722 reply_nterror(req, ntstatus);
2729 ntstatus = filename_convert_with_privilege(talloc_tos(),
2734 &mask_contains_wcard,
2737 ntstatus = filename_convert(talloc_tos(), conn,
2740 &mask_contains_wcard,
2744 if (!NT_STATUS_IS_OK(ntstatus)) {
2745 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2746 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2747 ERRSRV, ERRbadpath);
2750 reply_nterror(req, ntstatus);
2754 mask = smb_dname->original_lcomp;
2756 directory = smb_dname->base_name;
2758 p = strrchr_m(directory,'/');
2760 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2761 if((directory[0] == '.') && (directory[1] == '\0')) {
2762 mask = talloc_strdup(talloc_tos(),"*");
2764 reply_nterror(req, NT_STATUS_NO_MEMORY);
2767 mask_contains_wcard = True;
2773 if (p == NULL || p == directory) {
2774 /* Ensure we don't have a directory name of "". */
2775 directory = talloc_strdup(talloc_tos(), ".");
2777 reply_nterror(req, NT_STATUS_NO_MEMORY);
2780 /* Ensure smb_dname->base_name matches. */
2781 smb_dname->base_name = directory;
2784 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2786 if (info_level == SMB_FIND_EA_LIST) {
2789 if (total_data < 4) {
2790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2794 ea_size = IVAL(pdata,0);
2795 if (ea_size != total_data) {
2796 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2797 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2802 if (!lp_ea_support(SNUM(conn))) {
2803 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2807 /* Pull out the list of names. */
2808 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2815 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2816 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2820 *ppdata = (char *)SMB_REALLOC(
2821 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2822 if(*ppdata == NULL ) {
2823 reply_nterror(req, NT_STATUS_NO_MEMORY);
2827 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2829 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2832 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2833 /* Realloc the params space */
2834 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2835 if (*pparams == NULL) {
2836 reply_nterror(req, NT_STATUS_NO_MEMORY);
2841 /* Save the wildcard match and attribs we are using on this directory -
2842 needed as lanman2 assumes these are being saved between calls */
2844 ntstatus = dptr_create(conn,
2852 mask_contains_wcard,
2856 if (!NT_STATUS_IS_OK(ntstatus)) {
2857 reply_nterror(req, ntstatus);
2862 /* Remember this in case we have
2863 to do a findnext. */
2864 dptr_set_priv(dirptr);
2867 dptr_num = dptr_dnum(dirptr);
2868 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2870 /* We don't need to check for VOL here as this is returned by
2871 a different TRANS2 call. */
2873 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2874 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2875 if (in_list(directory,
2876 lp_dont_descend(talloc_tos(), SNUM(conn)),
2877 conn->case_sensitive)) {
2878 dont_descend = True;
2882 space_remaining = max_data_bytes;
2883 out_of_space = False;
2885 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2886 bool got_exact_match = False;
2888 /* this is a heuristic to avoid seeking the dirptr except when
2889 absolutely necessary. It allows for a filename of about 40 chars */
2890 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2891 out_of_space = True;
2894 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2898 mask,dirtype,info_level,
2899 requires_resume_key,dont_descend,
2904 &last_entry_off, ea_list);
2905 if (NT_STATUS_EQUAL(ntstatus,
2906 NT_STATUS_ILLEGAL_CHARACTER)) {
2908 * Bad character conversion on name. Ignore this
2913 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2914 out_of_space = true;
2916 finished = !NT_STATUS_IS_OK(ntstatus);
2920 if (!finished && !out_of_space)
2924 * As an optimisation if we know we aren't looking
2925 * for a wildcard name (ie. the name matches the wildcard exactly)
2926 * then we can finish on any (first) match.
2927 * This speeds up large directory searches. JRA.
2933 /* Ensure space_remaining never goes -ve. */
2934 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2935 space_remaining = 0;
2936 out_of_space = true;
2938 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2942 /* Check if we can close the dirptr */
2943 if(close_after_first || (finished && close_if_end)) {
2944 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2945 dptr_close(sconn, &dptr_num);
2949 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2950 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2951 * the protocol level is less than NT1. Tested with smbclient. JRA.
2952 * This should fix the OS/2 client bug #2335.
2955 if(numentries == 0) {
2956 dptr_close(sconn, &dptr_num);
2957 if (get_Protocol() < PROTOCOL_NT1) {
2958 reply_force_doserror(req, ERRDOS, ERRnofiles);
2961 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2962 ERRDOS, ERRbadfile);
2967 /* At this point pdata points to numentries directory entries. */
2969 /* Set up the return parameter block */
2970 SSVAL(params,0,dptr_num);
2971 SSVAL(params,2,numentries);
2972 SSVAL(params,4,finished);
2973 SSVAL(params,6,0); /* Never an EA error */
2974 SSVAL(params,8,last_entry_off);
2976 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2979 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2980 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2982 reply_nterror(req, NT_STATUS_NO_MEMORY);
2986 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2987 smb_fn_name(req->cmd),
2988 mask, directory, dirtype, numentries ) );
2991 * Force a name mangle here to ensure that the
2992 * mask as an 8.3 name is top of the mangled cache.
2993 * The reasons for this are subtle. Don't remove
2994 * this code unless you know what you are doing
2995 * (see PR#13758). JRA.
2998 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2999 char mangled_name[13];
3000 name_to_8_3(mask, mangled_name, True, conn->params);
3008 TALLOC_FREE(smb_dname);
3012 /****************************************************************************
3013 Reply to a TRANS2_FINDNEXT.
3014 ****************************************************************************/
3016 static void call_trans2findnext(connection_struct *conn,
3017 struct smb_request *req,
3018 char **pparams, int total_params,
3019 char **ppdata, int total_data,
3020 unsigned int max_data_bytes)
3022 /* We must be careful here that we don't return more than the
3023 allowed number of data bytes. If this means returning fewer than
3024 maxentries then so be it. We assume that the redirector has
3025 enough room for the fixed number of parameter bytes it has
3027 char *params = *pparams;
3028 char *pdata = *ppdata;
3032 uint16_t info_level;
3033 uint32_t resume_key;
3034 uint16_t findnext_flags;
3035 bool close_after_request;
3037 bool requires_resume_key;
3039 bool mask_contains_wcard = False;
3040 char *resume_name = NULL;
3041 const char *mask = NULL;
3042 const char *directory = NULL;
3046 int i, last_entry_off=0;
3047 bool finished = False;
3048 bool dont_descend = False;
3049 bool out_of_space = False;
3050 int space_remaining;
3051 struct ea_list *ea_list = NULL;
3052 NTSTATUS ntstatus = NT_STATUS_OK;
3053 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3054 TALLOC_CTX *ctx = talloc_tos();
3055 struct dptr_struct *dirptr;
3056 struct smbd_server_connection *sconn = req->sconn;
3057 bool backup_priv = false;
3058 bool as_root = false;
3060 if (total_params < 13) {
3061 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3065 dptr_num = SVAL(params,0);
3066 maxentries = SVAL(params,2);
3067 info_level = SVAL(params,4);
3068 resume_key = IVAL(params,6);
3069 findnext_flags = SVAL(params,10);
3070 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3071 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3072 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3073 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3075 if (!continue_bit) {
3076 /* We only need resume_name if continue_bit is zero. */
3077 if (req->posix_pathnames) {
3078 srvstr_get_path_wcard_posix(ctx,
3086 &mask_contains_wcard);
3088 srvstr_get_path_wcard(ctx,
3096 &mask_contains_wcard);
3098 if (!NT_STATUS_IS_OK(ntstatus)) {
3099 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3100 complain (it thinks we're asking for the directory above the shared
3101 path or an invalid name). Catch this as the resume name is only compared, never used in
3102 a file access. JRA. */
3103 srvstr_pull_talloc(ctx, params, req->flags2,
3104 &resume_name, params+12,
3108 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3109 reply_nterror(req, ntstatus);
3115 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3116 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3117 resume_key = %d resume name = %s continue=%d level = %d\n",
3118 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3119 requires_resume_key, resume_key,
3120 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3123 /* W2K3 seems to treat zero as 1. */
3127 switch (info_level) {
3128 case SMB_FIND_INFO_STANDARD:
3129 case SMB_FIND_EA_SIZE:
3130 case SMB_FIND_EA_LIST:
3131 case SMB_FIND_FILE_DIRECTORY_INFO:
3132 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3133 case SMB_FIND_FILE_NAMES_INFO:
3134 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3135 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3136 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3138 case SMB_FIND_FILE_UNIX:
3139 case SMB_FIND_FILE_UNIX_INFO2:
3140 /* Always use filesystem for UNIX mtime query. */
3141 ask_sharemode = false;
3142 if (!lp_unix_extensions()) {
3143 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3148 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3152 if (info_level == SMB_FIND_EA_LIST) {
3155 if (total_data < 4) {
3156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3160 ea_size = IVAL(pdata,0);
3161 if (ea_size != total_data) {
3162 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3163 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3168 if (!lp_ea_support(SNUM(conn))) {
3169 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3173 /* Pull out the list of names. */
3174 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3181 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3186 *ppdata = (char *)SMB_REALLOC(
3187 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3188 if(*ppdata == NULL) {
3189 reply_nterror(req, NT_STATUS_NO_MEMORY);
3194 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3197 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3200 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3201 /* Realloc the params space */
3202 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3203 if(*pparams == NULL ) {
3204 reply_nterror(req, NT_STATUS_NO_MEMORY);
3210 /* Check that the dptr is valid */
3211 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3212 reply_nterror(req, STATUS_NO_MORE_FILES);
3216 directory = dptr_path(sconn, dptr_num);
3218 /* Get the wildcard mask from the dptr */
3219 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3220 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3221 reply_nterror(req, STATUS_NO_MORE_FILES);
3225 /* Get the attr mask from the dptr */
3226 dirtype = dptr_attr(sconn, dptr_num);
3228 backup_priv = dptr_get_priv(dirptr);
3230 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3231 "backup_priv = %d\n",
3232 dptr_num, mask, dirtype,
3234 dptr_TellDir(dirptr),
3237 /* We don't need to check for VOL here as this is returned by
3238 a different TRANS2 call. */
3240 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3241 directory,lp_dont_descend(ctx, SNUM(conn))));
3242 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3243 dont_descend = True;
3246 space_remaining = max_data_bytes;
3247 out_of_space = False;
3255 * Seek to the correct position. We no longer use the resume key but
3256 * depend on the last file name instead.
3259 if(!continue_bit && resume_name && *resume_name) {
3262 long current_pos = 0;
3264 * Remember, name_to_8_3 is called by
3265 * get_lanman2_dir_entry(), so the resume name
3266 * could be mangled. Ensure we check the unmangled name.
3269 if (mangle_is_mangled(resume_name, conn->params)) {
3270 char *new_resume_name = NULL;
3271 mangle_lookup_name_from_8_3(ctx,
3275 if (new_resume_name) {
3276 resume_name = new_resume_name;
3281 * Fix for NT redirector problem triggered by resume key indexes
3282 * changing between directory scans. We now return a resume key of 0
3283 * and instead look for the filename to continue from (also given
3284 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3285 * findfirst/findnext (as is usual) then the directory pointer
3286 * should already be at the correct place.
3289 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3290 } /* end if resume_name && !continue_bit */
3292 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3293 bool got_exact_match = False;
3295 /* this is a heuristic to avoid seeking the dirptr except when
3296 absolutely necessary. It allows for a filename of about 40 chars */
3297 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3298 out_of_space = True;
3301 ntstatus = get_lanman2_dir_entry(ctx,
3305 mask,dirtype,info_level,
3306 requires_resume_key,dont_descend,
3311 &last_entry_off, ea_list);
3312 if (NT_STATUS_EQUAL(ntstatus,
3313 NT_STATUS_ILLEGAL_CHARACTER)) {
3315 * Bad character conversion on name. Ignore this
3320 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3321 out_of_space = true;
3323 finished = !NT_STATUS_IS_OK(ntstatus);
3327 if (!finished && !out_of_space)
3331 * As an optimisation if we know we aren't looking
3332 * for a wildcard name (ie. the name matches the wildcard exactly)
3333 * then we can finish on any (first) match.
3334 * This speeds up large directory searches. JRA.
3340 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3343 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3344 smb_fn_name(req->cmd),
3345 mask, directory, dirtype, numentries ) );
3347 /* Check if we can close the dirptr */
3348 if(close_after_request || (finished && close_if_end)) {
3349 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3350 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3357 /* Set up the return parameter block */
3358 SSVAL(params,0,numentries);
3359 SSVAL(params,2,finished);
3360 SSVAL(params,4,0); /* Never an EA error */
3361 SSVAL(params,6,last_entry_off);
3363 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3369 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3371 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3375 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3377 SMB_ASSERT(extended_info != NULL);
3379 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3380 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3381 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3382 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3383 #ifdef SAMBA_VERSION_REVISION
3384 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3386 extended_info->samba_subversion = 0;
3387 #ifdef SAMBA_VERSION_RC_RELEASE
3388 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3390 #ifdef SAMBA_VERSION_PRE_RELEASE
3391 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3394 #ifdef SAMBA_VERSION_VENDOR_PATCH
3395 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3397 extended_info->samba_gitcommitdate = 0;
3398 #ifdef SAMBA_VERSION_COMMIT_TIME
3399 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3402 memset(extended_info->samba_version_string, 0,
3403 sizeof(extended_info->samba_version_string));
3405 snprintf (extended_info->samba_version_string,
3406 sizeof(extended_info->samba_version_string),
3407 "%s", samba_version_string());
3410 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3411 connection_struct *conn,
3412 TALLOC_CTX *mem_ctx,
3413 uint16_t info_level,
3415 unsigned int max_data_bytes,
3416 size_t *fixed_portion,
3417 struct smb_filename *fname,
3421 char *pdata, *end_data;
3424 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3425 int snum = SNUM(conn);
3426 const char *fstype = lp_fstype(SNUM(conn));
3427 const char *filename = NULL;
3428 const uint64_t bytes_per_sector = 512;
3429 uint32_t additional_flags = 0;
3430 struct smb_filename smb_fname;
3432 NTSTATUS status = NT_STATUS_OK;
3435 if (fname == NULL || fname->base_name == NULL) {
3438 filename = fname->base_name;
3442 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3443 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3444 "info level (0x%x) on IPC$.\n",
3445 (unsigned int)info_level));
3446 return NT_STATUS_ACCESS_DENIED;
3450 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3452 ZERO_STRUCT(smb_fname);
3453 smb_fname.base_name = discard_const_p(char, filename);
3455 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3456 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3457 return map_nt_error_from_unix(errno);
3462 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3463 return NT_STATUS_INVALID_PARAMETER;
3466 *ppdata = (char *)SMB_REALLOC(
3467 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3468 if (*ppdata == NULL) {
3469 return NT_STATUS_NO_MEMORY;
3473 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3474 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3478 switch (info_level) {
3479 case SMB_INFO_ALLOCATION:
3481 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3483 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3485 if (df_ret == (uint64_t)-1) {
3486 return map_nt_error_from_unix(errno);
3489 block_size = lp_block_size(snum);
3490 if (bsize < block_size) {
3491 uint64_t factor = block_size/bsize;
3496 if (bsize > block_size) {
3497 uint64_t factor = bsize/block_size;
3502 sectors_per_unit = bsize/bytes_per_sector;
3504 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3505 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3506 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3509 * For large drives, return max values and not modulo.
3511 dsize = MIN(dsize, UINT32_MAX);
3512 dfree = MIN(dfree, UINT32_MAX);
3514 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3515 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3516 SIVAL(pdata,l1_cUnit,dsize);
3517 SIVAL(pdata,l1_cUnitAvail,dfree);
3518 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3522 case SMB_INFO_VOLUME:
3523 /* Return volume name */
3525 * Add volume serial number - hash of a combination of
3526 * the called hostname and the service name.
3528 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3530 * Win2k3 and previous mess this up by sending a name length
3531 * one byte short. I believe only older clients (OS/2 Win9x) use
3532 * this call so try fixing this by adding a terminating null to
3533 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3535 status = srvstr_push(
3537 pdata+l2_vol_szVolLabel, vname,
3538 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3539 STR_NOALIGN|STR_TERMINATE, &len);
3540 if (!NT_STATUS_IS_OK(status)) {
3543 SCVAL(pdata,l2_vol_cch,len);
3544 data_len = l2_vol_szVolLabel + len;
3545 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3546 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3547 (unsigned)len, vname));
3550 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3551 case SMB_FS_ATTRIBUTE_INFORMATION:
3553 additional_flags = 0;
3554 #if defined(HAVE_SYS_QUOTAS)
3555 additional_flags |= FILE_VOLUME_QUOTAS;
3558 if(lp_nt_acl_support(SNUM(conn))) {
3559 additional_flags |= FILE_PERSISTENT_ACLS;
3562 /* Capabilities are filled in at connection time through STATVFS call */
3563 additional_flags |= conn->fs_capabilities;
3564 additional_flags |= lp_parm_int(conn->params->service,
3565 "share", "fake_fscaps",
3568 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3569 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3570 additional_flags); /* FS ATTRIBUTES */
3572 SIVAL(pdata,4,255); /* Max filename component length */
3573 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3574 and will think we can't do long filenames */
3575 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3576 PTR_DIFF(end_data, pdata+12),
3578 if (!NT_STATUS_IS_OK(status)) {
3582 data_len = 12 + len;
3583 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3584 /* the client only requested a portion of the
3586 data_len = max_data_bytes;
3587 status = STATUS_BUFFER_OVERFLOW;
3589 *fixed_portion = 16;
3592 case SMB_QUERY_FS_LABEL_INFO:
3593 case SMB_FS_LABEL_INFORMATION:
3594 status = srvstr_push(pdata, flags2, pdata+4, vname,
3595 PTR_DIFF(end_data, pdata+4), 0, &len);
3596 if (!NT_STATUS_IS_OK(status)) {
3603 case SMB_QUERY_FS_VOLUME_INFO:
3604 case SMB_FS_VOLUME_INFORMATION:
3607 * Add volume serial number - hash of a combination of
3608 * the called hostname and the service name.
3610 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3611 (str_checksum(get_local_machine_name())<<16));
3613 /* Max label len is 32 characters. */
3614 status = srvstr_push(pdata, flags2, pdata+18, vname,
3615 PTR_DIFF(end_data, pdata+18),
3617 if (!NT_STATUS_IS_OK(status)) {
3620 SIVAL(pdata,12,len);
3623 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3624 (int)strlen(vname),vname,
3625 lp_servicename(talloc_tos(), snum)));
3626 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3627 /* the client only requested a portion of the
3629 data_len = max_data_bytes;
3630 status = STATUS_BUFFER_OVERFLOW;
3632 *fixed_portion = 24;
3635 case SMB_QUERY_FS_SIZE_INFO:
3636 case SMB_FS_SIZE_INFORMATION:
3638 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3640 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3642 if (df_ret == (uint64_t)-1) {
3643 return map_nt_error_from_unix(errno);
3645 block_size = lp_block_size(snum);
3646 if (bsize < block_size) {
3647 uint64_t factor = block_size/bsize;
3652 if (bsize > block_size) {
3653 uint64_t factor = bsize/block_size;
3658 sectors_per_unit = bsize/bytes_per_sector;
3659 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3660 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3661 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3662 SBIG_UINT(pdata,0,dsize);
3663 SBIG_UINT(pdata,8,dfree);
3664 SIVAL(pdata,16,sectors_per_unit);
3665 SIVAL(pdata,20,bytes_per_sector);
3666 *fixed_portion = 24;
3670 case SMB_FS_FULL_SIZE_INFORMATION:
3672 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3674 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3676 if (df_ret == (uint64_t)-1) {
3677 return map_nt_error_from_unix(errno);
3679 block_size = lp_block_size(snum);
3680 if (bsize < block_size) {
3681 uint64_t factor = block_size/bsize;
3686 if (bsize > block_size) {
3687 uint64_t factor = bsize/block_size;
3692 sectors_per_unit = bsize/bytes_per_sector;
3693 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3694 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3695 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3696 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3697 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3698 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3699 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3700 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3701 *fixed_portion = 32;
3705 case SMB_QUERY_FS_DEVICE_INFO:
3706 case SMB_FS_DEVICE_INFORMATION:
3708 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3710 if (!CAN_WRITE(conn)) {
3711 characteristics |= FILE_READ_ONLY_DEVICE;
3714 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3715 SIVAL(pdata,4,characteristics);
3720 #ifdef HAVE_SYS_QUOTAS
3721 case SMB_FS_QUOTA_INFORMATION:
3723 * what we have to send --metze:
3725 * Unknown1: 24 NULL bytes
3726 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3727 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3728 * Quota Flags: 2 byte :
3729 * Unknown3: 6 NULL bytes
3733 * details for Quota Flags:
3735 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3736 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3737 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3738 * 0x0001 Enable Quotas: enable quota for this fs
3742 /* we need to fake up a fsp here,
3743 * because its not send in this call
3746 SMB_NTQUOTA_STRUCT quotas;
3749 ZERO_STRUCT(quotas);
3752 fsp.fnum = FNUM_FIELD_INVALID;
3755 if (get_current_uid(conn) != 0) {
3756 DEBUG(0,("get_user_quota: access_denied "
3757 "service [%s] user [%s]\n",
3758 lp_servicename(talloc_tos(), SNUM(conn)),
3759 conn->session_info->unix_info->unix_name));
3760 return NT_STATUS_ACCESS_DENIED;
3763 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3765 if (!NT_STATUS_IS_OK(status)) {
3766 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3772 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3773 lp_servicename(talloc_tos(), SNUM(conn))));
3775 /* Unknown1 24 NULL bytes*/
3776 SBIG_UINT(pdata,0,(uint64_t)0);
3777 SBIG_UINT(pdata,8,(uint64_t)0);
3778 SBIG_UINT(pdata,16,(uint64_t)0);
3780 /* Default Soft Quota 8 bytes */
3781 SBIG_UINT(pdata,24,quotas.softlim);
3783 /* Default Hard Quota 8 bytes */
3784 SBIG_UINT(pdata,32,quotas.hardlim);
3786 /* Quota flag 2 bytes */
3787 SSVAL(pdata,40,quotas.qflags);
3789 /* Unknown3 6 NULL bytes */
3795 #endif /* HAVE_SYS_QUOTAS */
3796 case SMB_FS_OBJECTID_INFORMATION:
3798 unsigned char objid[16];
3799 struct smb_extended_info extended_info;
3800 memcpy(pdata,create_volume_objectid(conn, objid),16);
3801 samba_extended_info_version (&extended_info);
3802 SIVAL(pdata,16,extended_info.samba_magic);
3803 SIVAL(pdata,20,extended_info.samba_version);
3804 SIVAL(pdata,24,extended_info.samba_subversion);
3805 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3806 memcpy(pdata+36,extended_info.samba_version_string,28);
3811 case SMB_FS_SECTOR_SIZE_INFORMATION:
3815 * These values match a physical Windows Server 2012
3816 * share backed by NTFS atop spinning rust.
3818 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3819 /* logical_bytes_per_sector */
3820 SIVAL(pdata, 0, bytes_per_sector);
3821 /* phys_bytes_per_sector_atomic */
3822 SIVAL(pdata, 4, bytes_per_sector);
3823 /* phys_bytes_per_sector_perf */
3824 SIVAL(pdata, 8, bytes_per_sector);
3825 /* fs_effective_phys_bytes_per_sector_atomic */
3826 SIVAL(pdata, 12, bytes_per_sector);
3828 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3829 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3830 /* byte_off_sector_align */
3831 SIVAL(pdata, 20, 0);
3832 /* byte_off_partition_align */
3833 SIVAL(pdata, 24, 0);
3834 *fixed_portion = 28;
3840 * Query the version and capabilities of the CIFS UNIX extensions
3844 case SMB_QUERY_CIFS_UNIX_INFO:
3846 bool large_write = lp_min_receive_file_size() &&
3847 !srv_is_signing_active(xconn);
3848 bool large_read = !srv_is_signing_active(xconn);
3849 int encrypt_caps = 0;
3851 if (!lp_unix_extensions()) {
3852 return NT_STATUS_INVALID_LEVEL;
3855 switch (conn->encrypt_level) {
3856 case SMB_SIGNING_OFF:
3859 case SMB_SIGNING_DESIRED:
3860 case SMB_SIGNING_IF_REQUIRED:
3861 case SMB_SIGNING_DEFAULT:
3862 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3864 case SMB_SIGNING_REQUIRED:
3865 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3866 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3867 large_write = false;
3873 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3874 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3876 /* We have POSIX ACLs, pathname, encryption,
3877 * large read/write, and locking capability. */
3879 SBIG_UINT(pdata,4,((uint64_t)(
3880 CIFS_UNIX_POSIX_ACLS_CAP|
3881 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3882 CIFS_UNIX_FCNTL_LOCKS_CAP|
3883 CIFS_UNIX_EXTATTR_CAP|
3884 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3886 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3888 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3892 case SMB_QUERY_POSIX_FS_INFO:
3895 vfs_statvfs_struct svfs;
3897 if (!lp_unix_extensions()) {
3898 return NT_STATUS_INVALID_LEVEL;
3901 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3905 SIVAL(pdata,0,svfs.OptimalTransferSize);
3906 SIVAL(pdata,4,svfs.BlockSize);
3907 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3908 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3909 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3910 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3911 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3912 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3913 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3915 } else if (rc == EOPNOTSUPP) {
3916 return NT_STATUS_INVALID_LEVEL;
3917 #endif /* EOPNOTSUPP */
3919 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3920 return NT_STATUS_DOS(ERRSRV, ERRerror);
3925 case SMB_QUERY_POSIX_WHOAMI:
3931 if (!lp_unix_extensions()) {
3932 return NT_STATUS_INVALID_LEVEL;
3935 if (max_data_bytes < 40) {
3936 return NT_STATUS_BUFFER_TOO_SMALL;
3939 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3940 flags |= SMB_WHOAMI_GUEST;
3943 /* NOTE: 8 bytes for UID/GID, irrespective of native
3944 * platform size. This matches
3945 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3947 data_len = 4 /* flags */
3954 + 4 /* pad/reserved */
3955 + (conn->session_info->unix_token->ngroups * 8)
3957 + (conn->session_info->security_token->num_sids *
3961 SIVAL(pdata, 0, flags);
3962 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3964 (uint64_t)conn->session_info->unix_token->uid);
3965 SBIG_UINT(pdata, 16,
3966 (uint64_t)conn->session_info->unix_token->gid);
3969 if (data_len >= max_data_bytes) {
3970 /* Potential overflow, skip the GIDs and SIDs. */
3972 SIVAL(pdata, 24, 0); /* num_groups */
3973 SIVAL(pdata, 28, 0); /* num_sids */
3974 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3975 SIVAL(pdata, 36, 0); /* reserved */
3981 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3982 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3984 /* We walk the SID list twice, but this call is fairly
3985 * infrequent, and I don't expect that it's performance
3986 * sensitive -- jpeach
3988 for (i = 0, sid_bytes = 0;
3989 i < conn->session_info->security_token->num_sids; ++i) {
3990 sid_bytes += ndr_size_dom_sid(
3991 &conn->session_info->security_token->sids[i],
3995 /* SID list byte count */
3996 SIVAL(pdata, 32, sid_bytes);
3998 /* 4 bytes pad/reserved - must be zero */
3999 SIVAL(pdata, 36, 0);
4003 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4004 SBIG_UINT(pdata, data_len,
4005 (uint64_t)conn->session_info->unix_token->groups[i]);
4011 i < conn->session_info->security_token->num_sids; ++i) {
4012 int sid_len = ndr_size_dom_sid(
4013 &conn->session_info->security_token->sids[i],
4016 sid_linearize((uint8_t *)(pdata + data_len),
4018 &conn->session_info->security_token->sids[i]);
4019 data_len += sid_len;
4025 case SMB_MAC_QUERY_FS_INFO:
4027 * Thursby MAC extension... ONLY on NTFS filesystems
4028 * once we do streams then we don't need this
4030 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4032 SIVAL(pdata,84,0x100); /* Don't support mac... */
4038 return NT_STATUS_INVALID_LEVEL;
4041 *ret_data_len = data_len;
4045 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4046 struct smb_request *req,
4048 const DATA_BLOB *qdata)
4051 SMB_NTQUOTA_STRUCT quotas;
4053 ZERO_STRUCT(quotas);
4056 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4057 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4058 lp_servicename(talloc_tos(), SNUM(conn)),
4059 conn->session_info->unix_info->unix_name));
4060 return NT_STATUS_ACCESS_DENIED;
4063 if (!check_fsp_ntquota_handle(conn, req,
4065 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4066 return NT_STATUS_INVALID_HANDLE;
4069 /* note: normally there're 48 bytes,
4070 * but we didn't use the last 6 bytes for now
4073 if (qdata->length < 42) {
4074 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4075 (unsigned int)qdata->length));
4076 return NT_STATUS_INVALID_PARAMETER;
4079 /* unknown_1 24 NULL bytes in pdata*/
4081 /* the soft quotas 8 bytes (uint64_t)*/
4082 quotas.softlim = BVAL(qdata->data,24);
4084 /* the hard quotas 8 bytes (uint64_t)*/
4085 quotas.hardlim = BVAL(qdata->data,32);
4087 /* quota_flags 2 bytes **/
4088 quotas.qflags = SVAL(qdata->data,40);
4090 /* unknown_2 6 NULL bytes follow*/
4092 /* now set the quotas */
4093 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4094 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4095 lp_servicename(talloc_tos(), SNUM(conn))));
4096 status = map_nt_error_from_unix(errno);
4098 status = NT_STATUS_OK;
4103 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4104 struct smb_request *req,
4105 TALLOC_CTX *mem_ctx,
4106 uint16_t info_level,
4108 const DATA_BLOB *pdata)
4110 switch (info_level) {
4111 case SMB_FS_QUOTA_INFORMATION:
4113 return smb_set_fsquota(conn,
4122 return NT_STATUS_INVALID_LEVEL;
4125 /****************************************************************************
4126 Reply to a TRANS2_QFSINFO (query filesystem info).
4127 ****************************************************************************/
4129 static void call_trans2qfsinfo(connection_struct *conn,
4130 struct smb_request *req,
4131 char **pparams, int total_params,
4132 char **ppdata, int total_data,
4133 unsigned int max_data_bytes)
4135 char *params = *pparams;
4136 uint16_t info_level;
4138 size_t fixed_portion;
4141 if (total_params < 2) {
4142 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4146 info_level = SVAL(params,0);
4148 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4149 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4150 DEBUG(0,("call_trans2qfsinfo: encryption required "
4151 "and info level 0x%x sent.\n",
4152 (unsigned int)info_level));
4153 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4158 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4160 status = smbd_do_qfsinfo(req->xconn, conn, req,
4167 if (!NT_STATUS_IS_OK(status)) {
4168 reply_nterror(req, status);
4172 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4175 DEBUG( 4, ( "%s info_level = %d\n",
4176 smb_fn_name(req->cmd), info_level) );
4181 /****************************************************************************
4182 Reply to a TRANS2_SETFSINFO (set filesystem info).
4183 ****************************************************************************/
4185 static void call_trans2setfsinfo(connection_struct *conn,
4186 struct smb_request *req,
4187 char **pparams, int total_params,
4188 char **ppdata, int total_data,
4189 unsigned int max_data_bytes)
4191 struct smbXsrv_connection *xconn = req->xconn;
4192 char *pdata = *ppdata;
4193 char *params = *pparams;
4194 uint16_t info_level;
4196 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4197 lp_servicename(talloc_tos(), SNUM(conn))));
4200 if (total_params < 4) {
4201 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4207 info_level = SVAL(params,2);
4210 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4211 info_level != SMB_SET_CIFS_UNIX_INFO) {
4212 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4213 "info level (0x%x) on IPC$.\n",
4214 (unsigned int)info_level));
4215 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4220 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4221 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4222 DEBUG(0,("call_trans2setfsinfo: encryption required "
4223 "and info level 0x%x sent.\n",
4224 (unsigned int)info_level));
4225 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4230 switch(info_level) {
4231 case SMB_SET_CIFS_UNIX_INFO:
4232 if (!lp_unix_extensions()) {
4233 DEBUG(2,("call_trans2setfsinfo: "
4234 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4235 "unix extensions off\n"));
4237 NT_STATUS_INVALID_LEVEL);
4241 /* There should be 12 bytes of capabilities set. */
4242 if (total_data < 12) {
4245 NT_STATUS_INVALID_PARAMETER);
4248 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4249 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4250 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4251 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4252 /* Just print these values for now. */
4253 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4254 "major = %u, minor = %u cap_low = 0x%x, "
4256 (unsigned int)xconn->
4257 smb1.unix_info.client_major,
4258 (unsigned int)xconn->
4259 smb1.unix_info.client_minor,
4260 (unsigned int)xconn->
4261 smb1.unix_info.client_cap_low,
4262 (unsigned int)xconn->
4263 smb1.unix_info.client_cap_high));
4265 /* Here is where we must switch to posix pathname processing... */
4266 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4267 lp_set_posix_pathnames();
4268 mangle_change_to_posix();
4271 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4272 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4273 /* Client that knows how to do posix locks,
4274 * but not posix open/mkdir operations. Set a
4275 * default type for read/write checks. */
4277 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4282 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4285 size_t param_len = 0;
4286 size_t data_len = total_data;
4288 if (!lp_unix_extensions()) {
4291 NT_STATUS_INVALID_LEVEL);
4295 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4298 NT_STATUS_NOT_SUPPORTED);
4302 if (xconn->smb1.echo_handler.trusted_fde) {
4303 DEBUG( 2,("call_trans2setfsinfo: "
4304 "request transport encryption disabled"
4305 "with 'fork echo handler = yes'\n"));
4308 NT_STATUS_NOT_SUPPORTED);
4312 DEBUG( 4,("call_trans2setfsinfo: "
4313 "request transport encryption.\n"));
4315 status = srv_request_encryption_setup(conn,
4316 (unsigned char **)ppdata,
4318 (unsigned char **)pparams,
4321 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4322 !NT_STATUS_IS_OK(status)) {
4323 reply_nterror(req, status);
4327 send_trans2_replies(conn, req,
4335 if (NT_STATUS_IS_OK(status)) {
4336 /* Server-side transport
4337 * encryption is now *on*. */
4338 status = srv_encryption_start(conn);
4339 if (!NT_STATUS_IS_OK(status)) {
4340 char *reason = talloc_asprintf(talloc_tos(),
4341 "Failure in setting "
4342 "up encrypted transport: %s",
4344 exit_server_cleanly(reason);
4350 case SMB_FS_QUOTA_INFORMATION:
4354 .data = (uint8_t *)pdata,
4355 .length = total_data
4357 files_struct *fsp = NULL;
4358 fsp = file_fsp(req, SVAL(params,0));
4360 status = smb_set_fsquota(conn,
4364 if (!NT_STATUS_IS_OK(status)) {
4365 reply_nterror(req, status);
4371 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4373 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4379 * sending this reply works fine,
4380 * but I'm not sure it's the same
4381 * like windows do...
4384 reply_outbuf(req, 10, 0);
4387 #if defined(HAVE_POSIX_ACLS)
4388 /****************************************************************************
4389 Utility function to count the number of entries in a POSIX acl.
4390 ****************************************************************************/
4392 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4394 unsigned int ace_count = 0;
4395 int entry_id = SMB_ACL_FIRST_ENTRY;
4396 SMB_ACL_ENTRY_T entry;
4398 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4400 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4401 entry_id = SMB_ACL_NEXT_ENTRY;
4408 /****************************************************************************
4409 Utility function to marshall a POSIX acl into wire format.
4410 ****************************************************************************/
4412 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4414 int entry_id = SMB_ACL_FIRST_ENTRY;
4415 SMB_ACL_ENTRY_T entry;
4417 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4418 SMB_ACL_TAG_T tagtype;
4419 SMB_ACL_PERMSET_T permset;
4420 unsigned char perms = 0;
4421 unsigned int own_grp;
4424 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4425 entry_id = SMB_ACL_NEXT_ENTRY;
4428 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4429 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4433 if (sys_acl_get_permset(entry, &permset) == -1) {
4434 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4438 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4439 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4440 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4442 SCVAL(pdata,1,perms);
4445 case SMB_ACL_USER_OBJ:
4446 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4447 own_grp = (unsigned int)pst->st_ex_uid;
4448 SIVAL(pdata,2,own_grp);
4453 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4455 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4458 own_grp = (unsigned int)*puid;
4459 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4460 SIVAL(pdata,2,own_grp);
4464 case SMB_ACL_GROUP_OBJ:
4465 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4466 own_grp = (unsigned int)pst->st_ex_gid;
4467 SIVAL(pdata,2,own_grp);
4472 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4474 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4477 own_grp = (unsigned int)*pgid;
4478 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4479 SIVAL(pdata,2,own_grp);
4484 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4485 SIVAL(pdata,2,0xFFFFFFFF);
4486 SIVAL(pdata,6,0xFFFFFFFF);
4489 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4490 SIVAL(pdata,2,0xFFFFFFFF);
4491 SIVAL(pdata,6,0xFFFFFFFF);
4494 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4497 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4504 /****************************************************************************
4505 Store the FILE_UNIX_BASIC info.
4506 ****************************************************************************/
4508 static char *store_file_unix_basic(connection_struct *conn,
4511 const SMB_STRUCT_STAT *psbuf)
4513 uint64_t file_index = get_FileIndex(conn, psbuf);
4516 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4517 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4519 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4522 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4525 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4526 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4527 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4530 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4534 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4538 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4541 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4542 devno = psbuf->st_ex_rdev;
4544 devno = psbuf->st_ex_dev;
4547 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4551 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4555 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4558 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4562 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4569 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4570 * the chflags(2) (or equivalent) flags.
4572 * XXX: this really should be behind the VFS interface. To do this, we would
4573 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4574 * Each VFS module could then implement its own mapping as appropriate for the
4575 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4577 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4581 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4585 { UF_IMMUTABLE, EXT_IMMUTABLE },
4589 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4593 { UF_HIDDEN, EXT_HIDDEN },
4596 /* Do not remove. We need to guarantee that this array has at least one
4597 * entry to build on HP-UX.
4603 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4604 uint32_t *smb_fflags, uint32_t *smb_fmask)
4608 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4609 *smb_fmask |= info2_flags_map[i].smb_fflag;
4610 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4611 *smb_fflags |= info2_flags_map[i].smb_fflag;
4616 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4617 const uint32_t smb_fflags,
4618 const uint32_t smb_fmask,
4621 uint32_t max_fmask = 0;
4624 *stat_fflags = psbuf->st_ex_flags;
4626 /* For each flags requested in smb_fmask, check the state of the
4627 * corresponding flag in smb_fflags and set or clear the matching
4631 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4632 max_fmask |= info2_flags_map[i].smb_fflag;
4633 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4634 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4635 *stat_fflags |= info2_flags_map[i].stat_fflag;
4637 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4642 /* If smb_fmask is asking to set any bits that are not supported by
4643 * our flag mappings, we should fail.
4645 if ((smb_fmask & max_fmask) != smb_fmask) {
4653 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4654 * of file flags and birth (create) time.
4656 static char *store_file_unix_basic_info2(connection_struct *conn,
4659 const SMB_STRUCT_STAT *psbuf)
4661 uint32_t file_flags = 0;
4662 uint32_t flags_mask = 0;
4664 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4666 /* Create (birth) time 64 bit */
4667 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4670 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4671 SIVAL(pdata, 0, file_flags); /* flags */
4672 SIVAL(pdata, 4, flags_mask); /* mask */
4678 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4679 const struct stream_struct *streams,
4681 unsigned int max_data_bytes,
4682 unsigned int *data_size)
4685 unsigned int ofs = 0;
4687 if (max_data_bytes < 32) {
4688 return NT_STATUS_INFO_LENGTH_MISMATCH;
4691 for (i = 0; i < num_streams; i++) {
4692 unsigned int next_offset;
4694 smb_ucs2_t *namebuf;
4696 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4697 streams[i].name, &namelen) ||
4700 return NT_STATUS_INVALID_PARAMETER;
4704 * name_buf is now null-terminated, we need to marshall as not
4711 * We cannot overflow ...
4713 if ((ofs + 24 + namelen) > max_data_bytes) {
4714 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4716 TALLOC_FREE(namebuf);
4717 return STATUS_BUFFER_OVERFLOW;
4720 SIVAL(data, ofs+4, namelen);
4721 SOFF_T(data, ofs+8, streams[i].size);
4722 SOFF_T(data, ofs+16, streams[i].alloc_size);
4723 memcpy(data+ofs+24, namebuf, namelen);
4724 TALLOC_FREE(namebuf);
4726 next_offset = ofs + 24 + namelen;
4728 if (i == num_streams-1) {
4729 SIVAL(data, ofs, 0);
4732 unsigned int align = ndr_align_size(next_offset, 8);
4734 if ((next_offset + align) > max_data_bytes) {
4735 DEBUG(10, ("refusing to overflow align "
4736 "reply at stream %u\n",
4738 TALLOC_FREE(namebuf);
4739 return STATUS_BUFFER_OVERFLOW;
4742 memset(data+next_offset, 0, align);
4743 next_offset += align;
4745 SIVAL(data, ofs, next_offset - ofs);
4752 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4756 return NT_STATUS_OK;
4759 /****************************************************************************
4760 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4761 ****************************************************************************/
4763 static void call_trans2qpipeinfo(connection_struct *conn,
4764 struct smb_request *req,
4765 unsigned int tran_call,
4766 char **pparams, int total_params,
4767 char **ppdata, int total_data,
4768 unsigned int max_data_bytes)
4770 char *params = *pparams;
4771 char *pdata = *ppdata;
4772 unsigned int data_size = 0;
4773 unsigned int param_size = 2;
4774 uint16_t info_level;
4778 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4782 if (total_params < 4) {
4783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4787 fsp = file_fsp(req, SVAL(params,0));
4788 if (!fsp_is_np(fsp)) {
4789 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4793 info_level = SVAL(params,2);
4795 *pparams = (char *)SMB_REALLOC(*pparams,2);
4796 if (*pparams == NULL) {
4797 reply_nterror(req, NT_STATUS_NO_MEMORY);
4802 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4806 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4807 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4808 if (*ppdata == NULL ) {
4809 reply_nterror(req, NT_STATUS_NO_MEMORY);
4814 switch (info_level) {
4815 case SMB_FILE_STANDARD_INFORMATION:
4817 SOFF_T(pdata,0,4096LL);
4824 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4828 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4834 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4835 TALLOC_CTX *mem_ctx,
4836 uint16_t info_level,
4838 struct smb_filename *smb_fname,
4839 bool delete_pending,
4840 struct timespec write_time_ts,
4841 struct ea_list *ea_list,
4842 int lock_data_count,
4845 unsigned int max_data_bytes,
4846 size_t *fixed_portion,
4848 unsigned int *pdata_size)
4850 char *pdata = *ppdata;
4851 char *dstart, *dend;
4852 unsigned int data_size;
4853 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4854 time_t create_time, mtime, atime, c_time;
4855 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4862 uint64_t file_size = 0;
4864 uint64_t allocation_size = 0;
4865 uint64_t file_index = 0;
4866 uint32_t access_mask = 0;
4869 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4870 return NT_STATUS_INVALID_LEVEL;
4873 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4874 smb_fname_str_dbg(smb_fname),
4876 info_level, max_data_bytes));
4878 mode = dos_mode(conn, smb_fname);
4879 nlink = psbuf->st_ex_nlink;
4881 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4885 if ((nlink > 0) && delete_pending) {
4889 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4890 return NT_STATUS_INVALID_PARAMETER;
4893 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4894 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4895 if (*ppdata == NULL) {
4896 return NT_STATUS_NO_MEMORY;
4900 dend = dstart + data_size - 1;
4902 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4903 update_stat_ex_mtime(psbuf, write_time_ts);
4906 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4907 mtime_ts = psbuf->st_ex_mtime;
4908 atime_ts = psbuf->st_ex_atime;
4909 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4911 if (lp_dos_filetime_resolution(SNUM(conn))) {
4912 dos_filetime_timespec(&create_time_ts);
4913 dos_filetime_timespec(&mtime_ts);
4914 dos_filetime_timespec(&atime_ts);
4915 dos_filetime_timespec(&ctime_ts);
4918 create_time = convert_timespec_to_time_t(create_time_ts);
4919 mtime = convert_timespec_to_time_t(mtime_ts);
4920 atime = convert_timespec_to_time_t(atime_ts);
4921 c_time = convert_timespec_to_time_t(ctime_ts);
4923 p = strrchr_m(smb_fname->base_name,'/');
4925 base_name = smb_fname->base_name;
4929 /* NT expects the name to be in an exact form of the *full*
4930 filename. See the trans2 torture test */
4931 if (ISDOT(base_name)) {
4932 dos_fname = talloc_strdup(mem_ctx, "\\");
4934 return NT_STATUS_NO_MEMORY;
4937 dos_fname = talloc_asprintf(mem_ctx,
4939 smb_fname->base_name);
4941 return NT_STATUS_NO_MEMORY;
4943 if (is_ntfs_stream_smb_fname(smb_fname)) {
4944 dos_fname = talloc_asprintf(dos_fname, "%s",
4945 smb_fname->stream_name);
4947 return NT_STATUS_NO_MEMORY;
4951 string_replace(dos_fname, '/', '\\');
4954 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4957 /* Do we have this path open ? */
4959 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4960 fsp1 = file_find_di_first(conn->sconn, fileid);
4961 if (fsp1 && fsp1->initial_allocation_size) {
4962 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4966 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4967 file_size = get_file_size_stat(psbuf);
4971 pos = fsp->fh->position_information;
4975 access_mask = fsp->access_mask;
4977 /* GENERIC_EXECUTE mapping from Windows */
4978 access_mask = 0x12019F;
4981 /* This should be an index number - looks like
4984 I think this causes us to fail the IFSKIT
4985 BasicFileInformationTest. -tpot */
4986 file_index = get_FileIndex(conn, psbuf);
4990 switch (info_level) {
4991 case SMB_INFO_STANDARD:
4992 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4994 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4995 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4996 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4997 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4998 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4999 SSVAL(pdata,l1_attrFile,mode);
5002 case SMB_INFO_QUERY_EA_SIZE:
5004 unsigned int ea_size =
5005 estimate_ea_size(conn, fsp,
5007 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5009 srv_put_dos_date2(pdata,0,create_time);
5010 srv_put_dos_date2(pdata,4,atime);
5011 srv_put_dos_date2(pdata,8,mtime); /* write time */
5012 SIVAL(pdata,12,(uint32_t)file_size);
5013 SIVAL(pdata,16,(uint32_t)allocation_size);
5014 SSVAL(pdata,20,mode);
5015 SIVAL(pdata,22,ea_size);
5019 case SMB_INFO_IS_NAME_VALID:
5020 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5022 /* os/2 needs this ? really ?*/
5023 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5025 /* This is only reached for qpathinfo */
5029 case SMB_INFO_QUERY_EAS_FROM_LIST:
5031 size_t total_ea_len = 0;
5032 struct ea_list *ea_file_list = NULL;
5033 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5036 get_ea_list_from_file(mem_ctx, conn, fsp,
5038 &total_ea_len, &ea_file_list);
5039 if (!NT_STATUS_IS_OK(status)) {
5043 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5045 if (!ea_list || (total_ea_len > data_size)) {
5047 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5051 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5055 case SMB_INFO_QUERY_ALL_EAS:
5057 /* We have data_size bytes to put EA's into. */
5058 size_t total_ea_len = 0;
5059 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5061 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5063 &total_ea_len, &ea_list);
5064 if (!NT_STATUS_IS_OK(status)) {
5068 if (!ea_list || (total_ea_len > data_size)) {
5070 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5074 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5078 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5080 /* This is FileFullEaInformation - 0xF which maps to
5081 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5083 /* We have data_size bytes to put EA's into. */
5084 size_t total_ea_len = 0;
5085 struct ea_list *ea_file_list = NULL;
5087 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5089 /*TODO: add filtering and index handling */
5092 get_ea_list_from_file(mem_ctx, conn, fsp,
5094 &total_ea_len, &ea_file_list);
5095 if (!NT_STATUS_IS_OK(status)) {
5098 if (!ea_file_list) {
5099 return NT_STATUS_NO_EAS_ON_FILE;
5102 status = fill_ea_chained_buffer(mem_ctx,
5106 conn, ea_file_list);
5107 if (!NT_STATUS_IS_OK(status)) {
5113 case SMB_FILE_BASIC_INFORMATION:
5114 case SMB_QUERY_FILE_BASIC_INFO:
5116 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5117 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5118 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5120 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5124 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5125 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5126 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5127 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5128 SIVAL(pdata,32,mode);
5130 DEBUG(5,("SMB_QFBI - "));
5131 DEBUG(5,("create: %s ", ctime(&create_time)));
5132 DEBUG(5,("access: %s ", ctime(&atime)));
5133 DEBUG(5,("write: %s ", ctime(&mtime)));
5134 DEBUG(5,("change: %s ", ctime(&c_time)));
5135 DEBUG(5,("mode: %x\n", mode));
5136 *fixed_portion = data_size;
5139 case SMB_FILE_STANDARD_INFORMATION:
5140 case SMB_QUERY_FILE_STANDARD_INFO:
5142 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5144 SOFF_T(pdata,0,allocation_size);
5145 SOFF_T(pdata,8,file_size);
5146 SIVAL(pdata,16,nlink);
5147 SCVAL(pdata,20,delete_pending?1:0);
5148 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5149 SSVAL(pdata,22,0); /* Padding. */
5150 *fixed_portion = 24;
5153 case SMB_FILE_EA_INFORMATION:
5154 case SMB_QUERY_FILE_EA_INFO:
5156 unsigned int ea_size =
5157 estimate_ea_size(conn, fsp, smb_fname);
5158 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5161 SIVAL(pdata,0,ea_size);
5165 /* Get the 8.3 name - used if NT SMB was negotiated. */
5166 case SMB_QUERY_FILE_ALT_NAME_INFO:
5167 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5169 char mangled_name[13];
5170 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5171 if (!name_to_8_3(base_name,mangled_name,
5172 True,conn->params)) {
5173 return NT_STATUS_NO_MEMORY;
5175 status = srvstr_push(dstart, flags2,
5176 pdata+4, mangled_name,
5177 PTR_DIFF(dend, pdata+4),
5179 if (!NT_STATUS_IS_OK(status)) {
5182 data_size = 4 + len;
5188 case SMB_QUERY_FILE_NAME_INFO:
5191 this must be *exactly* right for ACLs on mapped drives to work
5193 status = srvstr_push(dstart, flags2,
5195 PTR_DIFF(dend, pdata+4),
5197 if (!NT_STATUS_IS_OK(status)) {
5200 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5201 data_size = 4 + len;
5206 case SMB_FILE_ALLOCATION_INFORMATION:
5207 case SMB_QUERY_FILE_ALLOCATION_INFO:
5208 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5210 SOFF_T(pdata,0,allocation_size);
5213 case SMB_FILE_END_OF_FILE_INFORMATION:
5214 case SMB_QUERY_FILE_END_OF_FILEINFO:
5215 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5217 SOFF_T(pdata,0,file_size);
5220 case SMB_QUERY_FILE_ALL_INFO:
5221 case SMB_FILE_ALL_INFORMATION:
5223 unsigned int ea_size =
5224 estimate_ea_size(conn, fsp, smb_fname);
5225 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5226 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5227 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5228 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5229 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5230 SIVAL(pdata,32,mode);
5231 SIVAL(pdata,36,0); /* padding. */
5233 SOFF_T(pdata,0,allocation_size);
5234 SOFF_T(pdata,8,file_size);
5235 SIVAL(pdata,16,nlink);
5236 SCVAL(pdata,20,delete_pending);
5237 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5240 SIVAL(pdata,0,ea_size);
5241 pdata += 4; /* EA info */
5242 status = srvstr_push(dstart, flags2,
5244 PTR_DIFF(dend, pdata+4),
5246 if (!NT_STATUS_IS_OK(status)) {
5251 data_size = PTR_DIFF(pdata,(*ppdata));
5252 *fixed_portion = 10;
5256 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5258 unsigned int ea_size =
5259 estimate_ea_size(conn, fsp, smb_fname);
5260 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5261 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5262 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5263 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5264 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5265 SIVAL(pdata, 0x20, mode);
5266 SIVAL(pdata, 0x24, 0); /* padding. */
5267 SBVAL(pdata, 0x28, allocation_size);
5268 SBVAL(pdata, 0x30, file_size);
5269 SIVAL(pdata, 0x38, nlink);
5270 SCVAL(pdata, 0x3C, delete_pending);
5271 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5272 SSVAL(pdata, 0x3E, 0); /* padding */
5273 SBVAL(pdata, 0x40, file_index);
5274 SIVAL(pdata, 0x48, ea_size);
5275 SIVAL(pdata, 0x4C, access_mask);
5276 SBVAL(pdata, 0x50, pos);
5277 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5278 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5282 status = srvstr_push(dstart, flags2,
5284 PTR_DIFF(dend, pdata+4),
5286 if (!NT_STATUS_IS_OK(status)) {
5291 data_size = PTR_DIFF(pdata,(*ppdata));
5292 *fixed_portion = 104;
5295 case SMB_FILE_INTERNAL_INFORMATION:
5297 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5298 SBVAL(pdata, 0, file_index);
5303 case SMB_FILE_ACCESS_INFORMATION:
5304 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5305 SIVAL(pdata, 0, access_mask);
5310 case SMB_FILE_NAME_INFORMATION:
5311 /* Pathname with leading '\'. */
5314 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5315 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5316 SIVAL(pdata,0,byte_len);
5317 data_size = 4 + byte_len;
5321 case SMB_FILE_DISPOSITION_INFORMATION:
5322 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5324 SCVAL(pdata,0,delete_pending);
5328 case SMB_FILE_POSITION_INFORMATION:
5329 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5331 SOFF_T(pdata,0,pos);
5335 case SMB_FILE_MODE_INFORMATION:
5336 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5337 SIVAL(pdata,0,mode);
5342 case SMB_FILE_ALIGNMENT_INFORMATION:
5343 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5344 SIVAL(pdata,0,0); /* No alignment needed. */
5350 * NT4 server just returns "invalid query" to this - if we try
5351 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5354 /* The first statement above is false - verified using Thursby
5355 * client against NT4 -- gcolley.
5357 case SMB_QUERY_FILE_STREAM_INFO:
5358 case SMB_FILE_STREAM_INFORMATION: {
5359 unsigned int num_streams = 0;
5360 struct stream_struct *streams = NULL;
5362 DEBUG(10,("smbd_do_qfilepathinfo: "
5363 "SMB_FILE_STREAM_INFORMATION\n"));
5365 if (is_ntfs_stream_smb_fname(smb_fname)) {
5366 return NT_STATUS_INVALID_PARAMETER;
5369 status = vfs_streaminfo(conn,
5376 if (!NT_STATUS_IS_OK(status)) {
5377 DEBUG(10, ("could not get stream info: %s\n",
5378 nt_errstr(status)));
5382 status = marshall_stream_info(num_streams, streams,
5383 pdata, max_data_bytes,
5386 if (!NT_STATUS_IS_OK(status)) {
5387 DEBUG(10, ("marshall_stream_info failed: %s\n",
5388 nt_errstr(status)));
5389 TALLOC_FREE(streams);
5393 TALLOC_FREE(streams);
5395 *fixed_portion = 32;
5399 case SMB_QUERY_COMPRESSION_INFO:
5400 case SMB_FILE_COMPRESSION_INFORMATION:
5401 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5402 SOFF_T(pdata,0,file_size);
5403 SIVAL(pdata,8,0); /* ??? */
5404 SIVAL(pdata,12,0); /* ??? */
5406 *fixed_portion = 16;
5409 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5410 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5411 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5412 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5413 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5414 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5415 SOFF_T(pdata,32,allocation_size);
5416 SOFF_T(pdata,40,file_size);
5417 SIVAL(pdata,48,mode);
5418 SIVAL(pdata,52,0); /* ??? */
5420 *fixed_portion = 56;
5423 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5424 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5425 SIVAL(pdata,0,mode);
5432 * CIFS UNIX Extensions.
5435 case SMB_QUERY_FILE_UNIX_BASIC:
5437 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5438 data_size = PTR_DIFF(pdata,(*ppdata));
5440 DEBUG(4,("smbd_do_qfilepathinfo: "
5441 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5442 dump_data(4, (uint8_t *)(*ppdata), data_size);
5446 case SMB_QUERY_FILE_UNIX_INFO2:
5448 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5449 data_size = PTR_DIFF(pdata,(*ppdata));
5453 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5455 for (i=0; i<100; i++)
5456 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5462 case SMB_QUERY_FILE_UNIX_LINK:
5465 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5468 return NT_STATUS_NO_MEMORY;
5471 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5473 if(!S_ISLNK(psbuf->st_ex_mode)) {
5474 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5477 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5479 link_len = SMB_VFS_READLINK(conn,
5482 if (link_len == -1) {
5483 return map_nt_error_from_unix(errno);
5485 buffer[link_len] = 0;
5486 status = srvstr_push(dstart, flags2,
5488 PTR_DIFF(dend, pdata),
5489 STR_TERMINATE, &len);
5490 if (!NT_STATUS_IS_OK(status)) {
5494 data_size = PTR_DIFF(pdata,(*ppdata));
5499 #if defined(HAVE_POSIX_ACLS)
5500 case SMB_QUERY_POSIX_ACL:
5502 SMB_ACL_T file_acl = NULL;
5503 SMB_ACL_T def_acl = NULL;
5504 uint16_t num_file_acls = 0;
5505 uint16_t num_def_acls = 0;
5507 status = refuse_symlink(conn,
5510 if (!NT_STATUS_IS_OK(status)) {
5514 if (fsp && fsp->fh->fd != -1) {
5515 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5519 SMB_VFS_SYS_ACL_GET_FILE(conn,
5521 SMB_ACL_TYPE_ACCESS,
5525 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5526 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5527 "not implemented on "
5528 "filesystem containing %s\n",
5529 smb_fname->base_name));
5530 return NT_STATUS_NOT_IMPLEMENTED;
5533 if (S_ISDIR(psbuf->st_ex_mode)) {
5534 if (fsp && fsp->is_directory) {
5536 SMB_VFS_SYS_ACL_GET_FILE(
5539 SMB_ACL_TYPE_DEFAULT,
5543 SMB_VFS_SYS_ACL_GET_FILE(
5546 SMB_ACL_TYPE_DEFAULT,
5549 def_acl = free_empty_sys_acl(conn, def_acl);
5552 num_file_acls = count_acl_entries(conn, file_acl);
5553 num_def_acls = count_acl_entries(conn, def_acl);
5555 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5556 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5558 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5559 SMB_POSIX_ACL_HEADER_SIZE) ));
5561 TALLOC_FREE(file_acl);
5564 TALLOC_FREE(def_acl);
5566 return NT_STATUS_BUFFER_TOO_SMALL;
5569 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5570 SSVAL(pdata,2,num_file_acls);
5571 SSVAL(pdata,4,num_def_acls);
5572 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5574 TALLOC_FREE(file_acl);
5577 TALLOC_FREE(def_acl);
5579 return NT_STATUS_INTERNAL_ERROR;
5581 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5583 TALLOC_FREE(file_acl);
5586 TALLOC_FREE(def_acl);
5588 return NT_STATUS_INTERNAL_ERROR;
5592 TALLOC_FREE(file_acl);
5595 TALLOC_FREE(def_acl);
5597 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5603 case SMB_QUERY_POSIX_LOCK:
5608 enum brl_type lock_type;
5610 /* We need an open file with a real fd for this. */
5611 if (!fsp || fsp->fh->fd == -1) {
5612 return NT_STATUS_INVALID_LEVEL;
5615 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5616 return NT_STATUS_INVALID_PARAMETER;
5619 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5620 case POSIX_LOCK_TYPE_READ:
5621 lock_type = READ_LOCK;
5623 case POSIX_LOCK_TYPE_WRITE:
5624 lock_type = WRITE_LOCK;
5626 case POSIX_LOCK_TYPE_UNLOCK:
5628 /* There's no point in asking for an unlock... */
5629 return NT_STATUS_INVALID_PARAMETER;
5632 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5633 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5634 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5636 status = query_lock(fsp,
5643 if (ERROR_WAS_LOCK_DENIED(status)) {
5644 /* Here we need to report who has it locked... */
5645 data_size = POSIX_LOCK_DATA_SIZE;
5647 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5648 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5649 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5650 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5651 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5653 } else if (NT_STATUS_IS_OK(status)) {
5654 /* For success we just return a copy of what we sent
5655 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5656 data_size = POSIX_LOCK_DATA_SIZE;
5657 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5658 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5666 return NT_STATUS_INVALID_LEVEL;
5669 *pdata_size = data_size;
5670 return NT_STATUS_OK;
5673 /****************************************************************************
5674 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5675 file name or file id).
5676 ****************************************************************************/
5678 static void call_trans2qfilepathinfo(connection_struct *conn,
5679 struct smb_request *req,
5680 unsigned int tran_call,
5681 char **pparams, int total_params,
5682 char **ppdata, int total_data,
5683 unsigned int max_data_bytes)
5685 char *params = *pparams;
5686 char *pdata = *ppdata;
5687 uint16_t info_level;
5688 unsigned int data_size = 0;
5689 unsigned int param_size = 2;
5690 struct smb_filename *smb_fname = NULL;
5691 bool delete_pending = False;
5692 struct timespec write_time_ts;
5693 files_struct *fsp = NULL;
5694 struct file_id fileid;
5695 struct ea_list *ea_list = NULL;
5696 int lock_data_count = 0;
5697 char *lock_data = NULL;
5698 size_t fixed_portion;
5699 NTSTATUS status = NT_STATUS_OK;
5702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5706 ZERO_STRUCT(write_time_ts);
5708 if (tran_call == TRANSACT2_QFILEINFO) {
5709 if (total_params < 4) {
5710 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5715 call_trans2qpipeinfo(conn, req, tran_call,
5716 pparams, total_params,
5722 fsp = file_fsp(req, SVAL(params,0));
5723 info_level = SVAL(params,2);
5725 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5727 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5728 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5732 /* Initial check for valid fsp ptr. */
5733 if (!check_fsp_open(conn, req, fsp)) {
5737 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5738 if (smb_fname == NULL) {
5739 reply_nterror(req, NT_STATUS_NO_MEMORY);
5743 if(fsp->fake_file_handle) {
5745 * This is actually for the QUOTA_FAKE_FILE --metze
5748 /* We know this name is ok, it's already passed the checks. */
5750 } else if(fsp->fh->fd == -1) {
5752 * This is actually a QFILEINFO on a directory
5753 * handle (returned from an NT SMB). NT5.0 seems
5754 * to do this call. JRA.
5757 if (INFO_LEVEL_IS_UNIX(info_level)) {
5758 /* Always do lstat for UNIX calls. */
5759 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5760 DEBUG(3,("call_trans2qfilepathinfo: "
5761 "SMB_VFS_LSTAT of %s failed "
5763 smb_fname_str_dbg(smb_fname),
5766 map_nt_error_from_unix(errno));
5769 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5770 DEBUG(3,("call_trans2qfilepathinfo: "
5771 "SMB_VFS_STAT of %s failed (%s)\n",
5772 smb_fname_str_dbg(smb_fname),
5775 map_nt_error_from_unix(errno));
5779 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5780 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5783 * Original code - this is an open file.
5785 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5786 DEBUG(3, ("fstat of %s failed (%s)\n",
5787 fsp_fnum_dbg(fsp), strerror(errno)));
5789 map_nt_error_from_unix(errno));
5792 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5793 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5799 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5802 if (total_params < 7) {
5803 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5807 info_level = SVAL(params,0);
5809 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5811 if (INFO_LEVEL_IS_UNIX(info_level)) {
5812 if (!lp_unix_extensions()) {
5813 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5816 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5817 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5818 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5819 req->posix_pathnames) {
5820 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5824 if (req->posix_pathnames) {
5825 srvstr_get_path_posix(req,
5834 srvstr_get_path(req,
5843 if (!NT_STATUS_IS_OK(status)) {
5844 reply_nterror(req, status);
5848 status = filename_convert(req,
5854 if (!NT_STATUS_IS_OK(status)) {
5855 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5856 reply_botherror(req,
5857 NT_STATUS_PATH_NOT_COVERED,
5858 ERRSRV, ERRbadpath);
5861 reply_nterror(req, status);
5865 /* If this is a stream, check if there is a delete_pending. */
5866 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5867 && is_ntfs_stream_smb_fname(smb_fname)) {
5868 struct smb_filename *smb_fname_base;
5870 /* Create an smb_filename with stream_name == NULL. */
5871 smb_fname_base = synthetic_smb_fname(
5873 smb_fname->base_name,
5877 if (smb_fname_base == NULL) {
5878 reply_nterror(req, NT_STATUS_NO_MEMORY);
5882 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5883 /* Always do lstat for UNIX calls. */
5884 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5885 DEBUG(3,("call_trans2qfilepathinfo: "
5886 "SMB_VFS_LSTAT of %s failed "
5888 smb_fname_str_dbg(smb_fname_base),
5890 TALLOC_FREE(smb_fname_base);
5892 map_nt_error_from_unix(errno));
5896 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5897 DEBUG(3,("call_trans2qfilepathinfo: "
5898 "fileinfo of %s failed "
5900 smb_fname_str_dbg(smb_fname_base),
5902 TALLOC_FREE(smb_fname_base);
5904 map_nt_error_from_unix(errno));
5909 status = file_name_hash(conn,
5910 smb_fname_str_dbg(smb_fname_base),
5912 if (!NT_STATUS_IS_OK(status)) {
5913 TALLOC_FREE(smb_fname_base);
5914 reply_nterror(req, status);
5918 fileid = vfs_file_id_from_sbuf(conn,
5919 &smb_fname_base->st);
5920 TALLOC_FREE(smb_fname_base);
5921 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5922 if (delete_pending) {
5923 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5928 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5929 /* Always do lstat for UNIX calls. */
5930 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5931 DEBUG(3,("call_trans2qfilepathinfo: "
5932 "SMB_VFS_LSTAT of %s failed (%s)\n",
5933 smb_fname_str_dbg(smb_fname),
5936 map_nt_error_from_unix(errno));
5941 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5942 DEBUG(3,("call_trans2qfilepathinfo: "
5943 "SMB_VFS_STAT of %s failed (%s)\n",
5944 smb_fname_str_dbg(smb_fname),
5947 map_nt_error_from_unix(errno));
5952 status = file_name_hash(conn,
5953 smb_fname_str_dbg(smb_fname),
5955 if (!NT_STATUS_IS_OK(status)) {
5956 reply_nterror(req, status);
5960 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5961 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5962 if (delete_pending) {
5963 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5968 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5969 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5971 info_level,tran_call,total_data));
5973 /* Pull out any data sent here before we realloc. */
5974 switch (info_level) {
5975 case SMB_INFO_QUERY_EAS_FROM_LIST:
5977 /* Pull any EA list from the data portion. */
5980 if (total_data < 4) {
5982 req, NT_STATUS_INVALID_PARAMETER);
5985 ea_size = IVAL(pdata,0);
5987 if (total_data > 0 && ea_size != total_data) {
5988 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5989 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5991 req, NT_STATUS_INVALID_PARAMETER);
5995 if (!lp_ea_support(SNUM(conn))) {
5996 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6000 /* Pull out the list of names. */
6001 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6004 req, NT_STATUS_INVALID_PARAMETER);
6010 case SMB_QUERY_POSIX_LOCK:
6012 if (fsp == NULL || fsp->fh->fd == -1) {
6013 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6017 if (total_data != POSIX_LOCK_DATA_SIZE) {
6019 req, NT_STATUS_INVALID_PARAMETER);
6023 /* Copy the lock range data. */
6024 lock_data = (char *)talloc_memdup(
6025 req, pdata, total_data);
6027 reply_nterror(req, NT_STATUS_NO_MEMORY);
6030 lock_data_count = total_data;
6036 *pparams = (char *)SMB_REALLOC(*pparams,2);
6037 if (*pparams == NULL) {
6038 reply_nterror(req, NT_STATUS_NO_MEMORY);
6045 * draft-leach-cifs-v1-spec-02.txt
6046 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6049 * The requested information is placed in the Data portion of the
6050 * transaction response. For the information levels greater than 0x100,
6051 * the transaction response has 1 parameter word which should be
6052 * ignored by the client.
6054 * However Windows only follows this rule for the IS_NAME_VALID call.
6056 switch (info_level) {
6057 case SMB_INFO_IS_NAME_VALID:
6062 if ((info_level & 0xFF00) == 0xFF00) {
6064 * We use levels that start with 0xFF00
6065 * internally to represent SMB2 specific levels
6067 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6071 status = smbd_do_qfilepathinfo(conn, req, info_level,
6073 delete_pending, write_time_ts,
6075 lock_data_count, lock_data,
6076 req->flags2, max_data_bytes,
6078 ppdata, &data_size);
6079 if (!NT_STATUS_IS_OK(status)) {
6080 reply_nterror(req, status);
6083 if (fixed_portion > max_data_bytes) {
6084 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6088 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6094 /****************************************************************************
6095 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6097 ****************************************************************************/
6099 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6100 connection_struct *conn,
6101 struct smb_request *req,
6102 bool overwrite_if_exists,
6103 const struct smb_filename *smb_fname_old,
6104 struct smb_filename *smb_fname_new)
6106 NTSTATUS status = NT_STATUS_OK;
6108 /* source must already exist. */
6109 if (!VALID_STAT(smb_fname_old->st)) {
6110 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6113 if (VALID_STAT(smb_fname_new->st)) {
6114 if (overwrite_if_exists) {
6115 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6116 return NT_STATUS_FILE_IS_A_DIRECTORY;
6118 status = unlink_internals(conn,
6120 FILE_ATTRIBUTE_NORMAL,
6123 if (!NT_STATUS_IS_OK(status)) {
6127 /* Disallow if newname already exists. */
6128 return NT_STATUS_OBJECT_NAME_COLLISION;
6132 /* No links from a directory. */
6133 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6134 return NT_STATUS_FILE_IS_A_DIRECTORY;
6137 /* Setting a hardlink to/from a stream isn't currently supported. */
6138 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6139 is_ntfs_stream_smb_fname(smb_fname_new)) {
6140 return NT_STATUS_INVALID_PARAMETER;
6143 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6144 smb_fname_old->base_name, smb_fname_new->base_name));
6146 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6147 status = map_nt_error_from_unix(errno);
6148 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6149 nt_errstr(status), smb_fname_old->base_name,
6150 smb_fname_new->base_name));
6155 /****************************************************************************
6156 Deal with setting the time from any of the setfilepathinfo functions.
6157 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6158 calling this function.
6159 ****************************************************************************/
6161 NTSTATUS smb_set_file_time(connection_struct *conn,
6163 const struct smb_filename *smb_fname,
6164 struct smb_file_time *ft,
6165 bool setting_write_time)
6167 struct smb_filename smb_fname_base;
6169 FILE_NOTIFY_CHANGE_LAST_ACCESS
6170 |FILE_NOTIFY_CHANGE_LAST_WRITE
6171 |FILE_NOTIFY_CHANGE_CREATION;
6173 if (!VALID_STAT(smb_fname->st)) {
6174 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6177 /* get some defaults (no modifications) if any info is zero or -1. */
6178 if (null_timespec(ft->create_time)) {
6179 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6182 if (null_timespec(ft->atime)) {
6183 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6186 if (null_timespec(ft->mtime)) {
6187 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6190 if (!setting_write_time) {
6191 /* ft->mtime comes from change time, not write time. */
6192 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6195 /* Ensure the resolution is the correct for
6196 * what we can store on this filesystem. */
6198 round_timespec(conn->ts_res, &ft->create_time);
6199 round_timespec(conn->ts_res, &ft->ctime);
6200 round_timespec(conn->ts_res, &ft->atime);
6201 round_timespec(conn->ts_res, &ft->mtime);
6203 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6204 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6205 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6206 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6207 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6208 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6209 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6210 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6212 if (setting_write_time) {
6214 * This was a Windows setfileinfo on an open file.
6215 * NT does this a lot. We also need to
6216 * set the time here, as it can be read by
6217 * FindFirst/FindNext and with the patch for bug #2045
6218 * in smbd/fileio.c it ensures that this timestamp is
6219 * kept sticky even after a write. We save the request
6220 * away and will set it on file close and after a write. JRA.
6223 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6224 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6227 if (fsp->base_fsp) {
6228 set_sticky_write_time_fsp(fsp->base_fsp,
6231 set_sticky_write_time_fsp(fsp, ft->mtime);
6234 set_sticky_write_time_path(
6235 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6240 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6242 /* Always call ntimes on the base, even if a stream was passed in. */
6243 smb_fname_base = *smb_fname;
6244 smb_fname_base.stream_name = NULL;
6246 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6247 return map_nt_error_from_unix(errno);
6250 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6251 smb_fname->base_name);
6252 return NT_STATUS_OK;
6255 /****************************************************************************
6256 Deal with setting the dosmode from any of the setfilepathinfo functions.
6257 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6258 done before calling this function.
6259 ****************************************************************************/
6261 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6262 const struct smb_filename *smb_fname,
6265 struct smb_filename *smb_fname_base;
6268 if (!VALID_STAT(smb_fname->st)) {
6269 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6272 /* Always operate on the base_name, even if a stream was passed in. */
6273 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6274 smb_fname->base_name,
6278 if (smb_fname_base == NULL) {
6279 return NT_STATUS_NO_MEMORY;
6283 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6284 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6286 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6290 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6292 /* check the mode isn't different, before changing it */
6293 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6294 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6295 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6296 (unsigned int)dosmode));
6298 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6300 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6302 smb_fname_str_dbg(smb_fname_base),
6304 status = map_nt_error_from_unix(errno);
6308 status = NT_STATUS_OK;
6310 TALLOC_FREE(smb_fname_base);
6314 /****************************************************************************
6315 Deal with setting the size from any of the setfilepathinfo functions.
6316 ****************************************************************************/
6318 static NTSTATUS smb_set_file_size(connection_struct *conn,
6319 struct smb_request *req,
6321 const struct smb_filename *smb_fname,
6322 const SMB_STRUCT_STAT *psbuf,
6324 bool fail_after_createfile)
6326 NTSTATUS status = NT_STATUS_OK;
6327 struct smb_filename *smb_fname_tmp = NULL;
6328 files_struct *new_fsp = NULL;
6330 if (!VALID_STAT(*psbuf)) {
6331 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6334 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6336 if (size == get_file_size_stat(psbuf)) {
6337 return NT_STATUS_OK;
6340 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6341 smb_fname_str_dbg(smb_fname), (double)size));
6343 if (fsp && fsp->fh->fd != -1) {
6344 /* Handle based call. */
6345 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6346 return NT_STATUS_ACCESS_DENIED;
6349 if (vfs_set_filelen(fsp, size) == -1) {
6350 return map_nt_error_from_unix(errno);
6352 trigger_write_time_update_immediate(fsp);
6353 return NT_STATUS_OK;
6356 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6357 if (smb_fname_tmp == NULL) {
6358 return NT_STATUS_NO_MEMORY;
6361 smb_fname_tmp->st = *psbuf;
6363 status = SMB_VFS_CREATE_FILE(
6366 0, /* root_dir_fid */
6367 smb_fname_tmp, /* fname */
6368 FILE_WRITE_DATA, /* access_mask */
6369 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6371 FILE_OPEN, /* create_disposition*/
6372 0, /* create_options */
6373 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6374 0, /* oplock_request */
6376 0, /* allocation_size */
6377 0, /* private_flags */
6380 &new_fsp, /* result */
6382 NULL, NULL); /* create context */
6384 TALLOC_FREE(smb_fname_tmp);
6386 if (!NT_STATUS_IS_OK(status)) {
6387 /* NB. We check for open_was_deferred in the caller. */
6391 /* See RAW-SFILEINFO-END-OF-FILE */
6392 if (fail_after_createfile) {
6393 close_file(req, new_fsp,NORMAL_CLOSE);
6394 return NT_STATUS_INVALID_LEVEL;
6397 if (vfs_set_filelen(new_fsp, size) == -1) {
6398 status = map_nt_error_from_unix(errno);
6399 close_file(req, new_fsp,NORMAL_CLOSE);
6403 trigger_write_time_update_immediate(new_fsp);
6404 close_file(req, new_fsp,NORMAL_CLOSE);
6405 return NT_STATUS_OK;
6408 /****************************************************************************
6409 Deal with SMB_INFO_SET_EA.
6410 ****************************************************************************/
6412 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6416 const struct smb_filename *smb_fname)
6418 struct ea_list *ea_list = NULL;
6419 TALLOC_CTX *ctx = NULL;
6420 NTSTATUS status = NT_STATUS_OK;
6422 if (total_data < 10) {
6424 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6425 length. They seem to have no effect. Bug #3212. JRA */
6427 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6428 /* We're done. We only get EA info in this call. */
6429 return NT_STATUS_OK;
6432 return NT_STATUS_INVALID_PARAMETER;
6435 if (IVAL(pdata,0) > total_data) {
6436 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6437 IVAL(pdata,0), (unsigned int)total_data));
6438 return NT_STATUS_INVALID_PARAMETER;
6442 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6444 return NT_STATUS_INVALID_PARAMETER;
6447 status = set_ea(conn, fsp, smb_fname, ea_list);
6452 /****************************************************************************
6453 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6454 ****************************************************************************/
6456 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6461 struct ea_list *ea_list = NULL;
6465 return NT_STATUS_INVALID_HANDLE;
6468 if (!lp_ea_support(SNUM(conn))) {
6469 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6470 "EA's not supported.\n",
6471 (unsigned int)total_data));
6472 return NT_STATUS_EAS_NOT_SUPPORTED;
6475 if (total_data < 10) {
6476 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6478 (unsigned int)total_data));
6479 return NT_STATUS_INVALID_PARAMETER;
6482 ea_list = read_nttrans_ea_list(talloc_tos(),
6487 return NT_STATUS_INVALID_PARAMETER;
6490 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6492 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6493 smb_fname_str_dbg(fsp->fsp_name),
6494 nt_errstr(status) ));
6500 /****************************************************************************
6501 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6502 ****************************************************************************/
6504 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6508 struct smb_filename *smb_fname)
6510 NTSTATUS status = NT_STATUS_OK;
6511 bool delete_on_close;
6512 uint32_t dosmode = 0;
6514 if (total_data < 1) {
6515 return NT_STATUS_INVALID_PARAMETER;
6519 return NT_STATUS_INVALID_HANDLE;
6522 delete_on_close = (CVAL(pdata,0) ? True : False);
6523 dosmode = dos_mode(conn, smb_fname);
6525 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6526 "delete_on_close = %u\n",
6527 smb_fname_str_dbg(smb_fname),
6528 (unsigned int)dosmode,
6529 (unsigned int)delete_on_close ));
6531 if (delete_on_close) {
6532 status = can_set_delete_on_close(fsp, dosmode);
6533 if (!NT_STATUS_IS_OK(status)) {
6538 /* The set is across all open files on this dev/inode pair. */
6539 if (!set_delete_on_close(fsp, delete_on_close,
6540 conn->session_info->security_token,
6541 conn->session_info->unix_token)) {
6542 return NT_STATUS_ACCESS_DENIED;
6544 return NT_STATUS_OK;
6547 /****************************************************************************
6548 Deal with SMB_FILE_POSITION_INFORMATION.
6549 ****************************************************************************/
6551 static NTSTATUS smb_file_position_information(connection_struct *conn,
6556 uint64_t position_information;
6558 if (total_data < 8) {
6559 return NT_STATUS_INVALID_PARAMETER;
6563 /* Ignore on pathname based set. */
6564 return NT_STATUS_OK;
6567 position_information = (uint64_t)IVAL(pdata,0);
6568 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6570 DEBUG(10,("smb_file_position_information: Set file position "
6571 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6572 (double)position_information));
6573 fsp->fh->position_information = position_information;
6574 return NT_STATUS_OK;
6577 /****************************************************************************
6578 Deal with SMB_FILE_MODE_INFORMATION.
6579 ****************************************************************************/
6581 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6587 if (total_data < 4) {
6588 return NT_STATUS_INVALID_PARAMETER;
6590 mode = IVAL(pdata,0);
6591 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6592 return NT_STATUS_INVALID_PARAMETER;
6594 return NT_STATUS_OK;
6597 /****************************************************************************
6598 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6599 ****************************************************************************/
6601 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6602 struct smb_request *req,
6605 const struct smb_filename *new_smb_fname)
6607 char *link_target = NULL;
6608 TALLOC_CTX *ctx = talloc_tos();
6610 /* Set a symbolic link. */
6611 /* Don't allow this if follow links is false. */
6613 if (total_data == 0) {
6614 return NT_STATUS_INVALID_PARAMETER;
6617 if (!lp_follow_symlinks(SNUM(conn))) {
6618 return NT_STATUS_ACCESS_DENIED;
6621 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6622 total_data, STR_TERMINATE);
6625 return NT_STATUS_INVALID_PARAMETER;
6628 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6629 new_smb_fname->base_name, link_target ));
6631 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6632 return map_nt_error_from_unix(errno);
6635 return NT_STATUS_OK;
6638 /****************************************************************************
6639 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6640 ****************************************************************************/
6642 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6643 struct smb_request *req,
6644 const char *pdata, int total_data,
6645 struct smb_filename *smb_fname_new)
6647 char *oldname = NULL;
6648 struct smb_filename *smb_fname_old = NULL;
6649 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6650 TALLOC_CTX *ctx = talloc_tos();
6651 NTSTATUS status = NT_STATUS_OK;
6653 /* Set a hard link. */
6654 if (total_data == 0) {
6655 return NT_STATUS_INVALID_PARAMETER;
6658 if (req->posix_pathnames) {
6659 srvstr_get_path_posix(ctx,
6668 srvstr_get_path(ctx,
6677 if (!NT_STATUS_IS_OK(status)) {
6681 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6682 smb_fname_str_dbg(smb_fname_new), oldname));
6684 status = filename_convert(ctx,
6690 if (!NT_STATUS_IS_OK(status)) {
6694 return hardlink_internals(ctx, conn, req, false,
6695 smb_fname_old, smb_fname_new);
6698 /****************************************************************************
6699 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6700 ****************************************************************************/
6702 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6703 struct smb_request *req,
6707 struct smb_filename *smb_fname_src)
6711 char *newname = NULL;
6712 struct smb_filename *smb_fname_dst = NULL;
6713 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6714 ucf_flags_from_smb_request(req);
6715 NTSTATUS status = NT_STATUS_OK;
6716 TALLOC_CTX *ctx = talloc_tos();
6719 return NT_STATUS_INVALID_HANDLE;
6722 if (total_data < 20) {
6723 return NT_STATUS_INVALID_PARAMETER;
6726 overwrite = (CVAL(pdata,0) ? True : False);
6727 len = IVAL(pdata,16);
6729 if (len > (total_data - 20) || (len == 0)) {
6730 return NT_STATUS_INVALID_PARAMETER;
6733 if (req->posix_pathnames) {
6734 srvstr_get_path_posix(ctx,
6743 srvstr_get_path(ctx,
6752 if (!NT_STATUS_IS_OK(status)) {
6756 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6759 status = filename_convert(ctx,
6765 if (!NT_STATUS_IS_OK(status)) {
6769 if (fsp->base_fsp) {
6770 /* newname must be a stream name. */
6771 if (newname[0] != ':') {
6772 return NT_STATUS_NOT_SUPPORTED;
6775 /* Create an smb_fname to call rename_internals_fsp() with. */
6776 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6777 fsp->base_fsp->fsp_name->base_name,
6780 fsp->base_fsp->fsp_name->flags);
6781 if (smb_fname_dst == NULL) {
6782 status = NT_STATUS_NO_MEMORY;
6787 * Set the original last component, since
6788 * rename_internals_fsp() requires it.
6790 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6792 if (smb_fname_dst->original_lcomp == NULL) {
6793 status = NT_STATUS_NO_MEMORY;
6799 DEBUG(10,("smb2_file_rename_information: "
6800 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6801 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6802 smb_fname_str_dbg(smb_fname_dst)));
6803 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6804 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6808 TALLOC_FREE(smb_fname_dst);
6812 static NTSTATUS smb_file_link_information(connection_struct *conn,
6813 struct smb_request *req,
6817 struct smb_filename *smb_fname_src)
6821 char *newname = NULL;
6822 struct smb_filename *smb_fname_dst = NULL;
6823 NTSTATUS status = NT_STATUS_OK;
6824 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6825 ucf_flags_from_smb_request(req);
6826 TALLOC_CTX *ctx = talloc_tos();
6829 return NT_STATUS_INVALID_HANDLE;
6832 if (total_data < 20) {
6833 return NT_STATUS_INVALID_PARAMETER;
6836 overwrite = (CVAL(pdata,0) ? true : false);
6837 len = IVAL(pdata,16);
6839 if (len > (total_data - 20) || (len == 0)) {
6840 return NT_STATUS_INVALID_PARAMETER;
6843 if (req->posix_pathnames) {
6844 srvstr_get_path_posix(ctx,
6853 srvstr_get_path(ctx,
6862 if (!NT_STATUS_IS_OK(status)) {
6866 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6869 status = filename_convert(ctx,
6875 if (!NT_STATUS_IS_OK(status)) {
6879 if (fsp->base_fsp) {
6880 /* No stream names. */
6881 return NT_STATUS_NOT_SUPPORTED;
6884 DEBUG(10,("smb_file_link_information: "
6885 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6886 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6887 smb_fname_str_dbg(smb_fname_dst)));
6888 status = hardlink_internals(ctx,
6895 TALLOC_FREE(smb_fname_dst);
6899 /****************************************************************************
6900 Deal with SMB_FILE_RENAME_INFORMATION.
6901 ****************************************************************************/
6903 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6904 struct smb_request *req,
6908 struct smb_filename *smb_fname_src)
6913 char *newname = NULL;
6914 struct smb_filename *smb_fname_dst = NULL;
6915 bool dest_has_wcard = False;
6916 NTSTATUS status = NT_STATUS_OK;
6918 TALLOC_CTX *ctx = talloc_tos();
6920 if (total_data < 13) {
6921 return NT_STATUS_INVALID_PARAMETER;
6924 overwrite = (CVAL(pdata,0) ? True : False);
6925 root_fid = IVAL(pdata,4);
6926 len = IVAL(pdata,8);
6928 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6929 return NT_STATUS_INVALID_PARAMETER;
6932 if (req->posix_pathnames) {
6933 srvstr_get_path_wcard_posix(ctx,
6943 srvstr_get_path_wcard(ctx,
6953 if (!NT_STATUS_IS_OK(status)) {
6957 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6960 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
6961 status = resolve_dfspath_wcard(ctx, conn,
6963 UCF_COND_ALLOW_WCARD_LCOMP,
6964 !conn->sconn->using_smb2,
6967 if (!NT_STATUS_IS_OK(status)) {
6972 /* Check the new name has no '/' characters. */
6973 if (strchr_m(newname, '/')) {
6974 return NT_STATUS_NOT_SUPPORTED;
6977 if (fsp && fsp->base_fsp) {
6978 /* newname must be a stream name. */
6979 if (newname[0] != ':') {
6980 return NT_STATUS_NOT_SUPPORTED;
6983 /* Create an smb_fname to call rename_internals_fsp() with. */
6984 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6985 fsp->base_fsp->fsp_name->base_name,
6988 fsp->base_fsp->fsp_name->flags);
6989 if (smb_fname_dst == NULL) {
6990 status = NT_STATUS_NO_MEMORY;
6995 * Set the original last component, since
6996 * rename_internals_fsp() requires it.
6998 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7000 if (smb_fname_dst->original_lcomp == NULL) {
7001 status = NT_STATUS_NO_MEMORY;
7007 * Build up an smb_fname_dst based on the filename passed in.
7008 * We basically just strip off the last component, and put on
7009 * the newname instead.
7011 char *base_name = NULL;
7012 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7013 ucf_flags_from_smb_request(req);
7015 if (dest_has_wcard) {
7016 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7019 /* newname must *not* be a stream name. */
7020 if (newname[0] == ':') {
7021 return NT_STATUS_NOT_SUPPORTED;
7025 * Strip off the last component (filename) of the path passed
7028 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7030 return NT_STATUS_NO_MEMORY;
7032 p = strrchr_m(base_name, '/');
7036 base_name = talloc_strdup(ctx, "");
7038 return NT_STATUS_NO_MEMORY;
7041 /* Append the new name. */
7042 base_name = talloc_asprintf_append(base_name,
7046 return NT_STATUS_NO_MEMORY;
7049 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7052 /* If an error we expect this to be
7053 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7055 if (!NT_STATUS_IS_OK(status)) {
7056 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7060 /* Create an smb_fname to call rename_internals_fsp() */
7061 smb_fname_dst = synthetic_smb_fname(ctx,
7065 smb_fname_src->flags);
7066 if (smb_fname_dst == NULL) {
7067 status = NT_STATUS_NO_MEMORY;
7074 DEBUG(10,("smb_file_rename_information: "
7075 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7076 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7077 smb_fname_str_dbg(smb_fname_dst)));
7078 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7081 DEBUG(10,("smb_file_rename_information: "
7082 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7083 smb_fname_str_dbg(smb_fname_src),
7084 smb_fname_str_dbg(smb_fname_dst)));
7085 status = rename_internals(ctx, conn, req, smb_fname_src,
7086 smb_fname_dst, 0, overwrite, false,
7088 FILE_WRITE_ATTRIBUTES);
7091 TALLOC_FREE(smb_fname_dst);
7095 /****************************************************************************
7096 Deal with SMB_SET_POSIX_ACL.
7097 ****************************************************************************/
7099 #if defined(HAVE_POSIX_ACLS)
7100 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7104 const struct smb_filename *smb_fname)
7106 uint16_t posix_acl_version;
7107 uint16_t num_file_acls;
7108 uint16_t num_def_acls;
7109 bool valid_file_acls = True;
7110 bool valid_def_acls = True;
7113 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7114 return NT_STATUS_INVALID_PARAMETER;
7116 posix_acl_version = SVAL(pdata,0);
7117 num_file_acls = SVAL(pdata,2);
7118 num_def_acls = SVAL(pdata,4);
7120 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7121 valid_file_acls = False;
7125 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7126 valid_def_acls = False;
7130 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7131 return NT_STATUS_INVALID_PARAMETER;
7134 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7135 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7136 return NT_STATUS_INVALID_PARAMETER;
7139 status = refuse_symlink(conn, fsp, smb_fname);
7140 if (!NT_STATUS_IS_OK(status)) {
7144 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7145 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7146 (unsigned int)num_file_acls,
7147 (unsigned int)num_def_acls));
7149 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7150 smb_fname, num_file_acls,
7151 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7152 return map_nt_error_from_unix(errno);
7155 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7156 smb_fname, num_def_acls,
7157 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7158 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7159 return map_nt_error_from_unix(errno);
7161 return NT_STATUS_OK;
7165 /****************************************************************************
7166 Deal with SMB_SET_POSIX_LOCK.
7167 ****************************************************************************/
7169 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7170 struct smb_request *req,
7178 bool blocking_lock = False;
7179 enum brl_type lock_type;
7181 NTSTATUS status = NT_STATUS_OK;
7183 if (fsp == NULL || fsp->fh->fd == -1) {
7184 return NT_STATUS_INVALID_HANDLE;
7187 if (total_data != POSIX_LOCK_DATA_SIZE) {
7188 return NT_STATUS_INVALID_PARAMETER;
7191 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7192 case POSIX_LOCK_TYPE_READ:
7193 lock_type = READ_LOCK;
7195 case POSIX_LOCK_TYPE_WRITE:
7196 /* Return the right POSIX-mappable error code for files opened read-only. */
7197 if (!fsp->can_write) {
7198 return NT_STATUS_INVALID_HANDLE;
7200 lock_type = WRITE_LOCK;
7202 case POSIX_LOCK_TYPE_UNLOCK:
7203 lock_type = UNLOCK_LOCK;
7206 return NT_STATUS_INVALID_PARAMETER;
7209 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7210 blocking_lock = False;
7211 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7212 blocking_lock = True;
7214 return NT_STATUS_INVALID_PARAMETER;
7217 if (!lp_blocking_locks(SNUM(conn))) {
7218 blocking_lock = False;
7221 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7222 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7223 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7224 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7225 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7227 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7228 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7230 (unsigned int)lock_type,
7231 (unsigned long long)smblctx,
7235 if (lock_type == UNLOCK_LOCK) {
7236 status = do_unlock(req->sconn->msg_ctx,
7243 uint64_t block_smblctx;
7245 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7256 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7258 * A blocking lock was requested. Package up
7259 * this smb into a queued request and push it
7260 * onto the blocking lock queue.
7262 if(push_blocking_lock_request(br_lck,
7265 -1, /* infinite timeout. */
7273 TALLOC_FREE(br_lck);
7277 TALLOC_FREE(br_lck);
7283 /****************************************************************************
7284 Deal with SMB_SET_FILE_BASIC_INFO.
7285 ****************************************************************************/
7287 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7291 const struct smb_filename *smb_fname)
7293 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7294 struct smb_file_time ft;
7295 uint32_t dosmode = 0;
7296 NTSTATUS status = NT_STATUS_OK;
7300 if (total_data < 36) {
7301 return NT_STATUS_INVALID_PARAMETER;
7304 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7305 if (!NT_STATUS_IS_OK(status)) {
7309 /* Set the attributes */
7310 dosmode = IVAL(pdata,32);
7311 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7312 if (!NT_STATUS_IS_OK(status)) {
7317 ft.create_time = interpret_long_date(pdata);
7320 ft.atime = interpret_long_date(pdata+8);
7323 ft.mtime = interpret_long_date(pdata+16);
7326 ft.ctime = interpret_long_date(pdata+24);
7328 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7329 smb_fname_str_dbg(smb_fname)));
7331 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7335 /****************************************************************************
7336 Deal with SMB_INFO_STANDARD.
7337 ****************************************************************************/
7339 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7343 const struct smb_filename *smb_fname)
7346 struct smb_file_time ft;
7350 if (total_data < 12) {
7351 return NT_STATUS_INVALID_PARAMETER;
7355 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7357 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7359 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7361 DEBUG(10,("smb_set_info_standard: file %s\n",
7362 smb_fname_str_dbg(smb_fname)));
7364 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7365 if (!NT_STATUS_IS_OK(status)) {
7369 return smb_set_file_time(conn,
7376 /****************************************************************************
7377 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7378 ****************************************************************************/
7380 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7381 struct smb_request *req,
7385 struct smb_filename *smb_fname)
7387 uint64_t allocation_size = 0;
7388 NTSTATUS status = NT_STATUS_OK;
7389 files_struct *new_fsp = NULL;
7391 if (!VALID_STAT(smb_fname->st)) {
7392 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7395 if (total_data < 8) {
7396 return NT_STATUS_INVALID_PARAMETER;
7399 allocation_size = (uint64_t)IVAL(pdata,0);
7400 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7401 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7402 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7403 (double)allocation_size));
7405 if (allocation_size) {
7406 allocation_size = smb_roundup(conn, allocation_size);
7409 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7410 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7411 (double)allocation_size));
7413 if (fsp && fsp->fh->fd != -1) {
7414 /* Open file handle. */
7415 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7416 return NT_STATUS_ACCESS_DENIED;
7419 /* Only change if needed. */
7420 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7421 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7422 return map_nt_error_from_unix(errno);
7425 /* But always update the time. */
7427 * This is equivalent to a write. Ensure it's seen immediately
7428 * if there are no pending writes.
7430 trigger_write_time_update_immediate(fsp);
7431 return NT_STATUS_OK;
7434 /* Pathname or stat or directory file. */
7435 status = SMB_VFS_CREATE_FILE(
7438 0, /* root_dir_fid */
7439 smb_fname, /* fname */
7440 FILE_WRITE_DATA, /* access_mask */
7441 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7443 FILE_OPEN, /* create_disposition*/
7444 0, /* create_options */
7445 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7446 0, /* oplock_request */
7448 0, /* allocation_size */
7449 0, /* private_flags */
7452 &new_fsp, /* result */
7454 NULL, NULL); /* create context */
7456 if (!NT_STATUS_IS_OK(status)) {
7457 /* NB. We check for open_was_deferred in the caller. */
7461 /* Only change if needed. */
7462 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7463 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7464 status = map_nt_error_from_unix(errno);
7465 close_file(req, new_fsp, NORMAL_CLOSE);
7470 /* Changing the allocation size should set the last mod time. */
7472 * This is equivalent to a write. Ensure it's seen immediately
7473 * if there are no pending writes.
7475 trigger_write_time_update_immediate(new_fsp);
7476 close_file(req, new_fsp, NORMAL_CLOSE);
7477 return NT_STATUS_OK;
7480 /****************************************************************************
7481 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7482 ****************************************************************************/
7484 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7485 struct smb_request *req,
7489 const struct smb_filename *smb_fname,
7490 bool fail_after_createfile)
7494 if (total_data < 8) {
7495 return NT_STATUS_INVALID_PARAMETER;
7498 size = IVAL(pdata,0);
7499 size |= (((off_t)IVAL(pdata,4)) << 32);
7500 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7501 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7504 return smb_set_file_size(conn, req,
7509 fail_after_createfile);
7512 /****************************************************************************
7513 Allow a UNIX info mknod.
7514 ****************************************************************************/
7516 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7519 const struct smb_filename *smb_fname)
7521 uint32_t file_type = IVAL(pdata,56);
7522 #if defined(HAVE_MAKEDEV)
7523 uint32_t dev_major = IVAL(pdata,60);
7524 uint32_t dev_minor = IVAL(pdata,68);
7526 SMB_DEV_T dev = (SMB_DEV_T)0;
7527 uint32_t raw_unixmode = IVAL(pdata,84);
7531 if (total_data < 100) {
7532 return NT_STATUS_INVALID_PARAMETER;
7535 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7536 PERM_NEW_FILE, &unixmode);
7537 if (!NT_STATUS_IS_OK(status)) {
7541 #if defined(HAVE_MAKEDEV)
7542 dev = makedev(dev_major, dev_minor);
7545 switch (file_type) {
7546 #if defined(S_IFIFO)
7547 case UNIX_TYPE_FIFO:
7548 unixmode |= S_IFIFO;
7551 #if defined(S_IFSOCK)
7552 case UNIX_TYPE_SOCKET:
7553 unixmode |= S_IFSOCK;
7556 #if defined(S_IFCHR)
7557 case UNIX_TYPE_CHARDEV:
7558 unixmode |= S_IFCHR;
7561 #if defined(S_IFBLK)
7562 case UNIX_TYPE_BLKDEV:
7563 unixmode |= S_IFBLK;
7567 return NT_STATUS_INVALID_PARAMETER;
7570 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7571 "%.0f mode 0%o for file %s\n", (double)dev,
7572 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7574 /* Ok - do the mknod. */
7575 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7576 return map_nt_error_from_unix(errno);
7579 /* If any of the other "set" calls fail we
7580 * don't want to end up with a half-constructed mknod.
7583 if (lp_inherit_permissions(SNUM(conn))) {
7585 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7587 return NT_STATUS_NO_MEMORY;
7589 inherit_access_posix_acl(conn, parent, smb_fname,
7591 TALLOC_FREE(parent);
7594 return NT_STATUS_OK;
7597 /****************************************************************************
7598 Deal with SMB_SET_FILE_UNIX_BASIC.
7599 ****************************************************************************/
7601 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7602 struct smb_request *req,
7606 const struct smb_filename *smb_fname)
7608 struct smb_file_time ft;
7609 uint32_t raw_unixmode;
7612 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7613 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7614 NTSTATUS status = NT_STATUS_OK;
7615 bool delete_on_fail = False;
7616 enum perm_type ptype;
7617 files_struct *all_fsps = NULL;
7618 bool modify_mtime = true;
7620 struct smb_filename *smb_fname_tmp = NULL;
7621 SMB_STRUCT_STAT sbuf;
7625 if (total_data < 100) {
7626 return NT_STATUS_INVALID_PARAMETER;
7629 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7630 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7631 size=IVAL(pdata,0); /* first 8 Bytes are size */
7632 size |= (((off_t)IVAL(pdata,4)) << 32);
7635 ft.atime = interpret_long_date(pdata+24); /* access_time */
7636 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7637 set_owner = (uid_t)IVAL(pdata,40);
7638 set_grp = (gid_t)IVAL(pdata,48);
7639 raw_unixmode = IVAL(pdata,84);
7641 if (VALID_STAT(smb_fname->st)) {
7642 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7643 ptype = PERM_EXISTING_DIR;
7645 ptype = PERM_EXISTING_FILE;
7648 ptype = PERM_NEW_FILE;
7651 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7653 if (!NT_STATUS_IS_OK(status)) {
7657 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7658 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7659 smb_fname_str_dbg(smb_fname), (double)size,
7660 (unsigned int)set_owner, (unsigned int)set_grp,
7661 (int)raw_unixmode));
7663 sbuf = smb_fname->st;
7665 if (!VALID_STAT(sbuf)) {
7667 * The only valid use of this is to create character and block
7668 * devices, and named pipes. This is deprecated (IMHO) and
7669 * a new info level should be used for mknod. JRA.
7672 status = smb_unix_mknod(conn,
7676 if (!NT_STATUS_IS_OK(status)) {
7680 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7681 if (smb_fname_tmp == NULL) {
7682 return NT_STATUS_NO_MEMORY;
7685 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7686 status = map_nt_error_from_unix(errno);
7687 TALLOC_FREE(smb_fname_tmp);
7688 SMB_VFS_UNLINK(conn, smb_fname);
7692 sbuf = smb_fname_tmp->st;
7693 smb_fname = smb_fname_tmp;
7695 /* Ensure we don't try and change anything else. */
7696 raw_unixmode = SMB_MODE_NO_CHANGE;
7697 size = get_file_size_stat(&sbuf);
7698 ft.atime = sbuf.st_ex_atime;
7699 ft.mtime = sbuf.st_ex_mtime;
7701 * We continue here as we might want to change the
7704 delete_on_fail = True;
7708 /* Horrible backwards compatibility hack as an old server bug
7709 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7713 size = get_file_size_stat(&sbuf);
7718 * Deal with the UNIX specific mode set.
7721 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7724 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7725 "setting mode 0%o for file %s\n",
7726 (unsigned int)unixmode,
7727 smb_fname_str_dbg(smb_fname)));
7728 if (fsp && fsp->fh->fd != -1) {
7729 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7731 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7734 return map_nt_error_from_unix(errno);
7739 * Deal with the UNIX specific uid set.
7742 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7743 (sbuf.st_ex_uid != set_owner)) {
7746 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7747 "changing owner %u for path %s\n",
7748 (unsigned int)set_owner,
7749 smb_fname_str_dbg(smb_fname)));
7751 if (fsp && fsp->fh->fd != -1) {
7752 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7755 * UNIX extensions calls must always operate
7758 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7759 set_owner, (gid_t)-1);
7763 status = map_nt_error_from_unix(errno);
7764 if (delete_on_fail) {
7765 SMB_VFS_UNLINK(conn, smb_fname);
7772 * Deal with the UNIX specific gid set.
7775 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7776 (sbuf.st_ex_gid != set_grp)) {
7779 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7780 "changing group %u for file %s\n",
7781 (unsigned int)set_grp,
7782 smb_fname_str_dbg(smb_fname)));
7783 if (fsp && fsp->fh->fd != -1) {
7784 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
7787 * UNIX extensions calls must always operate
7790 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7794 status = map_nt_error_from_unix(errno);
7795 if (delete_on_fail) {
7796 SMB_VFS_UNLINK(conn, smb_fname);
7802 /* Deal with any size changes. */
7804 status = smb_set_file_size(conn, req,
7810 if (!NT_STATUS_IS_OK(status)) {
7814 /* Deal with any time changes. */
7815 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7816 /* No change, don't cancel anything. */
7820 id = vfs_file_id_from_sbuf(conn, &sbuf);
7821 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7822 all_fsps = file_find_di_next(all_fsps)) {
7824 * We're setting the time explicitly for UNIX.
7825 * Cancel any pending changes over all handles.
7827 all_fsps->update_write_time_on_close = false;
7828 TALLOC_FREE(all_fsps->update_write_time_event);
7832 * Override the "setting_write_time"
7833 * parameter here as it almost does what
7834 * we need. Just remember if we modified
7835 * mtime and send the notify ourselves.
7837 if (null_timespec(ft.mtime)) {
7838 modify_mtime = false;
7841 status = smb_set_file_time(conn,
7847 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7848 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7853 /****************************************************************************
7854 Deal with SMB_SET_FILE_UNIX_INFO2.
7855 ****************************************************************************/
7857 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7858 struct smb_request *req,
7862 const struct smb_filename *smb_fname)
7865 uint32_t smb_fflags;
7868 if (total_data < 116) {
7869 return NT_STATUS_INVALID_PARAMETER;
7872 /* Start by setting all the fields that are common between UNIX_BASIC
7875 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7877 if (!NT_STATUS_IS_OK(status)) {
7881 smb_fflags = IVAL(pdata, 108);
7882 smb_fmask = IVAL(pdata, 112);
7884 /* NB: We should only attempt to alter the file flags if the client
7885 * sends a non-zero mask.
7887 if (smb_fmask != 0) {
7888 int stat_fflags = 0;
7890 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7891 smb_fmask, &stat_fflags)) {
7892 /* Client asked to alter a flag we don't understand. */
7893 return NT_STATUS_INVALID_PARAMETER;
7896 if (fsp && fsp->fh->fd != -1) {
7897 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7898 return NT_STATUS_NOT_SUPPORTED;
7900 if (SMB_VFS_CHFLAGS(conn, smb_fname,
7901 stat_fflags) != 0) {
7902 return map_nt_error_from_unix(errno);
7907 /* XXX: need to add support for changing the create_time here. You
7908 * can do this for paths on Darwin with setattrlist(2). The right way
7909 * to hook this up is probably by extending the VFS utimes interface.
7912 return NT_STATUS_OK;
7915 /****************************************************************************
7916 Create a directory with POSIX semantics.
7917 ****************************************************************************/
7919 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7920 struct smb_request *req,
7923 struct smb_filename *smb_fname,
7924 int *pdata_return_size)
7926 NTSTATUS status = NT_STATUS_OK;
7927 uint32_t raw_unixmode = 0;
7928 uint32_t mod_unixmode = 0;
7929 mode_t unixmode = (mode_t)0;
7930 files_struct *fsp = NULL;
7931 uint16_t info_level_return = 0;
7933 char *pdata = *ppdata;
7935 if (total_data < 18) {
7936 return NT_STATUS_INVALID_PARAMETER;
7939 raw_unixmode = IVAL(pdata,8);
7940 /* Next 4 bytes are not yet defined. */
7942 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7943 PERM_NEW_DIR, &unixmode);
7944 if (!NT_STATUS_IS_OK(status)) {
7948 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7950 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7951 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7953 status = SMB_VFS_CREATE_FILE(
7956 0, /* root_dir_fid */
7957 smb_fname, /* fname */
7958 FILE_READ_ATTRIBUTES, /* access_mask */
7959 FILE_SHARE_NONE, /* share_access */
7960 FILE_CREATE, /* create_disposition*/
7961 FILE_DIRECTORY_FILE, /* create_options */
7962 mod_unixmode, /* file_attributes */
7963 0, /* oplock_request */
7965 0, /* allocation_size */
7966 0, /* private_flags */
7971 NULL, NULL); /* create context */
7973 if (NT_STATUS_IS_OK(status)) {
7974 close_file(req, fsp, NORMAL_CLOSE);
7977 info_level_return = SVAL(pdata,16);
7979 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7980 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7981 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7982 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7984 *pdata_return_size = 12;
7987 /* Realloc the data size */
7988 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7989 if (*ppdata == NULL) {
7990 *pdata_return_size = 0;
7991 return NT_STATUS_NO_MEMORY;
7995 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7996 SSVAL(pdata,2,0); /* No fnum. */
7997 SIVAL(pdata,4,info); /* Was directory created. */
7999 switch (info_level_return) {
8000 case SMB_QUERY_FILE_UNIX_BASIC:
8001 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8002 SSVAL(pdata,10,0); /* Padding. */
8003 store_file_unix_basic(conn, pdata + 12, fsp,
8006 case SMB_QUERY_FILE_UNIX_INFO2:
8007 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8008 SSVAL(pdata,10,0); /* Padding. */
8009 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8013 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8014 SSVAL(pdata,10,0); /* Padding. */
8021 /****************************************************************************
8022 Open/Create a file with POSIX semantics.
8023 ****************************************************************************/
8025 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8026 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8028 static NTSTATUS smb_posix_open(connection_struct *conn,
8029 struct smb_request *req,
8032 struct smb_filename *smb_fname,
8033 int *pdata_return_size)
8035 bool extended_oplock_granted = False;
8036 char *pdata = *ppdata;
8038 uint32_t wire_open_mode = 0;
8039 uint32_t raw_unixmode = 0;
8040 uint32_t mod_unixmode = 0;
8041 uint32_t create_disp = 0;
8042 uint32_t access_mask = 0;
8043 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8044 NTSTATUS status = NT_STATUS_OK;
8045 mode_t unixmode = (mode_t)0;
8046 files_struct *fsp = NULL;
8047 int oplock_request = 0;
8049 uint16_t info_level_return = 0;
8051 if (total_data < 18) {
8052 return NT_STATUS_INVALID_PARAMETER;
8055 flags = IVAL(pdata,0);
8056 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8057 if (oplock_request) {
8058 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8061 wire_open_mode = IVAL(pdata,4);
8063 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8064 return smb_posix_mkdir(conn, req,
8071 switch (wire_open_mode & SMB_ACCMODE) {
8073 access_mask = SMB_O_RDONLY_MAPPING;
8076 access_mask = SMB_O_WRONLY_MAPPING;
8079 access_mask = (SMB_O_RDONLY_MAPPING|
8080 SMB_O_WRONLY_MAPPING);
8083 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8084 (unsigned int)wire_open_mode ));
8085 return NT_STATUS_INVALID_PARAMETER;
8088 wire_open_mode &= ~SMB_ACCMODE;
8090 /* First take care of O_CREAT|O_EXCL interactions. */
8091 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8092 case (SMB_O_CREAT | SMB_O_EXCL):
8093 /* File exists fail. File not exist create. */
8094 create_disp = FILE_CREATE;
8097 /* File exists open. File not exist create. */
8098 create_disp = FILE_OPEN_IF;
8101 /* O_EXCL on its own without O_CREAT is undefined.
8102 We deliberately ignore it as some versions of
8103 Linux CIFSFS can send a bare O_EXCL on the
8104 wire which other filesystems in the kernel
8105 ignore. See bug 9519 for details. */
8110 /* File exists open. File not exist fail. */
8111 create_disp = FILE_OPEN;
8114 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8115 (unsigned int)wire_open_mode ));
8116 return NT_STATUS_INVALID_PARAMETER;
8119 /* Next factor in the effects of O_TRUNC. */
8120 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8122 if (wire_open_mode & SMB_O_TRUNC) {
8123 switch (create_disp) {
8125 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8126 /* Leave create_disp alone as
8127 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8129 /* File exists fail. File not exist create. */
8132 /* SMB_O_CREAT | SMB_O_TRUNC */
8133 /* File exists overwrite. File not exist create. */
8134 create_disp = FILE_OVERWRITE_IF;
8138 /* File exists overwrite. File not exist fail. */
8139 create_disp = FILE_OVERWRITE;
8142 /* Cannot get here. */
8143 smb_panic("smb_posix_open: logic error");
8144 return NT_STATUS_INVALID_PARAMETER;
8148 raw_unixmode = IVAL(pdata,8);
8149 /* Next 4 bytes are not yet defined. */
8151 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8152 (VALID_STAT(smb_fname->st) ?
8153 PERM_EXISTING_FILE : PERM_NEW_FILE),
8156 if (!NT_STATUS_IS_OK(status)) {
8160 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8162 if (wire_open_mode & SMB_O_SYNC) {
8163 create_options |= FILE_WRITE_THROUGH;
8165 if (wire_open_mode & SMB_O_APPEND) {
8166 access_mask |= FILE_APPEND_DATA;
8168 if (wire_open_mode & SMB_O_DIRECT) {
8169 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8172 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8173 VALID_STAT_OF_DIR(smb_fname->st)) {
8174 if (access_mask != SMB_O_RDONLY_MAPPING) {
8175 return NT_STATUS_FILE_IS_A_DIRECTORY;
8177 create_options &= ~FILE_NON_DIRECTORY_FILE;
8178 create_options |= FILE_DIRECTORY_FILE;
8181 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8182 smb_fname_str_dbg(smb_fname),
8183 (unsigned int)wire_open_mode,
8184 (unsigned int)unixmode ));
8186 status = SMB_VFS_CREATE_FILE(
8189 0, /* root_dir_fid */
8190 smb_fname, /* fname */
8191 access_mask, /* access_mask */
8192 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8194 create_disp, /* create_disposition*/
8195 create_options, /* create_options */
8196 mod_unixmode, /* file_attributes */
8197 oplock_request, /* oplock_request */
8199 0, /* allocation_size */
8200 0, /* private_flags */
8205 NULL, NULL); /* create context */
8207 if (!NT_STATUS_IS_OK(status)) {
8211 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8212 extended_oplock_granted = True;
8215 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8216 extended_oplock_granted = True;
8219 info_level_return = SVAL(pdata,16);
8221 /* Allocate the correct return size. */
8223 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8224 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8225 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8226 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8228 *pdata_return_size = 12;
8231 /* Realloc the data size */
8232 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8233 if (*ppdata == NULL) {
8234 close_file(req, fsp, ERROR_CLOSE);
8235 *pdata_return_size = 0;
8236 return NT_STATUS_NO_MEMORY;
8240 if (extended_oplock_granted) {
8241 if (flags & REQUEST_BATCH_OPLOCK) {
8242 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8244 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8246 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8247 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8249 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8252 SSVAL(pdata,2,fsp->fnum);
8253 SIVAL(pdata,4,info); /* Was file created etc. */
8255 switch (info_level_return) {
8256 case SMB_QUERY_FILE_UNIX_BASIC:
8257 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8258 SSVAL(pdata,10,0); /* padding. */
8259 store_file_unix_basic(conn, pdata + 12, fsp,
8262 case SMB_QUERY_FILE_UNIX_INFO2:
8263 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8264 SSVAL(pdata,10,0); /* padding. */
8265 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8269 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8270 SSVAL(pdata,10,0); /* padding. */
8273 return NT_STATUS_OK;
8276 /****************************************************************************
8277 Delete a file with POSIX semantics.
8278 ****************************************************************************/
8280 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8281 struct smb_request *req,
8284 struct smb_filename *smb_fname)
8286 NTSTATUS status = NT_STATUS_OK;
8287 files_struct *fsp = NULL;
8291 int create_options = 0;
8293 struct share_mode_lock *lck = NULL;
8295 if (total_data < 2) {
8296 return NT_STATUS_INVALID_PARAMETER;
8299 flags = SVAL(pdata,0);
8301 if (!VALID_STAT(smb_fname->st)) {
8302 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8305 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8306 !VALID_STAT_OF_DIR(smb_fname->st)) {
8307 return NT_STATUS_NOT_A_DIRECTORY;
8310 DEBUG(10,("smb_posix_unlink: %s %s\n",
8311 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8312 smb_fname_str_dbg(smb_fname)));
8314 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8315 create_options |= FILE_DIRECTORY_FILE;
8318 status = SMB_VFS_CREATE_FILE(
8321 0, /* root_dir_fid */
8322 smb_fname, /* fname */
8323 DELETE_ACCESS, /* access_mask */
8324 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8326 FILE_OPEN, /* create_disposition*/
8327 create_options, /* create_options */
8328 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8329 0, /* oplock_request */
8331 0, /* allocation_size */
8332 0, /* private_flags */
8337 NULL, NULL); /* create context */
8339 if (!NT_STATUS_IS_OK(status)) {
8344 * Don't lie to client. If we can't really delete due to
8345 * non-POSIX opens return SHARING_VIOLATION.
8348 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8350 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8351 "lock for file %s\n", fsp_str_dbg(fsp)));
8352 close_file(req, fsp, NORMAL_CLOSE);
8353 return NT_STATUS_INVALID_PARAMETER;
8357 * See if others still have the file open. If this is the case, then
8358 * don't delete. If all opens are POSIX delete we can set the delete
8359 * on close disposition.
8361 for (i=0; i<lck->data->num_share_modes; i++) {
8362 struct share_mode_entry *e = &lck->data->share_modes[i];
8363 if (is_valid_share_mode_entry(e)) {
8364 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8367 if (share_mode_stale_pid(lck->data, i)) {
8370 /* Fail with sharing violation. */
8372 close_file(req, fsp, NORMAL_CLOSE);
8373 return NT_STATUS_SHARING_VIOLATION;
8378 * Set the delete on close.
8380 status = smb_set_file_disposition_info(conn,
8388 if (!NT_STATUS_IS_OK(status)) {
8389 close_file(req, fsp, NORMAL_CLOSE);
8392 return close_file(req, fsp, NORMAL_CLOSE);
8395 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8396 struct smb_request *req,
8397 TALLOC_CTX *mem_ctx,
8398 uint16_t info_level,
8400 struct smb_filename *smb_fname,
8401 char **ppdata, int total_data,
8404 char *pdata = *ppdata;
8405 NTSTATUS status = NT_STATUS_OK;
8406 int data_return_size = 0;
8410 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8411 return NT_STATUS_INVALID_LEVEL;
8414 if (!CAN_WRITE(conn)) {
8415 /* Allow POSIX opens. The open path will deny
8416 * any non-readonly opens. */
8417 if (info_level != SMB_POSIX_PATH_OPEN) {
8418 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8422 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8423 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8425 info_level, total_data));
8427 switch (info_level) {
8429 case SMB_INFO_STANDARD:
8431 status = smb_set_info_standard(conn,
8439 case SMB_INFO_SET_EA:
8441 status = smb_info_set_ea(conn,
8449 case SMB_SET_FILE_BASIC_INFO:
8450 case SMB_FILE_BASIC_INFORMATION:
8452 status = smb_set_file_basic_info(conn,
8460 case SMB_FILE_ALLOCATION_INFORMATION:
8461 case SMB_SET_FILE_ALLOCATION_INFO:
8463 status = smb_set_file_allocation_info(conn, req,
8471 case SMB_FILE_END_OF_FILE_INFORMATION:
8472 case SMB_SET_FILE_END_OF_FILE_INFO:
8475 * XP/Win7 both fail after the createfile with
8476 * SMB_SET_FILE_END_OF_FILE_INFO but not
8477 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8478 * The level is known here, so pass it down
8482 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8484 status = smb_set_file_end_of_file_info(conn, req,
8493 case SMB_FILE_DISPOSITION_INFORMATION:
8494 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8497 /* JRA - We used to just ignore this on a path ?
8498 * Shouldn't this be invalid level on a pathname
8501 if (tran_call != TRANSACT2_SETFILEINFO) {
8502 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8505 status = smb_set_file_disposition_info(conn,
8513 case SMB_FILE_POSITION_INFORMATION:
8515 status = smb_file_position_information(conn,
8522 case SMB_FILE_FULL_EA_INFORMATION:
8524 status = smb_set_file_full_ea_info(conn,
8531 /* From tridge Samba4 :
8532 * MODE_INFORMATION in setfileinfo (I have no
8533 * idea what "mode information" on a file is - it takes a value of 0,
8534 * 2, 4 or 6. What could it be?).
8537 case SMB_FILE_MODE_INFORMATION:
8539 status = smb_file_mode_information(conn,
8545 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8546 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8547 case SMB_FILE_SHORT_NAME_INFORMATION:
8548 return NT_STATUS_NOT_SUPPORTED;
8551 * CIFS UNIX extensions.
8554 case SMB_SET_FILE_UNIX_BASIC:
8556 status = smb_set_file_unix_basic(conn, req,
8564 case SMB_SET_FILE_UNIX_INFO2:
8566 status = smb_set_file_unix_info2(conn, req,
8574 case SMB_SET_FILE_UNIX_LINK:
8577 /* We must have a pathname for this. */
8578 return NT_STATUS_INVALID_LEVEL;
8580 status = smb_set_file_unix_link(conn, req, pdata,
8581 total_data, smb_fname);
8585 case SMB_SET_FILE_UNIX_HLINK:
8588 /* We must have a pathname for this. */
8589 return NT_STATUS_INVALID_LEVEL;
8591 status = smb_set_file_unix_hlink(conn, req,
8597 case SMB_FILE_RENAME_INFORMATION:
8599 status = smb_file_rename_information(conn, req,
8605 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8607 /* SMB2 rename information. */
8608 status = smb2_file_rename_information(conn, req,
8614 case SMB_FILE_LINK_INFORMATION:
8616 status = smb_file_link_information(conn, req,
8622 #if defined(HAVE_POSIX_ACLS)
8623 case SMB_SET_POSIX_ACL:
8625 status = smb_set_posix_acl(conn,
8634 case SMB_SET_POSIX_LOCK:
8637 return NT_STATUS_INVALID_LEVEL;
8639 status = smb_set_posix_lock(conn, req,
8640 pdata, total_data, fsp);
8644 case SMB_POSIX_PATH_OPEN:
8647 /* We must have a pathname for this. */
8648 return NT_STATUS_INVALID_LEVEL;
8651 status = smb_posix_open(conn, req,
8659 case SMB_POSIX_PATH_UNLINK:
8662 /* We must have a pathname for this. */
8663 return NT_STATUS_INVALID_LEVEL;
8666 status = smb_posix_unlink(conn, req,
8674 return NT_STATUS_INVALID_LEVEL;
8677 if (!NT_STATUS_IS_OK(status)) {
8681 *ret_data_size = data_return_size;
8682 return NT_STATUS_OK;
8685 /****************************************************************************
8686 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8687 ****************************************************************************/
8689 static void call_trans2setfilepathinfo(connection_struct *conn,
8690 struct smb_request *req,
8691 unsigned int tran_call,
8692 char **pparams, int total_params,
8693 char **ppdata, int total_data,
8694 unsigned int max_data_bytes)
8696 char *params = *pparams;
8697 char *pdata = *ppdata;
8698 uint16_t info_level;
8699 struct smb_filename *smb_fname = NULL;
8700 files_struct *fsp = NULL;
8701 NTSTATUS status = NT_STATUS_OK;
8702 int data_return_size = 0;
8705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8709 if (tran_call == TRANSACT2_SETFILEINFO) {
8710 if (total_params < 4) {
8711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8715 fsp = file_fsp(req, SVAL(params,0));
8716 /* Basic check for non-null fsp. */
8717 if (!check_fsp_open(conn, req, fsp)) {
8720 info_level = SVAL(params,2);
8722 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8723 if (smb_fname == NULL) {
8724 reply_nterror(req, NT_STATUS_NO_MEMORY);
8728 if(fsp->fh->fd == -1) {
8730 * This is actually a SETFILEINFO on a directory
8731 * handle (returned from an NT SMB). NT5.0 seems
8732 * to do this call. JRA.
8734 if (INFO_LEVEL_IS_UNIX(info_level)) {
8735 /* Always do lstat for UNIX calls. */
8736 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8737 DEBUG(3,("call_trans2setfilepathinfo: "
8738 "SMB_VFS_LSTAT of %s failed "
8740 smb_fname_str_dbg(smb_fname),
8742 reply_nterror(req, map_nt_error_from_unix(errno));
8746 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8747 DEBUG(3,("call_trans2setfilepathinfo: "
8748 "fileinfo of %s failed (%s)\n",
8749 smb_fname_str_dbg(smb_fname),
8751 reply_nterror(req, map_nt_error_from_unix(errno));
8755 } else if (fsp->print_file) {
8757 * Doing a DELETE_ON_CLOSE should cancel a print job.
8759 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8760 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8762 DEBUG(3,("call_trans2setfilepathinfo: "
8763 "Cancelling print job (%s)\n",
8767 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8773 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8778 * Original code - this is an open file.
8780 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8781 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8782 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8784 reply_nterror(req, map_nt_error_from_unix(errno));
8790 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8793 if (total_params < 7) {
8794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8798 info_level = SVAL(params,0);
8799 if (req->posix_pathnames) {
8800 srvstr_get_path_posix(req,
8809 srvstr_get_path(req,
8818 if (!NT_STATUS_IS_OK(status)) {
8819 reply_nterror(req, status);
8823 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8824 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8825 info_level == SMB_FILE_RENAME_INFORMATION ||
8826 info_level == SMB_POSIX_PATH_UNLINK) {
8827 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8830 status = filename_convert(req, conn,
8835 if (!NT_STATUS_IS_OK(status)) {
8836 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8837 reply_botherror(req,
8838 NT_STATUS_PATH_NOT_COVERED,
8839 ERRSRV, ERRbadpath);
8842 reply_nterror(req, status);
8846 if (INFO_LEVEL_IS_UNIX(info_level)) {
8848 * For CIFS UNIX extensions the target name may not exist.
8851 /* Always do lstat for UNIX calls. */
8852 SMB_VFS_LSTAT(conn, smb_fname);
8854 } else if (!VALID_STAT(smb_fname->st) &&
8855 SMB_VFS_STAT(conn, smb_fname)) {
8856 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8858 smb_fname_str_dbg(smb_fname),
8860 reply_nterror(req, map_nt_error_from_unix(errno));
8865 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8866 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8868 info_level,total_data));
8870 /* Realloc the parameter size */
8871 *pparams = (char *)SMB_REALLOC(*pparams,2);
8872 if (*pparams == NULL) {
8873 reply_nterror(req, NT_STATUS_NO_MEMORY);
8880 status = smbd_do_setfilepathinfo(conn, req, req,
8886 if (!NT_STATUS_IS_OK(status)) {
8887 if (open_was_deferred(req->xconn, req->mid)) {
8888 /* We have re-scheduled this call. */
8891 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8892 /* We have re-scheduled this call. */
8895 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8896 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8897 ERRSRV, ERRbadpath);
8900 if (info_level == SMB_POSIX_PATH_OPEN) {
8901 reply_openerror(req, status);
8906 * Invalid EA name needs to return 2 param bytes,
8907 * not a zero-length error packet.
8909 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8910 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8913 reply_nterror(req, status);
8918 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8924 /****************************************************************************
8925 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8926 ****************************************************************************/
8928 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8929 char **pparams, int total_params,
8930 char **ppdata, int total_data,
8931 unsigned int max_data_bytes)
8933 struct smb_filename *smb_dname = NULL;
8934 char *params = *pparams;
8935 char *pdata = *ppdata;
8936 char *directory = NULL;
8937 NTSTATUS status = NT_STATUS_OK;
8938 struct ea_list *ea_list = NULL;
8939 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8940 TALLOC_CTX *ctx = talloc_tos();
8942 if (!CAN_WRITE(conn)) {
8943 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8947 if (total_params < 5) {
8948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8952 if (req->posix_pathnames) {
8953 srvstr_get_path_posix(ctx,
8962 srvstr_get_path(ctx,
8971 if (!NT_STATUS_IS_OK(status)) {
8972 reply_nterror(req, status);
8976 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8978 status = filename_convert(ctx,
8985 if (!NT_STATUS_IS_OK(status)) {
8986 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8987 reply_botherror(req,
8988 NT_STATUS_PATH_NOT_COVERED,
8989 ERRSRV, ERRbadpath);
8992 reply_nterror(req, status);
8997 * OS/2 workplace shell seems to send SET_EA requests of "null"
8998 * length (4 bytes containing IVAL 4).
8999 * They seem to have no effect. Bug #3212. JRA.
9002 if (total_data && (total_data != 4)) {
9003 /* Any data in this call is an EA list. */
9004 if (total_data < 10) {
9005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9009 if (IVAL(pdata,0) > total_data) {
9010 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9011 IVAL(pdata,0), (unsigned int)total_data));
9012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9016 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9023 if (!lp_ea_support(SNUM(conn))) {
9024 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9028 /* If total_data == 4 Windows doesn't care what values
9029 * are placed in that field, it just ignores them.
9030 * The System i QNTC IBM SMB client puts bad values here,
9031 * so ignore them. */
9033 status = create_directory(conn, req, smb_dname);
9035 if (!NT_STATUS_IS_OK(status)) {
9036 reply_nterror(req, status);
9040 /* Try and set any given EA. */
9042 status = set_ea(conn, NULL, smb_dname, ea_list);
9043 if (!NT_STATUS_IS_OK(status)) {
9044 reply_nterror(req, status);
9049 /* Realloc the parameter and data sizes */
9050 *pparams = (char *)SMB_REALLOC(*pparams,2);
9051 if(*pparams == NULL) {
9052 reply_nterror(req, NT_STATUS_NO_MEMORY);
9059 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9062 TALLOC_FREE(smb_dname);
9066 /****************************************************************************
9067 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9068 We don't actually do this - we just send a null response.
9069 ****************************************************************************/
9071 static void call_trans2findnotifyfirst(connection_struct *conn,
9072 struct smb_request *req,
9073 char **pparams, int total_params,
9074 char **ppdata, int total_data,
9075 unsigned int max_data_bytes)
9077 char *params = *pparams;
9078 uint16_t info_level;
9080 if (total_params < 6) {
9081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9085 info_level = SVAL(params,4);
9086 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9088 switch (info_level) {
9093 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9097 /* Realloc the parameter and data sizes */
9098 *pparams = (char *)SMB_REALLOC(*pparams,6);
9099 if (*pparams == NULL) {
9100 reply_nterror(req, NT_STATUS_NO_MEMORY);
9105 SSVAL(params,0,fnf_handle);
9106 SSVAL(params,2,0); /* No changes */
9107 SSVAL(params,4,0); /* No EA errors */
9114 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9119 /****************************************************************************
9120 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9121 changes). Currently this does nothing.
9122 ****************************************************************************/
9124 static void call_trans2findnotifynext(connection_struct *conn,
9125 struct smb_request *req,
9126 char **pparams, int total_params,
9127 char **ppdata, int total_data,
9128 unsigned int max_data_bytes)
9130 char *params = *pparams;
9132 DEBUG(3,("call_trans2findnotifynext\n"));
9134 /* Realloc the parameter and data sizes */
9135 *pparams = (char *)SMB_REALLOC(*pparams,4);
9136 if (*pparams == NULL) {
9137 reply_nterror(req, NT_STATUS_NO_MEMORY);
9142 SSVAL(params,0,0); /* No changes */
9143 SSVAL(params,2,0); /* No EA errors */
9145 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9150 /****************************************************************************
9151 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9152 ****************************************************************************/
9154 static void call_trans2getdfsreferral(connection_struct *conn,
9155 struct smb_request *req,
9156 char **pparams, int total_params,
9157 char **ppdata, int total_data,
9158 unsigned int max_data_bytes)
9160 char *params = *pparams;
9161 char *pathname = NULL;
9163 int max_referral_level;
9164 NTSTATUS status = NT_STATUS_OK;
9165 TALLOC_CTX *ctx = talloc_tos();
9167 DEBUG(10,("call_trans2getdfsreferral\n"));
9169 if (total_params < 3) {
9170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9174 max_referral_level = SVAL(params,0);
9176 if(!lp_host_msdfs()) {
9177 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9181 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9182 total_params - 2, STR_TERMINATE);
9184 reply_nterror(req, NT_STATUS_NOT_FOUND);
9187 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9188 ppdata,&status)) < 0) {
9189 reply_nterror(req, status);
9193 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9194 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9195 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9200 #define LMCAT_SPL 0x53
9201 #define LMFUNC_GETJOBID 0x60
9203 /****************************************************************************
9204 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9205 ****************************************************************************/
9207 static void call_trans2ioctl(connection_struct *conn,
9208 struct smb_request *req,
9209 char **pparams, int total_params,
9210 char **ppdata, int total_data,
9211 unsigned int max_data_bytes)
9213 char *pdata = *ppdata;
9214 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9218 /* check for an invalid fid before proceeding */
9221 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9225 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9226 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9227 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9228 if (*ppdata == NULL) {
9229 reply_nterror(req, NT_STATUS_NO_MEMORY);
9234 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9235 CAN ACCEPT THIS IN UNICODE. JRA. */
9238 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9240 status = srvstr_push(pdata, req->flags2, pdata + 2,
9241 lp_netbios_name(), 15,
9242 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9243 if (!NT_STATUS_IS_OK(status)) {
9244 reply_nterror(req, status);
9247 status = srvstr_push(pdata, req->flags2, pdata+18,
9248 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9249 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9250 if (!NT_STATUS_IS_OK(status)) {
9251 reply_nterror(req, status);
9254 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9259 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9260 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9263 /****************************************************************************
9264 Reply to a SMBfindclose (stop trans2 directory search).
9265 ****************************************************************************/
9267 void reply_findclose(struct smb_request *req)
9270 struct smbd_server_connection *sconn = req->sconn;
9272 START_PROFILE(SMBfindclose);
9275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9276 END_PROFILE(SMBfindclose);
9280 dptr_num = SVALS(req->vwv+0, 0);
9282 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9284 dptr_close(sconn, &dptr_num);
9286 reply_outbuf(req, 0, 0);
9288 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9290 END_PROFILE(SMBfindclose);
9294 /****************************************************************************
9295 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9296 ****************************************************************************/
9298 void reply_findnclose(struct smb_request *req)
9302 START_PROFILE(SMBfindnclose);
9305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9306 END_PROFILE(SMBfindnclose);
9310 dptr_num = SVAL(req->vwv+0, 0);
9312 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9314 /* We never give out valid handles for a
9315 findnotifyfirst - so any dptr_num is ok here.
9318 reply_outbuf(req, 0, 0);
9320 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9322 END_PROFILE(SMBfindnclose);
9326 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9327 struct trans_state *state)
9329 if (get_Protocol() >= PROTOCOL_NT1) {
9330 req->flags2 |= 0x40; /* IS_LONG_NAME */
9331 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9334 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9335 if (state->call != TRANSACT2_QFSINFO &&
9336 state->call != TRANSACT2_SETFSINFO) {
9337 DEBUG(0,("handle_trans2: encryption required "
9339 (unsigned int)state->call));
9340 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9345 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9347 /* Now we must call the relevant TRANS2 function */
9348 switch(state->call) {
9349 case TRANSACT2_OPEN:
9351 START_PROFILE(Trans2_open);
9352 call_trans2open(conn, req,
9353 &state->param, state->total_param,
9354 &state->data, state->total_data,
9355 state->max_data_return);
9356 END_PROFILE(Trans2_open);
9360 case TRANSACT2_FINDFIRST:
9362 START_PROFILE(Trans2_findfirst);
9363 call_trans2findfirst(conn, req,
9364 &state->param, state->total_param,
9365 &state->data, state->total_data,
9366 state->max_data_return);
9367 END_PROFILE(Trans2_findfirst);
9371 case TRANSACT2_FINDNEXT:
9373 START_PROFILE(Trans2_findnext);
9374 call_trans2findnext(conn, req,
9375 &state->param, state->total_param,
9376 &state->data, state->total_data,
9377 state->max_data_return);
9378 END_PROFILE(Trans2_findnext);
9382 case TRANSACT2_QFSINFO:
9384 START_PROFILE(Trans2_qfsinfo);
9385 call_trans2qfsinfo(conn, req,
9386 &state->param, state->total_param,
9387 &state->data, state->total_data,
9388 state->max_data_return);
9389 END_PROFILE(Trans2_qfsinfo);
9393 case TRANSACT2_SETFSINFO:
9395 START_PROFILE(Trans2_setfsinfo);
9396 call_trans2setfsinfo(conn, req,
9397 &state->param, state->total_param,
9398 &state->data, state->total_data,
9399 state->max_data_return);
9400 END_PROFILE(Trans2_setfsinfo);
9404 case TRANSACT2_QPATHINFO:
9405 case TRANSACT2_QFILEINFO:
9407 START_PROFILE(Trans2_qpathinfo);
9408 call_trans2qfilepathinfo(conn, req, state->call,
9409 &state->param, state->total_param,
9410 &state->data, state->total_data,
9411 state->max_data_return);
9412 END_PROFILE(Trans2_qpathinfo);
9416 case TRANSACT2_SETPATHINFO:
9417 case TRANSACT2_SETFILEINFO:
9419 START_PROFILE(Trans2_setpathinfo);
9420 call_trans2setfilepathinfo(conn, req, state->call,
9421 &state->param, state->total_param,
9422 &state->data, state->total_data,
9423 state->max_data_return);
9424 END_PROFILE(Trans2_setpathinfo);
9428 case TRANSACT2_FINDNOTIFYFIRST:
9430 START_PROFILE(Trans2_findnotifyfirst);
9431 call_trans2findnotifyfirst(conn, req,
9432 &state->param, state->total_param,
9433 &state->data, state->total_data,
9434 state->max_data_return);
9435 END_PROFILE(Trans2_findnotifyfirst);
9439 case TRANSACT2_FINDNOTIFYNEXT:
9441 START_PROFILE(Trans2_findnotifynext);
9442 call_trans2findnotifynext(conn, req,
9443 &state->param, state->total_param,
9444 &state->data, state->total_data,
9445 state->max_data_return);
9446 END_PROFILE(Trans2_findnotifynext);
9450 case TRANSACT2_MKDIR:
9452 START_PROFILE(Trans2_mkdir);
9453 call_trans2mkdir(conn, req,
9454 &state->param, state->total_param,
9455 &state->data, state->total_data,
9456 state->max_data_return);
9457 END_PROFILE(Trans2_mkdir);
9461 case TRANSACT2_GET_DFS_REFERRAL:
9463 START_PROFILE(Trans2_get_dfs_referral);
9464 call_trans2getdfsreferral(conn, req,
9465 &state->param, state->total_param,
9466 &state->data, state->total_data,
9467 state->max_data_return);
9468 END_PROFILE(Trans2_get_dfs_referral);
9472 case TRANSACT2_IOCTL:
9474 START_PROFILE(Trans2_ioctl);
9475 call_trans2ioctl(conn, req,
9476 &state->param, state->total_param,
9477 &state->data, state->total_data,
9478 state->max_data_return);
9479 END_PROFILE(Trans2_ioctl);
9484 /* Error in request */
9485 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9486 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9490 /****************************************************************************
9491 Reply to a SMBtrans2.
9492 ****************************************************************************/
9494 void reply_trans2(struct smb_request *req)
9496 connection_struct *conn = req->conn;
9501 unsigned int tran_call;
9502 struct trans_state *state;
9505 START_PROFILE(SMBtrans2);
9507 if (req->wct < 14) {
9508 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9509 END_PROFILE(SMBtrans2);
9513 dsoff = SVAL(req->vwv+12, 0);
9514 dscnt = SVAL(req->vwv+11, 0);
9515 psoff = SVAL(req->vwv+10, 0);
9516 pscnt = SVAL(req->vwv+9, 0);
9517 tran_call = SVAL(req->vwv+14, 0);
9519 result = allow_new_trans(conn->pending_trans, req->mid);
9520 if (!NT_STATUS_IS_OK(result)) {
9521 DEBUG(2, ("Got invalid trans2 request: %s\n",
9522 nt_errstr(result)));
9523 reply_nterror(req, result);
9524 END_PROFILE(SMBtrans2);
9529 switch (tran_call) {
9530 /* List the allowed trans2 calls on IPC$ */
9531 case TRANSACT2_OPEN:
9532 case TRANSACT2_GET_DFS_REFERRAL:
9533 case TRANSACT2_QFILEINFO:
9534 case TRANSACT2_QFSINFO:
9535 case TRANSACT2_SETFSINFO:
9538 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9539 END_PROFILE(SMBtrans2);
9544 if ((state = talloc(conn, struct trans_state)) == NULL) {
9545 DEBUG(0, ("talloc failed\n"));
9546 reply_nterror(req, NT_STATUS_NO_MEMORY);
9547 END_PROFILE(SMBtrans2);
9551 state->cmd = SMBtrans2;
9553 state->mid = req->mid;
9554 state->vuid = req->vuid;
9555 state->setup_count = SVAL(req->vwv+13, 0);
9556 state->setup = NULL;
9557 state->total_param = SVAL(req->vwv+0, 0);
9558 state->param = NULL;
9559 state->total_data = SVAL(req->vwv+1, 0);
9561 state->max_param_return = SVAL(req->vwv+2, 0);
9562 state->max_data_return = SVAL(req->vwv+3, 0);
9563 state->max_setup_return = SVAL(req->vwv+4, 0);
9564 state->close_on_completion = BITSETW(req->vwv+5, 0);
9565 state->one_way = BITSETW(req->vwv+5, 1);
9567 state->call = tran_call;
9569 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9570 is so as a sanity check */
9571 if (state->setup_count != 1) {
9573 * Need to have rc=0 for ioctl to get job id for OS/2.
9574 * Network printing will fail if function is not successful.
9575 * Similar function in reply.c will be used if protocol
9576 * is LANMAN1.0 instead of LM1.2X002.
9577 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9578 * outbuf doesn't have to be set(only job id is used).
9580 if ( (state->setup_count == 4)
9581 && (tran_call == TRANSACT2_IOCTL)
9582 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9583 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9584 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9586 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9587 DEBUG(2,("Transaction is %d\n",tran_call));
9589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9590 END_PROFILE(SMBtrans2);
9595 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9598 if (state->total_data) {
9600 if (trans_oob(state->total_data, 0, dscnt)
9601 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9605 /* Can't use talloc here, the core routines do realloc on the
9606 * params and data. */
9607 state->data = (char *)SMB_MALLOC(state->total_data);
9608 if (state->data == NULL) {
9609 DEBUG(0,("reply_trans2: data malloc fail for %u "
9610 "bytes !\n", (unsigned int)state->total_data));
9612 reply_nterror(req, NT_STATUS_NO_MEMORY);
9613 END_PROFILE(SMBtrans2);
9617 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9620 if (state->total_param) {
9622 if (trans_oob(state->total_param, 0, pscnt)
9623 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9627 /* Can't use talloc here, the core routines do realloc on the
9628 * params and data. */
9629 state->param = (char *)SMB_MALLOC(state->total_param);
9630 if (state->param == NULL) {
9631 DEBUG(0,("reply_trans: param malloc fail for %u "
9632 "bytes !\n", (unsigned int)state->total_param));
9633 SAFE_FREE(state->data);
9635 reply_nterror(req, NT_STATUS_NO_MEMORY);
9636 END_PROFILE(SMBtrans2);
9640 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9643 state->received_data = dscnt;
9644 state->received_param = pscnt;
9646 if ((state->received_param == state->total_param) &&
9647 (state->received_data == state->total_data)) {
9649 handle_trans2(conn, req, state);
9651 SAFE_FREE(state->data);
9652 SAFE_FREE(state->param);
9654 END_PROFILE(SMBtrans2);
9658 DLIST_ADD(conn->pending_trans, state);
9660 /* We need to send an interim response then receive the rest
9661 of the parameter/data bytes */
9662 reply_outbuf(req, 0, 0);
9663 show_msg((char *)req->outbuf);
9664 END_PROFILE(SMBtrans2);
9669 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9670 SAFE_FREE(state->data);
9671 SAFE_FREE(state->param);
9673 END_PROFILE(SMBtrans2);
9674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9678 /****************************************************************************
9679 Reply to a SMBtranss2
9680 ****************************************************************************/
9682 void reply_transs2(struct smb_request *req)
9684 connection_struct *conn = req->conn;
9685 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9686 struct trans_state *state;
9688 START_PROFILE(SMBtranss2);
9690 show_msg((const char *)req->inbuf);
9692 /* Windows clients expect all replies to
9693 a transact secondary (SMBtranss2 0x33)
9694 to have a command code of transact
9695 (SMBtrans2 0x32). See bug #8989
9696 and also [MS-CIFS] section 2.2.4.47.2
9699 req->cmd = SMBtrans2;
9702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9703 END_PROFILE(SMBtranss2);
9707 for (state = conn->pending_trans; state != NULL;
9708 state = state->next) {
9709 if (state->mid == req->mid) {
9714 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9716 END_PROFILE(SMBtranss2);
9720 /* Revise state->total_param and state->total_data in case they have
9721 changed downwards */
9723 if (SVAL(req->vwv+0, 0) < state->total_param)
9724 state->total_param = SVAL(req->vwv+0, 0);
9725 if (SVAL(req->vwv+1, 0) < state->total_data)
9726 state->total_data = SVAL(req->vwv+1, 0);
9728 pcnt = SVAL(req->vwv+2, 0);
9729 poff = SVAL(req->vwv+3, 0);
9730 pdisp = SVAL(req->vwv+4, 0);
9732 dcnt = SVAL(req->vwv+5, 0);
9733 doff = SVAL(req->vwv+6, 0);
9734 ddisp = SVAL(req->vwv+7, 0);
9736 state->received_param += pcnt;
9737 state->received_data += dcnt;
9739 if ((state->received_data > state->total_data) ||
9740 (state->received_param > state->total_param))
9744 if (trans_oob(state->total_param, pdisp, pcnt)
9745 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9748 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9752 if (trans_oob(state->total_data, ddisp, dcnt)
9753 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9756 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9759 if ((state->received_param < state->total_param) ||
9760 (state->received_data < state->total_data)) {
9761 END_PROFILE(SMBtranss2);
9765 handle_trans2(conn, req, state);
9767 DLIST_REMOVE(conn->pending_trans, state);
9768 SAFE_FREE(state->data);
9769 SAFE_FREE(state->param);
9772 END_PROFILE(SMBtranss2);
9777 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9778 DLIST_REMOVE(conn->pending_trans, state);
9779 SAFE_FREE(state->data);
9780 SAFE_FREE(state->param);
9782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9783 END_PROFILE(SMBtranss2);