2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
41 #include "lib/util_ea.h"
42 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
55 const SMB_STRUCT_STAT *psbuf);
57 /****************************************************************************
58 Check if an open file handle or smb_fname is a symlink.
59 ****************************************************************************/
61 static NTSTATUS refuse_symlink(connection_struct *conn,
62 const files_struct *fsp,
63 const struct smb_filename *smb_fname)
66 const SMB_STRUCT_STAT *pst = NULL;
69 pst = &fsp->fsp_name->st;
74 if (!VALID_STAT(*pst)) {
75 int ret = vfs_stat_smb_basename(conn,
78 if (ret == -1 && errno != ENOENT) {
79 return map_nt_error_from_unix(errno);
80 } else if (ret == -1) {
81 /* it's not a symlink.. */
87 if (S_ISLNK(pst->st_ex_mode)) {
88 return NT_STATUS_ACCESS_DENIED;
93 NTSTATUS check_access_fsp(const struct files_struct *fsp,
96 if (!(fsp->access_mask & access_mask)) {
97 return NT_STATUS_ACCESS_DENIED;
102 /********************************************************************
103 The canonical "check access" based on object handle or path function.
104 ********************************************************************/
106 static 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 if (ea_list->ea.value.length > 0) {
569 memcpy(p + 4 + dos_namelen + 1,
570 ea_list->ea.value.data,
571 ea_list->ea.value.length);
574 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
575 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
578 ret_data_size = PTR_DIFF(p, pdata);
579 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
580 SIVAL(pdata,0,ret_data_size);
581 return ret_data_size;
584 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
586 unsigned int total_data_size,
587 unsigned int *ret_data_size,
588 connection_struct *conn,
589 struct ea_list *ea_list)
591 uint8_t *p = (uint8_t *)pdata;
592 uint8_t *last_start = NULL;
593 bool do_store_data = (pdata != NULL);
597 if (!lp_ea_support(SNUM(conn))) {
598 return NT_STATUS_NO_EAS_ON_FILE;
601 for (; ea_list; ea_list = ea_list->next) {
607 if (last_start != NULL && do_store_data) {
608 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
612 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
613 dos_namelen = strlen(dos_ea_name);
614 if (dos_namelen > 255 || dos_namelen == 0) {
615 return NT_STATUS_INTERNAL_ERROR;
617 if (ea_list->ea.value.length > 65535) {
618 return NT_STATUS_INTERNAL_ERROR;
621 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
624 pad = (4 - (this_size % 4)) % 4;
629 if (this_size > total_data_size) {
630 return NT_STATUS_INFO_LENGTH_MISMATCH;
633 /* We know we have room. */
634 SIVAL(p, 0x00, 0); /* next offset */
635 SCVAL(p, 0x04, ea_list->ea.flags);
636 SCVAL(p, 0x05, dos_namelen);
637 SSVAL(p, 0x06, ea_list->ea.value.length);
638 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
639 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
641 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
645 total_data_size -= this_size;
651 *ret_data_size = PTR_DIFF(p, pdata);
652 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
656 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
658 size_t total_ea_len = 0;
660 struct ea_list *ea_list = NULL;
662 if (!lp_ea_support(SNUM(conn))) {
665 mem_ctx = talloc_stackframe();
667 /* If this is a stream fsp, then we need to instead find the
668 * estimated ea len from the main file, not the stream
669 * (streams cannot have EAs), but the estimate isn't just 0 in
671 if (is_ntfs_stream_smb_fname(smb_fname)) {
674 (void)get_ea_list_from_file_path(mem_ctx,
680 if(conn->sconn->using_smb2) {
682 unsigned int ret_data_size;
684 * We're going to be using fill_ea_chained_buffer() to
685 * marshall EA's - this size is significantly larger
686 * than the SMB1 buffer. Re-calculate the size without
689 status = fill_ea_chained_buffer(mem_ctx,
695 if (!NT_STATUS_IS_OK(status)) {
698 total_ea_len = ret_data_size;
700 TALLOC_FREE(mem_ctx);
704 /****************************************************************************
705 Ensure the EA name is case insensitive by matching any existing EA name.
706 ****************************************************************************/
708 static void canonicalize_ea_name(connection_struct *conn,
710 const struct smb_filename *smb_fname,
711 fstring unix_ea_name)
714 TALLOC_CTX *mem_ctx = talloc_tos();
715 struct ea_list *ea_list;
716 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
722 if (!NT_STATUS_IS_OK(status)) {
726 for (; ea_list; ea_list = ea_list->next) {
727 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
728 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
729 &unix_ea_name[5], ea_list->ea.name));
730 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
736 /****************************************************************************
737 Set or delete an extended attribute.
738 ****************************************************************************/
740 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
741 const struct smb_filename *smb_fname, struct ea_list *ea_list)
744 bool posix_pathnames = false;
746 if (!lp_ea_support(SNUM(conn))) {
747 return NT_STATUS_EAS_NOT_SUPPORTED;
752 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
754 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
757 status = refuse_symlink(conn, fsp, smb_fname);
758 if (!NT_STATUS_IS_OK(status)) {
762 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
763 if (!NT_STATUS_IS_OK(status)) {
767 /* Setting EAs on streams isn't supported. */
768 if (is_ntfs_stream_smb_fname(smb_fname)) {
769 return NT_STATUS_INVALID_PARAMETER;
773 * Filter out invalid Windows EA names - before
774 * we set *any* of them.
777 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
778 return STATUS_INVALID_EA_NAME;
781 for (;ea_list; ea_list = ea_list->next) {
783 fstring unix_ea_name;
785 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
786 fstrcat(unix_ea_name, ea_list->ea.name);
788 canonicalize_ea_name(conn,
793 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
795 if (samba_private_attr_name(unix_ea_name)) {
796 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
797 return NT_STATUS_ACCESS_DENIED;
800 if (ea_list->ea.value.length == 0) {
801 /* Remove the attribute. */
802 if (fsp && (fsp->fh->fd != -1)) {
803 DEBUG(10,("set_ea: deleting ea name %s on "
804 "file %s by file descriptor.\n",
805 unix_ea_name, fsp_str_dbg(fsp)));
806 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
808 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
809 unix_ea_name, smb_fname->base_name));
810 ret = SMB_VFS_REMOVEXATTR(conn,
815 /* Removing a non existent attribute always succeeds. */
816 if (ret == -1 && errno == ENOATTR) {
817 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
823 if (fsp && (fsp->fh->fd != -1)) {
824 DEBUG(10,("set_ea: setting ea name %s on file "
825 "%s by file descriptor.\n",
826 unix_ea_name, fsp_str_dbg(fsp)));
827 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
828 ea_list->ea.value.data, ea_list->ea.value.length, 0);
830 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
831 unix_ea_name, smb_fname->base_name));
832 ret = SMB_VFS_SETXATTR(conn,
835 ea_list->ea.value.data,
836 ea_list->ea.value.length,
843 if (errno == ENOTSUP) {
844 return NT_STATUS_EAS_NOT_SUPPORTED;
847 return map_nt_error_from_unix(errno);
853 /****************************************************************************
854 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
855 ****************************************************************************/
857 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
859 struct ea_list *ea_list_head = NULL;
860 size_t converted_size, offset = 0;
862 while (offset + 2 < data_size) {
863 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
864 unsigned int namelen = CVAL(pdata,offset);
866 offset++; /* Go past the namelen byte. */
868 /* integer wrap paranioa. */
869 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
870 (offset > data_size) || (namelen > data_size) ||
871 (offset + namelen >= data_size)) {
874 /* Ensure the name is null terminated. */
875 if (pdata[offset + namelen] != '\0') {
878 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
880 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
881 "failed: %s", strerror(errno)));
887 offset += (namelen + 1); /* Go past the name + terminating zero. */
888 DLIST_ADD_END(ea_list_head, eal);
889 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
895 /****************************************************************************
896 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
897 ****************************************************************************/
899 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
901 struct ea_list *ea_list_head = NULL;
903 size_t bytes_used = 0;
905 while (offset < data_size) {
906 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
912 DLIST_ADD_END(ea_list_head, eal);
913 offset += bytes_used;
919 /****************************************************************************
920 Count the total EA size needed.
921 ****************************************************************************/
923 static size_t ea_list_size(struct ea_list *ealist)
926 struct ea_list *listp;
929 for (listp = ealist; listp; listp = listp->next) {
930 push_ascii_fstring(dos_ea_name, listp->ea.name);
931 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
933 /* Add on 4 for total length. */
941 /****************************************************************************
942 Return a union of EA's from a file list and a list of names.
943 The TALLOC context for the two lists *MUST* be identical as we steal
944 memory from one list to add to another. JRA.
945 ****************************************************************************/
947 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
949 struct ea_list *nlistp, *flistp;
951 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
952 for (flistp = file_list; flistp; flistp = flistp->next) {
953 if (strequal(nlistp->ea.name, flistp->ea.name)) {
959 /* Copy the data from this entry. */
960 nlistp->ea.flags = flistp->ea.flags;
961 nlistp->ea.value = flistp->ea.value;
964 nlistp->ea.flags = 0;
965 ZERO_STRUCT(nlistp->ea.value);
969 *total_ea_len = ea_list_size(name_list);
973 /****************************************************************************
974 Send the required number of replies back.
975 We assume all fields other than the data fields are
976 set correctly for the type of call.
977 HACK ! Always assumes smb_setup field is zero.
978 ****************************************************************************/
980 void send_trans2_replies(connection_struct *conn,
981 struct smb_request *req,
989 /* As we are using a protocol > LANMAN1 then the max_send
990 variable must have been set in the sessetupX call.
991 This takes precedence over the max_xmit field in the
992 global struct. These different max_xmit variables should
993 be merged as this is now too confusing */
995 int data_to_send = datasize;
996 int params_to_send = paramsize;
998 const char *pp = params;
999 const char *pd = pdata;
1000 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1001 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1002 int data_alignment_offset = 0;
1003 bool overflow = False;
1004 struct smbXsrv_connection *xconn = req->xconn;
1005 int max_send = xconn->smb1.sessions.max_send;
1007 /* Modify the data_to_send and datasize and set the error if
1008 we're trying to send more than max_data_bytes. We still send
1009 the part of the packet(s) that fit. Strange, but needed
1012 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1013 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1014 max_data_bytes, datasize ));
1015 datasize = data_to_send = max_data_bytes;
1019 /* If there genuinely are no parameters or data to send just send the empty packet */
1021 if(params_to_send == 0 && data_to_send == 0) {
1022 reply_outbuf(req, 10, 0);
1023 if (NT_STATUS_V(status)) {
1026 ntstatus_to_dos(status, &eclass, &ecode);
1027 error_packet_set((char *)req->outbuf,
1028 eclass, ecode, status,
1031 show_msg((char *)req->outbuf);
1032 if (!srv_send_smb(xconn,
1033 (char *)req->outbuf,
1034 true, req->seqnum+1,
1035 IS_CONN_ENCRYPTED(conn),
1037 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1039 TALLOC_FREE(req->outbuf);
1043 /* When sending params and data ensure that both are nicely aligned */
1044 /* Only do this alignment when there is also data to send - else
1045 can cause NT redirector problems. */
1047 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1048 data_alignment_offset = 4 - (params_to_send % 4);
1050 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1051 /* The alignment_offset is to align the param bytes on an even byte
1052 boundary. NT 4.0 Beta needs this to work correctly. */
1054 useable_space = max_send - (smb_size
1057 + data_alignment_offset);
1059 if (useable_space < 0) {
1060 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1061 "= %d!!!", useable_space));
1062 exit_server_cleanly("send_trans2_replies: Not enough space");
1065 while (params_to_send || data_to_send) {
1066 /* Calculate whether we will totally or partially fill this packet */
1068 total_sent_thistime = params_to_send + data_to_send;
1070 /* We can never send more than useable_space */
1072 * Note that 'useable_space' does not include the alignment offsets,
1073 * but we must include the alignment offsets in the calculation of
1074 * the length of the data we send over the wire, as the alignment offsets
1075 * are sent here. Fix from Marc_Jacobsen@hp.com.
1078 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1080 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1081 + data_alignment_offset);
1083 /* Set total params and data to be sent */
1084 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1085 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1087 /* Calculate how many parameters and data we can fit into
1088 * this packet. Parameters get precedence
1091 params_sent_thistime = MIN(params_to_send,useable_space);
1092 data_sent_thistime = useable_space - params_sent_thistime;
1093 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1095 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1097 /* smb_proff is the offset from the start of the SMB header to the
1098 parameter bytes, however the first 4 bytes of outbuf are
1099 the Netbios over TCP header. Thus use smb_base() to subtract
1100 them from the calculation */
1102 SSVAL(req->outbuf,smb_proff,
1103 ((smb_buf(req->outbuf)+alignment_offset)
1104 - smb_base(req->outbuf)));
1106 if(params_sent_thistime == 0)
1107 SSVAL(req->outbuf,smb_prdisp,0);
1109 /* Absolute displacement of param bytes sent in this packet */
1110 SSVAL(req->outbuf,smb_prdisp,pp - params);
1112 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1113 if(data_sent_thistime == 0) {
1114 SSVAL(req->outbuf,smb_droff,0);
1115 SSVAL(req->outbuf,smb_drdisp, 0);
1117 /* The offset of the data bytes is the offset of the
1118 parameter bytes plus the number of parameters being sent this time */
1119 SSVAL(req->outbuf, smb_droff,
1120 ((smb_buf(req->outbuf)+alignment_offset)
1121 - smb_base(req->outbuf))
1122 + params_sent_thistime + data_alignment_offset);
1123 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1126 /* Initialize the padding for alignment */
1128 if (alignment_offset != 0) {
1129 memset(smb_buf(req->outbuf), 0, alignment_offset);
1132 /* Copy the param bytes into the packet */
1134 if(params_sent_thistime) {
1135 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1136 params_sent_thistime);
1139 /* Copy in the data bytes */
1140 if(data_sent_thistime) {
1141 if (data_alignment_offset != 0) {
1142 memset((smb_buf(req->outbuf)+alignment_offset+
1143 params_sent_thistime), 0,
1144 data_alignment_offset);
1146 memcpy(smb_buf(req->outbuf)+alignment_offset
1147 +params_sent_thistime+data_alignment_offset,
1148 pd,data_sent_thistime);
1151 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1152 params_sent_thistime, data_sent_thistime, useable_space));
1153 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1154 params_to_send, data_to_send, paramsize, datasize));
1157 error_packet_set((char *)req->outbuf,
1158 ERRDOS,ERRbufferoverflow,
1159 STATUS_BUFFER_OVERFLOW,
1161 } else if (NT_STATUS_V(status)) {
1164 ntstatus_to_dos(status, &eclass, &ecode);
1165 error_packet_set((char *)req->outbuf,
1166 eclass, ecode, status,
1170 /* Send the packet */
1171 show_msg((char *)req->outbuf);
1172 if (!srv_send_smb(xconn,
1173 (char *)req->outbuf,
1174 true, req->seqnum+1,
1175 IS_CONN_ENCRYPTED(conn),
1177 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1179 TALLOC_FREE(req->outbuf);
1181 pp += params_sent_thistime;
1182 pd += data_sent_thistime;
1184 params_to_send -= params_sent_thistime;
1185 data_to_send -= data_sent_thistime;
1188 if(params_to_send < 0 || data_to_send < 0) {
1189 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1190 params_to_send, data_to_send));
1198 /****************************************************************************
1199 Reply to a TRANSACT2_OPEN.
1200 ****************************************************************************/
1202 static void call_trans2open(connection_struct *conn,
1203 struct smb_request *req,
1204 char **pparams, int total_params,
1205 char **ppdata, int total_data,
1206 unsigned int max_data_bytes)
1208 struct smb_filename *smb_fname = NULL;
1209 char *params = *pparams;
1210 char *pdata = *ppdata;
1213 bool oplock_request;
1215 bool return_additional_info;
1224 int fattr=0,mtime=0;
1225 SMB_INO_T inode = 0;
1228 struct ea_list *ea_list = NULL;
1231 uint32_t access_mask;
1232 uint32_t share_mode;
1233 uint32_t create_disposition;
1234 uint32_t create_options = 0;
1235 uint32_t private_flags = 0;
1236 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1237 TALLOC_CTX *ctx = talloc_tos();
1240 * Ensure we have enough parameters to perform the operation.
1243 if (total_params < 29) {
1244 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1248 flags = SVAL(params, 0);
1249 deny_mode = SVAL(params, 2);
1250 open_attr = SVAL(params,6);
1251 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1252 if (oplock_request) {
1253 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1257 return_additional_info = BITSETW(params,0);
1258 open_sattr = SVAL(params, 4);
1259 open_time = make_unix_date3(params+8);
1261 open_ofun = SVAL(params,12);
1262 open_size = IVAL(params,14);
1263 pname = ¶ms[28];
1266 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1270 if (req->posix_pathnames) {
1271 srvstr_get_path_posix(ctx,
1280 srvstr_get_path(ctx,
1289 if (!NT_STATUS_IS_OK(status)) {
1290 reply_nterror(req, status);
1294 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1295 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1296 (unsigned int)open_ofun, open_size));
1298 status = filename_convert(ctx,
1305 if (!NT_STATUS_IS_OK(status)) {
1306 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1307 reply_botherror(req,
1308 NT_STATUS_PATH_NOT_COVERED,
1309 ERRSRV, ERRbadpath);
1312 reply_nterror(req, status);
1316 if (open_ofun == 0) {
1317 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1321 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1323 &access_mask, &share_mode,
1324 &create_disposition,
1327 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1331 /* Any data in this call is an EA list. */
1332 if (total_data && (total_data != 4)) {
1333 if (total_data < 10) {
1334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1338 if (IVAL(pdata,0) > total_data) {
1339 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1340 IVAL(pdata,0), (unsigned int)total_data));
1341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1345 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1352 if (!lp_ea_support(SNUM(conn))) {
1353 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1357 if (!req->posix_pathnames &&
1358 ea_list_has_invalid_name(ea_list)) {
1360 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1361 if(*pparams == NULL ) {
1362 reply_nterror(req, NT_STATUS_NO_MEMORY);
1366 memset(params, '\0', param_len);
1367 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1368 params, param_len, NULL, 0, max_data_bytes);
1373 status = SMB_VFS_CREATE_FILE(
1376 0, /* root_dir_fid */
1377 smb_fname, /* fname */
1378 access_mask, /* access_mask */
1379 share_mode, /* share_access */
1380 create_disposition, /* create_disposition*/
1381 create_options, /* create_options */
1382 open_attr, /* file_attributes */
1383 oplock_request, /* oplock_request */
1385 open_size, /* allocation_size */
1388 ea_list, /* ea_list */
1390 &smb_action, /* psbuf */
1391 NULL, NULL); /* create context */
1393 if (!NT_STATUS_IS_OK(status)) {
1394 if (open_was_deferred(req->xconn, req->mid)) {
1395 /* We have re-scheduled this call. */
1398 reply_openerror(req, status);
1402 size = get_file_size_stat(&smb_fname->st);
1403 fattr = dos_mode(conn, smb_fname);
1404 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1405 inode = smb_fname->st.st_ex_ino;
1406 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1407 close_file(req, fsp, ERROR_CLOSE);
1408 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1412 /* Realloc the size of parameters and data we will return */
1413 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1414 if(*pparams == NULL ) {
1415 reply_nterror(req, NT_STATUS_NO_MEMORY);
1420 SSVAL(params,0,fsp->fnum);
1421 SSVAL(params,2,fattr);
1422 srv_put_dos_date2(params,4, mtime);
1423 SIVAL(params,8, (uint32_t)size);
1424 SSVAL(params,12,deny_mode);
1425 SSVAL(params,14,0); /* open_type - file or directory. */
1426 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1428 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1429 smb_action |= EXTENDED_OPLOCK_GRANTED;
1432 SSVAL(params,18,smb_action);
1435 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1437 SIVAL(params,20,inode);
1438 SSVAL(params,24,0); /* Padding. */
1440 uint32_t ea_size = estimate_ea_size(conn, fsp,
1442 SIVAL(params, 26, ea_size);
1444 SIVAL(params, 26, 0);
1447 /* Send the required number of replies */
1448 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1450 TALLOC_FREE(smb_fname);
1453 /*********************************************************
1454 Routine to check if a given string matches exactly.
1455 as a special case a mask of "." does NOT match. That
1456 is required for correct wildcard semantics
1457 Case can be significant or not.
1458 **********************************************************/
1460 static bool exact_match(bool has_wild,
1461 bool case_sensitive,
1465 if (mask[0] == '.' && mask[1] == 0) {
1473 if (case_sensitive) {
1474 return strcmp(str,mask)==0;
1476 return strcasecmp_m(str,mask) == 0;
1480 /****************************************************************************
1481 Return the filetype for UNIX extensions.
1482 ****************************************************************************/
1484 static uint32_t unix_filetype(mode_t mode)
1487 return UNIX_TYPE_FILE;
1488 else if(S_ISDIR(mode))
1489 return UNIX_TYPE_DIR;
1491 else if(S_ISLNK(mode))
1492 return UNIX_TYPE_SYMLINK;
1495 else if(S_ISCHR(mode))
1496 return UNIX_TYPE_CHARDEV;
1499 else if(S_ISBLK(mode))
1500 return UNIX_TYPE_BLKDEV;
1503 else if(S_ISFIFO(mode))
1504 return UNIX_TYPE_FIFO;
1507 else if(S_ISSOCK(mode))
1508 return UNIX_TYPE_SOCKET;
1511 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1512 return UNIX_TYPE_UNKNOWN;
1515 /****************************************************************************
1516 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1517 ****************************************************************************/
1519 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1521 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1522 const SMB_STRUCT_STAT *psbuf,
1524 enum perm_type ptype,
1529 if (perms == SMB_MODE_NO_CHANGE) {
1530 if (!VALID_STAT(*psbuf)) {
1531 return NT_STATUS_INVALID_PARAMETER;
1533 *ret_perms = psbuf->st_ex_mode;
1534 return NT_STATUS_OK;
1538 ret = wire_perms_to_unix(perms);
1540 if (ptype == PERM_NEW_FILE) {
1542 * "create mask"/"force create mode" are
1543 * only applied to new files, not existing ones.
1545 ret &= lp_create_mask(SNUM(conn));
1546 /* Add in force bits */
1547 ret |= lp_force_create_mode(SNUM(conn));
1548 } else if (ptype == PERM_NEW_DIR) {
1550 * "directory mask"/"force directory mode" are
1551 * only applied to new directories, not existing ones.
1553 ret &= lp_directory_mask(SNUM(conn));
1554 /* Add in force bits */
1555 ret |= lp_force_directory_mode(SNUM(conn));
1559 return NT_STATUS_OK;
1562 /****************************************************************************
1563 Needed to show the msdfs symlinks as directories. Modifies psbuf
1564 to be a directory if it's a msdfs link.
1565 ****************************************************************************/
1567 static bool check_msdfs_link(connection_struct *conn,
1568 struct smb_filename *smb_fname)
1570 int saved_errno = errno;
1571 if(lp_host_msdfs() &&
1572 lp_msdfs_root(SNUM(conn)) &&
1573 is_msdfs_link(conn, smb_fname)) {
1575 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1577 smb_fname->base_name));
1578 smb_fname->st.st_ex_mode =
1579 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1580 errno = saved_errno;
1583 errno = saved_errno;
1588 /****************************************************************************
1589 Get a level dependent lanman2 dir entry.
1590 ****************************************************************************/
1592 struct smbd_dirptr_lanman2_state {
1593 connection_struct *conn;
1594 uint32_t info_level;
1595 bool check_mangled_names;
1597 bool got_exact_match;
1600 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1606 struct smbd_dirptr_lanman2_state *state =
1607 (struct smbd_dirptr_lanman2_state *)private_data;
1609 char mangled_name[13]; /* mangled 8.3 name. */
1613 /* Mangle fname if it's an illegal name. */
1614 if (mangle_must_mangle(dname, state->conn->params)) {
1616 * Slow path - ensure we can push the original name as UCS2. If
1617 * not, then just don't return this name.
1621 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1622 uint8_t *tmp = talloc_array(talloc_tos(),
1626 status = srvstr_push(NULL,
1627 FLAGS2_UNICODE_STRINGS,
1636 if (!NT_STATUS_IS_OK(status)) {
1640 ok = name_to_8_3(dname, mangled_name,
1641 true, state->conn->params);
1645 fname = mangled_name;
1650 got_match = exact_match(state->has_wild,
1651 state->conn->case_sensitive,
1653 state->got_exact_match = got_match;
1655 got_match = mask_match(fname, mask,
1656 state->conn->case_sensitive);
1659 if(!got_match && state->check_mangled_names &&
1660 !mangle_is_8_3(fname, false, state->conn->params)) {
1662 * It turns out that NT matches wildcards against
1663 * both long *and* short names. This may explain some
1664 * of the wildcard wierdness from old DOS clients
1665 * that some people have been seeing.... JRA.
1667 /* Force the mangling into 8.3. */
1668 ok = name_to_8_3(fname, mangled_name,
1669 false, state->conn->params);
1674 got_match = exact_match(state->has_wild,
1675 state->conn->case_sensitive,
1676 mangled_name, mask);
1677 state->got_exact_match = got_match;
1679 got_match = mask_match(mangled_name, mask,
1680 state->conn->case_sensitive);
1688 *_fname = talloc_strdup(ctx, fname);
1689 if (*_fname == NULL) {
1696 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1698 struct smb_filename *smb_fname,
1702 struct smbd_dirptr_lanman2_state *state =
1703 (struct smbd_dirptr_lanman2_state *)private_data;
1704 bool ms_dfs_link = false;
1707 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1708 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1709 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1710 "Couldn't lstat [%s] (%s)\n",
1711 smb_fname_str_dbg(smb_fname),
1715 } else if (!VALID_STAT(smb_fname->st) &&
1716 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1717 /* Needed to show the msdfs symlinks as
1720 ms_dfs_link = check_msdfs_link(state->conn,
1723 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1724 "Couldn't stat [%s] (%s)\n",
1725 smb_fname_str_dbg(smb_fname),
1732 mode = dos_mode_msdfs(state->conn, smb_fname);
1733 } else if (get_dosmode) {
1734 mode = dos_mode(state->conn, smb_fname);
1741 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1742 connection_struct *conn,
1744 uint32_t info_level,
1745 struct ea_list *name_list,
1746 bool check_mangled_names,
1747 bool requires_resume_key,
1750 const struct smb_filename *smb_fname,
1751 int space_remaining,
1757 uint64_t *last_entry_off)
1759 char *p, *q, *pdata = *ppdata;
1761 uint64_t file_size = 0;
1762 uint64_t allocation_size = 0;
1763 uint64_t file_index = 0;
1765 struct timespec mdate_ts = {0};
1766 struct timespec adate_ts = {0};
1767 struct timespec cdate_ts = {0};
1768 struct timespec create_date_ts = {0};
1769 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1771 char *last_entry_ptr;
1776 struct readdir_attr_data *readdir_attr_data = NULL;
1778 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1779 file_size = get_file_size_stat(&smb_fname->st);
1781 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1783 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1784 if (!NT_STATUS_IS_OK(status)) {
1785 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1790 file_index = get_FileIndex(conn, &smb_fname->st);
1792 mdate_ts = smb_fname->st.st_ex_mtime;
1793 adate_ts = smb_fname->st.st_ex_atime;
1794 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1795 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1797 if (lp_dos_filetime_resolution(SNUM(conn))) {
1798 dos_filetime_timespec(&create_date_ts);
1799 dos_filetime_timespec(&mdate_ts);
1800 dos_filetime_timespec(&adate_ts);
1801 dos_filetime_timespec(&cdate_ts);
1804 create_date = convert_timespec_to_time_t(create_date_ts);
1805 mdate = convert_timespec_to_time_t(mdate_ts);
1806 adate = convert_timespec_to_time_t(adate_ts);
1808 /* align the record */
1809 SMB_ASSERT(align >= 1);
1811 off = (int)PTR_DIFF(pdata, base_data);
1812 pad = (off + (align-1)) & ~(align-1);
1815 if (pad && pad > space_remaining) {
1816 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1817 "for padding (wanted %u, had %d)\n",
1820 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1824 /* initialize padding to 0 */
1826 memset(pdata, 0, pad);
1828 space_remaining -= pad;
1830 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1840 switch (info_level) {
1841 case SMB_FIND_INFO_STANDARD:
1842 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1843 if(requires_resume_key) {
1847 srv_put_dos_date2(p,0,create_date);
1848 srv_put_dos_date2(p,4,adate);
1849 srv_put_dos_date2(p,8,mdate);
1850 SIVAL(p,12,(uint32_t)file_size);
1851 SIVAL(p,16,(uint32_t)allocation_size);
1855 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1856 p += ucs2_align(base_data, p, 0);
1858 status = srvstr_push(base_data, flags2, p,
1859 fname, PTR_DIFF(end_data, p),
1860 STR_TERMINATE, &len);
1861 if (!NT_STATUS_IS_OK(status)) {
1864 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1866 SCVAL(nameptr, -1, len - 2);
1868 SCVAL(nameptr, -1, 0);
1872 SCVAL(nameptr, -1, len - 1);
1874 SCVAL(nameptr, -1, 0);
1880 case SMB_FIND_EA_SIZE:
1881 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1882 if (requires_resume_key) {
1886 srv_put_dos_date2(p,0,create_date);
1887 srv_put_dos_date2(p,4,adate);
1888 srv_put_dos_date2(p,8,mdate);
1889 SIVAL(p,12,(uint32_t)file_size);
1890 SIVAL(p,16,(uint32_t)allocation_size);
1893 unsigned int ea_size = estimate_ea_size(conn, NULL,
1895 SIVAL(p,22,ea_size); /* Extended attributes */
1899 status = srvstr_push(base_data, flags2,
1900 p, fname, PTR_DIFF(end_data, p),
1901 STR_TERMINATE | STR_NOALIGN, &len);
1902 if (!NT_STATUS_IS_OK(status)) {
1905 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1918 SCVAL(nameptr,0,len);
1920 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1923 case SMB_FIND_EA_LIST:
1925 struct ea_list *file_list = NULL;
1928 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1930 return NT_STATUS_INVALID_PARAMETER;
1932 if (requires_resume_key) {
1936 srv_put_dos_date2(p,0,create_date);
1937 srv_put_dos_date2(p,4,adate);
1938 srv_put_dos_date2(p,8,mdate);
1939 SIVAL(p,12,(uint32_t)file_size);
1940 SIVAL(p,16,(uint32_t)allocation_size);
1942 p += 22; /* p now points to the EA area. */
1944 status = get_ea_list_from_file(ctx, conn, NULL,
1946 &ea_len, &file_list);
1947 if (!NT_STATUS_IS_OK(status)) {
1950 name_list = ea_list_union(name_list, file_list, &ea_len);
1952 /* We need to determine if this entry will fit in the space available. */
1953 /* Max string size is 255 bytes. */
1954 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1955 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1956 "(wanted %u, had %d)\n",
1957 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1959 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1962 /* Push the ea_data followed by the name. */
1963 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1965 status = srvstr_push(base_data, flags2,
1966 p + 1, fname, PTR_DIFF(end_data, p+1),
1967 STR_TERMINATE | STR_NOALIGN, &len);
1968 if (!NT_STATUS_IS_OK(status)) {
1971 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1984 SCVAL(nameptr,0,len);
1986 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1990 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1991 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1992 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1994 SIVAL(p,0,reskey); p += 4;
1995 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1996 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1997 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1998 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1999 SOFF_T(p,0,file_size); p += 8;
2000 SOFF_T(p,0,allocation_size); p += 8;
2001 SIVAL(p,0,mode); p += 4;
2002 q = p; p += 4; /* q is placeholder for name length. */
2003 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2004 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2006 unsigned int ea_size = estimate_ea_size(conn, NULL,
2008 SIVAL(p,0,ea_size); /* Extended attributes */
2011 /* Clear the short name buffer. This is
2012 * IMPORTANT as not doing so will trigger
2013 * a Win2k client bug. JRA.
2015 if (!was_8_3 && check_mangled_names) {
2016 char mangled_name[13]; /* mangled 8.3 name. */
2017 if (!name_to_8_3(fname,mangled_name,True,
2019 /* Error - mangle failed ! */
2020 memset(mangled_name,'\0',12);
2022 mangled_name[12] = 0;
2023 status = srvstr_push(base_data, flags2,
2024 p+2, mangled_name, 24,
2025 STR_UPPER|STR_UNICODE, &len);
2026 if (!NT_STATUS_IS_OK(status)) {
2030 memset(p + 2 + len,'\0',24 - len);
2037 status = srvstr_push(base_data, flags2, p,
2038 fname, PTR_DIFF(end_data, p),
2039 STR_TERMINATE_ASCII, &len);
2040 if (!NT_STATUS_IS_OK(status)) {
2046 len = PTR_DIFF(p, pdata);
2047 pad = (len + (align-1)) & ~(align-1);
2049 * offset to the next entry, the caller
2050 * will overwrite it for the last entry
2051 * that's why we always include the padding
2055 * set padding to zero
2058 memset(p, 0, pad - len);
2065 case SMB_FIND_FILE_DIRECTORY_INFO:
2066 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2068 SIVAL(p,0,reskey); p += 4;
2069 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2070 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2071 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2072 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2073 SOFF_T(p,0,file_size); p += 8;
2074 SOFF_T(p,0,allocation_size); p += 8;
2075 SIVAL(p,0,mode); p += 4;
2076 status = srvstr_push(base_data, flags2,
2077 p + 4, fname, PTR_DIFF(end_data, p+4),
2078 STR_TERMINATE_ASCII, &len);
2079 if (!NT_STATUS_IS_OK(status)) {
2085 len = PTR_DIFF(p, pdata);
2086 pad = (len + (align-1)) & ~(align-1);
2088 * offset to the next entry, the caller
2089 * will overwrite it for the last entry
2090 * that's why we always include the padding
2094 * set padding to zero
2097 memset(p, 0, pad - len);
2104 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2105 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2107 SIVAL(p,0,reskey); p += 4;
2108 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2109 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2110 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2111 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2112 SOFF_T(p,0,file_size); p += 8;
2113 SOFF_T(p,0,allocation_size); p += 8;
2114 SIVAL(p,0,mode); p += 4;
2115 q = p; p += 4; /* q is placeholder for name length. */
2116 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2117 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2119 unsigned int ea_size = estimate_ea_size(conn, NULL,
2121 SIVAL(p,0,ea_size); /* Extended attributes */
2124 status = srvstr_push(base_data, flags2, p,
2125 fname, PTR_DIFF(end_data, p),
2126 STR_TERMINATE_ASCII, &len);
2127 if (!NT_STATUS_IS_OK(status)) {
2133 len = PTR_DIFF(p, pdata);
2134 pad = (len + (align-1)) & ~(align-1);
2136 * offset to the next entry, the caller
2137 * will overwrite it for the last entry
2138 * that's why we always include the padding
2142 * set padding to zero
2145 memset(p, 0, pad - len);
2152 case SMB_FIND_FILE_NAMES_INFO:
2153 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2155 SIVAL(p,0,reskey); p += 4;
2157 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2158 acl on a dir (tridge) */
2159 status = srvstr_push(base_data, flags2, p,
2160 fname, PTR_DIFF(end_data, p),
2161 STR_TERMINATE_ASCII, &len);
2162 if (!NT_STATUS_IS_OK(status)) {
2168 len = PTR_DIFF(p, pdata);
2169 pad = (len + (align-1)) & ~(align-1);
2171 * offset to the next entry, the caller
2172 * will overwrite it for the last entry
2173 * that's why we always include the padding
2177 * set padding to zero
2180 memset(p, 0, pad - len);
2187 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2188 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2190 SIVAL(p,0,reskey); p += 4;
2191 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2192 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2193 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2194 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2195 SOFF_T(p,0,file_size); p += 8;
2196 SOFF_T(p,0,allocation_size); p += 8;
2197 SIVAL(p,0,mode); p += 4;
2198 q = p; p += 4; /* q is placeholder for name length. */
2199 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2200 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2202 unsigned int ea_size = estimate_ea_size(conn, NULL,
2204 SIVAL(p,0,ea_size); /* Extended attributes */
2207 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2208 SBVAL(p,0,file_index); p += 8;
2209 status = srvstr_push(base_data, flags2, p,
2210 fname, PTR_DIFF(end_data, p),
2211 STR_TERMINATE_ASCII, &len);
2212 if (!NT_STATUS_IS_OK(status)) {
2218 len = PTR_DIFF(p, pdata);
2219 pad = (len + (align-1)) & ~(align-1);
2221 * offset to the next entry, the caller
2222 * will overwrite it for the last entry
2223 * that's why we always include the padding
2227 * set padding to zero
2230 memset(p, 0, pad - len);
2237 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2238 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2239 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2241 SIVAL(p,0,reskey); p += 4;
2242 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2243 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2244 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2245 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2246 SOFF_T(p,0,file_size); p += 8;
2247 SOFF_T(p,0,allocation_size); p += 8;
2248 SIVAL(p,0,mode); p += 4;
2249 q = p; p += 4; /* q is placeholder for name length */
2250 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2251 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2252 } else if (readdir_attr_data &&
2253 readdir_attr_data->type == RDATTR_AAPL) {
2255 * OS X specific SMB2 extension negotiated via
2256 * AAPL create context: return max_access in
2259 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2261 unsigned int ea_size = estimate_ea_size(conn, NULL,
2263 SIVAL(p,0,ea_size); /* Extended attributes */
2267 if (readdir_attr_data &&
2268 readdir_attr_data->type == RDATTR_AAPL) {
2270 * OS X specific SMB2 extension negotiated via
2271 * AAPL create context: return resource fork
2272 * length and compressed FinderInfo in
2275 * According to documentation short_name_len
2276 * should be 0, but on the wire behaviour
2277 * shows its set to 24 by clients.
2281 /* Resourefork length */
2282 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2284 /* Compressed FinderInfo */
2285 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2286 } else if (!was_8_3 && check_mangled_names) {
2287 char mangled_name[13]; /* mangled 8.3 name. */
2288 if (!name_to_8_3(fname,mangled_name,True,
2290 /* Error - mangle failed ! */
2291 memset(mangled_name,'\0',12);
2293 mangled_name[12] = 0;
2294 status = srvstr_push(base_data, flags2,
2295 p+2, mangled_name, 24,
2296 STR_UPPER|STR_UNICODE, &len);
2297 if (!NT_STATUS_IS_OK(status)) {
2302 memset(p + 2 + len,'\0',24 - len);
2306 /* Clear the short name buffer. This is
2307 * IMPORTANT as not doing so will trigger
2308 * a Win2k client bug. JRA.
2315 if (readdir_attr_data &&
2316 readdir_attr_data->type == RDATTR_AAPL) {
2318 * OS X specific SMB2 extension negotiated via
2319 * AAPL create context: return UNIX mode in
2322 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2323 SSVAL(p, 0, aapl_mode);
2329 SBVAL(p,0,file_index); p += 8;
2330 status = srvstr_push(base_data, flags2, p,
2331 fname, PTR_DIFF(end_data, p),
2332 STR_TERMINATE_ASCII, &len);
2333 if (!NT_STATUS_IS_OK(status)) {
2339 len = PTR_DIFF(p, pdata);
2340 pad = (len + (align-1)) & ~(align-1);
2342 * offset to the next entry, the caller
2343 * will overwrite it for the last entry
2344 * that's why we always include the padding
2348 * set padding to zero
2351 memset(p, 0, pad - len);
2358 /* CIFS UNIX Extension. */
2360 case SMB_FIND_FILE_UNIX:
2361 case SMB_FIND_FILE_UNIX_INFO2:
2363 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2365 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2367 if (info_level == SMB_FIND_FILE_UNIX) {
2368 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2369 p = store_file_unix_basic(conn, p,
2370 NULL, &smb_fname->st);
2371 status = srvstr_push(base_data, flags2, p,
2372 fname, PTR_DIFF(end_data, p),
2373 STR_TERMINATE, &len);
2374 if (!NT_STATUS_IS_OK(status)) {
2378 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2379 p = store_file_unix_basic_info2(conn, p,
2380 NULL, &smb_fname->st);
2383 status = srvstr_push(base_data, flags2, p, fname,
2384 PTR_DIFF(end_data, p), 0, &len);
2385 if (!NT_STATUS_IS_OK(status)) {
2388 SIVAL(nameptr, 0, len);
2393 len = PTR_DIFF(p, pdata);
2394 pad = (len + (align-1)) & ~(align-1);
2396 * offset to the next entry, the caller
2397 * will overwrite it for the last entry
2398 * that's why we always include the padding
2402 * set padding to zero
2405 memset(p, 0, pad - len);
2410 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2415 return NT_STATUS_INVALID_LEVEL;
2418 if (PTR_DIFF(p,pdata) > space_remaining) {
2419 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2420 "(wanted %u, had %d)\n",
2421 (unsigned int)PTR_DIFF(p,pdata),
2423 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2426 /* Setup the last entry pointer, as an offset from base_data */
2427 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2428 /* Advance the data pointer to the next slot */
2431 return NT_STATUS_OK;
2434 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2435 connection_struct *conn,
2436 struct dptr_struct *dirptr,
2438 const char *path_mask,
2441 int requires_resume_key,
2450 int space_remaining,
2451 struct smb_filename **_smb_fname,
2452 bool *got_exact_match,
2453 int *_last_entry_off,
2454 struct ea_list *name_list,
2455 struct file_id *file_id)
2458 const char *mask = NULL;
2459 long prev_dirpos = 0;
2462 struct smb_filename *smb_fname = NULL;
2463 struct smbd_dirptr_lanman2_state state;
2465 uint64_t last_entry_off = 0;
2467 enum mangled_names_options mangled_names;
2468 bool marshall_with_83_names;
2470 mangled_names = lp_mangled_names(conn->params);
2474 state.info_level = info_level;
2475 if (mangled_names != MANGLED_NAMES_NO) {
2476 state.check_mangled_names = true;
2478 state.has_wild = dptr_has_wild(dirptr);
2479 state.got_exact_match = false;
2481 *got_exact_match = false;
2483 p = strrchr_m(path_mask,'/');
2494 ok = smbd_dirptr_get_entry(ctx,
2501 smbd_dirptr_lanman2_match_fn,
2502 smbd_dirptr_lanman2_mode_fn,
2509 return NT_STATUS_END_OF_FILE;
2512 *got_exact_match = state.got_exact_match;
2514 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2516 status = smbd_marshall_dir_entry(ctx,
2521 marshall_with_83_names,
2522 requires_resume_key,
2533 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2534 DEBUG(1,("Conversion error: illegal character: %s\n",
2535 smb_fname_str_dbg(smb_fname)));
2538 if (file_id != NULL) {
2539 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2542 if (!NT_STATUS_IS_OK(status) &&
2543 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2545 TALLOC_FREE(smb_fname);
2550 if (_smb_fname != NULL) {
2551 struct smb_filename *name = NULL;
2553 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2555 TALLOC_FREE(smb_fname);
2557 return NT_STATUS_NO_MEMORY;
2562 TALLOC_FREE(smb_fname);
2565 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2566 dptr_SeekDir(dirptr, prev_dirpos);
2570 *_last_entry_off = last_entry_off;
2571 return NT_STATUS_OK;
2574 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2575 connection_struct *conn,
2576 struct dptr_struct *dirptr,
2578 const char *path_mask,
2581 bool requires_resume_key,
2587 int space_remaining,
2588 bool *got_exact_match,
2589 int *last_entry_off,
2590 struct ea_list *name_list)
2593 const bool do_pad = true;
2595 if (info_level >= 1 && info_level <= 3) {
2596 /* No alignment on earlier info levels. */
2600 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2601 path_mask, dirtype, info_level,
2602 requires_resume_key, dont_descend, ask_sharemode,
2603 true, align, do_pad,
2604 ppdata, base_data, end_data,
2608 last_entry_off, name_list, NULL);
2611 /****************************************************************************
2612 Reply to a TRANS2_FINDFIRST.
2613 ****************************************************************************/
2615 static void call_trans2findfirst(connection_struct *conn,
2616 struct smb_request *req,
2617 char **pparams, int total_params,
2618 char **ppdata, int total_data,
2619 unsigned int max_data_bytes)
2621 /* We must be careful here that we don't return more than the
2622 allowed number of data bytes. If this means returning fewer than
2623 maxentries then so be it. We assume that the redirector has
2624 enough room for the fixed number of parameter bytes it has
2626 struct smb_filename *smb_dname = NULL;
2627 char *params = *pparams;
2628 char *pdata = *ppdata;
2632 uint16_t findfirst_flags;
2633 bool close_after_first;
2635 bool requires_resume_key;
2637 char *directory = NULL;
2640 int last_entry_off=0;
2644 bool finished = False;
2645 bool dont_descend = False;
2646 bool out_of_space = False;
2647 int space_remaining;
2648 bool mask_contains_wcard = False;
2649 struct ea_list *ea_list = NULL;
2650 NTSTATUS ntstatus = NT_STATUS_OK;
2651 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2652 struct dptr_struct *dirptr = NULL;
2653 struct smbd_server_connection *sconn = req->sconn;
2654 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2655 ucf_flags_from_smb_request(req);
2656 bool backup_priv = false;
2657 bool as_root = false;
2659 if (total_params < 13) {
2660 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2664 dirtype = SVAL(params,0);
2665 maxentries = SVAL(params,2);
2666 findfirst_flags = SVAL(params,4);
2667 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2668 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2669 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2670 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2671 security_token_has_privilege(get_current_nttok(conn),
2674 info_level = SVAL(params,6);
2676 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2677 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2678 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2680 info_level, max_data_bytes));
2683 /* W2K3 seems to treat zero as 1. */
2687 switch (info_level) {
2688 case SMB_FIND_INFO_STANDARD:
2689 case SMB_FIND_EA_SIZE:
2690 case SMB_FIND_EA_LIST:
2691 case SMB_FIND_FILE_DIRECTORY_INFO:
2692 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2693 case SMB_FIND_FILE_NAMES_INFO:
2694 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2695 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2696 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2698 case SMB_FIND_FILE_UNIX:
2699 case SMB_FIND_FILE_UNIX_INFO2:
2700 /* Always use filesystem for UNIX mtime query. */
2701 ask_sharemode = false;
2702 if (!lp_unix_extensions()) {
2703 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2706 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2709 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2713 if (req->posix_pathnames) {
2714 srvstr_get_path_wcard_posix(talloc_tos(),
2722 &mask_contains_wcard);
2724 srvstr_get_path_wcard(talloc_tos(),
2732 &mask_contains_wcard);
2734 if (!NT_STATUS_IS_OK(ntstatus)) {
2735 reply_nterror(req, ntstatus);
2742 ntstatus = filename_convert_with_privilege(talloc_tos(),
2747 &mask_contains_wcard,
2750 ntstatus = filename_convert(talloc_tos(), conn,
2754 &mask_contains_wcard,
2758 if (!NT_STATUS_IS_OK(ntstatus)) {
2759 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2760 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2761 ERRSRV, ERRbadpath);
2764 reply_nterror(req, ntstatus);
2768 mask = smb_dname->original_lcomp;
2770 directory = smb_dname->base_name;
2772 p = strrchr_m(directory,'/');
2774 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2775 if((directory[0] == '.') && (directory[1] == '\0')) {
2776 mask = talloc_strdup(talloc_tos(),"*");
2778 reply_nterror(req, NT_STATUS_NO_MEMORY);
2781 mask_contains_wcard = True;
2787 if (p == NULL || p == directory) {
2788 /* Ensure we don't have a directory name of "". */
2789 directory = talloc_strdup(talloc_tos(), ".");
2791 reply_nterror(req, NT_STATUS_NO_MEMORY);
2794 /* Ensure smb_dname->base_name matches. */
2795 smb_dname->base_name = directory;
2798 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2800 if (info_level == SMB_FIND_EA_LIST) {
2803 if (total_data < 4) {
2804 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2808 ea_size = IVAL(pdata,0);
2809 if (ea_size != total_data) {
2810 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2811 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2816 if (!lp_ea_support(SNUM(conn))) {
2817 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2821 /* Pull out the list of names. */
2822 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2829 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2830 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2834 *ppdata = (char *)SMB_REALLOC(
2835 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2836 if(*ppdata == NULL ) {
2837 reply_nterror(req, NT_STATUS_NO_MEMORY);
2841 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2843 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2846 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2847 /* Realloc the params space */
2848 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2849 if (*pparams == NULL) {
2850 reply_nterror(req, NT_STATUS_NO_MEMORY);
2855 /* Save the wildcard match and attribs we are using on this directory -
2856 needed as lanman2 assumes these are being saved between calls */
2858 ntstatus = dptr_create(conn,
2866 mask_contains_wcard,
2870 if (!NT_STATUS_IS_OK(ntstatus)) {
2871 reply_nterror(req, ntstatus);
2876 /* Remember this in case we have
2877 to do a findnext. */
2878 dptr_set_priv(dirptr);
2881 dptr_num = dptr_dnum(dirptr);
2882 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2884 /* We don't need to check for VOL here as this is returned by
2885 a different TRANS2 call. */
2887 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2888 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2889 if (in_list(directory,
2890 lp_dont_descend(talloc_tos(), SNUM(conn)),
2891 conn->case_sensitive)) {
2892 dont_descend = True;
2896 space_remaining = max_data_bytes;
2897 out_of_space = False;
2899 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2900 bool got_exact_match = False;
2902 /* this is a heuristic to avoid seeking the dirptr except when
2903 absolutely necessary. It allows for a filename of about 40 chars */
2904 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2905 out_of_space = True;
2908 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2912 mask,dirtype,info_level,
2913 requires_resume_key,dont_descend,
2918 &last_entry_off, ea_list);
2919 if (NT_STATUS_EQUAL(ntstatus,
2920 NT_STATUS_ILLEGAL_CHARACTER)) {
2922 * Bad character conversion on name. Ignore this
2927 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2928 out_of_space = true;
2930 finished = !NT_STATUS_IS_OK(ntstatus);
2934 if (!finished && !out_of_space)
2938 * As an optimisation if we know we aren't looking
2939 * for a wildcard name (ie. the name matches the wildcard exactly)
2940 * then we can finish on any (first) match.
2941 * This speeds up large directory searches. JRA.
2947 /* Ensure space_remaining never goes -ve. */
2948 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2949 space_remaining = 0;
2950 out_of_space = true;
2952 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2956 /* Check if we can close the dirptr */
2957 if(close_after_first || (finished && close_if_end)) {
2958 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2959 dptr_close(sconn, &dptr_num);
2963 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2964 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2965 * the protocol level is less than NT1. Tested with smbclient. JRA.
2966 * This should fix the OS/2 client bug #2335.
2969 if(numentries == 0) {
2970 dptr_close(sconn, &dptr_num);
2971 if (get_Protocol() < PROTOCOL_NT1) {
2972 reply_force_doserror(req, ERRDOS, ERRnofiles);
2975 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2976 ERRDOS, ERRbadfile);
2981 /* At this point pdata points to numentries directory entries. */
2983 /* Set up the return parameter block */
2984 SSVAL(params,0,dptr_num);
2985 SSVAL(params,2,numentries);
2986 SSVAL(params,4,finished);
2987 SSVAL(params,6,0); /* Never an EA error */
2988 SSVAL(params,8,last_entry_off);
2990 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2993 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2994 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2996 reply_nterror(req, NT_STATUS_NO_MEMORY);
3000 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3001 smb_fn_name(req->cmd),
3002 mask, directory, dirtype, numentries ) );
3005 * Force a name mangle here to ensure that the
3006 * mask as an 8.3 name is top of the mangled cache.
3007 * The reasons for this are subtle. Don't remove
3008 * this code unless you know what you are doing
3009 * (see PR#13758). JRA.
3012 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3013 char mangled_name[13];
3014 name_to_8_3(mask, mangled_name, True, conn->params);
3022 TALLOC_FREE(smb_dname);
3026 /****************************************************************************
3027 Reply to a TRANS2_FINDNEXT.
3028 ****************************************************************************/
3030 static void call_trans2findnext(connection_struct *conn,
3031 struct smb_request *req,
3032 char **pparams, int total_params,
3033 char **ppdata, int total_data,
3034 unsigned int max_data_bytes)
3036 /* We must be careful here that we don't return more than the
3037 allowed number of data bytes. If this means returning fewer than
3038 maxentries then so be it. We assume that the redirector has
3039 enough room for the fixed number of parameter bytes it has
3041 char *params = *pparams;
3042 char *pdata = *ppdata;
3046 uint16_t info_level;
3047 uint32_t resume_key;
3048 uint16_t findnext_flags;
3049 bool close_after_request;
3051 bool requires_resume_key;
3053 bool mask_contains_wcard = False;
3054 char *resume_name = NULL;
3055 const char *mask = NULL;
3056 const char *directory = NULL;
3060 int i, last_entry_off=0;
3061 bool finished = False;
3062 bool dont_descend = False;
3063 bool out_of_space = False;
3064 int space_remaining;
3065 struct ea_list *ea_list = NULL;
3066 NTSTATUS ntstatus = NT_STATUS_OK;
3067 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3068 TALLOC_CTX *ctx = talloc_tos();
3069 struct dptr_struct *dirptr;
3070 struct smbd_server_connection *sconn = req->sconn;
3071 bool backup_priv = false;
3072 bool as_root = false;
3074 if (total_params < 13) {
3075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3079 dptr_num = SVAL(params,0);
3080 maxentries = SVAL(params,2);
3081 info_level = SVAL(params,4);
3082 resume_key = IVAL(params,6);
3083 findnext_flags = SVAL(params,10);
3084 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3085 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3086 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3087 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3089 if (!continue_bit) {
3090 /* We only need resume_name if continue_bit is zero. */
3091 if (req->posix_pathnames) {
3092 srvstr_get_path_wcard_posix(ctx,
3100 &mask_contains_wcard);
3102 srvstr_get_path_wcard(ctx,
3110 &mask_contains_wcard);
3112 if (!NT_STATUS_IS_OK(ntstatus)) {
3113 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3114 complain (it thinks we're asking for the directory above the shared
3115 path or an invalid name). Catch this as the resume name is only compared, never used in
3116 a file access. JRA. */
3117 srvstr_pull_talloc(ctx, params, req->flags2,
3118 &resume_name, params+12,
3122 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3123 reply_nterror(req, ntstatus);
3129 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3130 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3131 resume_key = %d resume name = %s continue=%d level = %d\n",
3132 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3133 requires_resume_key, resume_key,
3134 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3137 /* W2K3 seems to treat zero as 1. */
3141 switch (info_level) {
3142 case SMB_FIND_INFO_STANDARD:
3143 case SMB_FIND_EA_SIZE:
3144 case SMB_FIND_EA_LIST:
3145 case SMB_FIND_FILE_DIRECTORY_INFO:
3146 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3147 case SMB_FIND_FILE_NAMES_INFO:
3148 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3149 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3150 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3152 case SMB_FIND_FILE_UNIX:
3153 case SMB_FIND_FILE_UNIX_INFO2:
3154 /* Always use filesystem for UNIX mtime query. */
3155 ask_sharemode = false;
3156 if (!lp_unix_extensions()) {
3157 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3162 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3166 if (info_level == SMB_FIND_EA_LIST) {
3169 if (total_data < 4) {
3170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3174 ea_size = IVAL(pdata,0);
3175 if (ea_size != total_data) {
3176 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3177 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3182 if (!lp_ea_support(SNUM(conn))) {
3183 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3187 /* Pull out the list of names. */
3188 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3195 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3200 *ppdata = (char *)SMB_REALLOC(
3201 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3202 if(*ppdata == NULL) {
3203 reply_nterror(req, NT_STATUS_NO_MEMORY);
3208 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3211 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3214 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3215 /* Realloc the params space */
3216 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3217 if(*pparams == NULL ) {
3218 reply_nterror(req, NT_STATUS_NO_MEMORY);
3224 /* Check that the dptr is valid */
3225 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3226 reply_nterror(req, STATUS_NO_MORE_FILES);
3230 directory = dptr_path(sconn, dptr_num);
3232 /* Get the wildcard mask from the dptr */
3233 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3234 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3235 reply_nterror(req, STATUS_NO_MORE_FILES);
3239 /* Get the attr mask from the dptr */
3240 dirtype = dptr_attr(sconn, dptr_num);
3242 backup_priv = dptr_get_priv(dirptr);
3244 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3245 "backup_priv = %d\n",
3246 dptr_num, mask, dirtype,
3248 dptr_TellDir(dirptr),
3251 /* We don't need to check for VOL here as this is returned by
3252 a different TRANS2 call. */
3254 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3255 directory,lp_dont_descend(ctx, SNUM(conn))));
3256 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3257 dont_descend = True;
3260 space_remaining = max_data_bytes;
3261 out_of_space = False;
3269 * Seek to the correct position. We no longer use the resume key but
3270 * depend on the last file name instead.
3273 if(!continue_bit && resume_name && *resume_name) {
3276 long current_pos = 0;
3278 * Remember, name_to_8_3 is called by
3279 * get_lanman2_dir_entry(), so the resume name
3280 * could be mangled. Ensure we check the unmangled name.
3283 if (mangle_is_mangled(resume_name, conn->params)) {
3284 char *new_resume_name = NULL;
3285 mangle_lookup_name_from_8_3(ctx,
3289 if (new_resume_name) {
3290 resume_name = new_resume_name;
3295 * Fix for NT redirector problem triggered by resume key indexes
3296 * changing between directory scans. We now return a resume key of 0
3297 * and instead look for the filename to continue from (also given
3298 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3299 * findfirst/findnext (as is usual) then the directory pointer
3300 * should already be at the correct place.
3303 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3304 } /* end if resume_name && !continue_bit */
3306 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3307 bool got_exact_match = False;
3309 /* this is a heuristic to avoid seeking the dirptr except when
3310 absolutely necessary. It allows for a filename of about 40 chars */
3311 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3312 out_of_space = True;
3315 ntstatus = get_lanman2_dir_entry(ctx,
3319 mask,dirtype,info_level,
3320 requires_resume_key,dont_descend,
3325 &last_entry_off, ea_list);
3326 if (NT_STATUS_EQUAL(ntstatus,
3327 NT_STATUS_ILLEGAL_CHARACTER)) {
3329 * Bad character conversion on name. Ignore this
3334 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3335 out_of_space = true;
3337 finished = !NT_STATUS_IS_OK(ntstatus);
3341 if (!finished && !out_of_space)
3345 * As an optimisation if we know we aren't looking
3346 * for a wildcard name (ie. the name matches the wildcard exactly)
3347 * then we can finish on any (first) match.
3348 * This speeds up large directory searches. JRA.
3354 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3357 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3358 smb_fn_name(req->cmd),
3359 mask, directory, dirtype, numentries ) );
3361 /* Check if we can close the dirptr */
3362 if(close_after_request || (finished && close_if_end)) {
3363 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3364 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3371 /* Set up the return parameter block */
3372 SSVAL(params,0,numentries);
3373 SSVAL(params,2,finished);
3374 SSVAL(params,4,0); /* Never an EA error */
3375 SSVAL(params,6,last_entry_off);
3377 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3383 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3385 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3389 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3391 SMB_ASSERT(extended_info != NULL);
3393 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3394 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3395 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3396 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3397 #ifdef SAMBA_VERSION_REVISION
3398 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3400 extended_info->samba_subversion = 0;
3401 #ifdef SAMBA_VERSION_RC_RELEASE
3402 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3404 #ifdef SAMBA_VERSION_PRE_RELEASE
3405 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3408 #ifdef SAMBA_VERSION_VENDOR_PATCH
3409 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3411 extended_info->samba_gitcommitdate = 0;
3412 #ifdef SAMBA_VERSION_COMMIT_TIME
3413 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3416 memset(extended_info->samba_version_string, 0,
3417 sizeof(extended_info->samba_version_string));
3419 snprintf (extended_info->samba_version_string,
3420 sizeof(extended_info->samba_version_string),
3421 "%s", samba_version_string());
3424 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3425 connection_struct *conn,
3426 TALLOC_CTX *mem_ctx,
3427 uint16_t info_level,
3429 unsigned int max_data_bytes,
3430 size_t *fixed_portion,
3431 struct smb_filename *fname,
3435 char *pdata, *end_data;
3438 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3439 int snum = SNUM(conn);
3440 const char *fstype = lp_fstype(SNUM(conn));
3441 const char *filename = NULL;
3442 const uint64_t bytes_per_sector = 512;
3443 uint32_t additional_flags = 0;
3444 struct smb_filename smb_fname;
3446 NTSTATUS status = NT_STATUS_OK;
3449 if (fname == NULL || fname->base_name == NULL) {
3452 filename = fname->base_name;
3456 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3457 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3458 "info level (0x%x) on IPC$.\n",
3459 (unsigned int)info_level));
3460 return NT_STATUS_ACCESS_DENIED;
3464 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3466 ZERO_STRUCT(smb_fname);
3467 smb_fname.base_name = discard_const_p(char, filename);
3469 if(info_level != SMB_FS_QUOTA_INFORMATION
3470 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3471 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3472 return map_nt_error_from_unix(errno);
3477 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3478 return NT_STATUS_INVALID_PARAMETER;
3481 *ppdata = (char *)SMB_REALLOC(
3482 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3483 if (*ppdata == NULL) {
3484 return NT_STATUS_NO_MEMORY;
3488 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3489 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3493 switch (info_level) {
3494 case SMB_INFO_ALLOCATION:
3496 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3498 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3500 if (df_ret == (uint64_t)-1) {
3501 return map_nt_error_from_unix(errno);
3504 block_size = lp_block_size(snum);
3505 if (bsize < block_size) {
3506 uint64_t factor = block_size/bsize;
3511 if (bsize > block_size) {
3512 uint64_t factor = bsize/block_size;
3517 sectors_per_unit = bsize/bytes_per_sector;
3519 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3520 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3521 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3524 * For large drives, return max values and not modulo.
3526 dsize = MIN(dsize, UINT32_MAX);
3527 dfree = MIN(dfree, UINT32_MAX);
3529 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3530 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3531 SIVAL(pdata,l1_cUnit,dsize);
3532 SIVAL(pdata,l1_cUnitAvail,dfree);
3533 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3537 case SMB_INFO_VOLUME:
3538 /* Return volume name */
3540 * Add volume serial number - hash of a combination of
3541 * the called hostname and the service name.
3543 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3545 * Win2k3 and previous mess this up by sending a name length
3546 * one byte short. I believe only older clients (OS/2 Win9x) use
3547 * this call so try fixing this by adding a terminating null to
3548 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3550 status = srvstr_push(
3552 pdata+l2_vol_szVolLabel, vname,
3553 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3554 STR_NOALIGN|STR_TERMINATE, &len);
3555 if (!NT_STATUS_IS_OK(status)) {
3558 SCVAL(pdata,l2_vol_cch,len);
3559 data_len = l2_vol_szVolLabel + len;
3560 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3561 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3562 (unsigned)len, vname));
3565 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3566 case SMB_FS_ATTRIBUTE_INFORMATION:
3568 additional_flags = 0;
3569 #if defined(HAVE_SYS_QUOTAS)
3570 additional_flags |= FILE_VOLUME_QUOTAS;
3573 if(lp_nt_acl_support(SNUM(conn))) {
3574 additional_flags |= FILE_PERSISTENT_ACLS;
3577 /* Capabilities are filled in at connection time through STATVFS call */
3578 additional_flags |= conn->fs_capabilities;
3579 additional_flags |= lp_parm_int(conn->params->service,
3580 "share", "fake_fscaps",
3583 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3584 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3585 additional_flags); /* FS ATTRIBUTES */
3587 SIVAL(pdata,4,255); /* Max filename component length */
3588 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3589 and will think we can't do long filenames */
3590 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3591 PTR_DIFF(end_data, pdata+12),
3593 if (!NT_STATUS_IS_OK(status)) {
3597 data_len = 12 + len;
3598 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3599 /* the client only requested a portion of the
3601 data_len = max_data_bytes;
3602 status = STATUS_BUFFER_OVERFLOW;
3604 *fixed_portion = 16;
3607 case SMB_QUERY_FS_LABEL_INFO:
3608 case SMB_FS_LABEL_INFORMATION:
3609 status = srvstr_push(pdata, flags2, pdata+4, vname,
3610 PTR_DIFF(end_data, pdata+4), 0, &len);
3611 if (!NT_STATUS_IS_OK(status)) {
3618 case SMB_QUERY_FS_VOLUME_INFO:
3619 case SMB_FS_VOLUME_INFORMATION:
3622 * Add volume serial number - hash of a combination of
3623 * the called hostname and the service name.
3625 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3626 (str_checksum(get_local_machine_name())<<16));
3628 /* Max label len is 32 characters. */
3629 status = srvstr_push(pdata, flags2, pdata+18, vname,
3630 PTR_DIFF(end_data, pdata+18),
3632 if (!NT_STATUS_IS_OK(status)) {
3635 SIVAL(pdata,12,len);
3638 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3639 (int)strlen(vname),vname,
3640 lp_servicename(talloc_tos(), snum)));
3641 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3642 /* the client only requested a portion of the
3644 data_len = max_data_bytes;
3645 status = STATUS_BUFFER_OVERFLOW;
3647 *fixed_portion = 24;
3650 case SMB_QUERY_FS_SIZE_INFO:
3651 case SMB_FS_SIZE_INFORMATION:
3653 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3655 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3657 if (df_ret == (uint64_t)-1) {
3658 return map_nt_error_from_unix(errno);
3660 block_size = lp_block_size(snum);
3661 if (bsize < block_size) {
3662 uint64_t factor = block_size/bsize;
3667 if (bsize > block_size) {
3668 uint64_t factor = bsize/block_size;
3673 sectors_per_unit = bsize/bytes_per_sector;
3674 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3675 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3676 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3677 SBIG_UINT(pdata,0,dsize);
3678 SBIG_UINT(pdata,8,dfree);
3679 SIVAL(pdata,16,sectors_per_unit);
3680 SIVAL(pdata,20,bytes_per_sector);
3681 *fixed_portion = 24;
3685 case SMB_FS_FULL_SIZE_INFORMATION:
3687 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3689 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3691 if (df_ret == (uint64_t)-1) {
3692 return map_nt_error_from_unix(errno);
3694 block_size = lp_block_size(snum);
3695 if (bsize < block_size) {
3696 uint64_t factor = block_size/bsize;
3701 if (bsize > block_size) {
3702 uint64_t factor = bsize/block_size;
3707 sectors_per_unit = bsize/bytes_per_sector;
3708 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3709 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3710 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3711 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3712 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3713 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3714 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3715 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3716 *fixed_portion = 32;
3720 case SMB_QUERY_FS_DEVICE_INFO:
3721 case SMB_FS_DEVICE_INFORMATION:
3723 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3725 if (!CAN_WRITE(conn)) {
3726 characteristics |= FILE_READ_ONLY_DEVICE;
3729 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3730 SIVAL(pdata,4,characteristics);
3735 #ifdef HAVE_SYS_QUOTAS
3736 case SMB_FS_QUOTA_INFORMATION:
3738 * what we have to send --metze:
3740 * Unknown1: 24 NULL bytes
3741 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3742 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3743 * Quota Flags: 2 byte :
3744 * Unknown3: 6 NULL bytes
3748 * details for Quota Flags:
3750 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3751 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3752 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3753 * 0x0001 Enable Quotas: enable quota for this fs
3757 /* we need to fake up a fsp here,
3758 * because its not send in this call
3761 SMB_NTQUOTA_STRUCT quotas;
3764 ZERO_STRUCT(quotas);
3767 fsp.fnum = FNUM_FIELD_INVALID;
3770 if (get_current_uid(conn) != 0) {
3771 DEBUG(0,("get_user_quota: access_denied "
3772 "service [%s] user [%s]\n",
3773 lp_servicename(talloc_tos(), SNUM(conn)),
3774 conn->session_info->unix_info->unix_name));
3775 return NT_STATUS_ACCESS_DENIED;
3778 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3780 if (!NT_STATUS_IS_OK(status)) {
3781 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3787 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3788 lp_servicename(talloc_tos(), SNUM(conn))));
3790 /* Unknown1 24 NULL bytes*/
3791 SBIG_UINT(pdata,0,(uint64_t)0);
3792 SBIG_UINT(pdata,8,(uint64_t)0);
3793 SBIG_UINT(pdata,16,(uint64_t)0);
3795 /* Default Soft Quota 8 bytes */
3796 SBIG_UINT(pdata,24,quotas.softlim);
3798 /* Default Hard Quota 8 bytes */
3799 SBIG_UINT(pdata,32,quotas.hardlim);
3801 /* Quota flag 2 bytes */
3802 SSVAL(pdata,40,quotas.qflags);
3804 /* Unknown3 6 NULL bytes */
3810 #endif /* HAVE_SYS_QUOTAS */
3811 case SMB_FS_OBJECTID_INFORMATION:
3813 unsigned char objid[16];
3814 struct smb_extended_info extended_info;
3815 memcpy(pdata,create_volume_objectid(conn, objid),16);
3816 samba_extended_info_version (&extended_info);
3817 SIVAL(pdata,16,extended_info.samba_magic);
3818 SIVAL(pdata,20,extended_info.samba_version);
3819 SIVAL(pdata,24,extended_info.samba_subversion);
3820 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3821 memcpy(pdata+36,extended_info.samba_version_string,28);
3826 case SMB_FS_SECTOR_SIZE_INFORMATION:
3830 * These values match a physical Windows Server 2012
3831 * share backed by NTFS atop spinning rust.
3833 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3834 /* logical_bytes_per_sector */
3835 SIVAL(pdata, 0, bytes_per_sector);
3836 /* phys_bytes_per_sector_atomic */
3837 SIVAL(pdata, 4, bytes_per_sector);
3838 /* phys_bytes_per_sector_perf */
3839 SIVAL(pdata, 8, bytes_per_sector);
3840 /* fs_effective_phys_bytes_per_sector_atomic */
3841 SIVAL(pdata, 12, bytes_per_sector);
3843 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3844 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3845 /* byte_off_sector_align */
3846 SIVAL(pdata, 20, 0);
3847 /* byte_off_partition_align */
3848 SIVAL(pdata, 24, 0);
3849 *fixed_portion = 28;
3855 * Query the version and capabilities of the CIFS UNIX extensions
3859 case SMB_QUERY_CIFS_UNIX_INFO:
3861 bool large_write = lp_min_receive_file_size() &&
3862 !srv_is_signing_active(xconn);
3863 bool large_read = !srv_is_signing_active(xconn);
3864 int encrypt_caps = 0;
3866 if (!lp_unix_extensions()) {
3867 return NT_STATUS_INVALID_LEVEL;
3870 switch (conn->encrypt_level) {
3871 case SMB_SIGNING_OFF:
3874 case SMB_SIGNING_DESIRED:
3875 case SMB_SIGNING_IF_REQUIRED:
3876 case SMB_SIGNING_DEFAULT:
3877 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3879 case SMB_SIGNING_REQUIRED:
3880 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3881 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3882 large_write = false;
3888 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3889 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3891 /* We have POSIX ACLs, pathname, encryption,
3892 * large read/write, and locking capability. */
3894 SBIG_UINT(pdata,4,((uint64_t)(
3895 CIFS_UNIX_POSIX_ACLS_CAP|
3896 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3897 CIFS_UNIX_FCNTL_LOCKS_CAP|
3898 CIFS_UNIX_EXTATTR_CAP|
3899 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3901 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3903 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3907 case SMB_QUERY_POSIX_FS_INFO:
3910 vfs_statvfs_struct svfs;
3912 if (!lp_unix_extensions()) {
3913 return NT_STATUS_INVALID_LEVEL;
3916 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3920 SIVAL(pdata,0,svfs.OptimalTransferSize);
3921 SIVAL(pdata,4,svfs.BlockSize);
3922 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3923 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3924 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3925 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3926 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3927 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3928 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3930 } else if (rc == EOPNOTSUPP) {
3931 return NT_STATUS_INVALID_LEVEL;
3932 #endif /* EOPNOTSUPP */
3934 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3935 return NT_STATUS_DOS(ERRSRV, ERRerror);
3940 case SMB_QUERY_POSIX_WHOAMI:
3946 if (!lp_unix_extensions()) {
3947 return NT_STATUS_INVALID_LEVEL;
3950 if (max_data_bytes < 40) {
3951 return NT_STATUS_BUFFER_TOO_SMALL;
3954 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3955 flags |= SMB_WHOAMI_GUEST;
3958 /* NOTE: 8 bytes for UID/GID, irrespective of native
3959 * platform size. This matches
3960 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3962 data_len = 4 /* flags */
3969 + 4 /* pad/reserved */
3970 + (conn->session_info->unix_token->ngroups * 8)
3972 + (conn->session_info->security_token->num_sids *
3976 SIVAL(pdata, 0, flags);
3977 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3979 (uint64_t)conn->session_info->unix_token->uid);
3980 SBIG_UINT(pdata, 16,
3981 (uint64_t)conn->session_info->unix_token->gid);
3984 if (data_len >= max_data_bytes) {
3985 /* Potential overflow, skip the GIDs and SIDs. */
3987 SIVAL(pdata, 24, 0); /* num_groups */
3988 SIVAL(pdata, 28, 0); /* num_sids */
3989 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3990 SIVAL(pdata, 36, 0); /* reserved */
3996 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3997 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3999 /* We walk the SID list twice, but this call is fairly
4000 * infrequent, and I don't expect that it's performance
4001 * sensitive -- jpeach
4003 for (i = 0, sid_bytes = 0;
4004 i < conn->session_info->security_token->num_sids; ++i) {
4005 sid_bytes += ndr_size_dom_sid(
4006 &conn->session_info->security_token->sids[i],
4010 /* SID list byte count */
4011 SIVAL(pdata, 32, sid_bytes);
4013 /* 4 bytes pad/reserved - must be zero */
4014 SIVAL(pdata, 36, 0);
4018 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4019 SBIG_UINT(pdata, data_len,
4020 (uint64_t)conn->session_info->unix_token->groups[i]);
4026 i < conn->session_info->security_token->num_sids; ++i) {
4027 int sid_len = ndr_size_dom_sid(
4028 &conn->session_info->security_token->sids[i],
4031 sid_linearize((uint8_t *)(pdata + data_len),
4033 &conn->session_info->security_token->sids[i]);
4034 data_len += sid_len;
4040 case SMB_MAC_QUERY_FS_INFO:
4042 * Thursby MAC extension... ONLY on NTFS filesystems
4043 * once we do streams then we don't need this
4045 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4047 SIVAL(pdata,84,0x100); /* Don't support mac... */
4053 return NT_STATUS_INVALID_LEVEL;
4056 *ret_data_len = data_len;
4060 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4061 struct smb_request *req,
4063 const DATA_BLOB *qdata)
4066 SMB_NTQUOTA_STRUCT quotas;
4068 ZERO_STRUCT(quotas);
4071 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4072 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4073 lp_servicename(talloc_tos(), SNUM(conn)),
4074 conn->session_info->unix_info->unix_name));
4075 return NT_STATUS_ACCESS_DENIED;
4078 if (!check_fsp_ntquota_handle(conn, req,
4080 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4081 return NT_STATUS_INVALID_HANDLE;
4084 /* note: normally there're 48 bytes,
4085 * but we didn't use the last 6 bytes for now
4088 if (qdata->length < 42) {
4089 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4090 (unsigned int)qdata->length));
4091 return NT_STATUS_INVALID_PARAMETER;
4094 /* unknown_1 24 NULL bytes in pdata*/
4096 /* the soft quotas 8 bytes (uint64_t)*/
4097 quotas.softlim = BVAL(qdata->data,24);
4099 /* the hard quotas 8 bytes (uint64_t)*/
4100 quotas.hardlim = BVAL(qdata->data,32);
4102 /* quota_flags 2 bytes **/
4103 quotas.qflags = SVAL(qdata->data,40);
4105 /* unknown_2 6 NULL bytes follow*/
4107 /* now set the quotas */
4108 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4109 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4110 lp_servicename(talloc_tos(), SNUM(conn))));
4111 status = map_nt_error_from_unix(errno);
4113 status = NT_STATUS_OK;
4118 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4119 struct smb_request *req,
4120 TALLOC_CTX *mem_ctx,
4121 uint16_t info_level,
4123 const DATA_BLOB *pdata)
4125 switch (info_level) {
4126 case SMB_FS_QUOTA_INFORMATION:
4128 return smb_set_fsquota(conn,
4137 return NT_STATUS_INVALID_LEVEL;
4140 /****************************************************************************
4141 Reply to a TRANS2_QFSINFO (query filesystem info).
4142 ****************************************************************************/
4144 static void call_trans2qfsinfo(connection_struct *conn,
4145 struct smb_request *req,
4146 char **pparams, int total_params,
4147 char **ppdata, int total_data,
4148 unsigned int max_data_bytes)
4150 char *params = *pparams;
4151 uint16_t info_level;
4153 size_t fixed_portion;
4156 if (total_params < 2) {
4157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4161 info_level = SVAL(params,0);
4163 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4164 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4165 DEBUG(0,("call_trans2qfsinfo: encryption required "
4166 "and info level 0x%x sent.\n",
4167 (unsigned int)info_level));
4168 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4173 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4175 status = smbd_do_qfsinfo(req->xconn, conn, req,
4182 if (!NT_STATUS_IS_OK(status)) {
4183 reply_nterror(req, status);
4187 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4190 DEBUG( 4, ( "%s info_level = %d\n",
4191 smb_fn_name(req->cmd), info_level) );
4196 /****************************************************************************
4197 Reply to a TRANS2_SETFSINFO (set filesystem info).
4198 ****************************************************************************/
4200 static void call_trans2setfsinfo(connection_struct *conn,
4201 struct smb_request *req,
4202 char **pparams, int total_params,
4203 char **ppdata, int total_data,
4204 unsigned int max_data_bytes)
4206 struct smbXsrv_connection *xconn = req->xconn;
4207 char *pdata = *ppdata;
4208 char *params = *pparams;
4209 uint16_t info_level;
4211 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4212 lp_servicename(talloc_tos(), SNUM(conn))));
4215 if (total_params < 4) {
4216 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4218 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4222 info_level = SVAL(params,2);
4225 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4226 info_level != SMB_SET_CIFS_UNIX_INFO) {
4227 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4228 "info level (0x%x) on IPC$.\n",
4229 (unsigned int)info_level));
4230 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4235 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4236 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4237 DEBUG(0,("call_trans2setfsinfo: encryption required "
4238 "and info level 0x%x sent.\n",
4239 (unsigned int)info_level));
4240 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4245 switch(info_level) {
4246 case SMB_SET_CIFS_UNIX_INFO:
4247 if (!lp_unix_extensions()) {
4248 DEBUG(2,("call_trans2setfsinfo: "
4249 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4250 "unix extensions off\n"));
4252 NT_STATUS_INVALID_LEVEL);
4256 /* There should be 12 bytes of capabilities set. */
4257 if (total_data < 12) {
4260 NT_STATUS_INVALID_PARAMETER);
4263 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4264 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4265 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4266 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4267 /* Just print these values for now. */
4268 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4269 "major = %u, minor = %u cap_low = 0x%x, "
4271 (unsigned int)xconn->
4272 smb1.unix_info.client_major,
4273 (unsigned int)xconn->
4274 smb1.unix_info.client_minor,
4275 (unsigned int)xconn->
4276 smb1.unix_info.client_cap_low,
4277 (unsigned int)xconn->
4278 smb1.unix_info.client_cap_high));
4280 /* Here is where we must switch to posix pathname processing... */
4281 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4282 lp_set_posix_pathnames();
4283 mangle_change_to_posix();
4286 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4287 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4288 /* Client that knows how to do posix locks,
4289 * but not posix open/mkdir operations. Set a
4290 * default type for read/write checks. */
4292 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4297 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4300 size_t param_len = 0;
4301 size_t data_len = total_data;
4303 if (!lp_unix_extensions()) {
4306 NT_STATUS_INVALID_LEVEL);
4310 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4313 NT_STATUS_NOT_SUPPORTED);
4317 if (xconn->smb1.echo_handler.trusted_fde) {
4318 DEBUG( 2,("call_trans2setfsinfo: "
4319 "request transport encryption disabled"
4320 "with 'fork echo handler = yes'\n"));
4323 NT_STATUS_NOT_SUPPORTED);
4327 DEBUG( 4,("call_trans2setfsinfo: "
4328 "request transport encryption.\n"));
4330 status = srv_request_encryption_setup(conn,
4331 (unsigned char **)ppdata,
4333 (unsigned char **)pparams,
4336 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4337 !NT_STATUS_IS_OK(status)) {
4338 reply_nterror(req, status);
4342 send_trans2_replies(conn, req,
4350 if (NT_STATUS_IS_OK(status)) {
4351 /* Server-side transport
4352 * encryption is now *on*. */
4353 status = srv_encryption_start(conn);
4354 if (!NT_STATUS_IS_OK(status)) {
4355 char *reason = talloc_asprintf(talloc_tos(),
4356 "Failure in setting "
4357 "up encrypted transport: %s",
4359 exit_server_cleanly(reason);
4365 case SMB_FS_QUOTA_INFORMATION:
4369 .data = (uint8_t *)pdata,
4370 .length = total_data
4372 files_struct *fsp = NULL;
4373 fsp = file_fsp(req, SVAL(params,0));
4375 status = smb_set_fsquota(conn,
4379 if (!NT_STATUS_IS_OK(status)) {
4380 reply_nterror(req, status);
4386 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4388 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4394 * sending this reply works fine,
4395 * but I'm not sure it's the same
4396 * like windows do...
4399 reply_outbuf(req, 10, 0);
4402 #if defined(HAVE_POSIX_ACLS)
4403 /****************************************************************************
4404 Utility function to count the number of entries in a POSIX acl.
4405 ****************************************************************************/
4407 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4409 unsigned int ace_count = 0;
4410 int entry_id = SMB_ACL_FIRST_ENTRY;
4411 SMB_ACL_ENTRY_T entry;
4413 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4415 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4416 entry_id = SMB_ACL_NEXT_ENTRY;
4423 /****************************************************************************
4424 Utility function to marshall a POSIX acl into wire format.
4425 ****************************************************************************/
4427 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4429 int entry_id = SMB_ACL_FIRST_ENTRY;
4430 SMB_ACL_ENTRY_T entry;
4432 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4433 SMB_ACL_TAG_T tagtype;
4434 SMB_ACL_PERMSET_T permset;
4435 unsigned char perms = 0;
4436 unsigned int own_grp;
4439 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4440 entry_id = SMB_ACL_NEXT_ENTRY;
4443 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4444 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4448 if (sys_acl_get_permset(entry, &permset) == -1) {
4449 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4453 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4454 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4455 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4457 SCVAL(pdata,1,perms);
4460 case SMB_ACL_USER_OBJ:
4461 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4462 own_grp = (unsigned int)pst->st_ex_uid;
4463 SIVAL(pdata,2,own_grp);
4468 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4470 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4473 own_grp = (unsigned int)*puid;
4474 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4475 SIVAL(pdata,2,own_grp);
4479 case SMB_ACL_GROUP_OBJ:
4480 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4481 own_grp = (unsigned int)pst->st_ex_gid;
4482 SIVAL(pdata,2,own_grp);
4487 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4489 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4492 own_grp = (unsigned int)*pgid;
4493 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4494 SIVAL(pdata,2,own_grp);
4499 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4500 SIVAL(pdata,2,0xFFFFFFFF);
4501 SIVAL(pdata,6,0xFFFFFFFF);
4504 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4505 SIVAL(pdata,2,0xFFFFFFFF);
4506 SIVAL(pdata,6,0xFFFFFFFF);
4509 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4512 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4519 /****************************************************************************
4520 Store the FILE_UNIX_BASIC info.
4521 ****************************************************************************/
4523 static char *store_file_unix_basic(connection_struct *conn,
4526 const SMB_STRUCT_STAT *psbuf)
4528 uint64_t file_index = get_FileIndex(conn, psbuf);
4531 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4532 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4534 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4537 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4540 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4541 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4542 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4545 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4549 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4553 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4556 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4557 devno = psbuf->st_ex_rdev;
4559 devno = psbuf->st_ex_dev;
4562 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4566 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4570 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4573 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4577 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4584 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4585 * the chflags(2) (or equivalent) flags.
4587 * XXX: this really should be behind the VFS interface. To do this, we would
4588 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4589 * Each VFS module could then implement its own mapping as appropriate for the
4590 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4592 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4596 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4600 { UF_IMMUTABLE, EXT_IMMUTABLE },
4604 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4608 { UF_HIDDEN, EXT_HIDDEN },
4611 /* Do not remove. We need to guarantee that this array has at least one
4612 * entry to build on HP-UX.
4618 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4619 uint32_t *smb_fflags, uint32_t *smb_fmask)
4623 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4624 *smb_fmask |= info2_flags_map[i].smb_fflag;
4625 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4626 *smb_fflags |= info2_flags_map[i].smb_fflag;
4631 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4632 const uint32_t smb_fflags,
4633 const uint32_t smb_fmask,
4636 uint32_t max_fmask = 0;
4639 *stat_fflags = psbuf->st_ex_flags;
4641 /* For each flags requested in smb_fmask, check the state of the
4642 * corresponding flag in smb_fflags and set or clear the matching
4646 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4647 max_fmask |= info2_flags_map[i].smb_fflag;
4648 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4649 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4650 *stat_fflags |= info2_flags_map[i].stat_fflag;
4652 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4657 /* If smb_fmask is asking to set any bits that are not supported by
4658 * our flag mappings, we should fail.
4660 if ((smb_fmask & max_fmask) != smb_fmask) {
4668 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4669 * of file flags and birth (create) time.
4671 static char *store_file_unix_basic_info2(connection_struct *conn,
4674 const SMB_STRUCT_STAT *psbuf)
4676 uint32_t file_flags = 0;
4677 uint32_t flags_mask = 0;
4679 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4681 /* Create (birth) time 64 bit */
4682 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4685 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4686 SIVAL(pdata, 0, file_flags); /* flags */
4687 SIVAL(pdata, 4, flags_mask); /* mask */
4693 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4694 const struct stream_struct *streams,
4696 unsigned int max_data_bytes,
4697 unsigned int *data_size)
4700 unsigned int ofs = 0;
4702 if (max_data_bytes < 32) {
4703 return NT_STATUS_INFO_LENGTH_MISMATCH;
4706 for (i = 0; i < num_streams; i++) {
4707 unsigned int next_offset;
4709 smb_ucs2_t *namebuf;
4711 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4712 streams[i].name, &namelen) ||
4715 return NT_STATUS_INVALID_PARAMETER;
4719 * name_buf is now null-terminated, we need to marshall as not
4726 * We cannot overflow ...
4728 if ((ofs + 24 + namelen) > max_data_bytes) {
4729 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4731 TALLOC_FREE(namebuf);
4732 return STATUS_BUFFER_OVERFLOW;
4735 SIVAL(data, ofs+4, namelen);
4736 SOFF_T(data, ofs+8, streams[i].size);
4737 SOFF_T(data, ofs+16, streams[i].alloc_size);
4738 memcpy(data+ofs+24, namebuf, namelen);
4739 TALLOC_FREE(namebuf);
4741 next_offset = ofs + 24 + namelen;
4743 if (i == num_streams-1) {
4744 SIVAL(data, ofs, 0);
4747 unsigned int align = ndr_align_size(next_offset, 8);
4749 if ((next_offset + align) > max_data_bytes) {
4750 DEBUG(10, ("refusing to overflow align "
4751 "reply at stream %u\n",
4753 TALLOC_FREE(namebuf);
4754 return STATUS_BUFFER_OVERFLOW;
4757 memset(data+next_offset, 0, align);
4758 next_offset += align;
4760 SIVAL(data, ofs, next_offset - ofs);
4767 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4771 return NT_STATUS_OK;
4774 /****************************************************************************
4775 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4776 ****************************************************************************/
4778 static void call_trans2qpipeinfo(connection_struct *conn,
4779 struct smb_request *req,
4780 unsigned int tran_call,
4781 char **pparams, int total_params,
4782 char **ppdata, int total_data,
4783 unsigned int max_data_bytes)
4785 char *params = *pparams;
4786 char *pdata = *ppdata;
4787 unsigned int data_size = 0;
4788 unsigned int param_size = 2;
4789 uint16_t info_level;
4793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4797 if (total_params < 4) {
4798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4802 fsp = file_fsp(req, SVAL(params,0));
4803 if (!fsp_is_np(fsp)) {
4804 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4808 info_level = SVAL(params,2);
4810 *pparams = (char *)SMB_REALLOC(*pparams,2);
4811 if (*pparams == NULL) {
4812 reply_nterror(req, NT_STATUS_NO_MEMORY);
4817 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4821 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4822 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4823 if (*ppdata == NULL ) {
4824 reply_nterror(req, NT_STATUS_NO_MEMORY);
4829 switch (info_level) {
4830 case SMB_FILE_STANDARD_INFORMATION:
4832 SOFF_T(pdata,0,4096LL);
4839 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4843 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4849 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4850 TALLOC_CTX *mem_ctx,
4851 uint16_t info_level,
4853 struct smb_filename *smb_fname,
4854 bool delete_pending,
4855 struct timespec write_time_ts,
4856 struct ea_list *ea_list,
4857 int lock_data_count,
4860 unsigned int max_data_bytes,
4861 size_t *fixed_portion,
4863 unsigned int *pdata_size)
4865 char *pdata = *ppdata;
4866 char *dstart, *dend;
4867 unsigned int data_size;
4868 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4869 time_t create_time, mtime, atime, c_time;
4870 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4877 uint64_t file_size = 0;
4879 uint64_t allocation_size = 0;
4880 uint64_t file_index = 0;
4881 uint32_t access_mask = 0;
4884 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4885 return NT_STATUS_INVALID_LEVEL;
4888 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4889 smb_fname_str_dbg(smb_fname),
4891 info_level, max_data_bytes));
4893 mode = dos_mode(conn, smb_fname);
4894 nlink = psbuf->st_ex_nlink;
4896 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4900 if ((nlink > 0) && delete_pending) {
4904 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4905 return NT_STATUS_INVALID_PARAMETER;
4908 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4909 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4910 if (*ppdata == NULL) {
4911 return NT_STATUS_NO_MEMORY;
4915 dend = dstart + data_size - 1;
4917 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4918 update_stat_ex_mtime(psbuf, write_time_ts);
4921 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4922 mtime_ts = psbuf->st_ex_mtime;
4923 atime_ts = psbuf->st_ex_atime;
4924 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4926 if (lp_dos_filetime_resolution(SNUM(conn))) {
4927 dos_filetime_timespec(&create_time_ts);
4928 dos_filetime_timespec(&mtime_ts);
4929 dos_filetime_timespec(&atime_ts);
4930 dos_filetime_timespec(&ctime_ts);
4933 create_time = convert_timespec_to_time_t(create_time_ts);
4934 mtime = convert_timespec_to_time_t(mtime_ts);
4935 atime = convert_timespec_to_time_t(atime_ts);
4936 c_time = convert_timespec_to_time_t(ctime_ts);
4938 p = strrchr_m(smb_fname->base_name,'/');
4940 base_name = smb_fname->base_name;
4944 /* NT expects the name to be in an exact form of the *full*
4945 filename. See the trans2 torture test */
4946 if (ISDOT(base_name)) {
4947 dos_fname = talloc_strdup(mem_ctx, "\\");
4949 return NT_STATUS_NO_MEMORY;
4952 dos_fname = talloc_asprintf(mem_ctx,
4954 smb_fname->base_name);
4956 return NT_STATUS_NO_MEMORY;
4958 if (is_ntfs_stream_smb_fname(smb_fname)) {
4959 dos_fname = talloc_asprintf(dos_fname, "%s",
4960 smb_fname->stream_name);
4962 return NT_STATUS_NO_MEMORY;
4966 string_replace(dos_fname, '/', '\\');
4969 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4972 /* Do we have this path open ? */
4974 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4975 fsp1 = file_find_di_first(conn->sconn, fileid);
4976 if (fsp1 && fsp1->initial_allocation_size) {
4977 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4981 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4982 file_size = get_file_size_stat(psbuf);
4986 pos = fsp->fh->position_information;
4990 access_mask = fsp->access_mask;
4992 /* GENERIC_EXECUTE mapping from Windows */
4993 access_mask = 0x12019F;
4996 /* This should be an index number - looks like
4999 I think this causes us to fail the IFSKIT
5000 BasicFileInformationTest. -tpot */
5001 file_index = get_FileIndex(conn, psbuf);
5005 switch (info_level) {
5006 case SMB_INFO_STANDARD:
5007 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5009 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5010 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5011 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5012 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5013 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5014 SSVAL(pdata,l1_attrFile,mode);
5017 case SMB_INFO_QUERY_EA_SIZE:
5019 unsigned int ea_size =
5020 estimate_ea_size(conn, fsp,
5022 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5024 srv_put_dos_date2(pdata,0,create_time);
5025 srv_put_dos_date2(pdata,4,atime);
5026 srv_put_dos_date2(pdata,8,mtime); /* write time */
5027 SIVAL(pdata,12,(uint32_t)file_size);
5028 SIVAL(pdata,16,(uint32_t)allocation_size);
5029 SSVAL(pdata,20,mode);
5030 SIVAL(pdata,22,ea_size);
5034 case SMB_INFO_IS_NAME_VALID:
5035 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5037 /* os/2 needs this ? really ?*/
5038 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5040 /* This is only reached for qpathinfo */
5044 case SMB_INFO_QUERY_EAS_FROM_LIST:
5046 size_t total_ea_len = 0;
5047 struct ea_list *ea_file_list = NULL;
5048 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5051 get_ea_list_from_file(mem_ctx, conn, fsp,
5053 &total_ea_len, &ea_file_list);
5054 if (!NT_STATUS_IS_OK(status)) {
5058 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5060 if (!ea_list || (total_ea_len > data_size)) {
5062 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5066 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5070 case SMB_INFO_QUERY_ALL_EAS:
5072 /* We have data_size bytes to put EA's into. */
5073 size_t total_ea_len = 0;
5074 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5076 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5078 &total_ea_len, &ea_list);
5079 if (!NT_STATUS_IS_OK(status)) {
5083 if (!ea_list || (total_ea_len > data_size)) {
5085 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5089 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5093 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5095 /* This is FileFullEaInformation - 0xF which maps to
5096 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5098 /* We have data_size bytes to put EA's into. */
5099 size_t total_ea_len = 0;
5100 struct ea_list *ea_file_list = NULL;
5102 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5104 /*TODO: add filtering and index handling */
5107 get_ea_list_from_file(mem_ctx, conn, fsp,
5109 &total_ea_len, &ea_file_list);
5110 if (!NT_STATUS_IS_OK(status)) {
5113 if (!ea_file_list) {
5114 return NT_STATUS_NO_EAS_ON_FILE;
5117 status = fill_ea_chained_buffer(mem_ctx,
5121 conn, ea_file_list);
5122 if (!NT_STATUS_IS_OK(status)) {
5128 case SMB_FILE_BASIC_INFORMATION:
5129 case SMB_QUERY_FILE_BASIC_INFO:
5131 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5132 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5133 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5135 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5139 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5140 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5141 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5142 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5143 SIVAL(pdata,32,mode);
5145 DEBUG(5,("SMB_QFBI - "));
5146 DEBUG(5,("create: %s ", ctime(&create_time)));
5147 DEBUG(5,("access: %s ", ctime(&atime)));
5148 DEBUG(5,("write: %s ", ctime(&mtime)));
5149 DEBUG(5,("change: %s ", ctime(&c_time)));
5150 DEBUG(5,("mode: %x\n", mode));
5151 *fixed_portion = data_size;
5154 case SMB_FILE_STANDARD_INFORMATION:
5155 case SMB_QUERY_FILE_STANDARD_INFO:
5157 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5159 SOFF_T(pdata,0,allocation_size);
5160 SOFF_T(pdata,8,file_size);
5161 SIVAL(pdata,16,nlink);
5162 SCVAL(pdata,20,delete_pending?1:0);
5163 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5164 SSVAL(pdata,22,0); /* Padding. */
5165 *fixed_portion = 24;
5168 case SMB_FILE_EA_INFORMATION:
5169 case SMB_QUERY_FILE_EA_INFO:
5171 unsigned int ea_size =
5172 estimate_ea_size(conn, fsp, smb_fname);
5173 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5176 SIVAL(pdata,0,ea_size);
5180 /* Get the 8.3 name - used if NT SMB was negotiated. */
5181 case SMB_QUERY_FILE_ALT_NAME_INFO:
5182 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5184 char mangled_name[13];
5185 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5186 if (!name_to_8_3(base_name,mangled_name,
5187 True,conn->params)) {
5188 return NT_STATUS_NO_MEMORY;
5190 status = srvstr_push(dstart, flags2,
5191 pdata+4, mangled_name,
5192 PTR_DIFF(dend, pdata+4),
5194 if (!NT_STATUS_IS_OK(status)) {
5197 data_size = 4 + len;
5203 case SMB_QUERY_FILE_NAME_INFO:
5206 this must be *exactly* right for ACLs on mapped drives to work
5208 status = srvstr_push(dstart, flags2,
5210 PTR_DIFF(dend, pdata+4),
5212 if (!NT_STATUS_IS_OK(status)) {
5215 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5216 data_size = 4 + len;
5221 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5223 char *nfname = NULL;
5225 if (!fsp->conn->sconn->using_smb2) {
5226 return NT_STATUS_INVALID_LEVEL;
5229 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5230 if (nfname == NULL) {
5231 return NT_STATUS_NO_MEMORY;
5234 if (ISDOT(nfname)) {
5237 string_replace(nfname, '/', '\\');
5239 if (smb_fname->stream_name != NULL) {
5240 const char *s = smb_fname->stream_name;
5241 const char *e = NULL;
5244 SMB_ASSERT(s[0] != '\0');
5247 * smb_fname->stream_name is in form
5248 * of ':StrEam:$DATA', but we should only
5249 * append ':StrEam' here.
5252 e = strchr(&s[1], ':');
5258 nfname = talloc_strndup_append(nfname, s, n);
5259 if (nfname == NULL) {
5260 return NT_STATUS_NO_MEMORY;
5264 status = srvstr_push(dstart, flags2,
5266 PTR_DIFF(dend, pdata+4),
5268 if (!NT_STATUS_IS_OK(status)) {
5271 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5272 data_size = 4 + len;
5278 case SMB_FILE_ALLOCATION_INFORMATION:
5279 case SMB_QUERY_FILE_ALLOCATION_INFO:
5280 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5282 SOFF_T(pdata,0,allocation_size);
5285 case SMB_FILE_END_OF_FILE_INFORMATION:
5286 case SMB_QUERY_FILE_END_OF_FILEINFO:
5287 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5289 SOFF_T(pdata,0,file_size);
5292 case SMB_QUERY_FILE_ALL_INFO:
5293 case SMB_FILE_ALL_INFORMATION:
5295 unsigned int ea_size =
5296 estimate_ea_size(conn, fsp, smb_fname);
5297 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5298 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5299 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5300 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5301 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5302 SIVAL(pdata,32,mode);
5303 SIVAL(pdata,36,0); /* padding. */
5305 SOFF_T(pdata,0,allocation_size);
5306 SOFF_T(pdata,8,file_size);
5307 SIVAL(pdata,16,nlink);
5308 SCVAL(pdata,20,delete_pending);
5309 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5312 SIVAL(pdata,0,ea_size);
5313 pdata += 4; /* EA info */
5314 status = srvstr_push(dstart, flags2,
5316 PTR_DIFF(dend, pdata+4),
5318 if (!NT_STATUS_IS_OK(status)) {
5323 data_size = PTR_DIFF(pdata,(*ppdata));
5324 *fixed_portion = 10;
5328 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5330 unsigned int ea_size =
5331 estimate_ea_size(conn, fsp, smb_fname);
5332 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5333 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5334 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5335 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5336 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5337 SIVAL(pdata, 0x20, mode);
5338 SIVAL(pdata, 0x24, 0); /* padding. */
5339 SBVAL(pdata, 0x28, allocation_size);
5340 SBVAL(pdata, 0x30, file_size);
5341 SIVAL(pdata, 0x38, nlink);
5342 SCVAL(pdata, 0x3C, delete_pending);
5343 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5344 SSVAL(pdata, 0x3E, 0); /* padding */
5345 SBVAL(pdata, 0x40, file_index);
5346 SIVAL(pdata, 0x48, ea_size);
5347 SIVAL(pdata, 0x4C, access_mask);
5348 SBVAL(pdata, 0x50, pos);
5349 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5350 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5354 status = srvstr_push(dstart, flags2,
5356 PTR_DIFF(dend, pdata+4),
5358 if (!NT_STATUS_IS_OK(status)) {
5363 data_size = PTR_DIFF(pdata,(*ppdata));
5364 *fixed_portion = 104;
5367 case SMB_FILE_INTERNAL_INFORMATION:
5369 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5370 SBVAL(pdata, 0, file_index);
5375 case SMB_FILE_ACCESS_INFORMATION:
5376 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5377 SIVAL(pdata, 0, access_mask);
5382 case SMB_FILE_NAME_INFORMATION:
5383 /* Pathname with leading '\'. */
5386 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5387 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5388 SIVAL(pdata,0,byte_len);
5389 data_size = 4 + byte_len;
5393 case SMB_FILE_DISPOSITION_INFORMATION:
5394 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5396 SCVAL(pdata,0,delete_pending);
5400 case SMB_FILE_POSITION_INFORMATION:
5401 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5403 SOFF_T(pdata,0,pos);
5407 case SMB_FILE_MODE_INFORMATION:
5408 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5409 SIVAL(pdata,0,mode);
5414 case SMB_FILE_ALIGNMENT_INFORMATION:
5415 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5416 SIVAL(pdata,0,0); /* No alignment needed. */
5422 * NT4 server just returns "invalid query" to this - if we try
5423 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5426 /* The first statement above is false - verified using Thursby
5427 * client against NT4 -- gcolley.
5429 case SMB_QUERY_FILE_STREAM_INFO:
5430 case SMB_FILE_STREAM_INFORMATION: {
5431 unsigned int num_streams = 0;
5432 struct stream_struct *streams = NULL;
5434 DEBUG(10,("smbd_do_qfilepathinfo: "
5435 "SMB_FILE_STREAM_INFORMATION\n"));
5437 if (is_ntfs_stream_smb_fname(smb_fname)) {
5438 return NT_STATUS_INVALID_PARAMETER;
5441 status = vfs_streaminfo(conn,
5448 if (!NT_STATUS_IS_OK(status)) {
5449 DEBUG(10, ("could not get stream info: %s\n",
5450 nt_errstr(status)));
5454 status = marshall_stream_info(num_streams, streams,
5455 pdata, max_data_bytes,
5458 if (!NT_STATUS_IS_OK(status)) {
5459 DEBUG(10, ("marshall_stream_info failed: %s\n",
5460 nt_errstr(status)));
5461 TALLOC_FREE(streams);
5465 TALLOC_FREE(streams);
5467 *fixed_portion = 32;
5471 case SMB_QUERY_COMPRESSION_INFO:
5472 case SMB_FILE_COMPRESSION_INFORMATION:
5473 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5474 SOFF_T(pdata,0,file_size);
5475 SIVAL(pdata,8,0); /* ??? */
5476 SIVAL(pdata,12,0); /* ??? */
5478 *fixed_portion = 16;
5481 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5482 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5483 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5484 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5485 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5486 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5487 SOFF_T(pdata,32,allocation_size);
5488 SOFF_T(pdata,40,file_size);
5489 SIVAL(pdata,48,mode);
5490 SIVAL(pdata,52,0); /* ??? */
5492 *fixed_portion = 56;
5495 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5496 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5497 SIVAL(pdata,0,mode);
5504 * CIFS UNIX Extensions.
5507 case SMB_QUERY_FILE_UNIX_BASIC:
5509 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5510 data_size = PTR_DIFF(pdata,(*ppdata));
5512 DEBUG(4,("smbd_do_qfilepathinfo: "
5513 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5514 dump_data(4, (uint8_t *)(*ppdata), data_size);
5518 case SMB_QUERY_FILE_UNIX_INFO2:
5520 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5521 data_size = PTR_DIFF(pdata,(*ppdata));
5525 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5527 for (i=0; i<100; i++)
5528 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5534 case SMB_QUERY_FILE_UNIX_LINK:
5537 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5540 return NT_STATUS_NO_MEMORY;
5543 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5545 if(!S_ISLNK(psbuf->st_ex_mode)) {
5546 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5549 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5551 link_len = SMB_VFS_READLINK(conn,
5554 if (link_len == -1) {
5555 return map_nt_error_from_unix(errno);
5557 buffer[link_len] = 0;
5558 status = srvstr_push(dstart, flags2,
5560 PTR_DIFF(dend, pdata),
5561 STR_TERMINATE, &len);
5562 if (!NT_STATUS_IS_OK(status)) {
5566 data_size = PTR_DIFF(pdata,(*ppdata));
5571 #if defined(HAVE_POSIX_ACLS)
5572 case SMB_QUERY_POSIX_ACL:
5574 SMB_ACL_T file_acl = NULL;
5575 SMB_ACL_T def_acl = NULL;
5576 uint16_t num_file_acls = 0;
5577 uint16_t num_def_acls = 0;
5579 status = refuse_symlink(conn,
5582 if (!NT_STATUS_IS_OK(status)) {
5586 if (fsp && fsp->fh->fd != -1) {
5587 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5591 SMB_VFS_SYS_ACL_GET_FILE(conn,
5593 SMB_ACL_TYPE_ACCESS,
5597 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5598 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5599 "not implemented on "
5600 "filesystem containing %s\n",
5601 smb_fname->base_name));
5602 return NT_STATUS_NOT_IMPLEMENTED;
5605 if (S_ISDIR(psbuf->st_ex_mode)) {
5606 if (fsp && fsp->is_directory) {
5608 SMB_VFS_SYS_ACL_GET_FILE(
5611 SMB_ACL_TYPE_DEFAULT,
5615 SMB_VFS_SYS_ACL_GET_FILE(
5618 SMB_ACL_TYPE_DEFAULT,
5621 def_acl = free_empty_sys_acl(conn, def_acl);
5624 num_file_acls = count_acl_entries(conn, file_acl);
5625 num_def_acls = count_acl_entries(conn, def_acl);
5627 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5628 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5630 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5631 SMB_POSIX_ACL_HEADER_SIZE) ));
5633 TALLOC_FREE(file_acl);
5636 TALLOC_FREE(def_acl);
5638 return NT_STATUS_BUFFER_TOO_SMALL;
5641 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5642 SSVAL(pdata,2,num_file_acls);
5643 SSVAL(pdata,4,num_def_acls);
5644 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5646 TALLOC_FREE(file_acl);
5649 TALLOC_FREE(def_acl);
5651 return NT_STATUS_INTERNAL_ERROR;
5653 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5655 TALLOC_FREE(file_acl);
5658 TALLOC_FREE(def_acl);
5660 return NT_STATUS_INTERNAL_ERROR;
5664 TALLOC_FREE(file_acl);
5667 TALLOC_FREE(def_acl);
5669 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5675 case SMB_QUERY_POSIX_LOCK:
5680 enum brl_type lock_type;
5682 /* We need an open file with a real fd for this. */
5683 if (!fsp || fsp->fh->fd == -1) {
5684 return NT_STATUS_INVALID_LEVEL;
5687 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5688 return NT_STATUS_INVALID_PARAMETER;
5691 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5692 case POSIX_LOCK_TYPE_READ:
5693 lock_type = READ_LOCK;
5695 case POSIX_LOCK_TYPE_WRITE:
5696 lock_type = WRITE_LOCK;
5698 case POSIX_LOCK_TYPE_UNLOCK:
5700 /* There's no point in asking for an unlock... */
5701 return NT_STATUS_INVALID_PARAMETER;
5704 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5705 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5706 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5708 status = query_lock(fsp,
5715 if (ERROR_WAS_LOCK_DENIED(status)) {
5716 /* Here we need to report who has it locked... */
5717 data_size = POSIX_LOCK_DATA_SIZE;
5719 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5720 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5721 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5722 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5723 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5725 } else if (NT_STATUS_IS_OK(status)) {
5726 /* For success we just return a copy of what we sent
5727 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5728 data_size = POSIX_LOCK_DATA_SIZE;
5729 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5730 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5738 return NT_STATUS_INVALID_LEVEL;
5741 *pdata_size = data_size;
5742 return NT_STATUS_OK;
5745 /****************************************************************************
5746 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5747 file name or file id).
5748 ****************************************************************************/
5750 static void call_trans2qfilepathinfo(connection_struct *conn,
5751 struct smb_request *req,
5752 unsigned int tran_call,
5753 char **pparams, int total_params,
5754 char **ppdata, int total_data,
5755 unsigned int max_data_bytes)
5757 char *params = *pparams;
5758 char *pdata = *ppdata;
5759 uint16_t info_level;
5760 unsigned int data_size = 0;
5761 unsigned int param_size = 2;
5762 struct smb_filename *smb_fname = NULL;
5763 bool delete_pending = False;
5764 struct timespec write_time_ts;
5765 files_struct *fsp = NULL;
5766 struct file_id fileid;
5767 struct ea_list *ea_list = NULL;
5768 int lock_data_count = 0;
5769 char *lock_data = NULL;
5770 size_t fixed_portion;
5771 NTSTATUS status = NT_STATUS_OK;
5774 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5778 ZERO_STRUCT(write_time_ts);
5780 if (tran_call == TRANSACT2_QFILEINFO) {
5781 if (total_params < 4) {
5782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5787 call_trans2qpipeinfo(conn, req, tran_call,
5788 pparams, total_params,
5794 fsp = file_fsp(req, SVAL(params,0));
5795 info_level = SVAL(params,2);
5797 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5799 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5800 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5804 /* Initial check for valid fsp ptr. */
5805 if (!check_fsp_open(conn, req, fsp)) {
5809 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5810 if (smb_fname == NULL) {
5811 reply_nterror(req, NT_STATUS_NO_MEMORY);
5815 if(fsp->fake_file_handle) {
5817 * This is actually for the QUOTA_FAKE_FILE --metze
5820 /* We know this name is ok, it's already passed the checks. */
5822 } else if(fsp->fh->fd == -1) {
5824 * This is actually a QFILEINFO on a directory
5825 * handle (returned from an NT SMB). NT5.0 seems
5826 * to do this call. JRA.
5829 if (INFO_LEVEL_IS_UNIX(info_level)) {
5830 /* Always do lstat for UNIX calls. */
5831 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5832 DEBUG(3,("call_trans2qfilepathinfo: "
5833 "SMB_VFS_LSTAT of %s failed "
5835 smb_fname_str_dbg(smb_fname),
5838 map_nt_error_from_unix(errno));
5841 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5842 DEBUG(3,("call_trans2qfilepathinfo: "
5843 "SMB_VFS_STAT of %s failed (%s)\n",
5844 smb_fname_str_dbg(smb_fname),
5847 map_nt_error_from_unix(errno));
5851 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5852 fileid = vfs_file_id_from_sbuf(
5853 conn, &smb_fname->st);
5854 get_file_infos(fileid, fsp->name_hash,
5860 * Original code - this is an open file.
5862 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5863 DEBUG(3, ("fstat of %s failed (%s)\n",
5864 fsp_fnum_dbg(fsp), strerror(errno)));
5866 map_nt_error_from_unix(errno));
5869 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5870 fileid = vfs_file_id_from_sbuf(
5871 conn, &smb_fname->st);
5872 get_file_infos(fileid, fsp->name_hash,
5881 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5884 if (total_params < 7) {
5885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5889 info_level = SVAL(params,0);
5891 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5893 if (INFO_LEVEL_IS_UNIX(info_level)) {
5894 if (!lp_unix_extensions()) {
5895 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5898 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5899 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5900 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5901 req->posix_pathnames) {
5902 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5906 if (req->posix_pathnames) {
5907 srvstr_get_path_posix(req,
5916 srvstr_get_path(req,
5925 if (!NT_STATUS_IS_OK(status)) {
5926 reply_nterror(req, status);
5930 status = filename_convert(req,
5937 if (!NT_STATUS_IS_OK(status)) {
5938 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5939 reply_botherror(req,
5940 NT_STATUS_PATH_NOT_COVERED,
5941 ERRSRV, ERRbadpath);
5944 reply_nterror(req, status);
5948 /* If this is a stream, check if there is a delete_pending. */
5949 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5950 && is_ntfs_stream_smb_fname(smb_fname)) {
5951 struct smb_filename *smb_fname_base;
5953 /* Create an smb_filename with stream_name == NULL. */
5954 smb_fname_base = synthetic_smb_fname(
5956 smb_fname->base_name,
5960 if (smb_fname_base == NULL) {
5961 reply_nterror(req, NT_STATUS_NO_MEMORY);
5965 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5966 /* Always do lstat for UNIX calls. */
5967 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5968 DEBUG(3,("call_trans2qfilepathinfo: "
5969 "SMB_VFS_LSTAT of %s failed "
5971 smb_fname_str_dbg(smb_fname_base),
5973 TALLOC_FREE(smb_fname_base);
5975 map_nt_error_from_unix(errno));
5979 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5980 DEBUG(3,("call_trans2qfilepathinfo: "
5981 "fileinfo of %s failed "
5983 smb_fname_str_dbg(smb_fname_base),
5985 TALLOC_FREE(smb_fname_base);
5987 map_nt_error_from_unix(errno));
5992 status = file_name_hash(conn,
5993 smb_fname_str_dbg(smb_fname_base),
5995 if (!NT_STATUS_IS_OK(status)) {
5996 TALLOC_FREE(smb_fname_base);
5997 reply_nterror(req, status);
6001 fileid = vfs_file_id_from_sbuf(conn,
6002 &smb_fname_base->st);
6003 TALLOC_FREE(smb_fname_base);
6004 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6005 if (delete_pending) {
6006 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6011 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6012 /* Always do lstat for UNIX calls. */
6013 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6014 DEBUG(3,("call_trans2qfilepathinfo: "
6015 "SMB_VFS_LSTAT of %s failed (%s)\n",
6016 smb_fname_str_dbg(smb_fname),
6019 map_nt_error_from_unix(errno));
6024 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6025 DEBUG(3,("call_trans2qfilepathinfo: "
6026 "SMB_VFS_STAT of %s failed (%s)\n",
6027 smb_fname_str_dbg(smb_fname),
6030 map_nt_error_from_unix(errno));
6035 status = file_name_hash(conn,
6036 smb_fname_str_dbg(smb_fname),
6038 if (!NT_STATUS_IS_OK(status)) {
6039 reply_nterror(req, status);
6043 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6044 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6045 get_file_infos(fileid, name_hash, &delete_pending,
6049 if (delete_pending) {
6050 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6055 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6056 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6058 info_level,tran_call,total_data));
6060 /* Pull out any data sent here before we realloc. */
6061 switch (info_level) {
6062 case SMB_INFO_QUERY_EAS_FROM_LIST:
6064 /* Pull any EA list from the data portion. */
6067 if (total_data < 4) {
6069 req, NT_STATUS_INVALID_PARAMETER);
6072 ea_size = IVAL(pdata,0);
6074 if (total_data > 0 && ea_size != total_data) {
6075 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6076 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6078 req, NT_STATUS_INVALID_PARAMETER);
6082 if (!lp_ea_support(SNUM(conn))) {
6083 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6087 /* Pull out the list of names. */
6088 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6091 req, NT_STATUS_INVALID_PARAMETER);
6097 case SMB_QUERY_POSIX_LOCK:
6099 if (fsp == NULL || fsp->fh->fd == -1) {
6100 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6104 if (total_data != POSIX_LOCK_DATA_SIZE) {
6106 req, NT_STATUS_INVALID_PARAMETER);
6110 /* Copy the lock range data. */
6111 lock_data = (char *)talloc_memdup(
6112 req, pdata, total_data);
6114 reply_nterror(req, NT_STATUS_NO_MEMORY);
6117 lock_data_count = total_data;
6123 *pparams = (char *)SMB_REALLOC(*pparams,2);
6124 if (*pparams == NULL) {
6125 reply_nterror(req, NT_STATUS_NO_MEMORY);
6132 * draft-leach-cifs-v1-spec-02.txt
6133 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6136 * The requested information is placed in the Data portion of the
6137 * transaction response. For the information levels greater than 0x100,
6138 * the transaction response has 1 parameter word which should be
6139 * ignored by the client.
6141 * However Windows only follows this rule for the IS_NAME_VALID call.
6143 switch (info_level) {
6144 case SMB_INFO_IS_NAME_VALID:
6149 if ((info_level & 0xFF00) == 0xFF00) {
6151 * We use levels that start with 0xFF00
6152 * internally to represent SMB2 specific levels
6154 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6158 status = smbd_do_qfilepathinfo(conn, req, info_level,
6160 delete_pending, write_time_ts,
6162 lock_data_count, lock_data,
6163 req->flags2, max_data_bytes,
6165 ppdata, &data_size);
6166 if (!NT_STATUS_IS_OK(status)) {
6167 reply_nterror(req, status);
6170 if (fixed_portion > max_data_bytes) {
6171 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6175 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6181 /****************************************************************************
6182 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6184 ****************************************************************************/
6186 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6187 connection_struct *conn,
6188 struct smb_request *req,
6189 bool overwrite_if_exists,
6190 const struct smb_filename *smb_fname_old,
6191 struct smb_filename *smb_fname_new)
6193 NTSTATUS status = NT_STATUS_OK;
6196 /* source must already exist. */
6197 if (!VALID_STAT(smb_fname_old->st)) {
6198 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6201 if (VALID_STAT(smb_fname_new->st)) {
6202 if (overwrite_if_exists) {
6203 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6204 return NT_STATUS_FILE_IS_A_DIRECTORY;
6206 status = unlink_internals(conn,
6208 FILE_ATTRIBUTE_NORMAL,
6211 if (!NT_STATUS_IS_OK(status)) {
6215 /* Disallow if newname already exists. */
6216 return NT_STATUS_OBJECT_NAME_COLLISION;
6220 /* No links from a directory. */
6221 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6222 return NT_STATUS_FILE_IS_A_DIRECTORY;
6225 /* Setting a hardlink to/from a stream isn't currently supported. */
6226 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6228 DBG_DEBUG("Old name has streams\n");
6229 return NT_STATUS_INVALID_PARAMETER;
6231 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6233 DBG_DEBUG("New name has streams\n");
6234 return NT_STATUS_INVALID_PARAMETER;
6237 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6238 smb_fname_old->base_name, smb_fname_new->base_name));
6240 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6241 status = map_nt_error_from_unix(errno);
6242 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6243 nt_errstr(status), smb_fname_old->base_name,
6244 smb_fname_new->base_name));
6249 /****************************************************************************
6250 Deal with setting the time from any of the setfilepathinfo functions.
6251 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6252 calling this function.
6253 ****************************************************************************/
6255 NTSTATUS smb_set_file_time(connection_struct *conn,
6257 const struct smb_filename *smb_fname,
6258 struct smb_file_time *ft,
6259 bool setting_write_time)
6261 struct smb_filename smb_fname_base;
6263 FILE_NOTIFY_CHANGE_LAST_ACCESS
6264 |FILE_NOTIFY_CHANGE_LAST_WRITE
6265 |FILE_NOTIFY_CHANGE_CREATION;
6267 if (!VALID_STAT(smb_fname->st)) {
6268 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6271 /* get some defaults (no modifications) if any info is zero or -1. */
6272 if (null_timespec(ft->create_time)) {
6273 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6276 if (null_timespec(ft->atime)) {
6277 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6280 if (null_timespec(ft->mtime)) {
6281 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6284 if (!setting_write_time) {
6285 /* ft->mtime comes from change time, not write time. */
6286 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6289 /* Ensure the resolution is the correct for
6290 * what we can store on this filesystem. */
6292 round_timespec(conn->ts_res, &ft->create_time);
6293 round_timespec(conn->ts_res, &ft->ctime);
6294 round_timespec(conn->ts_res, &ft->atime);
6295 round_timespec(conn->ts_res, &ft->mtime);
6297 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6298 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6299 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6300 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6301 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6302 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6303 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6304 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6306 if (setting_write_time) {
6308 * This was a Windows setfileinfo on an open file.
6309 * NT does this a lot. We also need to
6310 * set the time here, as it can be read by
6311 * FindFirst/FindNext and with the patch for bug #2045
6312 * in smbd/fileio.c it ensures that this timestamp is
6313 * kept sticky even after a write. We save the request
6314 * away and will set it on file close and after a write. JRA.
6317 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6318 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6321 if (fsp->base_fsp) {
6322 set_sticky_write_time_fsp(fsp->base_fsp,
6325 set_sticky_write_time_fsp(fsp, ft->mtime);
6328 set_sticky_write_time_path(
6329 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6334 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6336 /* Always call ntimes on the base, even if a stream was passed in. */
6337 smb_fname_base = *smb_fname;
6338 smb_fname_base.stream_name = NULL;
6340 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6341 return map_nt_error_from_unix(errno);
6344 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6345 smb_fname->base_name);
6346 return NT_STATUS_OK;
6349 /****************************************************************************
6350 Deal with setting the dosmode from any of the setfilepathinfo functions.
6351 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6352 done before calling this function.
6353 ****************************************************************************/
6355 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6356 const struct smb_filename *smb_fname,
6359 struct smb_filename *smb_fname_base;
6362 if (!VALID_STAT(smb_fname->st)) {
6363 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6366 /* Always operate on the base_name, even if a stream was passed in. */
6367 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6368 smb_fname->base_name,
6372 if (smb_fname_base == NULL) {
6373 return NT_STATUS_NO_MEMORY;
6377 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6378 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6380 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6384 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6386 /* check the mode isn't different, before changing it */
6387 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6388 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6389 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6390 (unsigned int)dosmode));
6392 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6394 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6396 smb_fname_str_dbg(smb_fname_base),
6398 status = map_nt_error_from_unix(errno);
6402 status = NT_STATUS_OK;
6404 TALLOC_FREE(smb_fname_base);
6408 /****************************************************************************
6409 Deal with setting the size from any of the setfilepathinfo functions.
6410 ****************************************************************************/
6412 static NTSTATUS smb_set_file_size(connection_struct *conn,
6413 struct smb_request *req,
6415 const struct smb_filename *smb_fname,
6416 const SMB_STRUCT_STAT *psbuf,
6418 bool fail_after_createfile)
6420 NTSTATUS status = NT_STATUS_OK;
6421 struct smb_filename *smb_fname_tmp = NULL;
6422 files_struct *new_fsp = NULL;
6424 if (!VALID_STAT(*psbuf)) {
6425 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6428 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6430 get_file_size_stat(psbuf));
6432 if (size == get_file_size_stat(psbuf)) {
6433 return NT_STATUS_OK;
6436 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6437 smb_fname_str_dbg(smb_fname), (double)size));
6439 if (fsp && fsp->fh->fd != -1) {
6440 /* Handle based call. */
6441 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6442 return NT_STATUS_ACCESS_DENIED;
6445 if (vfs_set_filelen(fsp, size) == -1) {
6446 return map_nt_error_from_unix(errno);
6448 trigger_write_time_update_immediate(fsp);
6449 return NT_STATUS_OK;
6452 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6453 if (smb_fname_tmp == NULL) {
6454 return NT_STATUS_NO_MEMORY;
6457 smb_fname_tmp->st = *psbuf;
6459 status = SMB_VFS_CREATE_FILE(
6462 0, /* root_dir_fid */
6463 smb_fname_tmp, /* fname */
6464 FILE_WRITE_DATA, /* access_mask */
6465 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6467 FILE_OPEN, /* create_disposition*/
6468 0, /* create_options */
6469 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6470 0, /* oplock_request */
6472 0, /* allocation_size */
6473 0, /* private_flags */
6476 &new_fsp, /* result */
6478 NULL, NULL); /* create context */
6480 TALLOC_FREE(smb_fname_tmp);
6482 if (!NT_STATUS_IS_OK(status)) {
6483 /* NB. We check for open_was_deferred in the caller. */
6487 /* See RAW-SFILEINFO-END-OF-FILE */
6488 if (fail_after_createfile) {
6489 close_file(req, new_fsp,NORMAL_CLOSE);
6490 return NT_STATUS_INVALID_LEVEL;
6493 if (vfs_set_filelen(new_fsp, size) == -1) {
6494 status = map_nt_error_from_unix(errno);
6495 close_file(req, new_fsp,NORMAL_CLOSE);
6499 trigger_write_time_update_immediate(new_fsp);
6500 close_file(req, new_fsp,NORMAL_CLOSE);
6501 return NT_STATUS_OK;
6504 /****************************************************************************
6505 Deal with SMB_INFO_SET_EA.
6506 ****************************************************************************/
6508 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6512 const struct smb_filename *smb_fname)
6514 struct ea_list *ea_list = NULL;
6515 TALLOC_CTX *ctx = NULL;
6516 NTSTATUS status = NT_STATUS_OK;
6518 if (total_data < 10) {
6520 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6521 length. They seem to have no effect. Bug #3212. JRA */
6523 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6524 /* We're done. We only get EA info in this call. */
6525 return NT_STATUS_OK;
6528 return NT_STATUS_INVALID_PARAMETER;
6531 if (IVAL(pdata,0) > total_data) {
6532 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6533 IVAL(pdata,0), (unsigned int)total_data));
6534 return NT_STATUS_INVALID_PARAMETER;
6538 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6540 return NT_STATUS_INVALID_PARAMETER;
6543 status = set_ea(conn, fsp, smb_fname, ea_list);
6548 /****************************************************************************
6549 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6550 ****************************************************************************/
6552 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6557 struct ea_list *ea_list = NULL;
6561 return NT_STATUS_INVALID_HANDLE;
6564 if (!lp_ea_support(SNUM(conn))) {
6565 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6566 "EA's not supported.\n",
6567 (unsigned int)total_data));
6568 return NT_STATUS_EAS_NOT_SUPPORTED;
6571 if (total_data < 10) {
6572 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6574 (unsigned int)total_data));
6575 return NT_STATUS_INVALID_PARAMETER;
6578 ea_list = read_nttrans_ea_list(talloc_tos(),
6583 return NT_STATUS_INVALID_PARAMETER;
6586 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6588 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6589 smb_fname_str_dbg(fsp->fsp_name),
6590 nt_errstr(status) ));
6596 /****************************************************************************
6597 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6598 ****************************************************************************/
6600 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6604 struct smb_filename *smb_fname)
6606 NTSTATUS status = NT_STATUS_OK;
6607 bool delete_on_close;
6608 uint32_t dosmode = 0;
6610 if (total_data < 1) {
6611 return NT_STATUS_INVALID_PARAMETER;
6615 return NT_STATUS_INVALID_HANDLE;
6618 delete_on_close = (CVAL(pdata,0) ? True : False);
6619 dosmode = dos_mode(conn, smb_fname);
6621 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6622 "delete_on_close = %u\n",
6623 smb_fname_str_dbg(smb_fname),
6624 (unsigned int)dosmode,
6625 (unsigned int)delete_on_close ));
6627 if (delete_on_close) {
6628 status = can_set_delete_on_close(fsp, dosmode);
6629 if (!NT_STATUS_IS_OK(status)) {
6634 /* The set is across all open files on this dev/inode pair. */
6635 if (!set_delete_on_close(fsp, delete_on_close,
6636 conn->session_info->security_token,
6637 conn->session_info->unix_token)) {
6638 return NT_STATUS_ACCESS_DENIED;
6640 return NT_STATUS_OK;
6643 /****************************************************************************
6644 Deal with SMB_FILE_POSITION_INFORMATION.
6645 ****************************************************************************/
6647 static NTSTATUS smb_file_position_information(connection_struct *conn,
6652 uint64_t position_information;
6654 if (total_data < 8) {
6655 return NT_STATUS_INVALID_PARAMETER;
6659 /* Ignore on pathname based set. */
6660 return NT_STATUS_OK;
6663 position_information = (uint64_t)IVAL(pdata,0);
6664 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6666 DEBUG(10,("smb_file_position_information: Set file position "
6667 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6668 (double)position_information));
6669 fsp->fh->position_information = position_information;
6670 return NT_STATUS_OK;
6673 /****************************************************************************
6674 Deal with SMB_FILE_MODE_INFORMATION.
6675 ****************************************************************************/
6677 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6683 if (total_data < 4) {
6684 return NT_STATUS_INVALID_PARAMETER;
6686 mode = IVAL(pdata,0);
6687 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6688 return NT_STATUS_INVALID_PARAMETER;
6690 return NT_STATUS_OK;
6693 /****************************************************************************
6694 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6695 ****************************************************************************/
6697 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6698 struct smb_request *req,
6701 const struct smb_filename *new_smb_fname)
6703 char *link_target = NULL;
6704 TALLOC_CTX *ctx = talloc_tos();
6706 /* Set a symbolic link. */
6707 /* Don't allow this if follow links is false. */
6709 if (total_data == 0) {
6710 return NT_STATUS_INVALID_PARAMETER;
6713 if (!lp_follow_symlinks(SNUM(conn))) {
6714 return NT_STATUS_ACCESS_DENIED;
6717 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6718 total_data, STR_TERMINATE);
6721 return NT_STATUS_INVALID_PARAMETER;
6724 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6725 new_smb_fname->base_name, link_target ));
6727 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6728 return map_nt_error_from_unix(errno);
6731 return NT_STATUS_OK;
6734 /****************************************************************************
6735 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6736 ****************************************************************************/
6738 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6739 struct smb_request *req,
6740 const char *pdata, int total_data,
6741 struct smb_filename *smb_fname_new)
6743 char *oldname = NULL;
6744 struct smb_filename *smb_fname_old = NULL;
6745 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6746 TALLOC_CTX *ctx = talloc_tos();
6747 NTSTATUS status = NT_STATUS_OK;
6749 /* Set a hard link. */
6750 if (total_data == 0) {
6751 return NT_STATUS_INVALID_PARAMETER;
6754 if (req->posix_pathnames) {
6755 srvstr_get_path_posix(ctx,
6764 srvstr_get_path(ctx,
6773 if (!NT_STATUS_IS_OK(status)) {
6777 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6778 smb_fname_str_dbg(smb_fname_new), oldname));
6780 status = filename_convert(ctx,
6787 if (!NT_STATUS_IS_OK(status)) {
6791 return hardlink_internals(ctx, conn, req, false,
6792 smb_fname_old, smb_fname_new);
6795 /****************************************************************************
6796 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6797 ****************************************************************************/
6799 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6800 struct smb_request *req,
6804 struct smb_filename *smb_fname_src)
6808 char *newname = NULL;
6809 struct smb_filename *smb_fname_dst = NULL;
6810 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6811 ucf_flags_from_smb_request(req);
6812 NTSTATUS status = NT_STATUS_OK;
6813 TALLOC_CTX *ctx = talloc_tos();
6816 return NT_STATUS_INVALID_HANDLE;
6819 if (total_data < 20) {
6820 return NT_STATUS_INVALID_PARAMETER;
6823 overwrite = (CVAL(pdata,0) ? True : False);
6824 len = IVAL(pdata,16);
6826 if (len > (total_data - 20) || (len == 0)) {
6827 return NT_STATUS_INVALID_PARAMETER;
6830 if (req->posix_pathnames) {
6831 srvstr_get_path_posix(ctx,
6840 srvstr_get_path(ctx,
6849 if (!NT_STATUS_IS_OK(status)) {
6853 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6856 status = filename_convert(ctx,
6863 if (!NT_STATUS_IS_OK(status)) {
6867 if (fsp->base_fsp) {
6868 /* newname must be a stream name. */
6869 if (newname[0] != ':') {
6870 return NT_STATUS_NOT_SUPPORTED;
6873 /* Create an smb_fname to call rename_internals_fsp() with. */
6874 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6875 fsp->base_fsp->fsp_name->base_name,
6878 fsp->base_fsp->fsp_name->flags);
6879 if (smb_fname_dst == NULL) {
6880 status = NT_STATUS_NO_MEMORY;
6885 * Set the original last component, since
6886 * rename_internals_fsp() requires it.
6888 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6890 if (smb_fname_dst->original_lcomp == NULL) {
6891 status = NT_STATUS_NO_MEMORY;
6897 DEBUG(10,("smb2_file_rename_information: "
6898 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6899 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6900 smb_fname_str_dbg(smb_fname_dst)));
6901 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6902 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6906 TALLOC_FREE(smb_fname_dst);
6910 static NTSTATUS smb_file_link_information(connection_struct *conn,
6911 struct smb_request *req,
6915 struct smb_filename *smb_fname_src)
6919 char *newname = NULL;
6920 struct smb_filename *smb_fname_dst = NULL;
6921 NTSTATUS status = NT_STATUS_OK;
6922 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6923 ucf_flags_from_smb_request(req);
6924 TALLOC_CTX *ctx = talloc_tos();
6927 return NT_STATUS_INVALID_HANDLE;
6930 if (total_data < 20) {
6931 return NT_STATUS_INVALID_PARAMETER;
6934 overwrite = (CVAL(pdata,0) ? true : false);
6935 len = IVAL(pdata,16);
6937 if (len > (total_data - 20) || (len == 0)) {
6938 return NT_STATUS_INVALID_PARAMETER;
6941 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
6942 srvstr_get_path_posix(ctx,
6950 ucf_flags |= UCF_POSIX_PATHNAMES;
6952 srvstr_get_path(ctx,
6961 if (!NT_STATUS_IS_OK(status)) {
6965 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6968 status = filename_convert(ctx,
6975 if (!NT_STATUS_IS_OK(status)) {
6979 if (fsp->base_fsp) {
6980 /* No stream names. */
6981 return NT_STATUS_NOT_SUPPORTED;
6984 DEBUG(10,("smb_file_link_information: "
6985 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6986 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6987 smb_fname_str_dbg(smb_fname_dst)));
6988 status = hardlink_internals(ctx,
6995 TALLOC_FREE(smb_fname_dst);
6999 /****************************************************************************
7000 Deal with SMB_FILE_RENAME_INFORMATION.
7001 ****************************************************************************/
7003 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7004 struct smb_request *req,
7008 struct smb_filename *smb_fname_src)
7013 char *newname = NULL;
7014 struct smb_filename *smb_fname_dst = NULL;
7015 bool dest_has_wcard = False;
7016 NTSTATUS status = NT_STATUS_OK;
7018 TALLOC_CTX *ctx = talloc_tos();
7020 if (total_data < 13) {
7021 return NT_STATUS_INVALID_PARAMETER;
7024 overwrite = (CVAL(pdata,0) ? True : False);
7025 root_fid = IVAL(pdata,4);
7026 len = IVAL(pdata,8);
7028 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7029 return NT_STATUS_INVALID_PARAMETER;
7032 if (req->posix_pathnames) {
7033 srvstr_get_path_wcard_posix(ctx,
7043 srvstr_get_path_wcard(ctx,
7053 if (!NT_STATUS_IS_OK(status)) {
7057 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7060 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7061 status = resolve_dfspath_wcard(ctx, conn,
7063 UCF_COND_ALLOW_WCARD_LCOMP,
7064 !conn->sconn->using_smb2,
7067 if (!NT_STATUS_IS_OK(status)) {
7072 /* Check the new name has no '/' characters. */
7073 if (strchr_m(newname, '/')) {
7074 return NT_STATUS_NOT_SUPPORTED;
7077 if (fsp && fsp->base_fsp) {
7078 /* newname must be a stream name. */
7079 if (newname[0] != ':') {
7080 return NT_STATUS_NOT_SUPPORTED;
7083 /* Create an smb_fname to call rename_internals_fsp() with. */
7084 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7085 fsp->base_fsp->fsp_name->base_name,
7088 fsp->base_fsp->fsp_name->flags);
7089 if (smb_fname_dst == NULL) {
7090 status = NT_STATUS_NO_MEMORY;
7095 * Set the original last component, since
7096 * rename_internals_fsp() requires it.
7098 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7100 if (smb_fname_dst->original_lcomp == NULL) {
7101 status = NT_STATUS_NO_MEMORY;
7107 * Build up an smb_fname_dst based on the filename passed in.
7108 * We basically just strip off the last component, and put on
7109 * the newname instead.
7111 char *base_name = NULL;
7112 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7113 ucf_flags_from_smb_request(req);
7115 if (dest_has_wcard) {
7116 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7119 /* newname must *not* be a stream name. */
7120 if (newname[0] == ':') {
7121 return NT_STATUS_NOT_SUPPORTED;
7125 * Strip off the last component (filename) of the path passed
7128 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7130 return NT_STATUS_NO_MEMORY;
7132 p = strrchr_m(base_name, '/');
7136 base_name = talloc_strdup(ctx, "");
7138 return NT_STATUS_NO_MEMORY;
7141 /* Append the new name. */
7142 base_name = talloc_asprintf_append(base_name,
7146 return NT_STATUS_NO_MEMORY;
7149 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7152 /* If an error we expect this to be
7153 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7155 if (!NT_STATUS_IS_OK(status)) {
7156 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7160 /* Create an smb_fname to call rename_internals_fsp() */
7161 smb_fname_dst = synthetic_smb_fname(ctx,
7165 smb_fname_src->flags);
7166 if (smb_fname_dst == NULL) {
7167 status = NT_STATUS_NO_MEMORY;
7174 DEBUG(10,("smb_file_rename_information: "
7175 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7176 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7177 smb_fname_str_dbg(smb_fname_dst)));
7178 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7181 DEBUG(10,("smb_file_rename_information: "
7182 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7183 smb_fname_str_dbg(smb_fname_src),
7184 smb_fname_str_dbg(smb_fname_dst)));
7185 status = rename_internals(ctx, conn, req, smb_fname_src,
7186 smb_fname_dst, 0, overwrite, false,
7188 FILE_WRITE_ATTRIBUTES);
7191 TALLOC_FREE(smb_fname_dst);
7195 /****************************************************************************
7196 Deal with SMB_SET_POSIX_ACL.
7197 ****************************************************************************/
7199 #if defined(HAVE_POSIX_ACLS)
7200 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7201 struct smb_request *req,
7205 const struct smb_filename *smb_fname)
7207 uint16_t posix_acl_version;
7208 uint16_t num_file_acls;
7209 uint16_t num_def_acls;
7210 bool valid_file_acls = true;
7211 bool valid_def_acls = true;
7213 unsigned int size_needed;
7214 unsigned int total_data;
7216 if (total_data_in < 0) {
7217 status = NT_STATUS_INVALID_PARAMETER;
7221 total_data = total_data_in;
7223 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7224 status = NT_STATUS_INVALID_PARAMETER;
7227 posix_acl_version = SVAL(pdata,0);
7228 num_file_acls = SVAL(pdata,2);
7229 num_def_acls = SVAL(pdata,4);
7231 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7232 valid_file_acls = false;
7236 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7237 valid_def_acls = false;
7241 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7242 status = NT_STATUS_INVALID_PARAMETER;
7247 if (num_file_acls + num_def_acls < num_file_acls) {
7248 status = NT_STATUS_INVALID_PARAMETER;
7252 size_needed = num_file_acls + num_def_acls;
7255 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7256 * than UINT_MAX, so check by division.
7258 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7259 status = NT_STATUS_INVALID_PARAMETER;
7263 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7264 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7265 status = NT_STATUS_INVALID_PARAMETER;
7268 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7270 if (total_data < size_needed) {
7271 status = NT_STATUS_INVALID_PARAMETER;
7275 status = refuse_symlink(conn, fsp, smb_fname);
7276 if (!NT_STATUS_IS_OK(status)) {
7280 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7281 "num_def_acls = %"PRIu16"\n",
7282 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7286 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7287 smb_fname, num_file_acls,
7288 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7289 status = map_nt_error_from_unix(errno);
7293 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7294 smb_fname, num_def_acls,
7295 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7296 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7297 status = map_nt_error_from_unix(errno);
7301 status = NT_STATUS_OK;
7309 /****************************************************************************
7310 Deal with SMB_SET_POSIX_LOCK.
7311 ****************************************************************************/
7313 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7315 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7316 struct smb_request *req,
7321 struct tevent_req *subreq = NULL;
7322 struct smbd_lock_element *lck = NULL;
7326 bool blocking_lock = False;
7327 enum brl_type lock_type;
7329 NTSTATUS status = NT_STATUS_OK;
7331 if (fsp == NULL || fsp->fh->fd == -1) {
7332 return NT_STATUS_INVALID_HANDLE;
7335 if (total_data != POSIX_LOCK_DATA_SIZE) {
7336 return NT_STATUS_INVALID_PARAMETER;
7339 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7340 case POSIX_LOCK_TYPE_READ:
7341 lock_type = READ_LOCK;
7343 case POSIX_LOCK_TYPE_WRITE:
7344 /* Return the right POSIX-mappable error code for files opened read-only. */
7345 if (!fsp->can_write) {
7346 return NT_STATUS_INVALID_HANDLE;
7348 lock_type = WRITE_LOCK;
7350 case POSIX_LOCK_TYPE_UNLOCK:
7351 lock_type = UNLOCK_LOCK;
7354 return NT_STATUS_INVALID_PARAMETER;
7357 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7358 case POSIX_LOCK_FLAG_NOWAIT:
7359 blocking_lock = false;
7361 case POSIX_LOCK_FLAG_WAIT:
7362 blocking_lock = true;
7365 return NT_STATUS_INVALID_PARAMETER;
7368 if (!lp_blocking_locks(SNUM(conn))) {
7369 blocking_lock = False;
7372 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7373 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7374 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7375 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7376 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7378 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7379 "count = %"PRIu64", offset = %"PRIu64"\n",
7381 (unsigned int)lock_type,
7386 if (lock_type == UNLOCK_LOCK) {
7387 struct smbd_lock_element l = {
7389 .brltype = UNLOCK_LOCK,
7393 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7397 lck = talloc(req, struct smbd_lock_element);
7399 return NT_STATUS_NO_MEMORY;
7402 *lck = (struct smbd_lock_element) {
7404 .brltype = lock_type,
7409 subreq = smbd_smb1_do_locks_send(
7412 req->sconn->msg_ctx,
7415 blocking_lock ? UINT32_MAX : 0,
7416 true, /* large_offset */
7420 if (subreq == NULL) {
7422 return NT_STATUS_NO_MEMORY;
7424 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7425 return NT_STATUS_EVENT_PENDING;
7428 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7430 struct smb_request *req = NULL;
7434 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7437 status = smbd_smb1_do_locks_recv(subreq);
7438 TALLOC_FREE(subreq);
7440 if (NT_STATUS_IS_OK(status)) {
7441 char params[2] = {0};
7442 /* Fake up max_data_bytes here - we know it fits. */
7443 send_trans2_replies(
7453 reply_nterror(req, status);
7456 (char *)req->outbuf,
7459 IS_CONN_ENCRYPTED(req->conn),
7462 exit_server_cleanly("smb_set_posix_lock_done: "
7463 "srv_send_smb failed.");
7471 /****************************************************************************
7472 Deal with SMB_SET_FILE_BASIC_INFO.
7473 ****************************************************************************/
7475 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7479 const struct smb_filename *smb_fname)
7481 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7482 struct smb_file_time ft;
7483 uint32_t dosmode = 0;
7484 NTSTATUS status = NT_STATUS_OK;
7488 if (total_data < 36) {
7489 return NT_STATUS_INVALID_PARAMETER;
7492 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7493 if (!NT_STATUS_IS_OK(status)) {
7497 /* Set the attributes */
7498 dosmode = IVAL(pdata,32);
7499 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7500 if (!NT_STATUS_IS_OK(status)) {
7505 ft.create_time = interpret_long_date(pdata);
7508 ft.atime = interpret_long_date(pdata+8);
7511 ft.mtime = interpret_long_date(pdata+16);
7514 ft.ctime = interpret_long_date(pdata+24);
7516 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7517 smb_fname_str_dbg(smb_fname)));
7519 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7523 /****************************************************************************
7524 Deal with SMB_INFO_STANDARD.
7525 ****************************************************************************/
7527 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7531 const struct smb_filename *smb_fname)
7534 struct smb_file_time ft;
7538 if (total_data < 12) {
7539 return NT_STATUS_INVALID_PARAMETER;
7543 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7545 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7547 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7549 DEBUG(10,("smb_set_info_standard: file %s\n",
7550 smb_fname_str_dbg(smb_fname)));
7552 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7553 if (!NT_STATUS_IS_OK(status)) {
7557 return smb_set_file_time(conn,
7564 /****************************************************************************
7565 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7566 ****************************************************************************/
7568 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7569 struct smb_request *req,
7573 struct smb_filename *smb_fname)
7575 uint64_t allocation_size = 0;
7576 NTSTATUS status = NT_STATUS_OK;
7577 files_struct *new_fsp = NULL;
7579 if (!VALID_STAT(smb_fname->st)) {
7580 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7583 if (total_data < 8) {
7584 return NT_STATUS_INVALID_PARAMETER;
7587 allocation_size = (uint64_t)IVAL(pdata,0);
7588 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7589 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7590 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7591 (double)allocation_size));
7593 if (allocation_size) {
7594 allocation_size = smb_roundup(conn, allocation_size);
7597 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7598 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7599 (double)allocation_size));
7601 if (fsp && fsp->fh->fd != -1) {
7602 /* Open file handle. */
7603 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7604 return NT_STATUS_ACCESS_DENIED;
7607 /* Only change if needed. */
7608 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7609 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7610 return map_nt_error_from_unix(errno);
7613 /* But always update the time. */
7615 * This is equivalent to a write. Ensure it's seen immediately
7616 * if there are no pending writes.
7618 trigger_write_time_update_immediate(fsp);
7619 return NT_STATUS_OK;
7622 /* Pathname or stat or directory file. */
7623 status = SMB_VFS_CREATE_FILE(
7626 0, /* root_dir_fid */
7627 smb_fname, /* fname */
7628 FILE_WRITE_DATA, /* access_mask */
7629 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7631 FILE_OPEN, /* create_disposition*/
7632 0, /* create_options */
7633 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7634 0, /* oplock_request */
7636 0, /* allocation_size */
7637 0, /* private_flags */
7640 &new_fsp, /* result */
7642 NULL, NULL); /* create context */
7644 if (!NT_STATUS_IS_OK(status)) {
7645 /* NB. We check for open_was_deferred in the caller. */
7649 /* Only change if needed. */
7650 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7651 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7652 status = map_nt_error_from_unix(errno);
7653 close_file(req, new_fsp, NORMAL_CLOSE);
7658 /* Changing the allocation size should set the last mod time. */
7660 * This is equivalent to a write. Ensure it's seen immediately
7661 * if there are no pending writes.
7663 trigger_write_time_update_immediate(new_fsp);
7664 close_file(req, new_fsp, NORMAL_CLOSE);
7665 return NT_STATUS_OK;
7668 /****************************************************************************
7669 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7670 ****************************************************************************/
7672 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7673 struct smb_request *req,
7677 const struct smb_filename *smb_fname,
7678 bool fail_after_createfile)
7682 if (total_data < 8) {
7683 return NT_STATUS_INVALID_PARAMETER;
7686 size = IVAL(pdata,0);
7687 size |= (((off_t)IVAL(pdata,4)) << 32);
7688 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7689 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7692 return smb_set_file_size(conn, req,
7697 fail_after_createfile);
7700 /****************************************************************************
7701 Allow a UNIX info mknod.
7702 ****************************************************************************/
7704 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7707 const struct smb_filename *smb_fname)
7709 uint32_t file_type = IVAL(pdata,56);
7710 #if defined(HAVE_MAKEDEV)
7711 uint32_t dev_major = IVAL(pdata,60);
7712 uint32_t dev_minor = IVAL(pdata,68);
7714 SMB_DEV_T dev = (SMB_DEV_T)0;
7715 uint32_t raw_unixmode = IVAL(pdata,84);
7719 if (total_data < 100) {
7720 return NT_STATUS_INVALID_PARAMETER;
7723 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7724 PERM_NEW_FILE, &unixmode);
7725 if (!NT_STATUS_IS_OK(status)) {
7729 #if defined(HAVE_MAKEDEV)
7730 dev = makedev(dev_major, dev_minor);
7733 switch (file_type) {
7734 #if defined(S_IFIFO)
7735 case UNIX_TYPE_FIFO:
7736 unixmode |= S_IFIFO;
7739 #if defined(S_IFSOCK)
7740 case UNIX_TYPE_SOCKET:
7741 unixmode |= S_IFSOCK;
7744 #if defined(S_IFCHR)
7745 case UNIX_TYPE_CHARDEV:
7746 unixmode |= S_IFCHR;
7749 #if defined(S_IFBLK)
7750 case UNIX_TYPE_BLKDEV:
7751 unixmode |= S_IFBLK;
7755 return NT_STATUS_INVALID_PARAMETER;
7758 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7759 "%.0f mode 0%o for file %s\n", (double)dev,
7760 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7762 /* Ok - do the mknod. */
7763 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7764 return map_nt_error_from_unix(errno);
7767 /* If any of the other "set" calls fail we
7768 * don't want to end up with a half-constructed mknod.
7771 if (lp_inherit_permissions(SNUM(conn))) {
7773 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7775 return NT_STATUS_NO_MEMORY;
7777 inherit_access_posix_acl(conn, parent, smb_fname,
7779 TALLOC_FREE(parent);
7782 return NT_STATUS_OK;
7785 /****************************************************************************
7786 Deal with SMB_SET_FILE_UNIX_BASIC.
7787 ****************************************************************************/
7789 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7790 struct smb_request *req,
7794 const struct smb_filename *smb_fname)
7796 struct smb_file_time ft;
7797 uint32_t raw_unixmode;
7800 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7801 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7802 NTSTATUS status = NT_STATUS_OK;
7803 bool delete_on_fail = False;
7804 enum perm_type ptype;
7805 files_struct *all_fsps = NULL;
7806 bool modify_mtime = true;
7808 struct smb_filename *smb_fname_tmp = NULL;
7809 SMB_STRUCT_STAT sbuf;
7813 if (total_data < 100) {
7814 return NT_STATUS_INVALID_PARAMETER;
7817 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7818 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7819 size=IVAL(pdata,0); /* first 8 Bytes are size */
7820 size |= (((off_t)IVAL(pdata,4)) << 32);
7823 ft.atime = interpret_long_date(pdata+24); /* access_time */
7824 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7825 set_owner = (uid_t)IVAL(pdata,40);
7826 set_grp = (gid_t)IVAL(pdata,48);
7827 raw_unixmode = IVAL(pdata,84);
7829 if (VALID_STAT(smb_fname->st)) {
7830 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7831 ptype = PERM_EXISTING_DIR;
7833 ptype = PERM_EXISTING_FILE;
7836 ptype = PERM_NEW_FILE;
7839 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7841 if (!NT_STATUS_IS_OK(status)) {
7845 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7846 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7847 smb_fname_str_dbg(smb_fname), (double)size,
7848 (unsigned int)set_owner, (unsigned int)set_grp,
7849 (int)raw_unixmode));
7851 sbuf = smb_fname->st;
7853 if (!VALID_STAT(sbuf)) {
7855 * The only valid use of this is to create character and block
7856 * devices, and named pipes. This is deprecated (IMHO) and
7857 * a new info level should be used for mknod. JRA.
7860 status = smb_unix_mknod(conn,
7864 if (!NT_STATUS_IS_OK(status)) {
7868 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7869 if (smb_fname_tmp == NULL) {
7870 return NT_STATUS_NO_MEMORY;
7873 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7874 status = map_nt_error_from_unix(errno);
7875 TALLOC_FREE(smb_fname_tmp);
7876 SMB_VFS_UNLINK(conn, smb_fname);
7880 sbuf = smb_fname_tmp->st;
7881 smb_fname = smb_fname_tmp;
7883 /* Ensure we don't try and change anything else. */
7884 raw_unixmode = SMB_MODE_NO_CHANGE;
7885 size = get_file_size_stat(&sbuf);
7886 ft.atime = sbuf.st_ex_atime;
7887 ft.mtime = sbuf.st_ex_mtime;
7889 * We continue here as we might want to change the
7892 delete_on_fail = True;
7896 /* Horrible backwards compatibility hack as an old server bug
7897 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7901 size = get_file_size_stat(&sbuf);
7906 * Deal with the UNIX specific mode set.
7909 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7912 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7913 "setting mode 0%o for file %s\n",
7914 (unsigned int)unixmode,
7915 smb_fname_str_dbg(smb_fname)));
7916 if (fsp && fsp->fh->fd != -1) {
7917 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7919 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7922 return map_nt_error_from_unix(errno);
7927 * Deal with the UNIX specific uid set.
7930 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7931 (sbuf.st_ex_uid != set_owner)) {
7934 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7935 "changing owner %u for path %s\n",
7936 (unsigned int)set_owner,
7937 smb_fname_str_dbg(smb_fname)));
7939 if (fsp && fsp->fh->fd != -1) {
7940 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7943 * UNIX extensions calls must always operate
7946 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7947 set_owner, (gid_t)-1);
7951 status = map_nt_error_from_unix(errno);
7952 if (delete_on_fail) {
7953 SMB_VFS_UNLINK(conn, smb_fname);
7960 * Deal with the UNIX specific gid set.
7963 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7964 (sbuf.st_ex_gid != set_grp)) {
7967 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7968 "changing group %u for file %s\n",
7969 (unsigned int)set_grp,
7970 smb_fname_str_dbg(smb_fname)));
7971 if (fsp && fsp->fh->fd != -1) {
7972 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
7975 * UNIX extensions calls must always operate
7978 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7982 status = map_nt_error_from_unix(errno);
7983 if (delete_on_fail) {
7984 SMB_VFS_UNLINK(conn, smb_fname);
7990 /* Deal with any size changes. */
7992 status = smb_set_file_size(conn, req,
7998 if (!NT_STATUS_IS_OK(status)) {
8002 /* Deal with any time changes. */
8003 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
8004 /* No change, don't cancel anything. */
8008 id = vfs_file_id_from_sbuf(conn, &sbuf);
8009 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8010 all_fsps = file_find_di_next(all_fsps)) {
8012 * We're setting the time explicitly for UNIX.
8013 * Cancel any pending changes over all handles.
8015 all_fsps->update_write_time_on_close = false;
8016 TALLOC_FREE(all_fsps->update_write_time_event);
8020 * Override the "setting_write_time"
8021 * parameter here as it almost does what
8022 * we need. Just remember if we modified
8023 * mtime and send the notify ourselves.
8025 if (null_timespec(ft.mtime)) {
8026 modify_mtime = false;
8029 status = smb_set_file_time(conn,
8035 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8036 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8041 /****************************************************************************
8042 Deal with SMB_SET_FILE_UNIX_INFO2.
8043 ****************************************************************************/
8045 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8046 struct smb_request *req,
8050 const struct smb_filename *smb_fname)
8053 uint32_t smb_fflags;
8056 if (total_data < 116) {
8057 return NT_STATUS_INVALID_PARAMETER;
8060 /* Start by setting all the fields that are common between UNIX_BASIC
8063 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8065 if (!NT_STATUS_IS_OK(status)) {
8069 smb_fflags = IVAL(pdata, 108);
8070 smb_fmask = IVAL(pdata, 112);
8072 /* NB: We should only attempt to alter the file flags if the client
8073 * sends a non-zero mask.
8075 if (smb_fmask != 0) {
8076 int stat_fflags = 0;
8078 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8079 smb_fmask, &stat_fflags)) {
8080 /* Client asked to alter a flag we don't understand. */
8081 return NT_STATUS_INVALID_PARAMETER;
8084 if (fsp && fsp->fh->fd != -1) {
8085 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8086 return NT_STATUS_NOT_SUPPORTED;
8088 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8089 stat_fflags) != 0) {
8090 return map_nt_error_from_unix(errno);
8095 /* XXX: need to add support for changing the create_time here. You
8096 * can do this for paths on Darwin with setattrlist(2). The right way
8097 * to hook this up is probably by extending the VFS utimes interface.
8100 return NT_STATUS_OK;
8103 /****************************************************************************
8104 Create a directory with POSIX semantics.
8105 ****************************************************************************/
8107 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8108 struct smb_request *req,
8111 struct smb_filename *smb_fname,
8112 int *pdata_return_size)
8114 NTSTATUS status = NT_STATUS_OK;
8115 uint32_t raw_unixmode = 0;
8116 uint32_t mod_unixmode = 0;
8117 mode_t unixmode = (mode_t)0;
8118 files_struct *fsp = NULL;
8119 uint16_t info_level_return = 0;
8121 char *pdata = *ppdata;
8123 if (total_data < 18) {
8124 return NT_STATUS_INVALID_PARAMETER;
8127 raw_unixmode = IVAL(pdata,8);
8128 /* Next 4 bytes are not yet defined. */
8130 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8131 PERM_NEW_DIR, &unixmode);
8132 if (!NT_STATUS_IS_OK(status)) {
8136 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8138 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8139 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8141 status = SMB_VFS_CREATE_FILE(
8144 0, /* root_dir_fid */
8145 smb_fname, /* fname */
8146 FILE_READ_ATTRIBUTES, /* access_mask */
8147 FILE_SHARE_NONE, /* share_access */
8148 FILE_CREATE, /* create_disposition*/
8149 FILE_DIRECTORY_FILE, /* create_options */
8150 mod_unixmode, /* file_attributes */
8151 0, /* oplock_request */
8153 0, /* allocation_size */
8154 0, /* private_flags */
8159 NULL, NULL); /* create context */
8161 if (NT_STATUS_IS_OK(status)) {
8162 close_file(req, fsp, NORMAL_CLOSE);
8165 info_level_return = SVAL(pdata,16);
8167 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8168 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8169 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8170 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8172 *pdata_return_size = 12;
8175 /* Realloc the data size */
8176 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8177 if (*ppdata == NULL) {
8178 *pdata_return_size = 0;
8179 return NT_STATUS_NO_MEMORY;
8183 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8184 SSVAL(pdata,2,0); /* No fnum. */
8185 SIVAL(pdata,4,info); /* Was directory created. */
8187 switch (info_level_return) {
8188 case SMB_QUERY_FILE_UNIX_BASIC:
8189 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8190 SSVAL(pdata,10,0); /* Padding. */
8191 store_file_unix_basic(conn, pdata + 12, fsp,
8194 case SMB_QUERY_FILE_UNIX_INFO2:
8195 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8196 SSVAL(pdata,10,0); /* Padding. */
8197 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8201 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8202 SSVAL(pdata,10,0); /* Padding. */
8209 /****************************************************************************
8210 Open/Create a file with POSIX semantics.
8211 ****************************************************************************/
8213 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8214 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8216 static NTSTATUS smb_posix_open(connection_struct *conn,
8217 struct smb_request *req,
8220 struct smb_filename *smb_fname,
8221 int *pdata_return_size)
8223 bool extended_oplock_granted = False;
8224 char *pdata = *ppdata;
8226 uint32_t wire_open_mode = 0;
8227 uint32_t raw_unixmode = 0;
8228 uint32_t mod_unixmode = 0;
8229 uint32_t create_disp = 0;
8230 uint32_t access_mask = 0;
8231 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8232 NTSTATUS status = NT_STATUS_OK;
8233 mode_t unixmode = (mode_t)0;
8234 files_struct *fsp = NULL;
8235 int oplock_request = 0;
8237 uint16_t info_level_return = 0;
8239 if (total_data < 18) {
8240 return NT_STATUS_INVALID_PARAMETER;
8243 flags = IVAL(pdata,0);
8244 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8245 if (oplock_request) {
8246 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8249 wire_open_mode = IVAL(pdata,4);
8251 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8252 return smb_posix_mkdir(conn, req,
8259 switch (wire_open_mode & SMB_ACCMODE) {
8261 access_mask = SMB_O_RDONLY_MAPPING;
8264 access_mask = SMB_O_WRONLY_MAPPING;
8267 access_mask = (SMB_O_RDONLY_MAPPING|
8268 SMB_O_WRONLY_MAPPING);
8271 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8272 (unsigned int)wire_open_mode ));
8273 return NT_STATUS_INVALID_PARAMETER;
8276 wire_open_mode &= ~SMB_ACCMODE;
8278 /* First take care of O_CREAT|O_EXCL interactions. */
8279 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8280 case (SMB_O_CREAT | SMB_O_EXCL):
8281 /* File exists fail. File not exist create. */
8282 create_disp = FILE_CREATE;
8285 /* File exists open. File not exist create. */
8286 create_disp = FILE_OPEN_IF;
8289 /* O_EXCL on its own without O_CREAT is undefined.
8290 We deliberately ignore it as some versions of
8291 Linux CIFSFS can send a bare O_EXCL on the
8292 wire which other filesystems in the kernel
8293 ignore. See bug 9519 for details. */
8298 /* File exists open. File not exist fail. */
8299 create_disp = FILE_OPEN;
8302 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8303 (unsigned int)wire_open_mode ));
8304 return NT_STATUS_INVALID_PARAMETER;
8307 /* Next factor in the effects of O_TRUNC. */
8308 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8310 if (wire_open_mode & SMB_O_TRUNC) {
8311 switch (create_disp) {
8313 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8314 /* Leave create_disp alone as
8315 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8317 /* File exists fail. File not exist create. */
8320 /* SMB_O_CREAT | SMB_O_TRUNC */
8321 /* File exists overwrite. File not exist create. */
8322 create_disp = FILE_OVERWRITE_IF;
8326 /* File exists overwrite. File not exist fail. */
8327 create_disp = FILE_OVERWRITE;
8330 /* Cannot get here. */
8331 smb_panic("smb_posix_open: logic error");
8332 return NT_STATUS_INVALID_PARAMETER;
8336 raw_unixmode = IVAL(pdata,8);
8337 /* Next 4 bytes are not yet defined. */
8339 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8340 (VALID_STAT(smb_fname->st) ?
8341 PERM_EXISTING_FILE : PERM_NEW_FILE),
8344 if (!NT_STATUS_IS_OK(status)) {
8348 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8350 if (wire_open_mode & SMB_O_SYNC) {
8351 create_options |= FILE_WRITE_THROUGH;
8353 if (wire_open_mode & SMB_O_APPEND) {
8354 access_mask |= FILE_APPEND_DATA;
8356 if (wire_open_mode & SMB_O_DIRECT) {
8357 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8360 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8361 VALID_STAT_OF_DIR(smb_fname->st)) {
8362 if (access_mask != SMB_O_RDONLY_MAPPING) {
8363 return NT_STATUS_FILE_IS_A_DIRECTORY;
8365 create_options &= ~FILE_NON_DIRECTORY_FILE;
8366 create_options |= FILE_DIRECTORY_FILE;
8369 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8370 smb_fname_str_dbg(smb_fname),
8371 (unsigned int)wire_open_mode,
8372 (unsigned int)unixmode ));
8374 status = SMB_VFS_CREATE_FILE(
8377 0, /* root_dir_fid */
8378 smb_fname, /* fname */
8379 access_mask, /* access_mask */
8380 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8382 create_disp, /* create_disposition*/
8383 create_options, /* create_options */
8384 mod_unixmode, /* file_attributes */
8385 oplock_request, /* oplock_request */
8387 0, /* allocation_size */
8388 0, /* private_flags */
8393 NULL, NULL); /* create context */
8395 if (!NT_STATUS_IS_OK(status)) {
8399 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8400 extended_oplock_granted = True;
8403 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8404 extended_oplock_granted = True;
8407 info_level_return = SVAL(pdata,16);
8409 /* Allocate the correct return size. */
8411 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8412 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8413 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8414 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8416 *pdata_return_size = 12;
8419 /* Realloc the data size */
8420 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8421 if (*ppdata == NULL) {
8422 close_file(req, fsp, ERROR_CLOSE);
8423 *pdata_return_size = 0;
8424 return NT_STATUS_NO_MEMORY;
8428 if (extended_oplock_granted) {
8429 if (flags & REQUEST_BATCH_OPLOCK) {
8430 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8432 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8434 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8435 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8437 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8440 SSVAL(pdata,2,fsp->fnum);
8441 SIVAL(pdata,4,info); /* Was file created etc. */
8443 switch (info_level_return) {
8444 case SMB_QUERY_FILE_UNIX_BASIC:
8445 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8446 SSVAL(pdata,10,0); /* padding. */
8447 store_file_unix_basic(conn, pdata + 12, fsp,
8450 case SMB_QUERY_FILE_UNIX_INFO2:
8451 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8452 SSVAL(pdata,10,0); /* padding. */
8453 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8457 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8458 SSVAL(pdata,10,0); /* padding. */
8461 return NT_STATUS_OK;
8464 /****************************************************************************
8465 Delete a file with POSIX semantics.
8466 ****************************************************************************/
8468 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8469 struct smb_request *req,
8472 struct smb_filename *smb_fname)
8474 struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
8475 NTSTATUS status = NT_STATUS_OK;
8476 files_struct *fsp = NULL;
8480 int create_options = 0;
8481 struct share_mode_lock *lck = NULL;
8482 bool other_nonposix_opens;
8484 if (total_data < 2) {
8485 return NT_STATUS_INVALID_PARAMETER;
8488 flags = SVAL(pdata,0);
8490 if (!VALID_STAT(smb_fname->st)) {
8491 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8494 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8495 !VALID_STAT_OF_DIR(smb_fname->st)) {
8496 return NT_STATUS_NOT_A_DIRECTORY;
8499 DEBUG(10,("smb_posix_unlink: %s %s\n",
8500 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8501 smb_fname_str_dbg(smb_fname)));
8503 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8504 create_options |= FILE_DIRECTORY_FILE;
8507 status = SMB_VFS_CREATE_FILE(
8510 0, /* root_dir_fid */
8511 smb_fname, /* fname */
8512 DELETE_ACCESS, /* access_mask */
8513 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8515 FILE_OPEN, /* create_disposition*/
8516 create_options, /* create_options */
8517 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8518 0, /* oplock_request */
8520 0, /* allocation_size */
8521 0, /* private_flags */
8526 NULL, NULL); /* create context */
8528 if (!NT_STATUS_IS_OK(status)) {
8533 * Don't lie to client. If we can't really delete due to
8534 * non-POSIX opens return SHARING_VIOLATION.
8537 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8539 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8540 "lock for file %s\n", fsp_str_dbg(fsp)));
8541 close_file(req, fsp, NORMAL_CLOSE);
8542 return NT_STATUS_INVALID_PARAMETER;
8545 other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
8546 if (other_nonposix_opens) {
8547 /* Fail with sharing violation. */
8549 close_file(req, fsp, NORMAL_CLOSE);
8550 return NT_STATUS_SHARING_VIOLATION;
8554 * Set the delete on close.
8556 status = smb_set_file_disposition_info(conn,
8564 if (!NT_STATUS_IS_OK(status)) {
8565 close_file(req, fsp, NORMAL_CLOSE);
8568 return close_file(req, fsp, NORMAL_CLOSE);
8571 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8572 struct smb_request *req,
8573 TALLOC_CTX *mem_ctx,
8574 uint16_t info_level,
8576 struct smb_filename *smb_fname,
8577 char **ppdata, int total_data,
8580 char *pdata = *ppdata;
8581 NTSTATUS status = NT_STATUS_OK;
8582 int data_return_size = 0;
8586 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8587 return NT_STATUS_INVALID_LEVEL;
8590 if (!CAN_WRITE(conn)) {
8591 /* Allow POSIX opens. The open path will deny
8592 * any non-readonly opens. */
8593 if (info_level != SMB_POSIX_PATH_OPEN) {
8594 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8598 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8599 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8601 info_level, total_data));
8603 switch (info_level) {
8605 case SMB_INFO_STANDARD:
8607 status = smb_set_info_standard(conn,
8615 case SMB_INFO_SET_EA:
8617 status = smb_info_set_ea(conn,
8625 case SMB_SET_FILE_BASIC_INFO:
8626 case SMB_FILE_BASIC_INFORMATION:
8628 status = smb_set_file_basic_info(conn,
8636 case SMB_FILE_ALLOCATION_INFORMATION:
8637 case SMB_SET_FILE_ALLOCATION_INFO:
8639 status = smb_set_file_allocation_info(conn, req,
8647 case SMB_FILE_END_OF_FILE_INFORMATION:
8648 case SMB_SET_FILE_END_OF_FILE_INFO:
8651 * XP/Win7 both fail after the createfile with
8652 * SMB_SET_FILE_END_OF_FILE_INFO but not
8653 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8654 * The level is known here, so pass it down
8658 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8660 status = smb_set_file_end_of_file_info(conn, req,
8669 case SMB_FILE_DISPOSITION_INFORMATION:
8670 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8673 /* JRA - We used to just ignore this on a path ?
8674 * Shouldn't this be invalid level on a pathname
8677 if (tran_call != TRANSACT2_SETFILEINFO) {
8678 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8681 status = smb_set_file_disposition_info(conn,
8689 case SMB_FILE_POSITION_INFORMATION:
8691 status = smb_file_position_information(conn,
8698 case SMB_FILE_FULL_EA_INFORMATION:
8700 status = smb_set_file_full_ea_info(conn,
8707 /* From tridge Samba4 :
8708 * MODE_INFORMATION in setfileinfo (I have no
8709 * idea what "mode information" on a file is - it takes a value of 0,
8710 * 2, 4 or 6. What could it be?).
8713 case SMB_FILE_MODE_INFORMATION:
8715 status = smb_file_mode_information(conn,
8721 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8722 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8723 case SMB_FILE_SHORT_NAME_INFORMATION:
8724 return NT_STATUS_NOT_SUPPORTED;
8727 * CIFS UNIX extensions.
8730 case SMB_SET_FILE_UNIX_BASIC:
8732 status = smb_set_file_unix_basic(conn, req,
8740 case SMB_SET_FILE_UNIX_INFO2:
8742 status = smb_set_file_unix_info2(conn, req,
8750 case SMB_SET_FILE_UNIX_LINK:
8753 /* We must have a pathname for this. */
8754 return NT_STATUS_INVALID_LEVEL;
8756 status = smb_set_file_unix_link(conn, req, pdata,
8757 total_data, smb_fname);
8761 case SMB_SET_FILE_UNIX_HLINK:
8764 /* We must have a pathname for this. */
8765 return NT_STATUS_INVALID_LEVEL;
8767 status = smb_set_file_unix_hlink(conn, req,
8773 case SMB_FILE_RENAME_INFORMATION:
8775 status = smb_file_rename_information(conn, req,
8781 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8783 /* SMB2 rename information. */
8784 status = smb2_file_rename_information(conn, req,
8790 case SMB_FILE_LINK_INFORMATION:
8792 status = smb_file_link_information(conn, req,
8798 #if defined(HAVE_POSIX_ACLS)
8799 case SMB_SET_POSIX_ACL:
8801 status = smb_set_posix_acl(conn,
8811 case SMB_SET_POSIX_LOCK:
8814 return NT_STATUS_INVALID_LEVEL;
8816 status = smb_set_posix_lock(conn, req,
8817 pdata, total_data, fsp);
8821 case SMB_POSIX_PATH_OPEN:
8824 /* We must have a pathname for this. */
8825 return NT_STATUS_INVALID_LEVEL;
8828 status = smb_posix_open(conn, req,
8836 case SMB_POSIX_PATH_UNLINK:
8839 /* We must have a pathname for this. */
8840 return NT_STATUS_INVALID_LEVEL;
8843 status = smb_posix_unlink(conn, req,
8851 return NT_STATUS_INVALID_LEVEL;
8854 if (!NT_STATUS_IS_OK(status)) {
8858 *ret_data_size = data_return_size;
8859 return NT_STATUS_OK;
8862 /****************************************************************************
8863 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8864 ****************************************************************************/
8866 static void call_trans2setfilepathinfo(connection_struct *conn,
8867 struct smb_request *req,
8868 unsigned int tran_call,
8869 char **pparams, int total_params,
8870 char **ppdata, int total_data,
8871 unsigned int max_data_bytes)
8873 char *params = *pparams;
8874 char *pdata = *ppdata;
8875 uint16_t info_level;
8876 struct smb_filename *smb_fname = NULL;
8877 files_struct *fsp = NULL;
8878 NTSTATUS status = NT_STATUS_OK;
8879 int data_return_size = 0;
8882 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8886 if (tran_call == TRANSACT2_SETFILEINFO) {
8887 if (total_params < 4) {
8888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8892 fsp = file_fsp(req, SVAL(params,0));
8893 /* Basic check for non-null fsp. */
8894 if (!check_fsp_open(conn, req, fsp)) {
8897 info_level = SVAL(params,2);
8899 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8900 if (smb_fname == NULL) {
8901 reply_nterror(req, NT_STATUS_NO_MEMORY);
8905 if(fsp->fh->fd == -1) {
8907 * This is actually a SETFILEINFO on a directory
8908 * handle (returned from an NT SMB). NT5.0 seems
8909 * to do this call. JRA.
8911 if (INFO_LEVEL_IS_UNIX(info_level)) {
8912 /* Always do lstat for UNIX calls. */
8913 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8914 DEBUG(3,("call_trans2setfilepathinfo: "
8915 "SMB_VFS_LSTAT of %s failed "
8917 smb_fname_str_dbg(smb_fname),
8919 reply_nterror(req, map_nt_error_from_unix(errno));
8923 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8924 DEBUG(3,("call_trans2setfilepathinfo: "
8925 "fileinfo of %s failed (%s)\n",
8926 smb_fname_str_dbg(smb_fname),
8928 reply_nterror(req, map_nt_error_from_unix(errno));
8932 } else if (fsp->print_file) {
8934 * Doing a DELETE_ON_CLOSE should cancel a print job.
8936 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8937 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8939 DEBUG(3,("call_trans2setfilepathinfo: "
8940 "Cancelling print job (%s)\n",
8944 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8950 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8955 * Original code - this is an open file.
8957 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8958 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8959 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8961 reply_nterror(req, map_nt_error_from_unix(errno));
8967 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8970 if (total_params < 7) {
8971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8975 info_level = SVAL(params,0);
8976 if (req->posix_pathnames) {
8977 srvstr_get_path_posix(req,
8986 srvstr_get_path(req,
8995 if (!NT_STATUS_IS_OK(status)) {
8996 reply_nterror(req, status);
9000 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9001 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9002 info_level == SMB_FILE_RENAME_INFORMATION ||
9003 info_level == SMB_POSIX_PATH_OPEN ||
9004 info_level == SMB_POSIX_PATH_UNLINK) {
9005 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9008 status = filename_convert(req, conn,
9014 if (!NT_STATUS_IS_OK(status)) {
9015 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9016 reply_botherror(req,
9017 NT_STATUS_PATH_NOT_COVERED,
9018 ERRSRV, ERRbadpath);
9021 reply_nterror(req, status);
9025 if (INFO_LEVEL_IS_UNIX(info_level)) {
9027 * For CIFS UNIX extensions the target name may not exist.
9030 /* Always do lstat for UNIX calls. */
9031 SMB_VFS_LSTAT(conn, smb_fname);
9033 } else if (!VALID_STAT(smb_fname->st) &&
9034 SMB_VFS_STAT(conn, smb_fname)) {
9035 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9037 smb_fname_str_dbg(smb_fname),
9039 reply_nterror(req, map_nt_error_from_unix(errno));
9044 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9045 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9047 info_level,total_data));
9049 /* Realloc the parameter size */
9050 *pparams = (char *)SMB_REALLOC(*pparams,2);
9051 if (*pparams == NULL) {
9052 reply_nterror(req, NT_STATUS_NO_MEMORY);
9059 status = smbd_do_setfilepathinfo(conn, req, req,
9065 if (!NT_STATUS_IS_OK(status)) {
9066 if (open_was_deferred(req->xconn, req->mid)) {
9067 /* We have re-scheduled this call. */
9070 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9071 /* We have re-scheduled this call. */
9074 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9075 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9076 ERRSRV, ERRbadpath);
9079 if (info_level == SMB_POSIX_PATH_OPEN) {
9080 reply_openerror(req, status);
9085 * Invalid EA name needs to return 2 param bytes,
9086 * not a zero-length error packet.
9088 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9089 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9092 reply_nterror(req, status);
9097 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9103 /****************************************************************************
9104 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9105 ****************************************************************************/
9107 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9108 char **pparams, int total_params,
9109 char **ppdata, int total_data,
9110 unsigned int max_data_bytes)
9112 struct smb_filename *smb_dname = NULL;
9113 char *params = *pparams;
9114 char *pdata = *ppdata;
9115 char *directory = NULL;
9116 NTSTATUS status = NT_STATUS_OK;
9117 struct ea_list *ea_list = NULL;
9118 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9119 TALLOC_CTX *ctx = talloc_tos();
9121 if (!CAN_WRITE(conn)) {
9122 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9126 if (total_params < 5) {
9127 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9131 if (req->posix_pathnames) {
9132 srvstr_get_path_posix(ctx,
9141 srvstr_get_path(ctx,
9150 if (!NT_STATUS_IS_OK(status)) {
9151 reply_nterror(req, status);
9155 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9157 status = filename_convert(ctx,
9165 if (!NT_STATUS_IS_OK(status)) {
9166 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9167 reply_botherror(req,
9168 NT_STATUS_PATH_NOT_COVERED,
9169 ERRSRV, ERRbadpath);
9172 reply_nterror(req, status);
9177 * OS/2 workplace shell seems to send SET_EA requests of "null"
9178 * length (4 bytes containing IVAL 4).
9179 * They seem to have no effect. Bug #3212. JRA.
9182 if (total_data && (total_data != 4)) {
9183 /* Any data in this call is an EA list. */
9184 if (total_data < 10) {
9185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9189 if (IVAL(pdata,0) > total_data) {
9190 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9191 IVAL(pdata,0), (unsigned int)total_data));
9192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9196 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9199 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9203 if (!lp_ea_support(SNUM(conn))) {
9204 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9208 /* If total_data == 4 Windows doesn't care what values
9209 * are placed in that field, it just ignores them.
9210 * The System i QNTC IBM SMB client puts bad values here,
9211 * so ignore them. */
9213 status = create_directory(conn, req, smb_dname);
9215 if (!NT_STATUS_IS_OK(status)) {
9216 reply_nterror(req, status);
9220 /* Try and set any given EA. */
9222 status = set_ea(conn, NULL, smb_dname, ea_list);
9223 if (!NT_STATUS_IS_OK(status)) {
9224 reply_nterror(req, status);
9229 /* Realloc the parameter and data sizes */
9230 *pparams = (char *)SMB_REALLOC(*pparams,2);
9231 if(*pparams == NULL) {
9232 reply_nterror(req, NT_STATUS_NO_MEMORY);
9239 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9242 TALLOC_FREE(smb_dname);
9246 /****************************************************************************
9247 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9248 We don't actually do this - we just send a null response.
9249 ****************************************************************************/
9251 static void call_trans2findnotifyfirst(connection_struct *conn,
9252 struct smb_request *req,
9253 char **pparams, int total_params,
9254 char **ppdata, int total_data,
9255 unsigned int max_data_bytes)
9257 char *params = *pparams;
9258 uint16_t info_level;
9260 if (total_params < 6) {
9261 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9265 info_level = SVAL(params,4);
9266 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9268 switch (info_level) {
9273 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9277 /* Realloc the parameter and data sizes */
9278 *pparams = (char *)SMB_REALLOC(*pparams,6);
9279 if (*pparams == NULL) {
9280 reply_nterror(req, NT_STATUS_NO_MEMORY);
9285 SSVAL(params,0,fnf_handle);
9286 SSVAL(params,2,0); /* No changes */
9287 SSVAL(params,4,0); /* No EA errors */
9294 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9299 /****************************************************************************
9300 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9301 changes). Currently this does nothing.
9302 ****************************************************************************/
9304 static void call_trans2findnotifynext(connection_struct *conn,
9305 struct smb_request *req,
9306 char **pparams, int total_params,
9307 char **ppdata, int total_data,
9308 unsigned int max_data_bytes)
9310 char *params = *pparams;
9312 DEBUG(3,("call_trans2findnotifynext\n"));
9314 /* Realloc the parameter and data sizes */
9315 *pparams = (char *)SMB_REALLOC(*pparams,4);
9316 if (*pparams == NULL) {
9317 reply_nterror(req, NT_STATUS_NO_MEMORY);
9322 SSVAL(params,0,0); /* No changes */
9323 SSVAL(params,2,0); /* No EA errors */
9325 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9330 /****************************************************************************
9331 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9332 ****************************************************************************/
9334 static void call_trans2getdfsreferral(connection_struct *conn,
9335 struct smb_request *req,
9336 char **pparams, int total_params,
9337 char **ppdata, int total_data,
9338 unsigned int max_data_bytes)
9340 char *params = *pparams;
9341 char *pathname = NULL;
9343 int max_referral_level;
9344 NTSTATUS status = NT_STATUS_OK;
9345 TALLOC_CTX *ctx = talloc_tos();
9347 DEBUG(10,("call_trans2getdfsreferral\n"));
9349 if (total_params < 3) {
9350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9354 max_referral_level = SVAL(params,0);
9356 if(!lp_host_msdfs()) {
9357 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9361 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9362 total_params - 2, STR_TERMINATE);
9364 reply_nterror(req, NT_STATUS_NOT_FOUND);
9367 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9368 ppdata,&status)) < 0) {
9369 reply_nterror(req, status);
9373 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9374 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9375 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9380 #define LMCAT_SPL 0x53
9381 #define LMFUNC_GETJOBID 0x60
9383 /****************************************************************************
9384 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9385 ****************************************************************************/
9387 static void call_trans2ioctl(connection_struct *conn,
9388 struct smb_request *req,
9389 char **pparams, int total_params,
9390 char **ppdata, int total_data,
9391 unsigned int max_data_bytes)
9393 char *pdata = *ppdata;
9394 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9398 /* check for an invalid fid before proceeding */
9401 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9405 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9406 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9407 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9408 if (*ppdata == NULL) {
9409 reply_nterror(req, NT_STATUS_NO_MEMORY);
9414 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9415 CAN ACCEPT THIS IN UNICODE. JRA. */
9418 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9420 status = srvstr_push(pdata, req->flags2, pdata + 2,
9421 lp_netbios_name(), 15,
9422 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9423 if (!NT_STATUS_IS_OK(status)) {
9424 reply_nterror(req, status);
9427 status = srvstr_push(pdata, req->flags2, pdata+18,
9428 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9429 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9430 if (!NT_STATUS_IS_OK(status)) {
9431 reply_nterror(req, status);
9434 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9439 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9440 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9443 /****************************************************************************
9444 Reply to a SMBfindclose (stop trans2 directory search).
9445 ****************************************************************************/
9447 void reply_findclose(struct smb_request *req)
9450 struct smbd_server_connection *sconn = req->sconn;
9452 START_PROFILE(SMBfindclose);
9455 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9456 END_PROFILE(SMBfindclose);
9460 dptr_num = SVALS(req->vwv+0, 0);
9462 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9464 dptr_close(sconn, &dptr_num);
9466 reply_outbuf(req, 0, 0);
9468 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9470 END_PROFILE(SMBfindclose);
9474 /****************************************************************************
9475 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9476 ****************************************************************************/
9478 void reply_findnclose(struct smb_request *req)
9482 START_PROFILE(SMBfindnclose);
9485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9486 END_PROFILE(SMBfindnclose);
9490 dptr_num = SVAL(req->vwv+0, 0);
9492 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9494 /* We never give out valid handles for a
9495 findnotifyfirst - so any dptr_num is ok here.
9498 reply_outbuf(req, 0, 0);
9500 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9502 END_PROFILE(SMBfindnclose);
9506 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9507 struct trans_state *state)
9509 if (get_Protocol() >= PROTOCOL_NT1) {
9510 req->flags2 |= 0x40; /* IS_LONG_NAME */
9511 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9514 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9515 if (state->call != TRANSACT2_QFSINFO &&
9516 state->call != TRANSACT2_SETFSINFO) {
9517 DEBUG(0,("handle_trans2: encryption required "
9519 (unsigned int)state->call));
9520 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9525 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9527 /* Now we must call the relevant TRANS2 function */
9528 switch(state->call) {
9529 case TRANSACT2_OPEN:
9531 START_PROFILE(Trans2_open);
9532 call_trans2open(conn, req,
9533 &state->param, state->total_param,
9534 &state->data, state->total_data,
9535 state->max_data_return);
9536 END_PROFILE(Trans2_open);
9540 case TRANSACT2_FINDFIRST:
9542 START_PROFILE(Trans2_findfirst);
9543 call_trans2findfirst(conn, req,
9544 &state->param, state->total_param,
9545 &state->data, state->total_data,
9546 state->max_data_return);
9547 END_PROFILE(Trans2_findfirst);
9551 case TRANSACT2_FINDNEXT:
9553 START_PROFILE(Trans2_findnext);
9554 call_trans2findnext(conn, req,
9555 &state->param, state->total_param,
9556 &state->data, state->total_data,
9557 state->max_data_return);
9558 END_PROFILE(Trans2_findnext);
9562 case TRANSACT2_QFSINFO:
9564 START_PROFILE(Trans2_qfsinfo);
9565 call_trans2qfsinfo(conn, req,
9566 &state->param, state->total_param,
9567 &state->data, state->total_data,
9568 state->max_data_return);
9569 END_PROFILE(Trans2_qfsinfo);
9573 case TRANSACT2_SETFSINFO:
9575 START_PROFILE(Trans2_setfsinfo);
9576 call_trans2setfsinfo(conn, req,
9577 &state->param, state->total_param,
9578 &state->data, state->total_data,
9579 state->max_data_return);
9580 END_PROFILE(Trans2_setfsinfo);
9584 case TRANSACT2_QPATHINFO:
9585 case TRANSACT2_QFILEINFO:
9587 START_PROFILE(Trans2_qpathinfo);
9588 call_trans2qfilepathinfo(conn, req, state->call,
9589 &state->param, state->total_param,
9590 &state->data, state->total_data,
9591 state->max_data_return);
9592 END_PROFILE(Trans2_qpathinfo);
9596 case TRANSACT2_SETPATHINFO:
9597 case TRANSACT2_SETFILEINFO:
9599 START_PROFILE(Trans2_setpathinfo);
9600 call_trans2setfilepathinfo(conn, req, state->call,
9601 &state->param, state->total_param,
9602 &state->data, state->total_data,
9603 state->max_data_return);
9604 END_PROFILE(Trans2_setpathinfo);
9608 case TRANSACT2_FINDNOTIFYFIRST:
9610 START_PROFILE(Trans2_findnotifyfirst);
9611 call_trans2findnotifyfirst(conn, req,
9612 &state->param, state->total_param,
9613 &state->data, state->total_data,
9614 state->max_data_return);
9615 END_PROFILE(Trans2_findnotifyfirst);
9619 case TRANSACT2_FINDNOTIFYNEXT:
9621 START_PROFILE(Trans2_findnotifynext);
9622 call_trans2findnotifynext(conn, req,
9623 &state->param, state->total_param,
9624 &state->data, state->total_data,
9625 state->max_data_return);
9626 END_PROFILE(Trans2_findnotifynext);
9630 case TRANSACT2_MKDIR:
9632 START_PROFILE(Trans2_mkdir);
9633 call_trans2mkdir(conn, req,
9634 &state->param, state->total_param,
9635 &state->data, state->total_data,
9636 state->max_data_return);
9637 END_PROFILE(Trans2_mkdir);
9641 case TRANSACT2_GET_DFS_REFERRAL:
9643 START_PROFILE(Trans2_get_dfs_referral);
9644 call_trans2getdfsreferral(conn, req,
9645 &state->param, state->total_param,
9646 &state->data, state->total_data,
9647 state->max_data_return);
9648 END_PROFILE(Trans2_get_dfs_referral);
9652 case TRANSACT2_IOCTL:
9654 START_PROFILE(Trans2_ioctl);
9655 call_trans2ioctl(conn, req,
9656 &state->param, state->total_param,
9657 &state->data, state->total_data,
9658 state->max_data_return);
9659 END_PROFILE(Trans2_ioctl);
9664 /* Error in request */
9665 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9666 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9670 /****************************************************************************
9671 Reply to a SMBtrans2.
9672 ****************************************************************************/
9674 void reply_trans2(struct smb_request *req)
9676 connection_struct *conn = req->conn;
9681 unsigned int tran_call;
9682 struct trans_state *state;
9685 START_PROFILE(SMBtrans2);
9687 if (req->wct < 14) {
9688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9689 END_PROFILE(SMBtrans2);
9693 dsoff = SVAL(req->vwv+12, 0);
9694 dscnt = SVAL(req->vwv+11, 0);
9695 psoff = SVAL(req->vwv+10, 0);
9696 pscnt = SVAL(req->vwv+9, 0);
9697 tran_call = SVAL(req->vwv+14, 0);
9699 result = allow_new_trans(conn->pending_trans, req->mid);
9700 if (!NT_STATUS_IS_OK(result)) {
9701 DEBUG(2, ("Got invalid trans2 request: %s\n",
9702 nt_errstr(result)));
9703 reply_nterror(req, result);
9704 END_PROFILE(SMBtrans2);
9709 switch (tran_call) {
9710 /* List the allowed trans2 calls on IPC$ */
9711 case TRANSACT2_OPEN:
9712 case TRANSACT2_GET_DFS_REFERRAL:
9713 case TRANSACT2_QFILEINFO:
9714 case TRANSACT2_QFSINFO:
9715 case TRANSACT2_SETFSINFO:
9718 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9719 END_PROFILE(SMBtrans2);
9724 if ((state = talloc(conn, struct trans_state)) == NULL) {
9725 DEBUG(0, ("talloc failed\n"));
9726 reply_nterror(req, NT_STATUS_NO_MEMORY);
9727 END_PROFILE(SMBtrans2);
9731 state->cmd = SMBtrans2;
9733 state->mid = req->mid;
9734 state->vuid = req->vuid;
9735 state->setup_count = SVAL(req->vwv+13, 0);
9736 state->setup = NULL;
9737 state->total_param = SVAL(req->vwv+0, 0);
9738 state->param = NULL;
9739 state->total_data = SVAL(req->vwv+1, 0);
9741 state->max_param_return = SVAL(req->vwv+2, 0);
9742 state->max_data_return = SVAL(req->vwv+3, 0);
9743 state->max_setup_return = SVAL(req->vwv+4, 0);
9744 state->close_on_completion = BITSETW(req->vwv+5, 0);
9745 state->one_way = BITSETW(req->vwv+5, 1);
9747 state->call = tran_call;
9749 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9750 is so as a sanity check */
9751 if (state->setup_count != 1) {
9753 * Need to have rc=0 for ioctl to get job id for OS/2.
9754 * Network printing will fail if function is not successful.
9755 * Similar function in reply.c will be used if protocol
9756 * is LANMAN1.0 instead of LM1.2X002.
9757 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9758 * outbuf doesn't have to be set(only job id is used).
9760 if ( (state->setup_count == 4)
9761 && (tran_call == TRANSACT2_IOCTL)
9762 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9763 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9764 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9766 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9767 DEBUG(2,("Transaction is %d\n",tran_call));
9769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9770 END_PROFILE(SMBtrans2);
9775 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9778 if (state->total_data) {
9780 if (trans_oob(state->total_data, 0, dscnt)
9781 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9785 /* Can't use talloc here, the core routines do realloc on the
9786 * params and data. */
9787 state->data = (char *)SMB_MALLOC(state->total_data);
9788 if (state->data == NULL) {
9789 DEBUG(0,("reply_trans2: data malloc fail for %u "
9790 "bytes !\n", (unsigned int)state->total_data));
9792 reply_nterror(req, NT_STATUS_NO_MEMORY);
9793 END_PROFILE(SMBtrans2);
9797 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9800 if (state->total_param) {
9802 if (trans_oob(state->total_param, 0, pscnt)
9803 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9807 /* Can't use talloc here, the core routines do realloc on the
9808 * params and data. */
9809 state->param = (char *)SMB_MALLOC(state->total_param);
9810 if (state->param == NULL) {
9811 DEBUG(0,("reply_trans: param malloc fail for %u "
9812 "bytes !\n", (unsigned int)state->total_param));
9813 SAFE_FREE(state->data);
9815 reply_nterror(req, NT_STATUS_NO_MEMORY);
9816 END_PROFILE(SMBtrans2);
9820 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9823 state->received_data = dscnt;
9824 state->received_param = pscnt;
9826 if ((state->received_param == state->total_param) &&
9827 (state->received_data == state->total_data)) {
9829 handle_trans2(conn, req, state);
9831 SAFE_FREE(state->data);
9832 SAFE_FREE(state->param);
9834 END_PROFILE(SMBtrans2);
9838 DLIST_ADD(conn->pending_trans, state);
9840 /* We need to send an interim response then receive the rest
9841 of the parameter/data bytes */
9842 reply_outbuf(req, 0, 0);
9843 show_msg((char *)req->outbuf);
9844 END_PROFILE(SMBtrans2);
9849 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9850 SAFE_FREE(state->data);
9851 SAFE_FREE(state->param);
9853 END_PROFILE(SMBtrans2);
9854 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9858 /****************************************************************************
9859 Reply to a SMBtranss2
9860 ****************************************************************************/
9862 void reply_transs2(struct smb_request *req)
9864 connection_struct *conn = req->conn;
9865 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9866 struct trans_state *state;
9868 START_PROFILE(SMBtranss2);
9870 show_msg((const char *)req->inbuf);
9872 /* Windows clients expect all replies to
9873 a transact secondary (SMBtranss2 0x33)
9874 to have a command code of transact
9875 (SMBtrans2 0x32). See bug #8989
9876 and also [MS-CIFS] section 2.2.4.47.2
9879 req->cmd = SMBtrans2;
9882 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9883 END_PROFILE(SMBtranss2);
9887 for (state = conn->pending_trans; state != NULL;
9888 state = state->next) {
9889 if (state->mid == req->mid) {
9894 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9896 END_PROFILE(SMBtranss2);
9900 /* Revise state->total_param and state->total_data in case they have
9901 changed downwards */
9903 if (SVAL(req->vwv+0, 0) < state->total_param)
9904 state->total_param = SVAL(req->vwv+0, 0);
9905 if (SVAL(req->vwv+1, 0) < state->total_data)
9906 state->total_data = SVAL(req->vwv+1, 0);
9908 pcnt = SVAL(req->vwv+2, 0);
9909 poff = SVAL(req->vwv+3, 0);
9910 pdisp = SVAL(req->vwv+4, 0);
9912 dcnt = SVAL(req->vwv+5, 0);
9913 doff = SVAL(req->vwv+6, 0);
9914 ddisp = SVAL(req->vwv+7, 0);
9916 state->received_param += pcnt;
9917 state->received_data += dcnt;
9919 if ((state->received_data > state->total_data) ||
9920 (state->received_param > state->total_param))
9924 if (trans_oob(state->total_param, pdisp, pcnt)
9925 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9928 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9932 if (trans_oob(state->total_data, ddisp, dcnt)
9933 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9936 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9939 if ((state->received_param < state->total_param) ||
9940 (state->received_data < state->total_data)) {
9941 END_PROFILE(SMBtranss2);
9945 handle_trans2(conn, req, state);
9947 DLIST_REMOVE(conn->pending_trans, state);
9948 SAFE_FREE(state->data);
9949 SAFE_FREE(state->param);
9952 END_PROFILE(SMBtranss2);
9957 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9958 DLIST_REMOVE(conn->pending_trans, state);
9959 SAFE_FREE(state->data);
9960 SAFE_FREE(state->param);
9962 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9963 END_PROFILE(SMBtranss2);