2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
55 const SMB_STRUCT_STAT *psbuf);
57 /****************************************************************************
58 Check if an open file handle or smb_fname is a symlink.
59 ****************************************************************************/
61 static NTSTATUS refuse_symlink(connection_struct *conn,
62 const files_struct *fsp,
63 const struct smb_filename *smb_fname)
66 const SMB_STRUCT_STAT *pst = NULL;
69 pst = &fsp->fsp_name->st;
74 if (!VALID_STAT(*pst)) {
75 int ret = vfs_stat_smb_basename(conn,
78 if (ret == -1 && errno != ENOENT) {
79 return map_nt_error_from_unix(errno);
80 } else if (ret == -1) {
81 /* it's not a symlink.. */
87 if (S_ISLNK(pst->st_ex_mode)) {
88 return NT_STATUS_ACCESS_DENIED;
93 NTSTATUS check_access_fsp(const struct files_struct *fsp,
96 if (!(fsp->access_mask & access_mask)) {
97 return NT_STATUS_ACCESS_DENIED;
102 /********************************************************************
103 The canonical "check access" based on object handle or path function.
104 ********************************************************************/
106 NTSTATUS check_access(connection_struct *conn,
108 const struct smb_filename *smb_fname,
109 uint32_t access_mask)
114 status = check_access_fsp(fsp, access_mask);
116 status = smbd_check_access_rights(conn, smb_fname,
123 /********************************************************************
124 Roundup a value to the nearest allocation roundup size boundary.
125 Only do this for Windows clients.
126 ********************************************************************/
128 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
130 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
132 /* Only roundup for Windows clients. */
133 enum remote_arch_types ra_type = get_remote_arch();
134 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
135 val = SMB_ROUNDUP(val,rval);
140 /********************************************************************
141 Create a 64 bit FileIndex. If the file is on the same device as
142 the root of the share, just return the 64-bit inode. If it isn't,
143 mangle as we used to do.
144 ********************************************************************/
146 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
149 if (conn->sconn->aapl_zero_file_id) {
152 if (conn->base_share_dev == psbuf->st_ex_dev) {
153 return (uint64_t)psbuf->st_ex_ino;
155 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
156 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
161 /********************************************************************
162 Globally (for this connection / multi-channel) disable file-ID
163 calculation. This is required to be global because it serves
164 Macs in AAPL mode, which is globally set.
165 ********************************************************************/
166 void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
168 sconn->aapl_zero_file_id = true;
171 /****************************************************************************
172 Utility functions for dealing with extended attributes.
173 ****************************************************************************/
175 /****************************************************************************
176 Refuse to allow clients to overwrite our private xattrs.
177 ****************************************************************************/
179 bool samba_private_attr_name(const char *unix_ea_name)
181 static const char * const prohibited_ea_names[] = {
182 SAMBA_POSIX_INHERITANCE_EA_NAME,
183 SAMBA_XATTR_DOS_ATTRIB,
191 for (i = 0; prohibited_ea_names[i]; i++) {
192 if (strequal( prohibited_ea_names[i], unix_ea_name))
195 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
196 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
202 /****************************************************************************
203 Get one EA value. Fill in a struct ea_struct.
204 ****************************************************************************/
206 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
207 files_struct *fsp, const char *fname,
208 const char *ea_name, struct ea_struct *pea)
210 /* Get the value of this xattr. Max size is 64k. */
211 size_t attr_size = 256;
217 val = talloc_realloc(mem_ctx, val, char, attr_size);
219 return NT_STATUS_NO_MEMORY;
222 if (fsp && fsp->fh->fd != -1) {
223 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
225 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
228 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
234 return map_nt_error_from_unix(errno);
237 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
238 dump_data(10, (uint8_t *)val, sizeret);
241 if (strnequal(ea_name, "user.", 5)) {
242 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
244 pea->name = talloc_strdup(mem_ctx, ea_name);
246 if (pea->name == NULL) {
248 return NT_STATUS_NO_MEMORY;
250 pea->value.data = (unsigned char *)val;
251 pea->value.length = (size_t)sizeret;
255 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
256 connection_struct *conn,
258 const struct smb_filename *smb_fname,
263 /* Get a list of all xattrs. Max namesize is 64k. */
264 size_t ea_namelist_size = 1024;
265 char *ea_namelist = smallbuf;
266 char *to_free = NULL;
271 ssize_t sizeret = -1;
279 status = refuse_symlink(conn, fsp, smb_fname);
280 if (!NT_STATUS_IS_OK(status)) {
282 * Just return no EA's on a symlink.
287 if (fsp && fsp->fh->fd != -1) {
288 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
291 sizeret = SMB_VFS_LISTXATTR(conn,
292 smb_fname->base_name,
297 if ((sizeret == -1) && (errno == ERANGE)) {
298 ea_namelist_size = 65536;
299 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
300 if (ea_namelist == NULL) {
301 return NT_STATUS_NO_MEMORY;
303 to_free = ea_namelist;
305 if (fsp && fsp->fh->fd != -1) {
306 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
309 sizeret = SMB_VFS_LISTXATTR(conn,
310 smb_fname->base_name,
317 status = map_nt_error_from_unix(errno);
318 TALLOC_FREE(to_free);
322 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
325 TALLOC_FREE(to_free);
330 * Ensure the result is 0-terminated
333 if (ea_namelist[sizeret-1] != '\0') {
334 TALLOC_FREE(to_free);
335 return NT_STATUS_INTERNAL_ERROR;
343 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
347 *pnum_names = num_names;
349 if (pnames == NULL) {
350 TALLOC_FREE(to_free);
354 names = talloc_array(mem_ctx, char *, num_names);
356 DEBUG(0, ("talloc failed\n"));
357 TALLOC_FREE(to_free);
358 return NT_STATUS_NO_MEMORY;
361 if (ea_namelist == smallbuf) {
362 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
363 if (ea_namelist == NULL) {
365 return NT_STATUS_NO_MEMORY;
368 talloc_steal(names, ea_namelist);
370 ea_namelist = talloc_realloc(names, ea_namelist, char,
372 if (ea_namelist == NULL) {
374 return NT_STATUS_NO_MEMORY;
380 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
381 names[num_names++] = p;
389 /****************************************************************************
390 Return a linked list of the total EA's. Plus the total size
391 ****************************************************************************/
393 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
394 connection_struct *conn,
396 const struct smb_filename *smb_fname,
397 size_t *pea_total_len,
398 struct ea_list **ea_list)
400 /* Get a list of all xattrs. Max namesize is 64k. */
403 struct ea_list *ea_list_head = NULL;
404 bool posix_pathnames = false;
410 if (!lp_ea_support(SNUM(conn))) {
416 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
418 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
421 status = get_ea_names_from_file(talloc_tos(),
428 if (!NT_STATUS_IS_OK(status)) {
432 if (num_names == 0) {
436 for (i=0; i<num_names; i++) {
437 struct ea_list *listp;
440 if (strnequal(names[i], "system.", 7)
441 || samba_private_attr_name(names[i]))
445 * Filter out any underlying POSIX EA names
446 * that a Windows client can't handle.
448 if (!posix_pathnames &&
449 is_invalid_windows_ea_name(names[i])) {
453 listp = talloc(mem_ctx, struct ea_list);
455 return NT_STATUS_NO_MEMORY;
458 status = get_ea_value(listp,
461 smb_fname->base_name,
465 if (!NT_STATUS_IS_OK(status)) {
470 if (listp->ea.value.length == 0) {
472 * We can never return a zero length EA.
473 * Windows reports the EA's as corrupted.
479 push_ascii_fstring(dos_ea_name, listp->ea.name);
482 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
484 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
485 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
486 (unsigned int)listp->ea.value.length));
488 DLIST_ADD_END(ea_list_head, listp);
492 /* Add on 4 for total length. */
493 if (*pea_total_len) {
497 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
498 (unsigned int)*pea_total_len));
500 *ea_list = ea_list_head;
504 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
505 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
510 if (!lp_ea_support(SNUM(conn))) {
514 if (is_ntfs_stream_smb_fname(smb_fname)) {
515 return NT_STATUS_INVALID_PARAMETER;
518 return get_ea_list_from_file_path(mem_ctx,
526 /****************************************************************************
527 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
529 ****************************************************************************/
531 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
532 connection_struct *conn, struct ea_list *ea_list)
534 unsigned int ret_data_size = 4;
537 SMB_ASSERT(total_data_size >= 4);
539 if (!lp_ea_support(SNUM(conn))) {
544 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
547 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
548 dos_namelen = strlen(dos_ea_name);
549 if (dos_namelen > 255 || dos_namelen == 0) {
552 if (ea_list->ea.value.length > 65535) {
555 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
559 /* We know we have room. */
560 SCVAL(p,0,ea_list->ea.flags);
561 SCVAL(p,1,dos_namelen);
562 SSVAL(p,2,ea_list->ea.value.length);
563 strlcpy(p+4, dos_ea_name, dos_namelen+1);
564 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
566 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
567 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
570 ret_data_size = PTR_DIFF(p, pdata);
571 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
572 SIVAL(pdata,0,ret_data_size);
573 return ret_data_size;
576 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
578 unsigned int total_data_size,
579 unsigned int *ret_data_size,
580 connection_struct *conn,
581 struct ea_list *ea_list)
583 uint8_t *p = (uint8_t *)pdata;
584 uint8_t *last_start = NULL;
585 bool do_store_data = (pdata != NULL);
589 if (!lp_ea_support(SNUM(conn))) {
590 return NT_STATUS_NO_EAS_ON_FILE;
593 for (; ea_list; ea_list = ea_list->next) {
599 if (last_start != NULL && do_store_data) {
600 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
604 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
605 dos_namelen = strlen(dos_ea_name);
606 if (dos_namelen > 255 || dos_namelen == 0) {
607 return NT_STATUS_INTERNAL_ERROR;
609 if (ea_list->ea.value.length > 65535) {
610 return NT_STATUS_INTERNAL_ERROR;
613 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
616 pad = (4 - (this_size % 4)) % 4;
621 if (this_size > total_data_size) {
622 return NT_STATUS_INFO_LENGTH_MISMATCH;
625 /* We know we have room. */
626 SIVAL(p, 0x00, 0); /* next offset */
627 SCVAL(p, 0x04, ea_list->ea.flags);
628 SCVAL(p, 0x05, dos_namelen);
629 SSVAL(p, 0x06, ea_list->ea.value.length);
630 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
631 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
633 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
637 total_data_size -= this_size;
643 *ret_data_size = PTR_DIFF(p, pdata);
644 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
648 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
650 size_t total_ea_len = 0;
652 struct ea_list *ea_list = NULL;
654 if (!lp_ea_support(SNUM(conn))) {
657 mem_ctx = talloc_stackframe();
659 /* If this is a stream fsp, then we need to instead find the
660 * estimated ea len from the main file, not the stream
661 * (streams cannot have EAs), but the estimate isn't just 0 in
663 if (is_ntfs_stream_smb_fname(smb_fname)) {
666 (void)get_ea_list_from_file_path(mem_ctx,
672 if(conn->sconn->using_smb2) {
674 unsigned int ret_data_size;
676 * We're going to be using fill_ea_chained_buffer() to
677 * marshall EA's - this size is significantly larger
678 * than the SMB1 buffer. Re-calculate the size without
681 status = fill_ea_chained_buffer(mem_ctx,
687 if (!NT_STATUS_IS_OK(status)) {
690 total_ea_len = ret_data_size;
692 TALLOC_FREE(mem_ctx);
696 /****************************************************************************
697 Ensure the EA name is case insensitive by matching any existing EA name.
698 ****************************************************************************/
700 static void canonicalize_ea_name(connection_struct *conn,
702 const struct smb_filename *smb_fname,
703 fstring unix_ea_name)
706 TALLOC_CTX *mem_ctx = talloc_tos();
707 struct ea_list *ea_list;
708 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
714 if (!NT_STATUS_IS_OK(status)) {
718 for (; ea_list; ea_list = ea_list->next) {
719 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
720 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
721 &unix_ea_name[5], ea_list->ea.name));
722 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
728 /****************************************************************************
729 Set or delete an extended attribute.
730 ****************************************************************************/
732 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
733 const struct smb_filename *smb_fname, struct ea_list *ea_list)
736 bool posix_pathnames = false;
738 if (!lp_ea_support(SNUM(conn))) {
739 return NT_STATUS_EAS_NOT_SUPPORTED;
744 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
746 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
749 status = refuse_symlink(conn, fsp, smb_fname);
750 if (!NT_STATUS_IS_OK(status)) {
754 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
755 if (!NT_STATUS_IS_OK(status)) {
759 /* Setting EAs on streams isn't supported. */
760 if (is_ntfs_stream_smb_fname(smb_fname)) {
761 return NT_STATUS_INVALID_PARAMETER;
765 * Filter out invalid Windows EA names - before
766 * we set *any* of them.
769 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
770 return STATUS_INVALID_EA_NAME;
773 for (;ea_list; ea_list = ea_list->next) {
775 fstring unix_ea_name;
777 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
778 fstrcat(unix_ea_name, ea_list->ea.name);
780 canonicalize_ea_name(conn,
785 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
787 if (samba_private_attr_name(unix_ea_name)) {
788 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
789 return NT_STATUS_ACCESS_DENIED;
792 if (ea_list->ea.value.length == 0) {
793 /* Remove the attribute. */
794 if (fsp && (fsp->fh->fd != -1)) {
795 DEBUG(10,("set_ea: deleting ea name %s on "
796 "file %s by file descriptor.\n",
797 unix_ea_name, fsp_str_dbg(fsp)));
798 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
800 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
801 unix_ea_name, smb_fname->base_name));
802 ret = SMB_VFS_REMOVEXATTR(conn,
803 smb_fname->base_name,
807 /* Removing a non existent attribute always succeeds. */
808 if (ret == -1 && errno == ENOATTR) {
809 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
815 if (fsp && (fsp->fh->fd != -1)) {
816 DEBUG(10,("set_ea: setting ea name %s on file "
817 "%s by file descriptor.\n",
818 unix_ea_name, fsp_str_dbg(fsp)));
819 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
820 ea_list->ea.value.data, ea_list->ea.value.length, 0);
822 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
823 unix_ea_name, smb_fname->base_name));
824 ret = SMB_VFS_SETXATTR(conn,
825 smb_fname->base_name,
827 ea_list->ea.value.data,
828 ea_list->ea.value.length,
835 if (errno == ENOTSUP) {
836 return NT_STATUS_EAS_NOT_SUPPORTED;
839 return map_nt_error_from_unix(errno);
845 /****************************************************************************
846 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
847 ****************************************************************************/
849 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
851 struct ea_list *ea_list_head = NULL;
852 size_t converted_size, offset = 0;
854 while (offset + 2 < data_size) {
855 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
856 unsigned int namelen = CVAL(pdata,offset);
858 offset++; /* Go past the namelen byte. */
860 /* integer wrap paranioa. */
861 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
862 (offset > data_size) || (namelen > data_size) ||
863 (offset + namelen >= data_size)) {
866 /* Ensure the name is null terminated. */
867 if (pdata[offset + namelen] != '\0') {
870 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
872 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
873 "failed: %s", strerror(errno)));
879 offset += (namelen + 1); /* Go past the name + terminating zero. */
880 DLIST_ADD_END(ea_list_head, eal);
881 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
887 /****************************************************************************
888 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
889 ****************************************************************************/
891 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
893 struct ea_list *ea_list_head = NULL;
895 size_t bytes_used = 0;
897 while (offset < data_size) {
898 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
904 DLIST_ADD_END(ea_list_head, eal);
905 offset += bytes_used;
911 /****************************************************************************
912 Count the total EA size needed.
913 ****************************************************************************/
915 static size_t ea_list_size(struct ea_list *ealist)
918 struct ea_list *listp;
921 for (listp = ealist; listp; listp = listp->next) {
922 push_ascii_fstring(dos_ea_name, listp->ea.name);
923 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
925 /* Add on 4 for total length. */
933 /****************************************************************************
934 Return a union of EA's from a file list and a list of names.
935 The TALLOC context for the two lists *MUST* be identical as we steal
936 memory from one list to add to another. JRA.
937 ****************************************************************************/
939 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
941 struct ea_list *nlistp, *flistp;
943 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
944 for (flistp = file_list; flistp; flistp = flistp->next) {
945 if (strequal(nlistp->ea.name, flistp->ea.name)) {
951 /* Copy the data from this entry. */
952 nlistp->ea.flags = flistp->ea.flags;
953 nlistp->ea.value = flistp->ea.value;
956 nlistp->ea.flags = 0;
957 ZERO_STRUCT(nlistp->ea.value);
961 *total_ea_len = ea_list_size(name_list);
965 /****************************************************************************
966 Send the required number of replies back.
967 We assume all fields other than the data fields are
968 set correctly for the type of call.
969 HACK ! Always assumes smb_setup field is zero.
970 ****************************************************************************/
972 void send_trans2_replies(connection_struct *conn,
973 struct smb_request *req,
981 /* As we are using a protocol > LANMAN1 then the max_send
982 variable must have been set in the sessetupX call.
983 This takes precedence over the max_xmit field in the
984 global struct. These different max_xmit variables should
985 be merged as this is now too confusing */
987 int data_to_send = datasize;
988 int params_to_send = paramsize;
990 const char *pp = params;
991 const char *pd = pdata;
992 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
993 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
994 int data_alignment_offset = 0;
995 bool overflow = False;
996 struct smbXsrv_connection *xconn = req->xconn;
997 int max_send = xconn->smb1.sessions.max_send;
999 /* Modify the data_to_send and datasize and set the error if
1000 we're trying to send more than max_data_bytes. We still send
1001 the part of the packet(s) that fit. Strange, but needed
1004 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1005 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1006 max_data_bytes, datasize ));
1007 datasize = data_to_send = max_data_bytes;
1011 /* If there genuinely are no parameters or data to send just send the empty packet */
1013 if(params_to_send == 0 && data_to_send == 0) {
1014 reply_outbuf(req, 10, 0);
1015 if (NT_STATUS_V(status)) {
1018 ntstatus_to_dos(status, &eclass, &ecode);
1019 error_packet_set((char *)req->outbuf,
1020 eclass, ecode, status,
1023 show_msg((char *)req->outbuf);
1024 if (!srv_send_smb(xconn,
1025 (char *)req->outbuf,
1026 true, req->seqnum+1,
1027 IS_CONN_ENCRYPTED(conn),
1029 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1031 TALLOC_FREE(req->outbuf);
1035 /* When sending params and data ensure that both are nicely aligned */
1036 /* Only do this alignment when there is also data to send - else
1037 can cause NT redirector problems. */
1039 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1040 data_alignment_offset = 4 - (params_to_send % 4);
1042 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1043 /* The alignment_offset is to align the param bytes on an even byte
1044 boundary. NT 4.0 Beta needs this to work correctly. */
1046 useable_space = max_send - (smb_size
1049 + data_alignment_offset);
1051 if (useable_space < 0) {
1052 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1053 "= %d!!!", useable_space));
1054 exit_server_cleanly("send_trans2_replies: Not enough space");
1057 while (params_to_send || data_to_send) {
1058 /* Calculate whether we will totally or partially fill this packet */
1060 total_sent_thistime = params_to_send + data_to_send;
1062 /* We can never send more than useable_space */
1064 * Note that 'useable_space' does not include the alignment offsets,
1065 * but we must include the alignment offsets in the calculation of
1066 * the length of the data we send over the wire, as the alignment offsets
1067 * are sent here. Fix from Marc_Jacobsen@hp.com.
1070 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1072 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1073 + data_alignment_offset);
1075 /* Set total params and data to be sent */
1076 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1077 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1079 /* Calculate how many parameters and data we can fit into
1080 * this packet. Parameters get precedence
1083 params_sent_thistime = MIN(params_to_send,useable_space);
1084 data_sent_thistime = useable_space - params_sent_thistime;
1085 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1087 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1089 /* smb_proff is the offset from the start of the SMB header to the
1090 parameter bytes, however the first 4 bytes of outbuf are
1091 the Netbios over TCP header. Thus use smb_base() to subtract
1092 them from the calculation */
1094 SSVAL(req->outbuf,smb_proff,
1095 ((smb_buf(req->outbuf)+alignment_offset)
1096 - smb_base(req->outbuf)));
1098 if(params_sent_thistime == 0)
1099 SSVAL(req->outbuf,smb_prdisp,0);
1101 /* Absolute displacement of param bytes sent in this packet */
1102 SSVAL(req->outbuf,smb_prdisp,pp - params);
1104 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1105 if(data_sent_thistime == 0) {
1106 SSVAL(req->outbuf,smb_droff,0);
1107 SSVAL(req->outbuf,smb_drdisp, 0);
1109 /* The offset of the data bytes is the offset of the
1110 parameter bytes plus the number of parameters being sent this time */
1111 SSVAL(req->outbuf, smb_droff,
1112 ((smb_buf(req->outbuf)+alignment_offset)
1113 - smb_base(req->outbuf))
1114 + params_sent_thistime + data_alignment_offset);
1115 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1118 /* Initialize the padding for alignment */
1120 if (alignment_offset != 0) {
1121 memset(smb_buf(req->outbuf), 0, alignment_offset);
1124 /* Copy the param bytes into the packet */
1126 if(params_sent_thistime) {
1127 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1128 params_sent_thistime);
1131 /* Copy in the data bytes */
1132 if(data_sent_thistime) {
1133 if (data_alignment_offset != 0) {
1134 memset((smb_buf(req->outbuf)+alignment_offset+
1135 params_sent_thistime), 0,
1136 data_alignment_offset);
1138 memcpy(smb_buf(req->outbuf)+alignment_offset
1139 +params_sent_thistime+data_alignment_offset,
1140 pd,data_sent_thistime);
1143 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1144 params_sent_thistime, data_sent_thistime, useable_space));
1145 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1146 params_to_send, data_to_send, paramsize, datasize));
1149 error_packet_set((char *)req->outbuf,
1150 ERRDOS,ERRbufferoverflow,
1151 STATUS_BUFFER_OVERFLOW,
1153 } else if (NT_STATUS_V(status)) {
1156 ntstatus_to_dos(status, &eclass, &ecode);
1157 error_packet_set((char *)req->outbuf,
1158 eclass, ecode, status,
1162 /* Send the packet */
1163 show_msg((char *)req->outbuf);
1164 if (!srv_send_smb(xconn,
1165 (char *)req->outbuf,
1166 true, req->seqnum+1,
1167 IS_CONN_ENCRYPTED(conn),
1169 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1171 TALLOC_FREE(req->outbuf);
1173 pp += params_sent_thistime;
1174 pd += data_sent_thistime;
1176 params_to_send -= params_sent_thistime;
1177 data_to_send -= data_sent_thistime;
1180 if(params_to_send < 0 || data_to_send < 0) {
1181 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1182 params_to_send, data_to_send));
1190 /****************************************************************************
1191 Reply to a TRANSACT2_OPEN.
1192 ****************************************************************************/
1194 static void call_trans2open(connection_struct *conn,
1195 struct smb_request *req,
1196 char **pparams, int total_params,
1197 char **ppdata, int total_data,
1198 unsigned int max_data_bytes)
1200 struct smb_filename *smb_fname = NULL;
1201 char *params = *pparams;
1202 char *pdata = *ppdata;
1205 bool oplock_request;
1207 bool return_additional_info;
1216 int fattr=0,mtime=0;
1217 SMB_INO_T inode = 0;
1220 struct ea_list *ea_list = NULL;
1223 uint32_t access_mask;
1224 uint32_t share_mode;
1225 uint32_t create_disposition;
1226 uint32_t create_options = 0;
1227 uint32_t private_flags = 0;
1228 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1229 TALLOC_CTX *ctx = talloc_tos();
1232 * Ensure we have enough parameters to perform the operation.
1235 if (total_params < 29) {
1236 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1240 flags = SVAL(params, 0);
1241 deny_mode = SVAL(params, 2);
1242 open_attr = SVAL(params,6);
1243 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1244 if (oplock_request) {
1245 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1249 return_additional_info = BITSETW(params,0);
1250 open_sattr = SVAL(params, 4);
1251 open_time = make_unix_date3(params+8);
1253 open_ofun = SVAL(params,12);
1254 open_size = IVAL(params,14);
1255 pname = ¶ms[28];
1258 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1262 if (req->posix_pathnames) {
1263 srvstr_get_path_posix(ctx,
1272 srvstr_get_path(ctx,
1281 if (!NT_STATUS_IS_OK(status)) {
1282 reply_nterror(req, status);
1286 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1287 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1288 (unsigned int)open_ofun, open_size));
1290 status = filename_convert(ctx,
1292 req->flags2 & FLAGS2_DFS_PATHNAMES,
1297 if (!NT_STATUS_IS_OK(status)) {
1298 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1299 reply_botherror(req,
1300 NT_STATUS_PATH_NOT_COVERED,
1301 ERRSRV, ERRbadpath);
1304 reply_nterror(req, status);
1308 if (open_ofun == 0) {
1309 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1313 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1315 &access_mask, &share_mode,
1316 &create_disposition,
1319 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1323 /* Any data in this call is an EA list. */
1324 if (total_data && (total_data != 4)) {
1325 if (total_data < 10) {
1326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1330 if (IVAL(pdata,0) > total_data) {
1331 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1332 IVAL(pdata,0), (unsigned int)total_data));
1333 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1337 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1340 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1344 if (!lp_ea_support(SNUM(conn))) {
1345 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1349 if (!req->posix_pathnames &&
1350 ea_list_has_invalid_name(ea_list)) {
1352 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1353 if(*pparams == NULL ) {
1354 reply_nterror(req, NT_STATUS_NO_MEMORY);
1358 memset(params, '\0', param_len);
1359 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1360 params, param_len, NULL, 0, max_data_bytes);
1365 status = SMB_VFS_CREATE_FILE(
1368 0, /* root_dir_fid */
1369 smb_fname, /* fname */
1370 access_mask, /* access_mask */
1371 share_mode, /* share_access */
1372 create_disposition, /* create_disposition*/
1373 create_options, /* create_options */
1374 open_attr, /* file_attributes */
1375 oplock_request, /* oplock_request */
1377 open_size, /* allocation_size */
1380 ea_list, /* ea_list */
1382 &smb_action, /* psbuf */
1383 NULL, NULL); /* create context */
1385 if (!NT_STATUS_IS_OK(status)) {
1386 if (open_was_deferred(req->xconn, req->mid)) {
1387 /* We have re-scheduled this call. */
1390 reply_openerror(req, status);
1394 size = get_file_size_stat(&smb_fname->st);
1395 fattr = dos_mode(conn, smb_fname);
1396 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1397 inode = smb_fname->st.st_ex_ino;
1398 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1399 close_file(req, fsp, ERROR_CLOSE);
1400 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1404 /* Realloc the size of parameters and data we will return */
1405 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1406 if(*pparams == NULL ) {
1407 reply_nterror(req, NT_STATUS_NO_MEMORY);
1412 SSVAL(params,0,fsp->fnum);
1413 SSVAL(params,2,fattr);
1414 srv_put_dos_date2(params,4, mtime);
1415 SIVAL(params,8, (uint32_t)size);
1416 SSVAL(params,12,deny_mode);
1417 SSVAL(params,14,0); /* open_type - file or directory. */
1418 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1420 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1421 smb_action |= EXTENDED_OPLOCK_GRANTED;
1424 SSVAL(params,18,smb_action);
1427 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1429 SIVAL(params,20,inode);
1430 SSVAL(params,24,0); /* Padding. */
1432 uint32_t ea_size = estimate_ea_size(conn, fsp,
1434 SIVAL(params, 26, ea_size);
1436 SIVAL(params, 26, 0);
1439 /* Send the required number of replies */
1440 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1442 TALLOC_FREE(smb_fname);
1445 /*********************************************************
1446 Routine to check if a given string matches exactly.
1447 as a special case a mask of "." does NOT match. That
1448 is required for correct wildcard semantics
1449 Case can be significant or not.
1450 **********************************************************/
1452 static bool exact_match(bool has_wild,
1453 bool case_sensitive,
1457 if (mask[0] == '.' && mask[1] == 0) {
1465 if (case_sensitive) {
1466 return strcmp(str,mask)==0;
1468 return strcasecmp_m(str,mask) == 0;
1472 /****************************************************************************
1473 Return the filetype for UNIX extensions.
1474 ****************************************************************************/
1476 static uint32_t unix_filetype(mode_t mode)
1479 return UNIX_TYPE_FILE;
1480 else if(S_ISDIR(mode))
1481 return UNIX_TYPE_DIR;
1483 else if(S_ISLNK(mode))
1484 return UNIX_TYPE_SYMLINK;
1487 else if(S_ISCHR(mode))
1488 return UNIX_TYPE_CHARDEV;
1491 else if(S_ISBLK(mode))
1492 return UNIX_TYPE_BLKDEV;
1495 else if(S_ISFIFO(mode))
1496 return UNIX_TYPE_FIFO;
1499 else if(S_ISSOCK(mode))
1500 return UNIX_TYPE_SOCKET;
1503 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1504 return UNIX_TYPE_UNKNOWN;
1507 /****************************************************************************
1508 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1509 ****************************************************************************/
1511 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1513 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1514 const SMB_STRUCT_STAT *psbuf,
1516 enum perm_type ptype,
1521 if (perms == SMB_MODE_NO_CHANGE) {
1522 if (!VALID_STAT(*psbuf)) {
1523 return NT_STATUS_INVALID_PARAMETER;
1525 *ret_perms = psbuf->st_ex_mode;
1526 return NT_STATUS_OK;
1530 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1531 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1532 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1533 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1534 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1535 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1536 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1537 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1538 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1540 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1543 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1546 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1549 if (ptype == PERM_NEW_FILE) {
1551 * "create mask"/"force create mode" are
1552 * only applied to new files, not existing ones.
1554 ret &= lp_create_mask(SNUM(conn));
1555 /* Add in force bits */
1556 ret |= lp_force_create_mode(SNUM(conn));
1557 } else if (ptype == PERM_NEW_DIR) {
1559 * "directory mask"/"force directory mode" are
1560 * only applied to new directories, not existing ones.
1562 ret &= lp_directory_mask(SNUM(conn));
1563 /* Add in force bits */
1564 ret |= lp_force_directory_mode(SNUM(conn));
1568 return NT_STATUS_OK;
1571 /****************************************************************************
1572 Needed to show the msdfs symlinks as directories. Modifies psbuf
1573 to be a directory if it's a msdfs link.
1574 ****************************************************************************/
1576 static bool check_msdfs_link(connection_struct *conn,
1577 const char *pathname,
1578 SMB_STRUCT_STAT *psbuf)
1580 int saved_errno = errno;
1581 if(lp_host_msdfs() &&
1582 lp_msdfs_root(SNUM(conn)) &&
1583 is_msdfs_link(conn, pathname, psbuf)) {
1585 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1588 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1589 errno = saved_errno;
1592 errno = saved_errno;
1597 /****************************************************************************
1598 Get a level dependent lanman2 dir entry.
1599 ****************************************************************************/
1601 struct smbd_dirptr_lanman2_state {
1602 connection_struct *conn;
1603 uint32_t info_level;
1604 bool check_mangled_names;
1606 bool got_exact_match;
1609 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1615 struct smbd_dirptr_lanman2_state *state =
1616 (struct smbd_dirptr_lanman2_state *)private_data;
1618 char mangled_name[13]; /* mangled 8.3 name. */
1622 /* Mangle fname if it's an illegal name. */
1623 if (mangle_must_mangle(dname, state->conn->params)) {
1625 * Slow path - ensure we can push the original name as UCS2. If
1626 * not, then just don't return this name.
1630 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1631 uint8_t *tmp = talloc_array(talloc_tos(),
1635 status = srvstr_push(NULL,
1636 FLAGS2_UNICODE_STRINGS,
1645 if (!NT_STATUS_IS_OK(status)) {
1649 ok = name_to_8_3(dname, mangled_name,
1650 true, state->conn->params);
1654 fname = mangled_name;
1659 got_match = exact_match(state->has_wild,
1660 state->conn->case_sensitive,
1662 state->got_exact_match = got_match;
1664 got_match = mask_match(fname, mask,
1665 state->conn->case_sensitive);
1668 if(!got_match && state->check_mangled_names &&
1669 !mangle_is_8_3(fname, false, state->conn->params)) {
1671 * It turns out that NT matches wildcards against
1672 * both long *and* short names. This may explain some
1673 * of the wildcard wierdness from old DOS clients
1674 * that some people have been seeing.... JRA.
1676 /* Force the mangling into 8.3. */
1677 ok = name_to_8_3(fname, mangled_name,
1678 false, state->conn->params);
1683 got_match = exact_match(state->has_wild,
1684 state->conn->case_sensitive,
1685 mangled_name, mask);
1686 state->got_exact_match = got_match;
1688 got_match = mask_match(mangled_name, mask,
1689 state->conn->case_sensitive);
1697 *_fname = talloc_strdup(ctx, fname);
1698 if (*_fname == NULL) {
1705 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1707 struct smb_filename *smb_fname,
1710 struct smbd_dirptr_lanman2_state *state =
1711 (struct smbd_dirptr_lanman2_state *)private_data;
1712 bool ms_dfs_link = false;
1715 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1716 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1717 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1718 "Couldn't lstat [%s] (%s)\n",
1719 smb_fname_str_dbg(smb_fname),
1723 } else if (!VALID_STAT(smb_fname->st) &&
1724 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1725 /* Needed to show the msdfs symlinks as
1728 ms_dfs_link = check_msdfs_link(state->conn,
1729 smb_fname->base_name,
1732 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1733 "Couldn't stat [%s] (%s)\n",
1734 smb_fname_str_dbg(smb_fname),
1741 mode = dos_mode_msdfs(state->conn, smb_fname);
1743 mode = dos_mode(state->conn, smb_fname);
1750 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1751 connection_struct *conn,
1753 uint32_t info_level,
1754 struct ea_list *name_list,
1755 bool check_mangled_names,
1756 bool requires_resume_key,
1759 const struct smb_filename *smb_fname,
1760 int space_remaining,
1766 uint64_t *last_entry_off)
1768 char *p, *q, *pdata = *ppdata;
1770 uint64_t file_size = 0;
1771 uint64_t allocation_size = 0;
1772 uint64_t file_index = 0;
1774 struct timespec mdate_ts = {0};
1775 struct timespec adate_ts = {0};
1776 struct timespec cdate_ts = {0};
1777 struct timespec create_date_ts = {0};
1778 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1780 char *last_entry_ptr;
1785 struct readdir_attr_data *readdir_attr_data = NULL;
1787 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1788 file_size = get_file_size_stat(&smb_fname->st);
1790 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1792 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1793 if (!NT_STATUS_IS_OK(status)) {
1794 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1799 file_index = get_FileIndex(conn, &smb_fname->st);
1801 mdate_ts = smb_fname->st.st_ex_mtime;
1802 adate_ts = smb_fname->st.st_ex_atime;
1803 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1804 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1806 if (lp_dos_filetime_resolution(SNUM(conn))) {
1807 dos_filetime_timespec(&create_date_ts);
1808 dos_filetime_timespec(&mdate_ts);
1809 dos_filetime_timespec(&adate_ts);
1810 dos_filetime_timespec(&cdate_ts);
1813 create_date = convert_timespec_to_time_t(create_date_ts);
1814 mdate = convert_timespec_to_time_t(mdate_ts);
1815 adate = convert_timespec_to_time_t(adate_ts);
1817 /* align the record */
1818 SMB_ASSERT(align >= 1);
1820 off = (int)PTR_DIFF(pdata, base_data);
1821 pad = (off + (align-1)) & ~(align-1);
1824 if (pad && pad > space_remaining) {
1825 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1826 "for padding (wanted %u, had %d)\n",
1829 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1833 /* initialize padding to 0 */
1835 memset(pdata, 0, pad);
1837 space_remaining -= pad;
1839 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1849 switch (info_level) {
1850 case SMB_FIND_INFO_STANDARD:
1851 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1852 if(requires_resume_key) {
1856 srv_put_dos_date2(p,0,create_date);
1857 srv_put_dos_date2(p,4,adate);
1858 srv_put_dos_date2(p,8,mdate);
1859 SIVAL(p,12,(uint32_t)file_size);
1860 SIVAL(p,16,(uint32_t)allocation_size);
1864 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1865 p += ucs2_align(base_data, p, 0);
1867 status = srvstr_push(base_data, flags2, p,
1868 fname, PTR_DIFF(end_data, p),
1869 STR_TERMINATE, &len);
1870 if (!NT_STATUS_IS_OK(status)) {
1873 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1875 SCVAL(nameptr, -1, len - 2);
1877 SCVAL(nameptr, -1, 0);
1881 SCVAL(nameptr, -1, len - 1);
1883 SCVAL(nameptr, -1, 0);
1889 case SMB_FIND_EA_SIZE:
1890 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1891 if (requires_resume_key) {
1895 srv_put_dos_date2(p,0,create_date);
1896 srv_put_dos_date2(p,4,adate);
1897 srv_put_dos_date2(p,8,mdate);
1898 SIVAL(p,12,(uint32_t)file_size);
1899 SIVAL(p,16,(uint32_t)allocation_size);
1902 unsigned int ea_size = estimate_ea_size(conn, NULL,
1904 SIVAL(p,22,ea_size); /* Extended attributes */
1908 status = srvstr_push(base_data, flags2,
1909 p, fname, PTR_DIFF(end_data, p),
1910 STR_TERMINATE | STR_NOALIGN, &len);
1911 if (!NT_STATUS_IS_OK(status)) {
1914 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1927 SCVAL(nameptr,0,len);
1929 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1932 case SMB_FIND_EA_LIST:
1934 struct ea_list *file_list = NULL;
1937 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1939 return NT_STATUS_INVALID_PARAMETER;
1941 if (requires_resume_key) {
1945 srv_put_dos_date2(p,0,create_date);
1946 srv_put_dos_date2(p,4,adate);
1947 srv_put_dos_date2(p,8,mdate);
1948 SIVAL(p,12,(uint32_t)file_size);
1949 SIVAL(p,16,(uint32_t)allocation_size);
1951 p += 22; /* p now points to the EA area. */
1953 status = get_ea_list_from_file(ctx, conn, NULL,
1955 &ea_len, &file_list);
1956 if (!NT_STATUS_IS_OK(status)) {
1959 name_list = ea_list_union(name_list, file_list, &ea_len);
1961 /* We need to determine if this entry will fit in the space available. */
1962 /* Max string size is 255 bytes. */
1963 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1964 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1965 "(wanted %u, had %d)\n",
1966 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1968 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1971 /* Push the ea_data followed by the name. */
1972 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1974 status = srvstr_push(base_data, flags2,
1975 p + 1, fname, PTR_DIFF(end_data, p+1),
1976 STR_TERMINATE | STR_NOALIGN, &len);
1977 if (!NT_STATUS_IS_OK(status)) {
1980 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1993 SCVAL(nameptr,0,len);
1995 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1999 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2000 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2001 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2003 SIVAL(p,0,reskey); p += 4;
2004 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2005 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2006 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2007 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2008 SOFF_T(p,0,file_size); p += 8;
2009 SOFF_T(p,0,allocation_size); p += 8;
2010 SIVAL(p,0,mode); p += 4;
2011 q = p; p += 4; /* q is placeholder for name length. */
2012 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2013 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2015 unsigned int ea_size = estimate_ea_size(conn, NULL,
2017 SIVAL(p,0,ea_size); /* Extended attributes */
2020 /* Clear the short name buffer. This is
2021 * IMPORTANT as not doing so will trigger
2022 * a Win2k client bug. JRA.
2024 if (!was_8_3 && check_mangled_names) {
2025 char mangled_name[13]; /* mangled 8.3 name. */
2026 if (!name_to_8_3(fname,mangled_name,True,
2028 /* Error - mangle failed ! */
2029 memset(mangled_name,'\0',12);
2031 mangled_name[12] = 0;
2032 status = srvstr_push(base_data, flags2,
2033 p+2, mangled_name, 24,
2034 STR_UPPER|STR_UNICODE, &len);
2035 if (!NT_STATUS_IS_OK(status)) {
2039 memset(p + 2 + len,'\0',24 - len);
2046 status = srvstr_push(base_data, flags2, p,
2047 fname, PTR_DIFF(end_data, p),
2048 STR_TERMINATE_ASCII, &len);
2049 if (!NT_STATUS_IS_OK(status)) {
2055 len = PTR_DIFF(p, pdata);
2056 pad = (len + (align-1)) & ~(align-1);
2058 * offset to the next entry, the caller
2059 * will overwrite it for the last entry
2060 * that's why we always include the padding
2064 * set padding to zero
2067 memset(p, 0, pad - len);
2074 case SMB_FIND_FILE_DIRECTORY_INFO:
2075 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2077 SIVAL(p,0,reskey); p += 4;
2078 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2079 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2080 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2081 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2082 SOFF_T(p,0,file_size); p += 8;
2083 SOFF_T(p,0,allocation_size); p += 8;
2084 SIVAL(p,0,mode); p += 4;
2085 status = srvstr_push(base_data, flags2,
2086 p + 4, fname, PTR_DIFF(end_data, p+4),
2087 STR_TERMINATE_ASCII, &len);
2088 if (!NT_STATUS_IS_OK(status)) {
2094 len = PTR_DIFF(p, pdata);
2095 pad = (len + (align-1)) & ~(align-1);
2097 * offset to the next entry, the caller
2098 * will overwrite it for the last entry
2099 * that's why we always include the padding
2103 * set padding to zero
2106 memset(p, 0, pad - len);
2113 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2114 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2116 SIVAL(p,0,reskey); p += 4;
2117 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2118 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2119 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2120 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2121 SOFF_T(p,0,file_size); p += 8;
2122 SOFF_T(p,0,allocation_size); p += 8;
2123 SIVAL(p,0,mode); p += 4;
2124 q = p; p += 4; /* q is placeholder for name length. */
2126 unsigned int ea_size = estimate_ea_size(conn, NULL,
2128 SIVAL(p,0,ea_size); /* Extended attributes */
2131 status = srvstr_push(base_data, flags2, p,
2132 fname, PTR_DIFF(end_data, p),
2133 STR_TERMINATE_ASCII, &len);
2134 if (!NT_STATUS_IS_OK(status)) {
2140 len = PTR_DIFF(p, pdata);
2141 pad = (len + (align-1)) & ~(align-1);
2143 * offset to the next entry, the caller
2144 * will overwrite it for the last entry
2145 * that's why we always include the padding
2149 * set padding to zero
2152 memset(p, 0, pad - len);
2159 case SMB_FIND_FILE_NAMES_INFO:
2160 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2162 SIVAL(p,0,reskey); p += 4;
2164 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2165 acl on a dir (tridge) */
2166 status = srvstr_push(base_data, flags2, p,
2167 fname, PTR_DIFF(end_data, p),
2168 STR_TERMINATE_ASCII, &len);
2169 if (!NT_STATUS_IS_OK(status)) {
2175 len = PTR_DIFF(p, pdata);
2176 pad = (len + (align-1)) & ~(align-1);
2178 * offset to the next entry, the caller
2179 * will overwrite it for the last entry
2180 * that's why we always include the padding
2184 * set padding to zero
2187 memset(p, 0, pad - len);
2194 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2195 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2197 SIVAL(p,0,reskey); p += 4;
2198 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2199 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2200 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2201 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2202 SOFF_T(p,0,file_size); p += 8;
2203 SOFF_T(p,0,allocation_size); p += 8;
2204 SIVAL(p,0,mode); p += 4;
2205 q = p; p += 4; /* q is placeholder for name length. */
2206 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2207 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2209 unsigned int ea_size = estimate_ea_size(conn, NULL,
2211 SIVAL(p,0,ea_size); /* Extended attributes */
2214 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2215 SBVAL(p,0,file_index); p += 8;
2216 status = srvstr_push(base_data, flags2, p,
2217 fname, PTR_DIFF(end_data, p),
2218 STR_TERMINATE_ASCII, &len);
2219 if (!NT_STATUS_IS_OK(status)) {
2225 len = PTR_DIFF(p, pdata);
2226 pad = (len + (align-1)) & ~(align-1);
2228 * offset to the next entry, the caller
2229 * will overwrite it for the last entry
2230 * that's why we always include the padding
2234 * set padding to zero
2237 memset(p, 0, pad - len);
2244 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2245 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2246 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2248 SIVAL(p,0,reskey); p += 4;
2249 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2250 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2251 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2252 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2253 SOFF_T(p,0,file_size); p += 8;
2254 SOFF_T(p,0,allocation_size); p += 8;
2255 SIVAL(p,0,mode); p += 4;
2256 q = p; p += 4; /* q is placeholder for name length */
2257 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2258 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2259 } else if (readdir_attr_data &&
2260 readdir_attr_data->type == RDATTR_AAPL) {
2262 * OS X specific SMB2 extension negotiated via
2263 * AAPL create context: return max_access in
2266 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2268 unsigned int ea_size = estimate_ea_size(conn, NULL,
2270 SIVAL(p,0,ea_size); /* Extended attributes */
2274 if (readdir_attr_data &&
2275 readdir_attr_data->type == RDATTR_AAPL) {
2277 * OS X specific SMB2 extension negotiated via
2278 * AAPL create context: return resource fork
2279 * length and compressed FinderInfo in
2282 * According to documentation short_name_len
2283 * should be 0, but on the wire behaviour
2284 * shows its set to 24 by clients.
2288 /* Resourefork length */
2289 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2291 /* Compressed FinderInfo */
2292 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2293 } else if (!was_8_3 && check_mangled_names) {
2294 char mangled_name[13]; /* mangled 8.3 name. */
2295 if (!name_to_8_3(fname,mangled_name,True,
2297 /* Error - mangle failed ! */
2298 memset(mangled_name,'\0',12);
2300 mangled_name[12] = 0;
2301 status = srvstr_push(base_data, flags2,
2302 p+2, mangled_name, 24,
2303 STR_UPPER|STR_UNICODE, &len);
2304 if (!NT_STATUS_IS_OK(status)) {
2309 memset(p + 2 + len,'\0',24 - len);
2313 /* Clear the short name buffer. This is
2314 * IMPORTANT as not doing so will trigger
2315 * a Win2k client bug. JRA.
2322 if (readdir_attr_data &&
2323 readdir_attr_data->type == RDATTR_AAPL) {
2325 * OS X specific SMB2 extension negotiated via
2326 * AAPL create context: return UNIX mode in
2329 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2330 SSVAL(p, 0, aapl_mode);
2336 SBVAL(p,0,file_index); p += 8;
2337 status = srvstr_push(base_data, flags2, p,
2338 fname, PTR_DIFF(end_data, p),
2339 STR_TERMINATE_ASCII, &len);
2340 if (!NT_STATUS_IS_OK(status)) {
2346 len = PTR_DIFF(p, pdata);
2347 pad = (len + (align-1)) & ~(align-1);
2349 * offset to the next entry, the caller
2350 * will overwrite it for the last entry
2351 * that's why we always include the padding
2355 * set padding to zero
2358 memset(p, 0, pad - len);
2365 /* CIFS UNIX Extension. */
2367 case SMB_FIND_FILE_UNIX:
2368 case SMB_FIND_FILE_UNIX_INFO2:
2370 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2372 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2374 if (info_level == SMB_FIND_FILE_UNIX) {
2375 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2376 p = store_file_unix_basic(conn, p,
2377 NULL, &smb_fname->st);
2378 status = srvstr_push(base_data, flags2, p,
2379 fname, PTR_DIFF(end_data, p),
2380 STR_TERMINATE, &len);
2381 if (!NT_STATUS_IS_OK(status)) {
2385 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2386 p = store_file_unix_basic_info2(conn, p,
2387 NULL, &smb_fname->st);
2390 status = srvstr_push(base_data, flags2, p, fname,
2391 PTR_DIFF(end_data, p), 0, &len);
2392 if (!NT_STATUS_IS_OK(status)) {
2395 SIVAL(nameptr, 0, len);
2400 len = PTR_DIFF(p, pdata);
2401 pad = (len + (align-1)) & ~(align-1);
2403 * offset to the next entry, the caller
2404 * will overwrite it for the last entry
2405 * that's why we always include the padding
2409 * set padding to zero
2412 memset(p, 0, pad - len);
2417 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2422 return NT_STATUS_INVALID_LEVEL;
2425 if (PTR_DIFF(p,pdata) > space_remaining) {
2426 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2427 "(wanted %u, had %d)\n",
2428 (unsigned int)PTR_DIFF(p,pdata),
2430 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2433 /* Setup the last entry pointer, as an offset from base_data */
2434 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2435 /* Advance the data pointer to the next slot */
2438 return NT_STATUS_OK;
2441 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2442 connection_struct *conn,
2443 struct dptr_struct *dirptr,
2445 const char *path_mask,
2448 int requires_resume_key,
2456 int space_remaining,
2457 bool *got_exact_match,
2458 int *_last_entry_off,
2459 struct ea_list *name_list,
2460 struct file_id *file_id)
2463 const char *mask = NULL;
2464 long prev_dirpos = 0;
2467 struct smb_filename *smb_fname = NULL;
2468 struct smbd_dirptr_lanman2_state state;
2470 uint64_t last_entry_off = 0;
2472 enum mangled_names_options mangled_names;
2473 bool marshall_with_83_names;
2475 mangled_names = lp_mangled_names(conn->params);
2479 state.info_level = info_level;
2480 if (mangled_names != MANGLED_NAMES_NO) {
2481 state.check_mangled_names = true;
2483 state.has_wild = dptr_has_wild(dirptr);
2484 state.got_exact_match = false;
2486 *got_exact_match = false;
2488 p = strrchr_m(path_mask,'/');
2499 ok = smbd_dirptr_get_entry(ctx,
2505 smbd_dirptr_lanman2_match_fn,
2506 smbd_dirptr_lanman2_mode_fn,
2513 return NT_STATUS_END_OF_FILE;
2516 *got_exact_match = state.got_exact_match;
2518 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2520 status = smbd_marshall_dir_entry(ctx,
2525 marshall_with_83_names,
2526 requires_resume_key,
2537 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2538 DEBUG(1,("Conversion error: illegal character: %s\n",
2539 smb_fname_str_dbg(smb_fname)));
2542 if (file_id != NULL) {
2543 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2547 TALLOC_FREE(smb_fname);
2548 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2549 dptr_SeekDir(dirptr, prev_dirpos);
2552 if (!NT_STATUS_IS_OK(status)) {
2556 *_last_entry_off = last_entry_off;
2557 return NT_STATUS_OK;
2560 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2561 connection_struct *conn,
2562 struct dptr_struct *dirptr,
2564 const char *path_mask,
2567 bool requires_resume_key,
2573 int space_remaining,
2574 bool *got_exact_match,
2575 int *last_entry_off,
2576 struct ea_list *name_list)
2579 const bool do_pad = true;
2581 if (info_level >= 1 && info_level <= 3) {
2582 /* No alignment on earlier info levels. */
2586 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2587 path_mask, dirtype, info_level,
2588 requires_resume_key, dont_descend, ask_sharemode,
2590 ppdata, base_data, end_data,
2593 last_entry_off, name_list, NULL);
2596 /****************************************************************************
2597 Reply to a TRANS2_FINDFIRST.
2598 ****************************************************************************/
2600 static void call_trans2findfirst(connection_struct *conn,
2601 struct smb_request *req,
2602 char **pparams, int total_params,
2603 char **ppdata, int total_data,
2604 unsigned int max_data_bytes)
2606 /* We must be careful here that we don't return more than the
2607 allowed number of data bytes. If this means returning fewer than
2608 maxentries then so be it. We assume that the redirector has
2609 enough room for the fixed number of parameter bytes it has
2611 struct smb_filename *smb_dname = NULL;
2612 char *params = *pparams;
2613 char *pdata = *ppdata;
2617 uint16_t findfirst_flags;
2618 bool close_after_first;
2620 bool requires_resume_key;
2622 char *directory = NULL;
2625 int last_entry_off=0;
2629 bool finished = False;
2630 bool dont_descend = False;
2631 bool out_of_space = False;
2632 int space_remaining;
2633 bool mask_contains_wcard = False;
2634 struct ea_list *ea_list = NULL;
2635 NTSTATUS ntstatus = NT_STATUS_OK;
2636 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2637 struct dptr_struct *dirptr = NULL;
2638 struct smbd_server_connection *sconn = req->sconn;
2639 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2640 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2641 bool backup_priv = false;
2642 bool as_root = false;
2644 if (total_params < 13) {
2645 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2649 dirtype = SVAL(params,0);
2650 maxentries = SVAL(params,2);
2651 findfirst_flags = SVAL(params,4);
2652 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2653 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2654 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2655 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2656 security_token_has_privilege(get_current_nttok(conn),
2659 info_level = SVAL(params,6);
2661 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2662 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2663 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2665 info_level, max_data_bytes));
2668 /* W2K3 seems to treat zero as 1. */
2672 switch (info_level) {
2673 case SMB_FIND_INFO_STANDARD:
2674 case SMB_FIND_EA_SIZE:
2675 case SMB_FIND_EA_LIST:
2676 case SMB_FIND_FILE_DIRECTORY_INFO:
2677 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2678 case SMB_FIND_FILE_NAMES_INFO:
2679 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2680 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2681 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2683 case SMB_FIND_FILE_UNIX:
2684 case SMB_FIND_FILE_UNIX_INFO2:
2685 /* Always use filesystem for UNIX mtime query. */
2686 ask_sharemode = false;
2687 if (!lp_unix_extensions()) {
2688 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2691 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2694 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2698 if (req->posix_pathnames) {
2699 srvstr_get_path_wcard_posix(talloc_tos(),
2707 &mask_contains_wcard);
2709 srvstr_get_path_wcard(talloc_tos(),
2717 &mask_contains_wcard);
2719 if (!NT_STATUS_IS_OK(ntstatus)) {
2720 reply_nterror(req, ntstatus);
2727 ntstatus = filename_convert_with_privilege(talloc_tos(),
2732 &mask_contains_wcard,
2735 ntstatus = filename_convert(talloc_tos(), conn,
2736 req->flags2 & FLAGS2_DFS_PATHNAMES,
2739 &mask_contains_wcard,
2743 if (!NT_STATUS_IS_OK(ntstatus)) {
2744 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2745 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2746 ERRSRV, ERRbadpath);
2749 reply_nterror(req, ntstatus);
2753 mask = smb_dname->original_lcomp;
2755 directory = smb_dname->base_name;
2757 p = strrchr_m(directory,'/');
2759 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2760 if((directory[0] == '.') && (directory[1] == '\0')) {
2761 mask = talloc_strdup(talloc_tos(),"*");
2763 reply_nterror(req, NT_STATUS_NO_MEMORY);
2766 mask_contains_wcard = True;
2772 if (p == NULL || p == directory) {
2773 /* Ensure we don't have a directory name of "". */
2774 directory = talloc_strdup(talloc_tos(), ".");
2776 reply_nterror(req, NT_STATUS_NO_MEMORY);
2779 /* Ensure smb_dname->base_name matches. */
2780 smb_dname->base_name = directory;
2783 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2785 if (info_level == SMB_FIND_EA_LIST) {
2788 if (total_data < 4) {
2789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2793 ea_size = IVAL(pdata,0);
2794 if (ea_size != total_data) {
2795 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2796 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2797 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2801 if (!lp_ea_support(SNUM(conn))) {
2802 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2806 /* Pull out the list of names. */
2807 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2809 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2814 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2819 *ppdata = (char *)SMB_REALLOC(
2820 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2821 if(*ppdata == NULL ) {
2822 reply_nterror(req, NT_STATUS_NO_MEMORY);
2826 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2828 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2831 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2832 /* Realloc the params space */
2833 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2834 if (*pparams == NULL) {
2835 reply_nterror(req, NT_STATUS_NO_MEMORY);
2840 /* Save the wildcard match and attribs we are using on this directory -
2841 needed as lanman2 assumes these are being saved between calls */
2843 ntstatus = dptr_create(conn,
2851 mask_contains_wcard,
2855 if (!NT_STATUS_IS_OK(ntstatus)) {
2856 reply_nterror(req, ntstatus);
2861 /* Remember this in case we have
2862 to do a findnext. */
2863 dptr_set_priv(dirptr);
2866 dptr_num = dptr_dnum(dirptr);
2867 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2869 /* Initialize per TRANS2_FIND_FIRST operation data */
2870 dptr_init_search_op(dirptr);
2872 /* We don't need to check for VOL here as this is returned by
2873 a different TRANS2 call. */
2875 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2876 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2877 if (in_list(directory,
2878 lp_dont_descend(talloc_tos(), SNUM(conn)),
2879 conn->case_sensitive)) {
2880 dont_descend = True;
2884 space_remaining = max_data_bytes;
2885 out_of_space = False;
2887 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2888 bool got_exact_match = False;
2890 /* this is a heuristic to avoid seeking the dirptr except when
2891 absolutely necessary. It allows for a filename of about 40 chars */
2892 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2893 out_of_space = True;
2896 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2900 mask,dirtype,info_level,
2901 requires_resume_key,dont_descend,
2906 &last_entry_off, ea_list);
2907 if (NT_STATUS_EQUAL(ntstatus,
2908 NT_STATUS_ILLEGAL_CHARACTER)) {
2910 * Bad character conversion on name. Ignore this
2915 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2916 out_of_space = true;
2918 finished = !NT_STATUS_IS_OK(ntstatus);
2922 if (!finished && !out_of_space)
2926 * As an optimisation if we know we aren't looking
2927 * for a wildcard name (ie. the name matches the wildcard exactly)
2928 * then we can finish on any (first) match.
2929 * This speeds up large directory searches. JRA.
2935 /* Ensure space_remaining never goes -ve. */
2936 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2937 space_remaining = 0;
2938 out_of_space = true;
2940 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2944 /* Check if we can close the dirptr */
2945 if(close_after_first || (finished && close_if_end)) {
2946 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2947 dptr_close(sconn, &dptr_num);
2951 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2952 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2953 * the protocol level is less than NT1. Tested with smbclient. JRA.
2954 * This should fix the OS/2 client bug #2335.
2957 if(numentries == 0) {
2958 dptr_close(sconn, &dptr_num);
2959 if (get_Protocol() < PROTOCOL_NT1) {
2960 reply_force_doserror(req, ERRDOS, ERRnofiles);
2963 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2964 ERRDOS, ERRbadfile);
2969 /* At this point pdata points to numentries directory entries. */
2971 /* Set up the return parameter block */
2972 SSVAL(params,0,dptr_num);
2973 SSVAL(params,2,numentries);
2974 SSVAL(params,4,finished);
2975 SSVAL(params,6,0); /* Never an EA error */
2976 SSVAL(params,8,last_entry_off);
2978 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2981 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2982 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2984 reply_nterror(req, NT_STATUS_NO_MEMORY);
2988 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2989 smb_fn_name(req->cmd),
2990 mask, directory, dirtype, numentries ) );
2993 * Force a name mangle here to ensure that the
2994 * mask as an 8.3 name is top of the mangled cache.
2995 * The reasons for this are subtle. Don't remove
2996 * this code unless you know what you are doing
2997 * (see PR#13758). JRA.
3000 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3001 char mangled_name[13];
3002 name_to_8_3(mask, mangled_name, True, conn->params);
3010 TALLOC_FREE(smb_dname);
3014 /****************************************************************************
3015 Reply to a TRANS2_FINDNEXT.
3016 ****************************************************************************/
3018 static void call_trans2findnext(connection_struct *conn,
3019 struct smb_request *req,
3020 char **pparams, int total_params,
3021 char **ppdata, int total_data,
3022 unsigned int max_data_bytes)
3024 /* We must be careful here that we don't return more than the
3025 allowed number of data bytes. If this means returning fewer than
3026 maxentries then so be it. We assume that the redirector has
3027 enough room for the fixed number of parameter bytes it has
3029 char *params = *pparams;
3030 char *pdata = *ppdata;
3034 uint16_t info_level;
3035 uint32_t resume_key;
3036 uint16_t findnext_flags;
3037 bool close_after_request;
3039 bool requires_resume_key;
3041 bool mask_contains_wcard = False;
3042 char *resume_name = NULL;
3043 const char *mask = NULL;
3044 const char *directory = NULL;
3048 int i, last_entry_off=0;
3049 bool finished = False;
3050 bool dont_descend = False;
3051 bool out_of_space = False;
3052 int space_remaining;
3053 struct ea_list *ea_list = NULL;
3054 NTSTATUS ntstatus = NT_STATUS_OK;
3055 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3056 TALLOC_CTX *ctx = talloc_tos();
3057 struct dptr_struct *dirptr;
3058 struct smbd_server_connection *sconn = req->sconn;
3059 bool backup_priv = false;
3060 bool as_root = false;
3062 if (total_params < 13) {
3063 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3067 dptr_num = SVAL(params,0);
3068 maxentries = SVAL(params,2);
3069 info_level = SVAL(params,4);
3070 resume_key = IVAL(params,6);
3071 findnext_flags = SVAL(params,10);
3072 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3073 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3074 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3075 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3077 if (!continue_bit) {
3078 /* We only need resume_name if continue_bit is zero. */
3079 if (req->posix_pathnames) {
3080 srvstr_get_path_wcard_posix(ctx,
3088 &mask_contains_wcard);
3090 srvstr_get_path_wcard(ctx,
3098 &mask_contains_wcard);
3100 if (!NT_STATUS_IS_OK(ntstatus)) {
3101 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3102 complain (it thinks we're asking for the directory above the shared
3103 path or an invalid name). Catch this as the resume name is only compared, never used in
3104 a file access. JRA. */
3105 srvstr_pull_talloc(ctx, params, req->flags2,
3106 &resume_name, params+12,
3110 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3111 reply_nterror(req, ntstatus);
3117 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3118 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3119 resume_key = %d resume name = %s continue=%d level = %d\n",
3120 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3121 requires_resume_key, resume_key,
3122 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3125 /* W2K3 seems to treat zero as 1. */
3129 switch (info_level) {
3130 case SMB_FIND_INFO_STANDARD:
3131 case SMB_FIND_EA_SIZE:
3132 case SMB_FIND_EA_LIST:
3133 case SMB_FIND_FILE_DIRECTORY_INFO:
3134 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3135 case SMB_FIND_FILE_NAMES_INFO:
3136 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3137 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3138 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3140 case SMB_FIND_FILE_UNIX:
3141 case SMB_FIND_FILE_UNIX_INFO2:
3142 /* Always use filesystem for UNIX mtime query. */
3143 ask_sharemode = false;
3144 if (!lp_unix_extensions()) {
3145 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3150 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3154 if (info_level == SMB_FIND_EA_LIST) {
3157 if (total_data < 4) {
3158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3162 ea_size = IVAL(pdata,0);
3163 if (ea_size != total_data) {
3164 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3165 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3170 if (!lp_ea_support(SNUM(conn))) {
3171 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3175 /* Pull out the list of names. */
3176 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3178 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3183 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3184 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3188 *ppdata = (char *)SMB_REALLOC(
3189 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3190 if(*ppdata == NULL) {
3191 reply_nterror(req, NT_STATUS_NO_MEMORY);
3196 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3199 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3202 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3203 /* Realloc the params space */
3204 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3205 if(*pparams == NULL ) {
3206 reply_nterror(req, NT_STATUS_NO_MEMORY);
3212 /* Check that the dptr is valid */
3213 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3214 reply_nterror(req, STATUS_NO_MORE_FILES);
3218 directory = dptr_path(sconn, dptr_num);
3220 /* Get the wildcard mask from the dptr */
3221 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3222 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3223 reply_nterror(req, STATUS_NO_MORE_FILES);
3227 /* Get the attr mask from the dptr */
3228 dirtype = dptr_attr(sconn, dptr_num);
3230 backup_priv = dptr_get_priv(dirptr);
3232 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3233 "backup_priv = %d\n",
3234 dptr_num, mask, dirtype,
3236 dptr_TellDir(dirptr),
3239 /* Initialize per TRANS2_FIND_NEXT operation data */
3240 dptr_init_search_op(dirptr);
3242 /* We don't need to check for VOL here as this is returned by
3243 a different TRANS2 call. */
3245 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3246 directory,lp_dont_descend(ctx, SNUM(conn))));
3247 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3248 dont_descend = True;
3251 space_remaining = max_data_bytes;
3252 out_of_space = False;
3260 * Seek to the correct position. We no longer use the resume key but
3261 * depend on the last file name instead.
3264 if(!continue_bit && resume_name && *resume_name) {
3267 long current_pos = 0;
3269 * Remember, name_to_8_3 is called by
3270 * get_lanman2_dir_entry(), so the resume name
3271 * could be mangled. Ensure we check the unmangled name.
3274 if (mangle_is_mangled(resume_name, conn->params)) {
3275 char *new_resume_name = NULL;
3276 mangle_lookup_name_from_8_3(ctx,
3280 if (new_resume_name) {
3281 resume_name = new_resume_name;
3286 * Fix for NT redirector problem triggered by resume key indexes
3287 * changing between directory scans. We now return a resume key of 0
3288 * and instead look for the filename to continue from (also given
3289 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3290 * findfirst/findnext (as is usual) then the directory pointer
3291 * should already be at the correct place.
3294 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3295 } /* end if resume_name && !continue_bit */
3297 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3298 bool got_exact_match = False;
3300 /* this is a heuristic to avoid seeking the dirptr except when
3301 absolutely necessary. It allows for a filename of about 40 chars */
3302 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3303 out_of_space = True;
3306 ntstatus = get_lanman2_dir_entry(ctx,
3310 mask,dirtype,info_level,
3311 requires_resume_key,dont_descend,
3316 &last_entry_off, ea_list);
3317 if (NT_STATUS_EQUAL(ntstatus,
3318 NT_STATUS_ILLEGAL_CHARACTER)) {
3320 * Bad character conversion on name. Ignore this
3325 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3326 out_of_space = true;
3328 finished = !NT_STATUS_IS_OK(ntstatus);
3332 if (!finished && !out_of_space)
3336 * As an optimisation if we know we aren't looking
3337 * for a wildcard name (ie. the name matches the wildcard exactly)
3338 * then we can finish on any (first) match.
3339 * This speeds up large directory searches. JRA.
3345 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3348 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3349 smb_fn_name(req->cmd),
3350 mask, directory, dirtype, numentries ) );
3352 /* Check if we can close the dirptr */
3353 if(close_after_request || (finished && close_if_end)) {
3354 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3355 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3362 /* Set up the return parameter block */
3363 SSVAL(params,0,numentries);
3364 SSVAL(params,2,finished);
3365 SSVAL(params,4,0); /* Never an EA error */
3366 SSVAL(params,6,last_entry_off);
3368 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3374 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3376 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3380 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3382 SMB_ASSERT(extended_info != NULL);
3384 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3385 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3386 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3387 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3388 #ifdef SAMBA_VERSION_REVISION
3389 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3391 extended_info->samba_subversion = 0;
3392 #ifdef SAMBA_VERSION_RC_RELEASE
3393 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3395 #ifdef SAMBA_VERSION_PRE_RELEASE
3396 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3399 #ifdef SAMBA_VERSION_VENDOR_PATCH
3400 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3402 extended_info->samba_gitcommitdate = 0;
3403 #ifdef SAMBA_VERSION_COMMIT_TIME
3404 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3407 memset(extended_info->samba_version_string, 0,
3408 sizeof(extended_info->samba_version_string));
3410 snprintf (extended_info->samba_version_string,
3411 sizeof(extended_info->samba_version_string),
3412 "%s", samba_version_string());
3415 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3416 connection_struct *conn,
3417 TALLOC_CTX *mem_ctx,
3418 uint16_t info_level,
3420 unsigned int max_data_bytes,
3421 size_t *fixed_portion,
3422 struct smb_filename *fname,
3426 char *pdata, *end_data;
3429 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3430 int snum = SNUM(conn);
3431 const char *fstype = lp_fstype(SNUM(conn));
3432 const char *filename = NULL;
3433 const uint64_t bytes_per_sector = 512;
3434 uint32_t additional_flags = 0;
3435 struct smb_filename smb_fname;
3437 NTSTATUS status = NT_STATUS_OK;
3440 if (fname == NULL || fname->base_name == NULL) {
3443 filename = fname->base_name;
3447 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3448 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3449 "info level (0x%x) on IPC$.\n",
3450 (unsigned int)info_level));
3451 return NT_STATUS_ACCESS_DENIED;
3455 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3457 ZERO_STRUCT(smb_fname);
3458 smb_fname.base_name = discard_const_p(char, filename);
3460 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3461 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3462 return map_nt_error_from_unix(errno);
3467 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3468 return NT_STATUS_INVALID_PARAMETER;
3471 *ppdata = (char *)SMB_REALLOC(
3472 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3473 if (*ppdata == NULL) {
3474 return NT_STATUS_NO_MEMORY;
3478 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3479 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3483 switch (info_level) {
3484 case SMB_INFO_ALLOCATION:
3486 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3488 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3490 if (df_ret == (uint64_t)-1) {
3491 return map_nt_error_from_unix(errno);
3494 block_size = lp_block_size(snum);
3495 if (bsize < block_size) {
3496 uint64_t factor = block_size/bsize;
3501 if (bsize > block_size) {
3502 uint64_t factor = bsize/block_size;
3507 sectors_per_unit = bsize/bytes_per_sector;
3509 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3510 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3511 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3513 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3514 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3515 SIVAL(pdata,l1_cUnit,dsize);
3516 SIVAL(pdata,l1_cUnitAvail,dfree);
3517 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3521 case SMB_INFO_VOLUME:
3522 /* Return volume name */
3524 * Add volume serial number - hash of a combination of
3525 * the called hostname and the service name.
3527 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3529 * Win2k3 and previous mess this up by sending a name length
3530 * one byte short. I believe only older clients (OS/2 Win9x) use
3531 * this call so try fixing this by adding a terminating null to
3532 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3534 status = srvstr_push(
3536 pdata+l2_vol_szVolLabel, vname,
3537 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3538 STR_NOALIGN|STR_TERMINATE, &len);
3539 if (!NT_STATUS_IS_OK(status)) {
3542 SCVAL(pdata,l2_vol_cch,len);
3543 data_len = l2_vol_szVolLabel + len;
3544 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3545 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3546 (unsigned)len, vname));
3549 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3550 case SMB_FS_ATTRIBUTE_INFORMATION:
3552 additional_flags = 0;
3553 #if defined(HAVE_SYS_QUOTAS)
3554 additional_flags |= FILE_VOLUME_QUOTAS;
3557 if(lp_nt_acl_support(SNUM(conn))) {
3558 additional_flags |= FILE_PERSISTENT_ACLS;
3561 /* Capabilities are filled in at connection time through STATVFS call */
3562 additional_flags |= conn->fs_capabilities;
3563 additional_flags |= lp_parm_int(conn->params->service,
3564 "share", "fake_fscaps",
3567 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3568 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3569 additional_flags); /* FS ATTRIBUTES */
3571 SIVAL(pdata,4,255); /* Max filename component length */
3572 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3573 and will think we can't do long filenames */
3574 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3575 PTR_DIFF(end_data, pdata+12),
3577 if (!NT_STATUS_IS_OK(status)) {
3581 data_len = 12 + len;
3582 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3583 /* the client only requested a portion of the
3585 data_len = max_data_bytes;
3586 status = STATUS_BUFFER_OVERFLOW;
3588 *fixed_portion = 16;
3591 case SMB_QUERY_FS_LABEL_INFO:
3592 case SMB_FS_LABEL_INFORMATION:
3593 status = srvstr_push(pdata, flags2, pdata+4, vname,
3594 PTR_DIFF(end_data, pdata+4), 0, &len);
3595 if (!NT_STATUS_IS_OK(status)) {
3602 case SMB_QUERY_FS_VOLUME_INFO:
3603 case SMB_FS_VOLUME_INFORMATION:
3606 * Add volume serial number - hash of a combination of
3607 * the called hostname and the service name.
3609 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3610 (str_checksum(get_local_machine_name())<<16));
3612 /* Max label len is 32 characters. */
3613 status = srvstr_push(pdata, flags2, pdata+18, vname,
3614 PTR_DIFF(end_data, pdata+18),
3616 if (!NT_STATUS_IS_OK(status)) {
3619 SIVAL(pdata,12,len);
3622 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3623 (int)strlen(vname),vname,
3624 lp_servicename(talloc_tos(), snum)));
3625 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3626 /* the client only requested a portion of the
3628 data_len = max_data_bytes;
3629 status = STATUS_BUFFER_OVERFLOW;
3631 *fixed_portion = 24;
3634 case SMB_QUERY_FS_SIZE_INFO:
3635 case SMB_FS_SIZE_INFORMATION:
3637 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3639 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3641 if (df_ret == (uint64_t)-1) {
3642 return map_nt_error_from_unix(errno);
3644 block_size = lp_block_size(snum);
3645 if (bsize < block_size) {
3646 uint64_t factor = block_size/bsize;
3651 if (bsize > block_size) {
3652 uint64_t factor = bsize/block_size;
3657 sectors_per_unit = bsize/bytes_per_sector;
3658 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3659 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3660 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3661 SBIG_UINT(pdata,0,dsize);
3662 SBIG_UINT(pdata,8,dfree);
3663 SIVAL(pdata,16,sectors_per_unit);
3664 SIVAL(pdata,20,bytes_per_sector);
3665 *fixed_portion = 24;
3669 case SMB_FS_FULL_SIZE_INFORMATION:
3671 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3673 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3675 if (df_ret == (uint64_t)-1) {
3676 return map_nt_error_from_unix(errno);
3678 block_size = lp_block_size(snum);
3679 if (bsize < block_size) {
3680 uint64_t factor = block_size/bsize;
3685 if (bsize > block_size) {
3686 uint64_t factor = bsize/block_size;
3691 sectors_per_unit = bsize/bytes_per_sector;
3692 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3693 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3694 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3695 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3696 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3697 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3698 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3699 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3700 *fixed_portion = 32;
3704 case SMB_QUERY_FS_DEVICE_INFO:
3705 case SMB_FS_DEVICE_INFORMATION:
3707 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3709 if (!CAN_WRITE(conn)) {
3710 characteristics |= FILE_READ_ONLY_DEVICE;
3713 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3714 SIVAL(pdata,4,characteristics);
3719 #ifdef HAVE_SYS_QUOTAS
3720 case SMB_FS_QUOTA_INFORMATION:
3722 * what we have to send --metze:
3724 * Unknown1: 24 NULL bytes
3725 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3726 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3727 * Quota Flags: 2 byte :
3728 * Unknown3: 6 NULL bytes
3732 * details for Quota Flags:
3734 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3735 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3736 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3737 * 0x0001 Enable Quotas: enable quota for this fs
3741 /* we need to fake up a fsp here,
3742 * because its not send in this call
3745 SMB_NTQUOTA_STRUCT quotas;
3748 ZERO_STRUCT(quotas);
3751 fsp.fnum = FNUM_FIELD_INVALID;
3754 if (get_current_uid(conn) != 0) {
3755 DEBUG(0,("get_user_quota: access_denied "
3756 "service [%s] user [%s]\n",
3757 lp_servicename(talloc_tos(), SNUM(conn)),
3758 conn->session_info->unix_info->unix_name));
3759 return NT_STATUS_ACCESS_DENIED;
3762 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3764 if (!NT_STATUS_IS_OK(status)) {
3765 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3771 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3772 lp_servicename(talloc_tos(), SNUM(conn))));
3774 /* Unknown1 24 NULL bytes*/
3775 SBIG_UINT(pdata,0,(uint64_t)0);
3776 SBIG_UINT(pdata,8,(uint64_t)0);
3777 SBIG_UINT(pdata,16,(uint64_t)0);
3779 /* Default Soft Quota 8 bytes */
3780 SBIG_UINT(pdata,24,quotas.softlim);
3782 /* Default Hard Quota 8 bytes */
3783 SBIG_UINT(pdata,32,quotas.hardlim);
3785 /* Quota flag 2 bytes */
3786 SSVAL(pdata,40,quotas.qflags);
3788 /* Unknown3 6 NULL bytes */
3794 #endif /* HAVE_SYS_QUOTAS */
3795 case SMB_FS_OBJECTID_INFORMATION:
3797 unsigned char objid[16];
3798 struct smb_extended_info extended_info;
3799 memcpy(pdata,create_volume_objectid(conn, objid),16);
3800 samba_extended_info_version (&extended_info);
3801 SIVAL(pdata,16,extended_info.samba_magic);
3802 SIVAL(pdata,20,extended_info.samba_version);
3803 SIVAL(pdata,24,extended_info.samba_subversion);
3804 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3805 memcpy(pdata+36,extended_info.samba_version_string,28);
3810 case SMB_FS_SECTOR_SIZE_INFORMATION:
3814 * These values match a physical Windows Server 2012
3815 * share backed by NTFS atop spinning rust.
3817 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3818 /* logical_bytes_per_sector */
3819 SIVAL(pdata, 0, bytes_per_sector);
3820 /* phys_bytes_per_sector_atomic */
3821 SIVAL(pdata, 4, bytes_per_sector);
3822 /* phys_bytes_per_sector_perf */
3823 SIVAL(pdata, 8, bytes_per_sector);
3824 /* fs_effective_phys_bytes_per_sector_atomic */
3825 SIVAL(pdata, 12, bytes_per_sector);
3827 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3828 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3829 /* byte_off_sector_align */
3830 SIVAL(pdata, 20, 0);
3831 /* byte_off_partition_align */
3832 SIVAL(pdata, 24, 0);
3833 *fixed_portion = 28;
3839 * Query the version and capabilities of the CIFS UNIX extensions
3843 case SMB_QUERY_CIFS_UNIX_INFO:
3845 bool large_write = lp_min_receive_file_size() &&
3846 !srv_is_signing_active(xconn);
3847 bool large_read = !srv_is_signing_active(xconn);
3848 int encrypt_caps = 0;
3850 if (!lp_unix_extensions()) {
3851 return NT_STATUS_INVALID_LEVEL;
3854 switch (conn->encrypt_level) {
3855 case SMB_SIGNING_OFF:
3858 case SMB_SIGNING_DESIRED:
3859 case SMB_SIGNING_IF_REQUIRED:
3860 case SMB_SIGNING_DEFAULT:
3861 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3863 case SMB_SIGNING_REQUIRED:
3864 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3865 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3866 large_write = false;
3872 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3873 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3875 /* We have POSIX ACLs, pathname, encryption,
3876 * large read/write, and locking capability. */
3878 SBIG_UINT(pdata,4,((uint64_t)(
3879 CIFS_UNIX_POSIX_ACLS_CAP|
3880 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3881 CIFS_UNIX_FCNTL_LOCKS_CAP|
3882 CIFS_UNIX_EXTATTR_CAP|
3883 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3885 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3887 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3891 case SMB_QUERY_POSIX_FS_INFO:
3894 vfs_statvfs_struct svfs;
3896 if (!lp_unix_extensions()) {
3897 return NT_STATUS_INVALID_LEVEL;
3900 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3904 SIVAL(pdata,0,svfs.OptimalTransferSize);
3905 SIVAL(pdata,4,svfs.BlockSize);
3906 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3907 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3908 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3909 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3910 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3911 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3912 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3914 } else if (rc == EOPNOTSUPP) {
3915 return NT_STATUS_INVALID_LEVEL;
3916 #endif /* EOPNOTSUPP */
3918 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3919 return NT_STATUS_DOS(ERRSRV, ERRerror);
3924 case SMB_QUERY_POSIX_WHOAMI:
3930 if (!lp_unix_extensions()) {
3931 return NT_STATUS_INVALID_LEVEL;
3934 if (max_data_bytes < 40) {
3935 return NT_STATUS_BUFFER_TOO_SMALL;
3938 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3939 flags |= SMB_WHOAMI_GUEST;
3942 /* NOTE: 8 bytes for UID/GID, irrespective of native
3943 * platform size. This matches
3944 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3946 data_len = 4 /* flags */
3953 + 4 /* pad/reserved */
3954 + (conn->session_info->unix_token->ngroups * 8)
3956 + (conn->session_info->security_token->num_sids *
3960 SIVAL(pdata, 0, flags);
3961 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3963 (uint64_t)conn->session_info->unix_token->uid);
3964 SBIG_UINT(pdata, 16,
3965 (uint64_t)conn->session_info->unix_token->gid);
3968 if (data_len >= max_data_bytes) {
3969 /* Potential overflow, skip the GIDs and SIDs. */
3971 SIVAL(pdata, 24, 0); /* num_groups */
3972 SIVAL(pdata, 28, 0); /* num_sids */
3973 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3974 SIVAL(pdata, 36, 0); /* reserved */
3980 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3981 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3983 /* We walk the SID list twice, but this call is fairly
3984 * infrequent, and I don't expect that it's performance
3985 * sensitive -- jpeach
3987 for (i = 0, sid_bytes = 0;
3988 i < conn->session_info->security_token->num_sids; ++i) {
3989 sid_bytes += ndr_size_dom_sid(
3990 &conn->session_info->security_token->sids[i],
3994 /* SID list byte count */
3995 SIVAL(pdata, 32, sid_bytes);
3997 /* 4 bytes pad/reserved - must be zero */
3998 SIVAL(pdata, 36, 0);
4002 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4003 SBIG_UINT(pdata, data_len,
4004 (uint64_t)conn->session_info->unix_token->groups[i]);
4010 i < conn->session_info->security_token->num_sids; ++i) {
4011 int sid_len = ndr_size_dom_sid(
4012 &conn->session_info->security_token->sids[i],
4015 sid_linearize((uint8_t *)(pdata + data_len),
4017 &conn->session_info->security_token->sids[i]);
4018 data_len += sid_len;
4024 case SMB_MAC_QUERY_FS_INFO:
4026 * Thursby MAC extension... ONLY on NTFS filesystems
4027 * once we do streams then we don't need this
4029 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4031 SIVAL(pdata,84,0x100); /* Don't support mac... */
4036 return NT_STATUS_INVALID_LEVEL;
4039 *ret_data_len = data_len;
4043 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4044 struct smb_request *req,
4046 const DATA_BLOB *qdata)
4049 SMB_NTQUOTA_STRUCT quotas;
4051 ZERO_STRUCT(quotas);
4054 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4055 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4056 lp_servicename(talloc_tos(), SNUM(conn)),
4057 conn->session_info->unix_info->unix_name));
4058 return NT_STATUS_ACCESS_DENIED;
4061 if (!check_fsp_ntquota_handle(conn, req,
4063 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4064 return NT_STATUS_INVALID_HANDLE;
4067 /* note: normally there're 48 bytes,
4068 * but we didn't use the last 6 bytes for now
4071 if (qdata->length < 42) {
4072 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4073 (unsigned int)qdata->length));
4074 return NT_STATUS_INVALID_PARAMETER;
4077 /* unknown_1 24 NULL bytes in pdata*/
4079 /* the soft quotas 8 bytes (uint64_t)*/
4080 quotas.softlim = BVAL(qdata->data,24);
4082 /* the hard quotas 8 bytes (uint64_t)*/
4083 quotas.hardlim = BVAL(qdata->data,32);
4085 /* quota_flags 2 bytes **/
4086 quotas.qflags = SVAL(qdata->data,40);
4088 /* unknown_2 6 NULL bytes follow*/
4090 /* now set the quotas */
4091 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4092 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4093 lp_servicename(talloc_tos(), SNUM(conn))));
4094 status = map_nt_error_from_unix(errno);
4096 status = NT_STATUS_OK;
4101 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4102 struct smb_request *req,
4103 TALLOC_CTX *mem_ctx,
4104 uint16_t info_level,
4106 const DATA_BLOB *pdata)
4108 switch (info_level) {
4109 case SMB_FS_QUOTA_INFORMATION:
4111 return smb_set_fsquota(conn,
4120 return NT_STATUS_INVALID_LEVEL;
4123 /****************************************************************************
4124 Reply to a TRANS2_QFSINFO (query filesystem info).
4125 ****************************************************************************/
4127 static void call_trans2qfsinfo(connection_struct *conn,
4128 struct smb_request *req,
4129 char **pparams, int total_params,
4130 char **ppdata, int total_data,
4131 unsigned int max_data_bytes)
4133 char *params = *pparams;
4134 uint16_t info_level;
4136 size_t fixed_portion;
4139 if (total_params < 2) {
4140 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4144 info_level = SVAL(params,0);
4146 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4147 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4148 DEBUG(0,("call_trans2qfsinfo: encryption required "
4149 "and info level 0x%x sent.\n",
4150 (unsigned int)info_level));
4151 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4156 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4158 status = smbd_do_qfsinfo(req->xconn, conn, req,
4165 if (!NT_STATUS_IS_OK(status)) {
4166 reply_nterror(req, status);
4170 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4173 DEBUG( 4, ( "%s info_level = %d\n",
4174 smb_fn_name(req->cmd), info_level) );
4179 /****************************************************************************
4180 Reply to a TRANS2_SETFSINFO (set filesystem info).
4181 ****************************************************************************/
4183 static void call_trans2setfsinfo(connection_struct *conn,
4184 struct smb_request *req,
4185 char **pparams, int total_params,
4186 char **ppdata, int total_data,
4187 unsigned int max_data_bytes)
4189 struct smbXsrv_connection *xconn = req->xconn;
4190 char *pdata = *ppdata;
4191 char *params = *pparams;
4192 uint16_t info_level;
4194 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4195 lp_servicename(talloc_tos(), SNUM(conn))));
4198 if (total_params < 4) {
4199 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4205 info_level = SVAL(params,2);
4208 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4209 info_level != SMB_SET_CIFS_UNIX_INFO) {
4210 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4211 "info level (0x%x) on IPC$.\n",
4212 (unsigned int)info_level));
4213 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4218 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4219 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4220 DEBUG(0,("call_trans2setfsinfo: encryption required "
4221 "and info level 0x%x sent.\n",
4222 (unsigned int)info_level));
4223 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4228 switch(info_level) {
4229 case SMB_SET_CIFS_UNIX_INFO:
4230 if (!lp_unix_extensions()) {
4231 DEBUG(2,("call_trans2setfsinfo: "
4232 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4233 "unix extensions off\n"));
4235 NT_STATUS_INVALID_LEVEL);
4239 /* There should be 12 bytes of capabilities set. */
4240 if (total_data < 12) {
4243 NT_STATUS_INVALID_PARAMETER);
4246 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4247 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4248 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4249 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4250 /* Just print these values for now. */
4251 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4252 "major = %u, minor = %u cap_low = 0x%x, "
4254 (unsigned int)xconn->
4255 smb1.unix_info.client_major,
4256 (unsigned int)xconn->
4257 smb1.unix_info.client_minor,
4258 (unsigned int)xconn->
4259 smb1.unix_info.client_cap_low,
4260 (unsigned int)xconn->
4261 smb1.unix_info.client_cap_high));
4263 /* Here is where we must switch to posix pathname processing... */
4264 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4265 lp_set_posix_pathnames();
4266 mangle_change_to_posix();
4269 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4270 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4271 /* Client that knows how to do posix locks,
4272 * but not posix open/mkdir operations. Set a
4273 * default type for read/write checks. */
4275 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4280 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4283 size_t param_len = 0;
4284 size_t data_len = total_data;
4286 if (!lp_unix_extensions()) {
4289 NT_STATUS_INVALID_LEVEL);
4293 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4296 NT_STATUS_NOT_SUPPORTED);
4300 if (xconn->smb1.echo_handler.trusted_fde) {
4301 DEBUG( 2,("call_trans2setfsinfo: "
4302 "request transport encryption disabled"
4303 "with 'fork echo handler = yes'\n"));
4306 NT_STATUS_NOT_SUPPORTED);
4310 DEBUG( 4,("call_trans2setfsinfo: "
4311 "request transport encryption.\n"));
4313 status = srv_request_encryption_setup(conn,
4314 (unsigned char **)ppdata,
4316 (unsigned char **)pparams,
4319 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4320 !NT_STATUS_IS_OK(status)) {
4321 reply_nterror(req, status);
4325 send_trans2_replies(conn, req,
4333 if (NT_STATUS_IS_OK(status)) {
4334 /* Server-side transport
4335 * encryption is now *on*. */
4336 status = srv_encryption_start(conn);
4337 if (!NT_STATUS_IS_OK(status)) {
4338 char *reason = talloc_asprintf(talloc_tos(),
4339 "Failure in setting "
4340 "up encrypted transport: %s",
4342 exit_server_cleanly(reason);
4348 case SMB_FS_QUOTA_INFORMATION:
4352 .data = (uint8_t *)pdata,
4353 .length = total_data
4355 files_struct *fsp = NULL;
4356 fsp = file_fsp(req, SVAL(params,0));
4358 status = smb_set_fsquota(conn,
4362 if (!NT_STATUS_IS_OK(status)) {
4363 reply_nterror(req, status);
4369 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4371 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4377 * sending this reply works fine,
4378 * but I'm not sure it's the same
4379 * like windows do...
4382 reply_outbuf(req, 10, 0);
4385 #if defined(HAVE_POSIX_ACLS)
4386 /****************************************************************************
4387 Utility function to count the number of entries in a POSIX acl.
4388 ****************************************************************************/
4390 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4392 unsigned int ace_count = 0;
4393 int entry_id = SMB_ACL_FIRST_ENTRY;
4394 SMB_ACL_ENTRY_T entry;
4396 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4398 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4399 entry_id = SMB_ACL_NEXT_ENTRY;
4406 /****************************************************************************
4407 Utility function to marshall a POSIX acl into wire format.
4408 ****************************************************************************/
4410 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4412 int entry_id = SMB_ACL_FIRST_ENTRY;
4413 SMB_ACL_ENTRY_T entry;
4415 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4416 SMB_ACL_TAG_T tagtype;
4417 SMB_ACL_PERMSET_T permset;
4418 unsigned char perms = 0;
4419 unsigned int own_grp;
4422 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4423 entry_id = SMB_ACL_NEXT_ENTRY;
4426 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4427 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4431 if (sys_acl_get_permset(entry, &permset) == -1) {
4432 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4436 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4437 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4438 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4440 SCVAL(pdata,1,perms);
4443 case SMB_ACL_USER_OBJ:
4444 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4445 own_grp = (unsigned int)pst->st_ex_uid;
4446 SIVAL(pdata,2,own_grp);
4451 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4453 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4456 own_grp = (unsigned int)*puid;
4457 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4458 SIVAL(pdata,2,own_grp);
4462 case SMB_ACL_GROUP_OBJ:
4463 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4464 own_grp = (unsigned int)pst->st_ex_gid;
4465 SIVAL(pdata,2,own_grp);
4470 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4472 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4475 own_grp = (unsigned int)*pgid;
4476 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4477 SIVAL(pdata,2,own_grp);
4482 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4483 SIVAL(pdata,2,0xFFFFFFFF);
4484 SIVAL(pdata,6,0xFFFFFFFF);
4487 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4488 SIVAL(pdata,2,0xFFFFFFFF);
4489 SIVAL(pdata,6,0xFFFFFFFF);
4492 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4495 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4502 /****************************************************************************
4503 Store the FILE_UNIX_BASIC info.
4504 ****************************************************************************/
4506 static char *store_file_unix_basic(connection_struct *conn,
4509 const SMB_STRUCT_STAT *psbuf)
4511 uint64_t file_index = get_FileIndex(conn, psbuf);
4514 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4515 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4517 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4520 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4523 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4524 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4525 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4528 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4532 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4536 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4539 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4540 devno = psbuf->st_ex_rdev;
4542 devno = psbuf->st_ex_dev;
4545 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4549 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4553 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4556 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4560 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4567 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4568 * the chflags(2) (or equivalent) flags.
4570 * XXX: this really should be behind the VFS interface. To do this, we would
4571 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4572 * Each VFS module could then implement its own mapping as appropriate for the
4573 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4575 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4579 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4583 { UF_IMMUTABLE, EXT_IMMUTABLE },
4587 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4591 { UF_HIDDEN, EXT_HIDDEN },
4594 /* Do not remove. We need to guarantee that this array has at least one
4595 * entry to build on HP-UX.
4601 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4602 uint32_t *smb_fflags, uint32_t *smb_fmask)
4606 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4607 *smb_fmask |= info2_flags_map[i].smb_fflag;
4608 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4609 *smb_fflags |= info2_flags_map[i].smb_fflag;
4614 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4615 const uint32_t smb_fflags,
4616 const uint32_t smb_fmask,
4619 uint32_t max_fmask = 0;
4622 *stat_fflags = psbuf->st_ex_flags;
4624 /* For each flags requested in smb_fmask, check the state of the
4625 * corresponding flag in smb_fflags and set or clear the matching
4629 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4630 max_fmask |= info2_flags_map[i].smb_fflag;
4631 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4632 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4633 *stat_fflags |= info2_flags_map[i].stat_fflag;
4635 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4640 /* If smb_fmask is asking to set any bits that are not supported by
4641 * our flag mappings, we should fail.
4643 if ((smb_fmask & max_fmask) != smb_fmask) {
4651 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4652 * of file flags and birth (create) time.
4654 static char *store_file_unix_basic_info2(connection_struct *conn,
4657 const SMB_STRUCT_STAT *psbuf)
4659 uint32_t file_flags = 0;
4660 uint32_t flags_mask = 0;
4662 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4664 /* Create (birth) time 64 bit */
4665 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4668 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4669 SIVAL(pdata, 0, file_flags); /* flags */
4670 SIVAL(pdata, 4, flags_mask); /* mask */
4676 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4677 const struct stream_struct *streams,
4679 unsigned int max_data_bytes,
4680 unsigned int *data_size)
4683 unsigned int ofs = 0;
4685 if (max_data_bytes < 32) {
4686 return NT_STATUS_INFO_LENGTH_MISMATCH;
4689 for (i = 0; i < num_streams; i++) {
4690 unsigned int next_offset;
4692 smb_ucs2_t *namebuf;
4694 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4695 streams[i].name, &namelen) ||
4698 return NT_STATUS_INVALID_PARAMETER;
4702 * name_buf is now null-terminated, we need to marshall as not
4709 * We cannot overflow ...
4711 if ((ofs + 24 + namelen) > max_data_bytes) {
4712 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4714 TALLOC_FREE(namebuf);
4715 return STATUS_BUFFER_OVERFLOW;
4718 SIVAL(data, ofs+4, namelen);
4719 SOFF_T(data, ofs+8, streams[i].size);
4720 SOFF_T(data, ofs+16, streams[i].alloc_size);
4721 memcpy(data+ofs+24, namebuf, namelen);
4722 TALLOC_FREE(namebuf);
4724 next_offset = ofs + 24 + namelen;
4726 if (i == num_streams-1) {
4727 SIVAL(data, ofs, 0);
4730 unsigned int align = ndr_align_size(next_offset, 8);
4732 if ((next_offset + align) > max_data_bytes) {
4733 DEBUG(10, ("refusing to overflow align "
4734 "reply at stream %u\n",
4736 TALLOC_FREE(namebuf);
4737 return STATUS_BUFFER_OVERFLOW;
4740 memset(data+next_offset, 0, align);
4741 next_offset += align;
4743 SIVAL(data, ofs, next_offset - ofs);
4750 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4754 return NT_STATUS_OK;
4757 /****************************************************************************
4758 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4759 ****************************************************************************/
4761 static void call_trans2qpipeinfo(connection_struct *conn,
4762 struct smb_request *req,
4763 unsigned int tran_call,
4764 char **pparams, int total_params,
4765 char **ppdata, int total_data,
4766 unsigned int max_data_bytes)
4768 char *params = *pparams;
4769 char *pdata = *ppdata;
4770 unsigned int data_size = 0;
4771 unsigned int param_size = 2;
4772 uint16_t info_level;
4776 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4780 if (total_params < 4) {
4781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4785 fsp = file_fsp(req, SVAL(params,0));
4786 if (!fsp_is_np(fsp)) {
4787 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4791 info_level = SVAL(params,2);
4793 *pparams = (char *)SMB_REALLOC(*pparams,2);
4794 if (*pparams == NULL) {
4795 reply_nterror(req, NT_STATUS_NO_MEMORY);
4800 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4801 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4804 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4805 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4806 if (*ppdata == NULL ) {
4807 reply_nterror(req, NT_STATUS_NO_MEMORY);
4812 switch (info_level) {
4813 case SMB_FILE_STANDARD_INFORMATION:
4815 SOFF_T(pdata,0,4096LL);
4822 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4826 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4832 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4833 TALLOC_CTX *mem_ctx,
4834 uint16_t info_level,
4836 struct smb_filename *smb_fname,
4837 bool delete_pending,
4838 struct timespec write_time_ts,
4839 struct ea_list *ea_list,
4840 int lock_data_count,
4843 unsigned int max_data_bytes,
4844 size_t *fixed_portion,
4846 unsigned int *pdata_size)
4848 char *pdata = *ppdata;
4849 char *dstart, *dend;
4850 unsigned int data_size;
4851 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4852 time_t create_time, mtime, atime, c_time;
4853 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4860 uint64_t file_size = 0;
4862 uint64_t allocation_size = 0;
4863 uint64_t file_index = 0;
4864 uint32_t access_mask = 0;
4867 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4868 return NT_STATUS_INVALID_LEVEL;
4871 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4872 smb_fname_str_dbg(smb_fname),
4874 info_level, max_data_bytes));
4876 mode = dos_mode(conn, smb_fname);
4877 nlink = psbuf->st_ex_nlink;
4879 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4883 if ((nlink > 0) && delete_pending) {
4887 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4888 return NT_STATUS_INVALID_PARAMETER;
4891 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4892 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4893 if (*ppdata == NULL) {
4894 return NT_STATUS_NO_MEMORY;
4898 dend = dstart + data_size - 1;
4900 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4901 update_stat_ex_mtime(psbuf, write_time_ts);
4904 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4905 mtime_ts = psbuf->st_ex_mtime;
4906 atime_ts = psbuf->st_ex_atime;
4907 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4909 if (lp_dos_filetime_resolution(SNUM(conn))) {
4910 dos_filetime_timespec(&create_time_ts);
4911 dos_filetime_timespec(&mtime_ts);
4912 dos_filetime_timespec(&atime_ts);
4913 dos_filetime_timespec(&ctime_ts);
4916 create_time = convert_timespec_to_time_t(create_time_ts);
4917 mtime = convert_timespec_to_time_t(mtime_ts);
4918 atime = convert_timespec_to_time_t(atime_ts);
4919 c_time = convert_timespec_to_time_t(ctime_ts);
4921 p = strrchr_m(smb_fname->base_name,'/');
4923 base_name = smb_fname->base_name;
4927 /* NT expects the name to be in an exact form of the *full*
4928 filename. See the trans2 torture test */
4929 if (ISDOT(base_name)) {
4930 dos_fname = talloc_strdup(mem_ctx, "\\");
4932 return NT_STATUS_NO_MEMORY;
4935 dos_fname = talloc_asprintf(mem_ctx,
4937 smb_fname->base_name);
4939 return NT_STATUS_NO_MEMORY;
4941 if (is_ntfs_stream_smb_fname(smb_fname)) {
4942 dos_fname = talloc_asprintf(dos_fname, "%s",
4943 smb_fname->stream_name);
4945 return NT_STATUS_NO_MEMORY;
4949 string_replace(dos_fname, '/', '\\');
4952 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4955 /* Do we have this path open ? */
4957 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4958 fsp1 = file_find_di_first(conn->sconn, fileid);
4959 if (fsp1 && fsp1->initial_allocation_size) {
4960 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4964 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4965 file_size = get_file_size_stat(psbuf);
4969 pos = fsp->fh->position_information;
4973 access_mask = fsp->access_mask;
4975 /* GENERIC_EXECUTE mapping from Windows */
4976 access_mask = 0x12019F;
4979 /* This should be an index number - looks like
4982 I think this causes us to fail the IFSKIT
4983 BasicFileInformationTest. -tpot */
4984 file_index = get_FileIndex(conn, psbuf);
4988 switch (info_level) {
4989 case SMB_INFO_STANDARD:
4990 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4992 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4993 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4994 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4995 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4996 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4997 SSVAL(pdata,l1_attrFile,mode);
5000 case SMB_INFO_QUERY_EA_SIZE:
5002 unsigned int ea_size =
5003 estimate_ea_size(conn, fsp,
5005 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5007 srv_put_dos_date2(pdata,0,create_time);
5008 srv_put_dos_date2(pdata,4,atime);
5009 srv_put_dos_date2(pdata,8,mtime); /* write time */
5010 SIVAL(pdata,12,(uint32_t)file_size);
5011 SIVAL(pdata,16,(uint32_t)allocation_size);
5012 SSVAL(pdata,20,mode);
5013 SIVAL(pdata,22,ea_size);
5017 case SMB_INFO_IS_NAME_VALID:
5018 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5020 /* os/2 needs this ? really ?*/
5021 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5023 /* This is only reached for qpathinfo */
5027 case SMB_INFO_QUERY_EAS_FROM_LIST:
5029 size_t total_ea_len = 0;
5030 struct ea_list *ea_file_list = NULL;
5031 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5034 get_ea_list_from_file(mem_ctx, conn, fsp,
5036 &total_ea_len, &ea_file_list);
5037 if (!NT_STATUS_IS_OK(status)) {
5041 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5043 if (!ea_list || (total_ea_len > data_size)) {
5045 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5049 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5053 case SMB_INFO_QUERY_ALL_EAS:
5055 /* We have data_size bytes to put EA's into. */
5056 size_t total_ea_len = 0;
5057 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5059 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5061 &total_ea_len, &ea_list);
5062 if (!NT_STATUS_IS_OK(status)) {
5066 if (!ea_list || (total_ea_len > data_size)) {
5068 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5072 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5076 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5078 /* This is FileFullEaInformation - 0xF which maps to
5079 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5081 /* We have data_size bytes to put EA's into. */
5082 size_t total_ea_len = 0;
5083 struct ea_list *ea_file_list = NULL;
5085 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5087 /*TODO: add filtering and index handling */
5090 get_ea_list_from_file(mem_ctx, conn, fsp,
5092 &total_ea_len, &ea_file_list);
5093 if (!NT_STATUS_IS_OK(status)) {
5096 if (!ea_file_list) {
5097 return NT_STATUS_NO_EAS_ON_FILE;
5100 status = fill_ea_chained_buffer(mem_ctx,
5104 conn, ea_file_list);
5105 if (!NT_STATUS_IS_OK(status)) {
5111 case SMB_FILE_BASIC_INFORMATION:
5112 case SMB_QUERY_FILE_BASIC_INFO:
5114 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5115 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5116 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5118 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5122 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5123 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5124 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5125 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5126 SIVAL(pdata,32,mode);
5128 DEBUG(5,("SMB_QFBI - "));
5129 DEBUG(5,("create: %s ", ctime(&create_time)));
5130 DEBUG(5,("access: %s ", ctime(&atime)));
5131 DEBUG(5,("write: %s ", ctime(&mtime)));
5132 DEBUG(5,("change: %s ", ctime(&c_time)));
5133 DEBUG(5,("mode: %x\n", mode));
5134 *fixed_portion = data_size;
5137 case SMB_FILE_STANDARD_INFORMATION:
5138 case SMB_QUERY_FILE_STANDARD_INFO:
5140 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5142 SOFF_T(pdata,0,allocation_size);
5143 SOFF_T(pdata,8,file_size);
5144 SIVAL(pdata,16,nlink);
5145 SCVAL(pdata,20,delete_pending?1:0);
5146 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5147 SSVAL(pdata,22,0); /* Padding. */
5148 *fixed_portion = 24;
5151 case SMB_FILE_EA_INFORMATION:
5152 case SMB_QUERY_FILE_EA_INFO:
5154 unsigned int ea_size =
5155 estimate_ea_size(conn, fsp, smb_fname);
5156 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5159 SIVAL(pdata,0,ea_size);
5163 /* Get the 8.3 name - used if NT SMB was negotiated. */
5164 case SMB_QUERY_FILE_ALT_NAME_INFO:
5165 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5167 char mangled_name[13];
5168 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5169 if (!name_to_8_3(base_name,mangled_name,
5170 True,conn->params)) {
5171 return NT_STATUS_NO_MEMORY;
5173 status = srvstr_push(dstart, flags2,
5174 pdata+4, mangled_name,
5175 PTR_DIFF(dend, pdata+4),
5177 if (!NT_STATUS_IS_OK(status)) {
5180 data_size = 4 + len;
5186 case SMB_QUERY_FILE_NAME_INFO:
5189 this must be *exactly* right for ACLs on mapped drives to work
5191 status = srvstr_push(dstart, flags2,
5193 PTR_DIFF(dend, pdata+4),
5195 if (!NT_STATUS_IS_OK(status)) {
5198 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5199 data_size = 4 + len;
5204 case SMB_FILE_ALLOCATION_INFORMATION:
5205 case SMB_QUERY_FILE_ALLOCATION_INFO:
5206 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5208 SOFF_T(pdata,0,allocation_size);
5211 case SMB_FILE_END_OF_FILE_INFORMATION:
5212 case SMB_QUERY_FILE_END_OF_FILEINFO:
5213 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5215 SOFF_T(pdata,0,file_size);
5218 case SMB_QUERY_FILE_ALL_INFO:
5219 case SMB_FILE_ALL_INFORMATION:
5221 unsigned int ea_size =
5222 estimate_ea_size(conn, fsp, smb_fname);
5223 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5224 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5225 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5226 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5227 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5228 SIVAL(pdata,32,mode);
5229 SIVAL(pdata,36,0); /* padding. */
5231 SOFF_T(pdata,0,allocation_size);
5232 SOFF_T(pdata,8,file_size);
5233 SIVAL(pdata,16,nlink);
5234 SCVAL(pdata,20,delete_pending);
5235 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5238 SIVAL(pdata,0,ea_size);
5239 pdata += 4; /* EA info */
5240 status = srvstr_push(dstart, flags2,
5242 PTR_DIFF(dend, pdata+4),
5244 if (!NT_STATUS_IS_OK(status)) {
5249 data_size = PTR_DIFF(pdata,(*ppdata));
5250 *fixed_portion = 10;
5254 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5256 unsigned int ea_size =
5257 estimate_ea_size(conn, fsp, smb_fname);
5258 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5259 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5260 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5261 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5262 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5263 SIVAL(pdata, 0x20, mode);
5264 SIVAL(pdata, 0x24, 0); /* padding. */
5265 SBVAL(pdata, 0x28, allocation_size);
5266 SBVAL(pdata, 0x30, file_size);
5267 SIVAL(pdata, 0x38, nlink);
5268 SCVAL(pdata, 0x3C, delete_pending);
5269 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5270 SSVAL(pdata, 0x3E, 0); /* padding */
5271 SBVAL(pdata, 0x40, file_index);
5272 SIVAL(pdata, 0x48, ea_size);
5273 SIVAL(pdata, 0x4C, access_mask);
5274 SBVAL(pdata, 0x50, pos);
5275 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5276 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5280 status = srvstr_push(dstart, flags2,
5282 PTR_DIFF(dend, pdata+4),
5284 if (!NT_STATUS_IS_OK(status)) {
5289 data_size = PTR_DIFF(pdata,(*ppdata));
5290 *fixed_portion = 104;
5293 case SMB_FILE_INTERNAL_INFORMATION:
5295 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5296 SBVAL(pdata, 0, file_index);
5301 case SMB_FILE_ACCESS_INFORMATION:
5302 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5303 SIVAL(pdata, 0, access_mask);
5308 case SMB_FILE_NAME_INFORMATION:
5309 /* Pathname with leading '\'. */
5312 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5313 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5314 SIVAL(pdata,0,byte_len);
5315 data_size = 4 + byte_len;
5319 case SMB_FILE_DISPOSITION_INFORMATION:
5320 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5322 SCVAL(pdata,0,delete_pending);
5326 case SMB_FILE_POSITION_INFORMATION:
5327 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5329 SOFF_T(pdata,0,pos);
5333 case SMB_FILE_MODE_INFORMATION:
5334 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5335 SIVAL(pdata,0,mode);
5340 case SMB_FILE_ALIGNMENT_INFORMATION:
5341 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5342 SIVAL(pdata,0,0); /* No alignment needed. */
5348 * NT4 server just returns "invalid query" to this - if we try
5349 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5352 /* The first statement above is false - verified using Thursby
5353 * client against NT4 -- gcolley.
5355 case SMB_QUERY_FILE_STREAM_INFO:
5356 case SMB_FILE_STREAM_INFORMATION: {
5357 unsigned int num_streams = 0;
5358 struct stream_struct *streams = NULL;
5360 DEBUG(10,("smbd_do_qfilepathinfo: "
5361 "SMB_FILE_STREAM_INFORMATION\n"));
5363 if (is_ntfs_stream_smb_fname(smb_fname)) {
5364 return NT_STATUS_INVALID_PARAMETER;
5367 status = vfs_streaminfo(conn,
5374 if (!NT_STATUS_IS_OK(status)) {
5375 DEBUG(10, ("could not get stream info: %s\n",
5376 nt_errstr(status)));
5380 status = marshall_stream_info(num_streams, streams,
5381 pdata, max_data_bytes,
5384 if (!NT_STATUS_IS_OK(status)) {
5385 DEBUG(10, ("marshall_stream_info failed: %s\n",
5386 nt_errstr(status)));
5387 TALLOC_FREE(streams);
5391 TALLOC_FREE(streams);
5393 *fixed_portion = 32;
5397 case SMB_QUERY_COMPRESSION_INFO:
5398 case SMB_FILE_COMPRESSION_INFORMATION:
5399 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5400 SOFF_T(pdata,0,file_size);
5401 SIVAL(pdata,8,0); /* ??? */
5402 SIVAL(pdata,12,0); /* ??? */
5404 *fixed_portion = 16;
5407 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5408 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5409 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5410 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5411 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5412 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5413 SOFF_T(pdata,32,allocation_size);
5414 SOFF_T(pdata,40,file_size);
5415 SIVAL(pdata,48,mode);
5416 SIVAL(pdata,52,0); /* ??? */
5418 *fixed_portion = 56;
5421 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5423 SIVAL(pdata,0,mode);
5430 * CIFS UNIX Extensions.
5433 case SMB_QUERY_FILE_UNIX_BASIC:
5435 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5436 data_size = PTR_DIFF(pdata,(*ppdata));
5438 DEBUG(4,("smbd_do_qfilepathinfo: "
5439 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5440 dump_data(4, (uint8_t *)(*ppdata), data_size);
5444 case SMB_QUERY_FILE_UNIX_INFO2:
5446 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5447 data_size = PTR_DIFF(pdata,(*ppdata));
5451 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5453 for (i=0; i<100; i++)
5454 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5460 case SMB_QUERY_FILE_UNIX_LINK:
5463 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5466 return NT_STATUS_NO_MEMORY;
5469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5471 if(!S_ISLNK(psbuf->st_ex_mode)) {
5472 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5475 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5477 link_len = SMB_VFS_READLINK(conn,
5478 smb_fname->base_name,
5480 if (link_len == -1) {
5481 return map_nt_error_from_unix(errno);
5483 buffer[link_len] = 0;
5484 status = srvstr_push(dstart, flags2,
5486 PTR_DIFF(dend, pdata),
5487 STR_TERMINATE, &len);
5488 if (!NT_STATUS_IS_OK(status)) {
5492 data_size = PTR_DIFF(pdata,(*ppdata));
5497 #if defined(HAVE_POSIX_ACLS)
5498 case SMB_QUERY_POSIX_ACL:
5500 SMB_ACL_T file_acl = NULL;
5501 SMB_ACL_T def_acl = NULL;
5502 uint16_t num_file_acls = 0;
5503 uint16_t num_def_acls = 0;
5505 status = refuse_symlink(conn,
5508 if (!NT_STATUS_IS_OK(status)) {
5512 if (fsp && fsp->fh->fd != -1) {
5513 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5517 SMB_VFS_SYS_ACL_GET_FILE(conn,
5518 smb_fname->base_name,
5519 SMB_ACL_TYPE_ACCESS,
5523 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5524 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5525 "not implemented on "
5526 "filesystem containing %s\n",
5527 smb_fname->base_name));
5528 return NT_STATUS_NOT_IMPLEMENTED;
5531 if (S_ISDIR(psbuf->st_ex_mode)) {
5532 if (fsp && fsp->is_directory) {
5534 SMB_VFS_SYS_ACL_GET_FILE(
5536 fsp->fsp_name->base_name,
5537 SMB_ACL_TYPE_DEFAULT,
5541 SMB_VFS_SYS_ACL_GET_FILE(
5543 smb_fname->base_name,
5544 SMB_ACL_TYPE_DEFAULT,
5547 def_acl = free_empty_sys_acl(conn, def_acl);
5550 num_file_acls = count_acl_entries(conn, file_acl);
5551 num_def_acls = count_acl_entries(conn, def_acl);
5553 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5554 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5556 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5557 SMB_POSIX_ACL_HEADER_SIZE) ));
5559 TALLOC_FREE(file_acl);
5562 TALLOC_FREE(def_acl);
5564 return NT_STATUS_BUFFER_TOO_SMALL;
5567 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5568 SSVAL(pdata,2,num_file_acls);
5569 SSVAL(pdata,4,num_def_acls);
5570 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5572 TALLOC_FREE(file_acl);
5575 TALLOC_FREE(def_acl);
5577 return NT_STATUS_INTERNAL_ERROR;
5579 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5581 TALLOC_FREE(file_acl);
5584 TALLOC_FREE(def_acl);
5586 return NT_STATUS_INTERNAL_ERROR;
5590 TALLOC_FREE(file_acl);
5593 TALLOC_FREE(def_acl);
5595 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5601 case SMB_QUERY_POSIX_LOCK:
5606 enum brl_type lock_type;
5608 /* We need an open file with a real fd for this. */
5609 if (!fsp || fsp->fh->fd == -1) {
5610 return NT_STATUS_INVALID_LEVEL;
5613 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5614 return NT_STATUS_INVALID_PARAMETER;
5617 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5618 case POSIX_LOCK_TYPE_READ:
5619 lock_type = READ_LOCK;
5621 case POSIX_LOCK_TYPE_WRITE:
5622 lock_type = WRITE_LOCK;
5624 case POSIX_LOCK_TYPE_UNLOCK:
5626 /* There's no point in asking for an unlock... */
5627 return NT_STATUS_INVALID_PARAMETER;
5630 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5631 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5632 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5634 status = query_lock(fsp,
5641 if (ERROR_WAS_LOCK_DENIED(status)) {
5642 /* Here we need to report who has it locked... */
5643 data_size = POSIX_LOCK_DATA_SIZE;
5645 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5646 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5647 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5648 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5649 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5651 } else if (NT_STATUS_IS_OK(status)) {
5652 /* For success we just return a copy of what we sent
5653 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5654 data_size = POSIX_LOCK_DATA_SIZE;
5655 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5656 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5664 return NT_STATUS_INVALID_LEVEL;
5667 *pdata_size = data_size;
5668 return NT_STATUS_OK;
5671 /****************************************************************************
5672 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5673 file name or file id).
5674 ****************************************************************************/
5676 static void call_trans2qfilepathinfo(connection_struct *conn,
5677 struct smb_request *req,
5678 unsigned int tran_call,
5679 char **pparams, int total_params,
5680 char **ppdata, int total_data,
5681 unsigned int max_data_bytes)
5683 char *params = *pparams;
5684 char *pdata = *ppdata;
5685 uint16_t info_level;
5686 unsigned int data_size = 0;
5687 unsigned int param_size = 2;
5688 struct smb_filename *smb_fname = NULL;
5689 bool delete_pending = False;
5690 struct timespec write_time_ts;
5691 files_struct *fsp = NULL;
5692 struct file_id fileid;
5693 struct ea_list *ea_list = NULL;
5694 int lock_data_count = 0;
5695 char *lock_data = NULL;
5696 size_t fixed_portion;
5697 NTSTATUS status = NT_STATUS_OK;
5700 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5704 ZERO_STRUCT(write_time_ts);
5706 if (tran_call == TRANSACT2_QFILEINFO) {
5707 if (total_params < 4) {
5708 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5713 call_trans2qpipeinfo(conn, req, tran_call,
5714 pparams, total_params,
5720 fsp = file_fsp(req, SVAL(params,0));
5721 info_level = SVAL(params,2);
5723 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5725 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5726 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5730 /* Initial check for valid fsp ptr. */
5731 if (!check_fsp_open(conn, req, fsp)) {
5735 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5736 if (smb_fname == NULL) {
5737 reply_nterror(req, NT_STATUS_NO_MEMORY);
5741 if(fsp->fake_file_handle) {
5743 * This is actually for the QUOTA_FAKE_FILE --metze
5746 /* We know this name is ok, it's already passed the checks. */
5748 } else if(fsp->fh->fd == -1) {
5750 * This is actually a QFILEINFO on a directory
5751 * handle (returned from an NT SMB). NT5.0 seems
5752 * to do this call. JRA.
5755 if (INFO_LEVEL_IS_UNIX(info_level)) {
5756 /* Always do lstat for UNIX calls. */
5757 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5758 DEBUG(3,("call_trans2qfilepathinfo: "
5759 "SMB_VFS_LSTAT of %s failed "
5761 smb_fname_str_dbg(smb_fname),
5764 map_nt_error_from_unix(errno));
5767 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5768 DEBUG(3,("call_trans2qfilepathinfo: "
5769 "SMB_VFS_STAT of %s failed (%s)\n",
5770 smb_fname_str_dbg(smb_fname),
5773 map_nt_error_from_unix(errno));
5777 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5778 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5781 * Original code - this is an open file.
5783 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5784 DEBUG(3, ("fstat of %s failed (%s)\n",
5785 fsp_fnum_dbg(fsp), strerror(errno)));
5787 map_nt_error_from_unix(errno));
5790 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5791 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5797 uint32_t ucf_flags = (req->posix_pathnames ?
5798 UCF_POSIX_PATHNAMES : 0);
5801 if (total_params < 7) {
5802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5806 info_level = SVAL(params,0);
5808 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5810 if (INFO_LEVEL_IS_UNIX(info_level)) {
5811 if (!lp_unix_extensions()) {
5812 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5815 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5816 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5817 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5818 req->posix_pathnames) {
5819 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5823 if (req->posix_pathnames) {
5824 srvstr_get_path_posix(req,
5833 srvstr_get_path(req,
5842 if (!NT_STATUS_IS_OK(status)) {
5843 reply_nterror(req, status);
5847 status = filename_convert(req,
5849 req->flags2 & FLAGS2_DFS_PATHNAMES,
5854 if (!NT_STATUS_IS_OK(status)) {
5855 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5856 reply_botherror(req,
5857 NT_STATUS_PATH_NOT_COVERED,
5858 ERRSRV, ERRbadpath);
5861 reply_nterror(req, status);
5865 /* If this is a stream, check if there is a delete_pending. */
5866 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5867 && is_ntfs_stream_smb_fname(smb_fname)) {
5868 struct smb_filename *smb_fname_base;
5870 /* Create an smb_filename with stream_name == NULL. */
5871 smb_fname_base = synthetic_smb_fname(
5873 smb_fname->base_name,
5877 if (smb_fname_base == NULL) {
5878 reply_nterror(req, NT_STATUS_NO_MEMORY);
5882 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5883 /* Always do lstat for UNIX calls. */
5884 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5885 DEBUG(3,("call_trans2qfilepathinfo: "
5886 "SMB_VFS_LSTAT of %s failed "
5888 smb_fname_str_dbg(smb_fname_base),
5890 TALLOC_FREE(smb_fname_base);
5892 map_nt_error_from_unix(errno));
5896 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5897 DEBUG(3,("call_trans2qfilepathinfo: "
5898 "fileinfo of %s failed "
5900 smb_fname_str_dbg(smb_fname_base),
5902 TALLOC_FREE(smb_fname_base);
5904 map_nt_error_from_unix(errno));
5909 status = file_name_hash(conn,
5910 smb_fname_str_dbg(smb_fname_base),
5912 if (!NT_STATUS_IS_OK(status)) {
5913 TALLOC_FREE(smb_fname_base);
5914 reply_nterror(req, status);
5918 fileid = vfs_file_id_from_sbuf(conn,
5919 &smb_fname_base->st);
5920 TALLOC_FREE(smb_fname_base);
5921 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5922 if (delete_pending) {
5923 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5928 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5929 /* Always do lstat for UNIX calls. */
5930 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5931 DEBUG(3,("call_trans2qfilepathinfo: "
5932 "SMB_VFS_LSTAT of %s failed (%s)\n",
5933 smb_fname_str_dbg(smb_fname),
5936 map_nt_error_from_unix(errno));
5941 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5942 DEBUG(3,("call_trans2qfilepathinfo: "
5943 "SMB_VFS_STAT of %s failed (%s)\n",
5944 smb_fname_str_dbg(smb_fname),
5947 map_nt_error_from_unix(errno));
5952 status = file_name_hash(conn,
5953 smb_fname_str_dbg(smb_fname),
5955 if (!NT_STATUS_IS_OK(status)) {
5956 reply_nterror(req, status);
5960 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5961 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5962 if (delete_pending) {
5963 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5968 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5969 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5971 info_level,tran_call,total_data));
5973 /* Pull out any data sent here before we realloc. */
5974 switch (info_level) {
5975 case SMB_INFO_QUERY_EAS_FROM_LIST:
5977 /* Pull any EA list from the data portion. */
5980 if (total_data < 4) {
5982 req, NT_STATUS_INVALID_PARAMETER);
5985 ea_size = IVAL(pdata,0);
5987 if (total_data > 0 && ea_size != total_data) {
5988 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5989 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5991 req, NT_STATUS_INVALID_PARAMETER);
5995 if (!lp_ea_support(SNUM(conn))) {
5996 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6000 /* Pull out the list of names. */
6001 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6004 req, NT_STATUS_INVALID_PARAMETER);
6010 case SMB_QUERY_POSIX_LOCK:
6012 if (fsp == NULL || fsp->fh->fd == -1) {
6013 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6017 if (total_data != POSIX_LOCK_DATA_SIZE) {
6019 req, NT_STATUS_INVALID_PARAMETER);
6023 /* Copy the lock range data. */
6024 lock_data = (char *)talloc_memdup(
6025 req, pdata, total_data);
6027 reply_nterror(req, NT_STATUS_NO_MEMORY);
6030 lock_data_count = total_data;
6036 *pparams = (char *)SMB_REALLOC(*pparams,2);
6037 if (*pparams == NULL) {
6038 reply_nterror(req, NT_STATUS_NO_MEMORY);
6045 * draft-leach-cifs-v1-spec-02.txt
6046 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6049 * The requested information is placed in the Data portion of the
6050 * transaction response. For the information levels greater than 0x100,
6051 * the transaction response has 1 parameter word which should be
6052 * ignored by the client.
6054 * However Windows only follows this rule for the IS_NAME_VALID call.
6056 switch (info_level) {
6057 case SMB_INFO_IS_NAME_VALID:
6062 if ((info_level & 0xFF00) == 0xFF00) {
6064 * We use levels that start with 0xFF00
6065 * internally to represent SMB2 specific levels
6067 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6071 status = smbd_do_qfilepathinfo(conn, req, info_level,
6073 delete_pending, write_time_ts,
6075 lock_data_count, lock_data,
6076 req->flags2, max_data_bytes,
6078 ppdata, &data_size);
6079 if (!NT_STATUS_IS_OK(status)) {
6080 reply_nterror(req, status);
6083 if (fixed_portion > max_data_bytes) {
6084 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6088 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6094 /****************************************************************************
6095 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6097 ****************************************************************************/
6099 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6100 connection_struct *conn,
6101 struct smb_request *req,
6102 bool overwrite_if_exists,
6103 const struct smb_filename *smb_fname_old,
6104 struct smb_filename *smb_fname_new)
6106 NTSTATUS status = NT_STATUS_OK;
6108 /* source must already exist. */
6109 if (!VALID_STAT(smb_fname_old->st)) {
6110 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6113 if (VALID_STAT(smb_fname_new->st)) {
6114 if (overwrite_if_exists) {
6115 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6116 return NT_STATUS_FILE_IS_A_DIRECTORY;
6118 status = unlink_internals(conn,
6120 FILE_ATTRIBUTE_NORMAL,
6123 if (!NT_STATUS_IS_OK(status)) {
6127 /* Disallow if newname already exists. */
6128 return NT_STATUS_OBJECT_NAME_COLLISION;
6132 /* No links from a directory. */
6133 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6134 return NT_STATUS_FILE_IS_A_DIRECTORY;
6137 /* Setting a hardlink to/from a stream isn't currently supported. */
6138 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6139 is_ntfs_stream_smb_fname(smb_fname_new)) {
6140 return NT_STATUS_INVALID_PARAMETER;
6143 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6144 smb_fname_old->base_name, smb_fname_new->base_name));
6146 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
6147 smb_fname_new->base_name) != 0) {
6148 status = map_nt_error_from_unix(errno);
6149 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6150 nt_errstr(status), smb_fname_old->base_name,
6151 smb_fname_new->base_name));
6156 /****************************************************************************
6157 Deal with setting the time from any of the setfilepathinfo functions.
6158 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6159 calling this function.
6160 ****************************************************************************/
6162 NTSTATUS smb_set_file_time(connection_struct *conn,
6164 const struct smb_filename *smb_fname,
6165 struct smb_file_time *ft,
6166 bool setting_write_time)
6168 struct smb_filename smb_fname_base;
6170 FILE_NOTIFY_CHANGE_LAST_ACCESS
6171 |FILE_NOTIFY_CHANGE_LAST_WRITE
6172 |FILE_NOTIFY_CHANGE_CREATION;
6174 if (!VALID_STAT(smb_fname->st)) {
6175 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6178 /* get some defaults (no modifications) if any info is zero or -1. */
6179 if (null_timespec(ft->create_time)) {
6180 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6183 if (null_timespec(ft->atime)) {
6184 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6187 if (null_timespec(ft->mtime)) {
6188 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6191 if (!setting_write_time) {
6192 /* ft->mtime comes from change time, not write time. */
6193 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6196 /* Ensure the resolution is the correct for
6197 * what we can store on this filesystem. */
6199 round_timespec(conn->ts_res, &ft->create_time);
6200 round_timespec(conn->ts_res, &ft->ctime);
6201 round_timespec(conn->ts_res, &ft->atime);
6202 round_timespec(conn->ts_res, &ft->mtime);
6204 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6205 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6206 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6207 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6208 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6209 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6210 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6211 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6213 if (setting_write_time) {
6215 * This was a Windows setfileinfo on an open file.
6216 * NT does this a lot. We also need to
6217 * set the time here, as it can be read by
6218 * FindFirst/FindNext and with the patch for bug #2045
6219 * in smbd/fileio.c it ensures that this timestamp is
6220 * kept sticky even after a write. We save the request
6221 * away and will set it on file close and after a write. JRA.
6224 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6225 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6228 if (fsp->base_fsp) {
6229 set_sticky_write_time_fsp(fsp->base_fsp,
6232 set_sticky_write_time_fsp(fsp, ft->mtime);
6235 set_sticky_write_time_path(
6236 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6241 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6243 /* Always call ntimes on the base, even if a stream was passed in. */
6244 smb_fname_base = *smb_fname;
6245 smb_fname_base.stream_name = NULL;
6247 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6248 return map_nt_error_from_unix(errno);
6251 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6252 smb_fname->base_name);
6253 return NT_STATUS_OK;
6256 /****************************************************************************
6257 Deal with setting the dosmode from any of the setfilepathinfo functions.
6258 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6259 done before calling this function.
6260 ****************************************************************************/
6262 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6263 const struct smb_filename *smb_fname,
6266 struct smb_filename *smb_fname_base;
6269 if (!VALID_STAT(smb_fname->st)) {
6270 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6273 /* Always operate on the base_name, even if a stream was passed in. */
6274 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6275 smb_fname->base_name,
6279 if (smb_fname_base == NULL) {
6280 return NT_STATUS_NO_MEMORY;
6284 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6285 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6287 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6291 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6293 /* check the mode isn't different, before changing it */
6294 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6295 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6296 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6297 (unsigned int)dosmode));
6299 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6301 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6303 smb_fname_str_dbg(smb_fname_base),
6305 status = map_nt_error_from_unix(errno);
6309 status = NT_STATUS_OK;
6311 TALLOC_FREE(smb_fname_base);
6315 /****************************************************************************
6316 Deal with setting the size from any of the setfilepathinfo functions.
6317 ****************************************************************************/
6319 static NTSTATUS smb_set_file_size(connection_struct *conn,
6320 struct smb_request *req,
6322 const struct smb_filename *smb_fname,
6323 const SMB_STRUCT_STAT *psbuf,
6325 bool fail_after_createfile)
6327 NTSTATUS status = NT_STATUS_OK;
6328 struct smb_filename *smb_fname_tmp = NULL;
6329 files_struct *new_fsp = NULL;
6331 if (!VALID_STAT(*psbuf)) {
6332 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6335 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6337 if (size == get_file_size_stat(psbuf)) {
6338 return NT_STATUS_OK;
6341 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6342 smb_fname_str_dbg(smb_fname), (double)size));
6344 if (fsp && fsp->fh->fd != -1) {
6345 /* Handle based call. */
6346 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6347 return NT_STATUS_ACCESS_DENIED;
6350 if (vfs_set_filelen(fsp, size) == -1) {
6351 return map_nt_error_from_unix(errno);
6353 trigger_write_time_update_immediate(fsp);
6354 return NT_STATUS_OK;
6357 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6358 if (smb_fname_tmp == NULL) {
6359 return NT_STATUS_NO_MEMORY;
6362 smb_fname_tmp->st = *psbuf;
6364 status = SMB_VFS_CREATE_FILE(
6367 0, /* root_dir_fid */
6368 smb_fname_tmp, /* fname */
6369 FILE_WRITE_DATA, /* access_mask */
6370 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6372 FILE_OPEN, /* create_disposition*/
6373 0, /* create_options */
6374 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6375 0, /* oplock_request */
6377 0, /* allocation_size */
6378 0, /* private_flags */
6381 &new_fsp, /* result */
6383 NULL, NULL); /* create context */
6385 TALLOC_FREE(smb_fname_tmp);
6387 if (!NT_STATUS_IS_OK(status)) {
6388 /* NB. We check for open_was_deferred in the caller. */
6392 /* See RAW-SFILEINFO-END-OF-FILE */
6393 if (fail_after_createfile) {
6394 close_file(req, new_fsp,NORMAL_CLOSE);
6395 return NT_STATUS_INVALID_LEVEL;
6398 if (vfs_set_filelen(new_fsp, size) == -1) {
6399 status = map_nt_error_from_unix(errno);
6400 close_file(req, new_fsp,NORMAL_CLOSE);
6404 trigger_write_time_update_immediate(new_fsp);
6405 close_file(req, new_fsp,NORMAL_CLOSE);
6406 return NT_STATUS_OK;
6409 /****************************************************************************
6410 Deal with SMB_INFO_SET_EA.
6411 ****************************************************************************/
6413 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6417 const struct smb_filename *smb_fname)
6419 struct ea_list *ea_list = NULL;
6420 TALLOC_CTX *ctx = NULL;
6421 NTSTATUS status = NT_STATUS_OK;
6423 if (total_data < 10) {
6425 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6426 length. They seem to have no effect. Bug #3212. JRA */
6428 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6429 /* We're done. We only get EA info in this call. */
6430 return NT_STATUS_OK;
6433 return NT_STATUS_INVALID_PARAMETER;
6436 if (IVAL(pdata,0) > total_data) {
6437 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6438 IVAL(pdata,0), (unsigned int)total_data));
6439 return NT_STATUS_INVALID_PARAMETER;
6443 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6445 return NT_STATUS_INVALID_PARAMETER;
6448 status = set_ea(conn, fsp, smb_fname, ea_list);
6453 /****************************************************************************
6454 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6455 ****************************************************************************/
6457 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6462 struct ea_list *ea_list = NULL;
6466 return NT_STATUS_INVALID_HANDLE;
6469 if (!lp_ea_support(SNUM(conn))) {
6470 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6471 "EA's not supported.\n",
6472 (unsigned int)total_data));
6473 return NT_STATUS_EAS_NOT_SUPPORTED;
6476 if (total_data < 10) {
6477 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6479 (unsigned int)total_data));
6480 return NT_STATUS_INVALID_PARAMETER;
6483 ea_list = read_nttrans_ea_list(talloc_tos(),
6488 return NT_STATUS_INVALID_PARAMETER;
6491 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6493 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6494 smb_fname_str_dbg(fsp->fsp_name),
6495 nt_errstr(status) ));
6501 /****************************************************************************
6502 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6503 ****************************************************************************/
6505 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6509 struct smb_filename *smb_fname)
6511 NTSTATUS status = NT_STATUS_OK;
6512 bool delete_on_close;
6513 uint32_t dosmode = 0;
6515 if (total_data < 1) {
6516 return NT_STATUS_INVALID_PARAMETER;
6520 return NT_STATUS_INVALID_HANDLE;
6523 delete_on_close = (CVAL(pdata,0) ? True : False);
6524 dosmode = dos_mode(conn, smb_fname);
6526 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6527 "delete_on_close = %u\n",
6528 smb_fname_str_dbg(smb_fname),
6529 (unsigned int)dosmode,
6530 (unsigned int)delete_on_close ));
6532 if (delete_on_close) {
6533 status = can_set_delete_on_close(fsp, dosmode);
6534 if (!NT_STATUS_IS_OK(status)) {
6539 /* The set is across all open files on this dev/inode pair. */
6540 if (!set_delete_on_close(fsp, delete_on_close,
6541 conn->session_info->security_token,
6542 conn->session_info->unix_token)) {
6543 return NT_STATUS_ACCESS_DENIED;
6545 return NT_STATUS_OK;
6548 /****************************************************************************
6549 Deal with SMB_FILE_POSITION_INFORMATION.
6550 ****************************************************************************/
6552 static NTSTATUS smb_file_position_information(connection_struct *conn,
6557 uint64_t position_information;
6559 if (total_data < 8) {
6560 return NT_STATUS_INVALID_PARAMETER;
6564 /* Ignore on pathname based set. */
6565 return NT_STATUS_OK;
6568 position_information = (uint64_t)IVAL(pdata,0);
6569 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6571 DEBUG(10,("smb_file_position_information: Set file position "
6572 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6573 (double)position_information));
6574 fsp->fh->position_information = position_information;
6575 return NT_STATUS_OK;
6578 /****************************************************************************
6579 Deal with SMB_FILE_MODE_INFORMATION.
6580 ****************************************************************************/
6582 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6588 if (total_data < 4) {
6589 return NT_STATUS_INVALID_PARAMETER;
6591 mode = IVAL(pdata,0);
6592 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6593 return NT_STATUS_INVALID_PARAMETER;
6595 return NT_STATUS_OK;
6598 /****************************************************************************
6599 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6600 ****************************************************************************/
6602 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6603 struct smb_request *req,
6606 const struct smb_filename *smb_fname)
6608 char *link_target = NULL;
6609 const char *newname = smb_fname->base_name;
6610 TALLOC_CTX *ctx = talloc_tos();
6612 /* Set a symbolic link. */
6613 /* Don't allow this if follow links is false. */
6615 if (total_data == 0) {
6616 return NT_STATUS_INVALID_PARAMETER;
6619 if (!lp_follow_symlinks(SNUM(conn))) {
6620 return NT_STATUS_ACCESS_DENIED;
6623 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6624 total_data, STR_TERMINATE);
6627 return NT_STATUS_INVALID_PARAMETER;
6630 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6631 newname, link_target ));
6633 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6634 return map_nt_error_from_unix(errno);
6637 return NT_STATUS_OK;
6640 /****************************************************************************
6641 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6642 ****************************************************************************/
6644 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6645 struct smb_request *req,
6646 const char *pdata, int total_data,
6647 struct smb_filename *smb_fname_new)
6649 char *oldname = NULL;
6650 struct smb_filename *smb_fname_old = NULL;
6651 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6652 TALLOC_CTX *ctx = talloc_tos();
6653 NTSTATUS status = NT_STATUS_OK;
6655 /* Set a hard link. */
6656 if (total_data == 0) {
6657 return NT_STATUS_INVALID_PARAMETER;
6660 if (req->posix_pathnames) {
6661 srvstr_get_path_posix(ctx,
6670 srvstr_get_path(ctx,
6679 if (!NT_STATUS_IS_OK(status)) {
6683 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6684 smb_fname_str_dbg(smb_fname_new), oldname));
6686 status = filename_convert(ctx,
6688 req->flags2 & FLAGS2_DFS_PATHNAMES,
6693 if (!NT_STATUS_IS_OK(status)) {
6697 return hardlink_internals(ctx, conn, req, false,
6698 smb_fname_old, smb_fname_new);
6701 /****************************************************************************
6702 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6703 ****************************************************************************/
6705 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6706 struct smb_request *req,
6710 struct smb_filename *smb_fname_src)
6714 char *newname = NULL;
6715 struct smb_filename *smb_fname_dst = NULL;
6716 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6717 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6718 NTSTATUS status = NT_STATUS_OK;
6719 TALLOC_CTX *ctx = talloc_tos();
6722 return NT_STATUS_INVALID_HANDLE;
6725 if (total_data < 20) {
6726 return NT_STATUS_INVALID_PARAMETER;
6729 overwrite = (CVAL(pdata,0) ? True : False);
6730 len = IVAL(pdata,16);
6732 if (len > (total_data - 20) || (len == 0)) {
6733 return NT_STATUS_INVALID_PARAMETER;
6736 if (req->posix_pathnames) {
6737 srvstr_get_path_posix(ctx,
6746 srvstr_get_path(ctx,
6755 if (!NT_STATUS_IS_OK(status)) {
6759 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6762 status = filename_convert(ctx,
6764 req->flags2 & FLAGS2_DFS_PATHNAMES,
6769 if (!NT_STATUS_IS_OK(status)) {
6773 if (fsp->base_fsp) {
6774 /* newname must be a stream name. */
6775 if (newname[0] != ':') {
6776 return NT_STATUS_NOT_SUPPORTED;
6779 /* Create an smb_fname to call rename_internals_fsp() with. */
6780 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6781 fsp->base_fsp->fsp_name->base_name,
6784 fsp->base_fsp->fsp_name->flags);
6785 if (smb_fname_dst == NULL) {
6786 status = NT_STATUS_NO_MEMORY;
6791 * Set the original last component, since
6792 * rename_internals_fsp() requires it.
6794 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6796 if (smb_fname_dst->original_lcomp == NULL) {
6797 status = NT_STATUS_NO_MEMORY;
6803 DEBUG(10,("smb2_file_rename_information: "
6804 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6805 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6806 smb_fname_str_dbg(smb_fname_dst)));
6807 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6808 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6812 TALLOC_FREE(smb_fname_dst);
6816 static NTSTATUS smb_file_link_information(connection_struct *conn,
6817 struct smb_request *req,
6821 struct smb_filename *smb_fname_src)
6825 char *newname = NULL;
6826 struct smb_filename *smb_fname_dst = NULL;
6827 NTSTATUS status = NT_STATUS_OK;
6828 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6829 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6830 TALLOC_CTX *ctx = talloc_tos();
6833 return NT_STATUS_INVALID_HANDLE;
6836 if (total_data < 20) {
6837 return NT_STATUS_INVALID_PARAMETER;
6840 overwrite = (CVAL(pdata,0) ? true : false);
6841 len = IVAL(pdata,16);
6843 if (len > (total_data - 20) || (len == 0)) {
6844 return NT_STATUS_INVALID_PARAMETER;
6847 if (req->posix_pathnames) {
6848 srvstr_get_path_posix(ctx,
6857 srvstr_get_path(ctx,
6866 if (!NT_STATUS_IS_OK(status)) {
6870 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6873 status = filename_convert(ctx,
6875 req->flags2 & FLAGS2_DFS_PATHNAMES,
6880 if (!NT_STATUS_IS_OK(status)) {
6884 if (fsp->base_fsp) {
6885 /* No stream names. */
6886 return NT_STATUS_NOT_SUPPORTED;
6889 DEBUG(10,("smb_file_link_information: "
6890 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6891 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6892 smb_fname_str_dbg(smb_fname_dst)));
6893 status = hardlink_internals(ctx,
6900 TALLOC_FREE(smb_fname_dst);
6904 /****************************************************************************
6905 Deal with SMB_FILE_RENAME_INFORMATION.
6906 ****************************************************************************/
6908 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6909 struct smb_request *req,
6913 struct smb_filename *smb_fname_src)
6918 char *newname = NULL;
6919 struct smb_filename *smb_fname_dst = NULL;
6920 bool dest_has_wcard = False;
6921 NTSTATUS status = NT_STATUS_OK;
6923 TALLOC_CTX *ctx = talloc_tos();
6925 if (total_data < 13) {
6926 return NT_STATUS_INVALID_PARAMETER;
6929 overwrite = (CVAL(pdata,0) ? True : False);
6930 root_fid = IVAL(pdata,4);
6931 len = IVAL(pdata,8);
6933 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6934 return NT_STATUS_INVALID_PARAMETER;
6937 if (req->posix_pathnames) {
6938 srvstr_get_path_wcard_posix(ctx,
6948 srvstr_get_path_wcard(ctx,
6958 if (!NT_STATUS_IS_OK(status)) {
6962 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6965 status = resolve_dfspath_wcard(ctx, conn,
6966 req->flags2 & FLAGS2_DFS_PATHNAMES,
6968 UCF_COND_ALLOW_WCARD_LCOMP,
6969 !conn->sconn->using_smb2,
6972 if (!NT_STATUS_IS_OK(status)) {
6976 /* Check the new name has no '/' characters. */
6977 if (strchr_m(newname, '/')) {
6978 return NT_STATUS_NOT_SUPPORTED;
6981 if (fsp && fsp->base_fsp) {
6982 /* newname must be a stream name. */
6983 if (newname[0] != ':') {
6984 return NT_STATUS_NOT_SUPPORTED;
6987 /* Create an smb_fname to call rename_internals_fsp() with. */
6988 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6989 fsp->base_fsp->fsp_name->base_name,
6992 fsp->base_fsp->fsp_name->flags);
6993 if (smb_fname_dst == NULL) {
6994 status = NT_STATUS_NO_MEMORY;
6999 * Set the original last component, since
7000 * rename_internals_fsp() requires it.
7002 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7004 if (smb_fname_dst->original_lcomp == NULL) {
7005 status = NT_STATUS_NO_MEMORY;
7011 * Build up an smb_fname_dst based on the filename passed in.
7012 * We basically just strip off the last component, and put on
7013 * the newname instead.
7015 char *base_name = NULL;
7017 /* newname must *not* be a stream name. */
7018 if (newname[0] == ':') {
7019 return NT_STATUS_NOT_SUPPORTED;
7023 * Strip off the last component (filename) of the path passed
7026 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7028 return NT_STATUS_NO_MEMORY;
7030 p = strrchr_m(base_name, '/');
7034 base_name = talloc_strdup(ctx, "");
7036 return NT_STATUS_NO_MEMORY;
7039 /* Append the new name. */
7040 base_name = talloc_asprintf_append(base_name,
7044 return NT_STATUS_NO_MEMORY;
7047 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7050 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
7053 /* If an error we expect this to be
7054 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7056 if (!NT_STATUS_IS_OK(status)) {
7057 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7061 /* Create an smb_fname to call rename_internals_fsp() */
7062 smb_fname_dst = synthetic_smb_fname(ctx,
7066 smb_fname_src->flags);
7067 if (smb_fname_dst == NULL) {
7068 status = NT_STATUS_NO_MEMORY;
7075 DEBUG(10,("smb_file_rename_information: "
7076 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7077 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7078 smb_fname_str_dbg(smb_fname_dst)));
7079 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7082 DEBUG(10,("smb_file_rename_information: "
7083 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7084 smb_fname_str_dbg(smb_fname_src),
7085 smb_fname_str_dbg(smb_fname_dst)));
7086 status = rename_internals(ctx, conn, req, smb_fname_src,
7087 smb_fname_dst, 0, overwrite, false,
7089 FILE_WRITE_ATTRIBUTES);
7092 TALLOC_FREE(smb_fname_dst);
7096 /****************************************************************************
7097 Deal with SMB_SET_POSIX_ACL.
7098 ****************************************************************************/
7100 #if defined(HAVE_POSIX_ACLS)
7101 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7105 const struct smb_filename *smb_fname)
7107 uint16_t posix_acl_version;
7108 uint16_t num_file_acls;
7109 uint16_t num_def_acls;
7110 bool valid_file_acls = True;
7111 bool valid_def_acls = True;
7114 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7115 return NT_STATUS_INVALID_PARAMETER;
7117 posix_acl_version = SVAL(pdata,0);
7118 num_file_acls = SVAL(pdata,2);
7119 num_def_acls = SVAL(pdata,4);
7121 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7122 valid_file_acls = False;
7126 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7127 valid_def_acls = False;
7131 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7132 return NT_STATUS_INVALID_PARAMETER;
7135 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7136 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7137 return NT_STATUS_INVALID_PARAMETER;
7140 status = refuse_symlink(conn, fsp, smb_fname);
7141 if (!NT_STATUS_IS_OK(status)) {
7145 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7146 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7147 (unsigned int)num_file_acls,
7148 (unsigned int)num_def_acls));
7150 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7151 smb_fname->base_name, num_file_acls,
7152 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7153 return map_nt_error_from_unix(errno);
7156 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7157 smb_fname->base_name, &smb_fname->st, num_def_acls,
7158 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7159 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7160 return map_nt_error_from_unix(errno);
7162 return NT_STATUS_OK;
7166 /****************************************************************************
7167 Deal with SMB_SET_POSIX_LOCK.
7168 ****************************************************************************/
7170 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7171 struct smb_request *req,
7179 bool blocking_lock = False;
7180 enum brl_type lock_type;
7182 NTSTATUS status = NT_STATUS_OK;
7184 if (fsp == NULL || fsp->fh->fd == -1) {
7185 return NT_STATUS_INVALID_HANDLE;
7188 if (total_data != POSIX_LOCK_DATA_SIZE) {
7189 return NT_STATUS_INVALID_PARAMETER;
7192 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7193 case POSIX_LOCK_TYPE_READ:
7194 lock_type = READ_LOCK;
7196 case POSIX_LOCK_TYPE_WRITE:
7197 /* Return the right POSIX-mappable error code for files opened read-only. */
7198 if (!fsp->can_write) {
7199 return NT_STATUS_INVALID_HANDLE;
7201 lock_type = WRITE_LOCK;
7203 case POSIX_LOCK_TYPE_UNLOCK:
7204 lock_type = UNLOCK_LOCK;
7207 return NT_STATUS_INVALID_PARAMETER;
7210 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7211 blocking_lock = False;
7212 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7213 blocking_lock = True;
7215 return NT_STATUS_INVALID_PARAMETER;
7218 if (!lp_blocking_locks(SNUM(conn))) {
7219 blocking_lock = False;
7222 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7223 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7224 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7225 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7226 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7228 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7229 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7231 (unsigned int)lock_type,
7232 (unsigned long long)smblctx,
7236 if (lock_type == UNLOCK_LOCK) {
7237 status = do_unlock(req->sconn->msg_ctx,
7244 uint64_t block_smblctx;
7246 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7257 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7259 * A blocking lock was requested. Package up
7260 * this smb into a queued request and push it
7261 * onto the blocking lock queue.
7263 if(push_blocking_lock_request(br_lck,
7266 -1, /* infinite timeout. */
7274 TALLOC_FREE(br_lck);
7278 TALLOC_FREE(br_lck);
7284 /****************************************************************************
7285 Deal with SMB_SET_FILE_BASIC_INFO.
7286 ****************************************************************************/
7288 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7292 const struct smb_filename *smb_fname)
7294 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7295 struct smb_file_time ft;
7296 uint32_t dosmode = 0;
7297 NTSTATUS status = NT_STATUS_OK;
7301 if (total_data < 36) {
7302 return NT_STATUS_INVALID_PARAMETER;
7305 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7306 if (!NT_STATUS_IS_OK(status)) {
7310 /* Set the attributes */
7311 dosmode = IVAL(pdata,32);
7312 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7313 if (!NT_STATUS_IS_OK(status)) {
7318 ft.create_time = interpret_long_date(pdata);
7321 ft.atime = interpret_long_date(pdata+8);
7324 ft.mtime = interpret_long_date(pdata+16);
7327 ft.ctime = interpret_long_date(pdata+24);
7329 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7330 smb_fname_str_dbg(smb_fname)));
7332 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7336 /****************************************************************************
7337 Deal with SMB_INFO_STANDARD.
7338 ****************************************************************************/
7340 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7344 const struct smb_filename *smb_fname)
7347 struct smb_file_time ft;
7351 if (total_data < 12) {
7352 return NT_STATUS_INVALID_PARAMETER;
7356 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7358 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7360 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7362 DEBUG(10,("smb_set_info_standard: file %s\n",
7363 smb_fname_str_dbg(smb_fname)));
7365 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7366 if (!NT_STATUS_IS_OK(status)) {
7370 return smb_set_file_time(conn,
7377 /****************************************************************************
7378 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7379 ****************************************************************************/
7381 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7382 struct smb_request *req,
7386 struct smb_filename *smb_fname)
7388 uint64_t allocation_size = 0;
7389 NTSTATUS status = NT_STATUS_OK;
7390 files_struct *new_fsp = NULL;
7392 if (!VALID_STAT(smb_fname->st)) {
7393 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7396 if (total_data < 8) {
7397 return NT_STATUS_INVALID_PARAMETER;
7400 allocation_size = (uint64_t)IVAL(pdata,0);
7401 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7402 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7403 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7404 (double)allocation_size));
7406 if (allocation_size) {
7407 allocation_size = smb_roundup(conn, allocation_size);
7410 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7411 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7412 (double)allocation_size));
7414 if (fsp && fsp->fh->fd != -1) {
7415 /* Open file handle. */
7416 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7417 return NT_STATUS_ACCESS_DENIED;
7420 /* Only change if needed. */
7421 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7422 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7423 return map_nt_error_from_unix(errno);
7426 /* But always update the time. */
7428 * This is equivalent to a write. Ensure it's seen immediately
7429 * if there are no pending writes.
7431 trigger_write_time_update_immediate(fsp);
7432 return NT_STATUS_OK;
7435 /* Pathname or stat or directory file. */
7436 status = SMB_VFS_CREATE_FILE(
7439 0, /* root_dir_fid */
7440 smb_fname, /* fname */
7441 FILE_WRITE_DATA, /* access_mask */
7442 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7444 FILE_OPEN, /* create_disposition*/
7445 0, /* create_options */
7446 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7447 0, /* oplock_request */
7449 0, /* allocation_size */
7450 0, /* private_flags */
7453 &new_fsp, /* result */
7455 NULL, NULL); /* create context */
7457 if (!NT_STATUS_IS_OK(status)) {
7458 /* NB. We check for open_was_deferred in the caller. */
7462 /* Only change if needed. */
7463 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7464 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7465 status = map_nt_error_from_unix(errno);
7466 close_file(req, new_fsp, NORMAL_CLOSE);
7471 /* Changing the allocation size should set the last mod time. */
7473 * This is equivalent to a write. Ensure it's seen immediately
7474 * if there are no pending writes.
7476 trigger_write_time_update_immediate(new_fsp);
7477 close_file(req, new_fsp, NORMAL_CLOSE);
7478 return NT_STATUS_OK;
7481 /****************************************************************************
7482 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7483 ****************************************************************************/
7485 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7486 struct smb_request *req,
7490 const struct smb_filename *smb_fname,
7491 bool fail_after_createfile)
7495 if (total_data < 8) {
7496 return NT_STATUS_INVALID_PARAMETER;
7499 size = IVAL(pdata,0);
7500 size |= (((off_t)IVAL(pdata,4)) << 32);
7501 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7502 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7505 return smb_set_file_size(conn, req,
7510 fail_after_createfile);
7513 /****************************************************************************
7514 Allow a UNIX info mknod.
7515 ****************************************************************************/
7517 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7520 const struct smb_filename *smb_fname)
7522 uint32_t file_type = IVAL(pdata,56);
7523 #if defined(HAVE_MAKEDEV)
7524 uint32_t dev_major = IVAL(pdata,60);
7525 uint32_t dev_minor = IVAL(pdata,68);
7527 SMB_DEV_T dev = (SMB_DEV_T)0;
7528 uint32_t raw_unixmode = IVAL(pdata,84);
7532 if (total_data < 100) {
7533 return NT_STATUS_INVALID_PARAMETER;
7536 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7537 PERM_NEW_FILE, &unixmode);
7538 if (!NT_STATUS_IS_OK(status)) {
7542 #if defined(HAVE_MAKEDEV)
7543 dev = makedev(dev_major, dev_minor);
7546 switch (file_type) {
7547 #if defined(S_IFIFO)
7548 case UNIX_TYPE_FIFO:
7549 unixmode |= S_IFIFO;
7552 #if defined(S_IFSOCK)
7553 case UNIX_TYPE_SOCKET:
7554 unixmode |= S_IFSOCK;
7557 #if defined(S_IFCHR)
7558 case UNIX_TYPE_CHARDEV:
7559 unixmode |= S_IFCHR;
7562 #if defined(S_IFBLK)
7563 case UNIX_TYPE_BLKDEV:
7564 unixmode |= S_IFBLK;
7568 return NT_STATUS_INVALID_PARAMETER;
7571 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7572 "%.0f mode 0%o for file %s\n", (double)dev,
7573 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7575 /* Ok - do the mknod. */
7576 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7577 return map_nt_error_from_unix(errno);
7580 /* If any of the other "set" calls fail we
7581 * don't want to end up with a half-constructed mknod.
7584 if (lp_inherit_permissions(SNUM(conn))) {
7586 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7588 return NT_STATUS_NO_MEMORY;
7590 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7592 TALLOC_FREE(parent);
7595 return NT_STATUS_OK;
7598 /****************************************************************************
7599 Deal with SMB_SET_FILE_UNIX_BASIC.
7600 ****************************************************************************/
7602 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7603 struct smb_request *req,
7607 const struct smb_filename *smb_fname)
7609 struct smb_file_time ft;
7610 uint32_t raw_unixmode;
7613 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7614 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7615 NTSTATUS status = NT_STATUS_OK;
7616 bool delete_on_fail = False;
7617 enum perm_type ptype;
7618 files_struct *all_fsps = NULL;
7619 bool modify_mtime = true;
7621 struct smb_filename *smb_fname_tmp = NULL;
7622 SMB_STRUCT_STAT sbuf;
7626 if (total_data < 100) {
7627 return NT_STATUS_INVALID_PARAMETER;
7630 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7631 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7632 size=IVAL(pdata,0); /* first 8 Bytes are size */
7633 size |= (((off_t)IVAL(pdata,4)) << 32);
7636 ft.atime = interpret_long_date(pdata+24); /* access_time */
7637 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7638 set_owner = (uid_t)IVAL(pdata,40);
7639 set_grp = (gid_t)IVAL(pdata,48);
7640 raw_unixmode = IVAL(pdata,84);
7642 if (VALID_STAT(smb_fname->st)) {
7643 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7644 ptype = PERM_EXISTING_DIR;
7646 ptype = PERM_EXISTING_FILE;
7649 ptype = PERM_NEW_FILE;
7652 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7654 if (!NT_STATUS_IS_OK(status)) {
7658 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7659 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7660 smb_fname_str_dbg(smb_fname), (double)size,
7661 (unsigned int)set_owner, (unsigned int)set_grp,
7662 (int)raw_unixmode));
7664 sbuf = smb_fname->st;
7666 if (!VALID_STAT(sbuf)) {
7668 * The only valid use of this is to create character and block
7669 * devices, and named pipes. This is deprecated (IMHO) and
7670 * a new info level should be used for mknod. JRA.
7673 status = smb_unix_mknod(conn,
7677 if (!NT_STATUS_IS_OK(status)) {
7681 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7682 if (smb_fname_tmp == NULL) {
7683 return NT_STATUS_NO_MEMORY;
7686 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7687 status = map_nt_error_from_unix(errno);
7688 TALLOC_FREE(smb_fname_tmp);
7689 SMB_VFS_UNLINK(conn, smb_fname);
7693 sbuf = smb_fname_tmp->st;
7694 smb_fname = smb_fname_tmp;
7696 /* Ensure we don't try and change anything else. */
7697 raw_unixmode = SMB_MODE_NO_CHANGE;
7698 size = get_file_size_stat(&sbuf);
7699 ft.atime = sbuf.st_ex_atime;
7700 ft.mtime = sbuf.st_ex_mtime;
7702 * We continue here as we might want to change the
7705 delete_on_fail = True;
7709 /* Horrible backwards compatibility hack as an old server bug
7710 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7714 size = get_file_size_stat(&sbuf);
7719 * Deal with the UNIX specific mode set.
7722 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7725 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7726 "setting mode 0%o for file %s\n",
7727 (unsigned int)unixmode,
7728 smb_fname_str_dbg(smb_fname)));
7729 if (fsp && fsp->fh->fd != -1) {
7730 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7732 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7735 return map_nt_error_from_unix(errno);
7740 * Deal with the UNIX specific uid set.
7743 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7744 (sbuf.st_ex_uid != set_owner)) {
7747 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7748 "changing owner %u for path %s\n",
7749 (unsigned int)set_owner,
7750 smb_fname_str_dbg(smb_fname)));
7752 if (fsp && fsp->fh->fd != -1) {
7753 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7756 * UNIX extensions calls must always operate
7759 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7760 set_owner, (gid_t)-1);
7764 status = map_nt_error_from_unix(errno);
7765 if (delete_on_fail) {
7766 SMB_VFS_UNLINK(conn, smb_fname);
7773 * Deal with the UNIX specific gid set.
7776 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7777 (sbuf.st_ex_gid != set_grp)) {
7780 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7781 "changing group %u for file %s\n",
7782 (unsigned int)set_owner,
7783 smb_fname_str_dbg(smb_fname)));
7784 if (fsp && fsp->fh->fd != -1) {
7785 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7788 * UNIX extensions calls must always operate
7791 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7795 status = map_nt_error_from_unix(errno);
7796 if (delete_on_fail) {
7797 SMB_VFS_UNLINK(conn, smb_fname);
7803 /* Deal with any size changes. */
7805 status = smb_set_file_size(conn, req,
7811 if (!NT_STATUS_IS_OK(status)) {
7815 /* Deal with any time changes. */
7816 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7817 /* No change, don't cancel anything. */
7821 id = vfs_file_id_from_sbuf(conn, &sbuf);
7822 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7823 all_fsps = file_find_di_next(all_fsps)) {
7825 * We're setting the time explicitly for UNIX.
7826 * Cancel any pending changes over all handles.
7828 all_fsps->update_write_time_on_close = false;
7829 TALLOC_FREE(all_fsps->update_write_time_event);
7833 * Override the "setting_write_time"
7834 * parameter here as it almost does what
7835 * we need. Just remember if we modified
7836 * mtime and send the notify ourselves.
7838 if (null_timespec(ft.mtime)) {
7839 modify_mtime = false;
7842 status = smb_set_file_time(conn,
7848 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7849 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7854 /****************************************************************************
7855 Deal with SMB_SET_FILE_UNIX_INFO2.
7856 ****************************************************************************/
7858 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7859 struct smb_request *req,
7863 const struct smb_filename *smb_fname)
7866 uint32_t smb_fflags;
7869 if (total_data < 116) {
7870 return NT_STATUS_INVALID_PARAMETER;
7873 /* Start by setting all the fields that are common between UNIX_BASIC
7876 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7878 if (!NT_STATUS_IS_OK(status)) {
7882 smb_fflags = IVAL(pdata, 108);
7883 smb_fmask = IVAL(pdata, 112);
7885 /* NB: We should only attempt to alter the file flags if the client
7886 * sends a non-zero mask.
7888 if (smb_fmask != 0) {
7889 int stat_fflags = 0;
7891 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7892 smb_fmask, &stat_fflags)) {
7893 /* Client asked to alter a flag we don't understand. */
7894 return NT_STATUS_INVALID_PARAMETER;
7897 if (fsp && fsp->fh->fd != -1) {
7898 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7899 return NT_STATUS_NOT_SUPPORTED;
7901 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7902 stat_fflags) != 0) {
7903 return map_nt_error_from_unix(errno);
7908 /* XXX: need to add support for changing the create_time here. You
7909 * can do this for paths on Darwin with setattrlist(2). The right way
7910 * to hook this up is probably by extending the VFS utimes interface.
7913 return NT_STATUS_OK;
7916 /****************************************************************************
7917 Create a directory with POSIX semantics.
7918 ****************************************************************************/
7920 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7921 struct smb_request *req,
7924 struct smb_filename *smb_fname,
7925 int *pdata_return_size)
7927 NTSTATUS status = NT_STATUS_OK;
7928 uint32_t raw_unixmode = 0;
7929 uint32_t mod_unixmode = 0;
7930 mode_t unixmode = (mode_t)0;
7931 files_struct *fsp = NULL;
7932 uint16_t info_level_return = 0;
7934 char *pdata = *ppdata;
7936 if (total_data < 18) {
7937 return NT_STATUS_INVALID_PARAMETER;
7940 raw_unixmode = IVAL(pdata,8);
7941 /* Next 4 bytes are not yet defined. */
7943 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7944 PERM_NEW_DIR, &unixmode);
7945 if (!NT_STATUS_IS_OK(status)) {
7949 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7951 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7952 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7954 status = SMB_VFS_CREATE_FILE(
7957 0, /* root_dir_fid */
7958 smb_fname, /* fname */
7959 FILE_READ_ATTRIBUTES, /* access_mask */
7960 FILE_SHARE_NONE, /* share_access */
7961 FILE_CREATE, /* create_disposition*/
7962 FILE_DIRECTORY_FILE, /* create_options */
7963 mod_unixmode, /* file_attributes */
7964 0, /* oplock_request */
7966 0, /* allocation_size */
7967 0, /* private_flags */
7972 NULL, NULL); /* create context */
7974 if (NT_STATUS_IS_OK(status)) {
7975 close_file(req, fsp, NORMAL_CLOSE);
7978 info_level_return = SVAL(pdata,16);
7980 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7981 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7982 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7983 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7985 *pdata_return_size = 12;
7988 /* Realloc the data size */
7989 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7990 if (*ppdata == NULL) {
7991 *pdata_return_size = 0;
7992 return NT_STATUS_NO_MEMORY;
7996 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7997 SSVAL(pdata,2,0); /* No fnum. */
7998 SIVAL(pdata,4,info); /* Was directory created. */
8000 switch (info_level_return) {
8001 case SMB_QUERY_FILE_UNIX_BASIC:
8002 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8003 SSVAL(pdata,10,0); /* Padding. */
8004 store_file_unix_basic(conn, pdata + 12, fsp,
8007 case SMB_QUERY_FILE_UNIX_INFO2:
8008 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8009 SSVAL(pdata,10,0); /* Padding. */
8010 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8014 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8015 SSVAL(pdata,10,0); /* Padding. */
8022 /****************************************************************************
8023 Open/Create a file with POSIX semantics.
8024 ****************************************************************************/
8026 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8027 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8029 static NTSTATUS smb_posix_open(connection_struct *conn,
8030 struct smb_request *req,
8033 struct smb_filename *smb_fname,
8034 int *pdata_return_size)
8036 bool extended_oplock_granted = False;
8037 char *pdata = *ppdata;
8039 uint32_t wire_open_mode = 0;
8040 uint32_t raw_unixmode = 0;
8041 uint32_t mod_unixmode = 0;
8042 uint32_t create_disp = 0;
8043 uint32_t access_mask = 0;
8044 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8045 NTSTATUS status = NT_STATUS_OK;
8046 mode_t unixmode = (mode_t)0;
8047 files_struct *fsp = NULL;
8048 int oplock_request = 0;
8050 uint16_t info_level_return = 0;
8052 if (total_data < 18) {
8053 return NT_STATUS_INVALID_PARAMETER;
8056 flags = IVAL(pdata,0);
8057 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8058 if (oplock_request) {
8059 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8062 wire_open_mode = IVAL(pdata,4);
8064 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8065 return smb_posix_mkdir(conn, req,
8072 switch (wire_open_mode & SMB_ACCMODE) {
8074 access_mask = SMB_O_RDONLY_MAPPING;
8077 access_mask = SMB_O_WRONLY_MAPPING;
8080 access_mask = (SMB_O_RDONLY_MAPPING|
8081 SMB_O_WRONLY_MAPPING);
8084 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8085 (unsigned int)wire_open_mode ));
8086 return NT_STATUS_INVALID_PARAMETER;
8089 wire_open_mode &= ~SMB_ACCMODE;
8091 /* First take care of O_CREAT|O_EXCL interactions. */
8092 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8093 case (SMB_O_CREAT | SMB_O_EXCL):
8094 /* File exists fail. File not exist create. */
8095 create_disp = FILE_CREATE;
8098 /* File exists open. File not exist create. */
8099 create_disp = FILE_OPEN_IF;
8102 /* O_EXCL on its own without O_CREAT is undefined.
8103 We deliberately ignore it as some versions of
8104 Linux CIFSFS can send a bare O_EXCL on the
8105 wire which other filesystems in the kernel
8106 ignore. See bug 9519 for details. */
8111 /* File exists open. File not exist fail. */
8112 create_disp = FILE_OPEN;
8115 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8116 (unsigned int)wire_open_mode ));
8117 return NT_STATUS_INVALID_PARAMETER;
8120 /* Next factor in the effects of O_TRUNC. */
8121 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8123 if (wire_open_mode & SMB_O_TRUNC) {
8124 switch (create_disp) {
8126 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8127 /* Leave create_disp alone as
8128 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8130 /* File exists fail. File not exist create. */
8133 /* SMB_O_CREAT | SMB_O_TRUNC */
8134 /* File exists overwrite. File not exist create. */
8135 create_disp = FILE_OVERWRITE_IF;
8139 /* File exists overwrite. File not exist fail. */
8140 create_disp = FILE_OVERWRITE;
8143 /* Cannot get here. */
8144 smb_panic("smb_posix_open: logic error");
8145 return NT_STATUS_INVALID_PARAMETER;
8149 raw_unixmode = IVAL(pdata,8);
8150 /* Next 4 bytes are not yet defined. */
8152 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8153 (VALID_STAT(smb_fname->st) ?
8154 PERM_EXISTING_FILE : PERM_NEW_FILE),
8157 if (!NT_STATUS_IS_OK(status)) {
8161 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8163 if (wire_open_mode & SMB_O_SYNC) {
8164 create_options |= FILE_WRITE_THROUGH;
8166 if (wire_open_mode & SMB_O_APPEND) {
8167 access_mask |= FILE_APPEND_DATA;
8169 if (wire_open_mode & SMB_O_DIRECT) {
8170 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8173 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8174 VALID_STAT_OF_DIR(smb_fname->st)) {
8175 if (access_mask != SMB_O_RDONLY_MAPPING) {
8176 return NT_STATUS_FILE_IS_A_DIRECTORY;
8178 create_options &= ~FILE_NON_DIRECTORY_FILE;
8179 create_options |= FILE_DIRECTORY_FILE;
8182 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8183 smb_fname_str_dbg(smb_fname),
8184 (unsigned int)wire_open_mode,
8185 (unsigned int)unixmode ));
8187 status = SMB_VFS_CREATE_FILE(
8190 0, /* root_dir_fid */
8191 smb_fname, /* fname */
8192 access_mask, /* access_mask */
8193 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8195 create_disp, /* create_disposition*/
8196 create_options, /* create_options */
8197 mod_unixmode, /* file_attributes */
8198 oplock_request, /* oplock_request */
8200 0, /* allocation_size */
8201 0, /* private_flags */
8206 NULL, NULL); /* create context */
8208 if (!NT_STATUS_IS_OK(status)) {
8212 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8213 extended_oplock_granted = True;
8216 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8217 extended_oplock_granted = True;
8220 info_level_return = SVAL(pdata,16);
8222 /* Allocate the correct return size. */
8224 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8225 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8226 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8227 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8229 *pdata_return_size = 12;
8232 /* Realloc the data size */
8233 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8234 if (*ppdata == NULL) {
8235 close_file(req, fsp, ERROR_CLOSE);
8236 *pdata_return_size = 0;
8237 return NT_STATUS_NO_MEMORY;
8241 if (extended_oplock_granted) {
8242 if (flags & REQUEST_BATCH_OPLOCK) {
8243 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8245 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8247 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8248 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8250 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8253 SSVAL(pdata,2,fsp->fnum);
8254 SIVAL(pdata,4,info); /* Was file created etc. */
8256 switch (info_level_return) {
8257 case SMB_QUERY_FILE_UNIX_BASIC:
8258 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8259 SSVAL(pdata,10,0); /* padding. */
8260 store_file_unix_basic(conn, pdata + 12, fsp,
8263 case SMB_QUERY_FILE_UNIX_INFO2:
8264 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8265 SSVAL(pdata,10,0); /* padding. */
8266 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8270 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8271 SSVAL(pdata,10,0); /* padding. */
8274 return NT_STATUS_OK;
8277 /****************************************************************************
8278 Delete a file with POSIX semantics.
8279 ****************************************************************************/
8281 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8282 struct smb_request *req,
8285 struct smb_filename *smb_fname)
8287 NTSTATUS status = NT_STATUS_OK;
8288 files_struct *fsp = NULL;
8292 int create_options = 0;
8294 struct share_mode_lock *lck = NULL;
8296 if (total_data < 2) {
8297 return NT_STATUS_INVALID_PARAMETER;
8300 flags = SVAL(pdata,0);
8302 if (!VALID_STAT(smb_fname->st)) {
8303 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8306 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8307 !VALID_STAT_OF_DIR(smb_fname->st)) {
8308 return NT_STATUS_NOT_A_DIRECTORY;
8311 DEBUG(10,("smb_posix_unlink: %s %s\n",
8312 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8313 smb_fname_str_dbg(smb_fname)));
8315 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8316 create_options |= FILE_DIRECTORY_FILE;
8319 status = SMB_VFS_CREATE_FILE(
8322 0, /* root_dir_fid */
8323 smb_fname, /* fname */
8324 DELETE_ACCESS, /* access_mask */
8325 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8327 FILE_OPEN, /* create_disposition*/
8328 create_options, /* create_options */
8329 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8330 0, /* oplock_request */
8332 0, /* allocation_size */
8333 0, /* private_flags */
8338 NULL, NULL); /* create context */
8340 if (!NT_STATUS_IS_OK(status)) {
8345 * Don't lie to client. If we can't really delete due to
8346 * non-POSIX opens return SHARING_VIOLATION.
8349 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8351 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8352 "lock for file %s\n", fsp_str_dbg(fsp)));
8353 close_file(req, fsp, NORMAL_CLOSE);
8354 return NT_STATUS_INVALID_PARAMETER;
8358 * See if others still have the file open. If this is the case, then
8359 * don't delete. If all opens are POSIX delete we can set the delete
8360 * on close disposition.
8362 for (i=0; i<lck->data->num_share_modes; i++) {
8363 struct share_mode_entry *e = &lck->data->share_modes[i];
8364 if (is_valid_share_mode_entry(e)) {
8365 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8368 if (share_mode_stale_pid(lck->data, i)) {
8371 /* Fail with sharing violation. */
8373 close_file(req, fsp, NORMAL_CLOSE);
8374 return NT_STATUS_SHARING_VIOLATION;
8379 * Set the delete on close.
8381 status = smb_set_file_disposition_info(conn,
8389 if (!NT_STATUS_IS_OK(status)) {
8390 close_file(req, fsp, NORMAL_CLOSE);
8393 return close_file(req, fsp, NORMAL_CLOSE);
8396 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8397 struct smb_request *req,
8398 TALLOC_CTX *mem_ctx,
8399 uint16_t info_level,
8401 struct smb_filename *smb_fname,
8402 char **ppdata, int total_data,
8405 char *pdata = *ppdata;
8406 NTSTATUS status = NT_STATUS_OK;
8407 int data_return_size = 0;
8411 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8412 return NT_STATUS_INVALID_LEVEL;
8415 if (!CAN_WRITE(conn)) {
8416 /* Allow POSIX opens. The open path will deny
8417 * any non-readonly opens. */
8418 if (info_level != SMB_POSIX_PATH_OPEN) {
8419 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8423 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8424 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8426 info_level, total_data));
8428 switch (info_level) {
8430 case SMB_INFO_STANDARD:
8432 status = smb_set_info_standard(conn,
8440 case SMB_INFO_SET_EA:
8442 status = smb_info_set_ea(conn,
8450 case SMB_SET_FILE_BASIC_INFO:
8451 case SMB_FILE_BASIC_INFORMATION:
8453 status = smb_set_file_basic_info(conn,
8461 case SMB_FILE_ALLOCATION_INFORMATION:
8462 case SMB_SET_FILE_ALLOCATION_INFO:
8464 status = smb_set_file_allocation_info(conn, req,
8472 case SMB_FILE_END_OF_FILE_INFORMATION:
8473 case SMB_SET_FILE_END_OF_FILE_INFO:
8476 * XP/Win7 both fail after the createfile with
8477 * SMB_SET_FILE_END_OF_FILE_INFO but not
8478 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8479 * The level is known here, so pass it down
8483 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8485 status = smb_set_file_end_of_file_info(conn, req,
8494 case SMB_FILE_DISPOSITION_INFORMATION:
8495 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8498 /* JRA - We used to just ignore this on a path ?
8499 * Shouldn't this be invalid level on a pathname
8502 if (tran_call != TRANSACT2_SETFILEINFO) {
8503 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8506 status = smb_set_file_disposition_info(conn,
8514 case SMB_FILE_POSITION_INFORMATION:
8516 status = smb_file_position_information(conn,
8523 case SMB_FILE_FULL_EA_INFORMATION:
8525 status = smb_set_file_full_ea_info(conn,
8532 /* From tridge Samba4 :
8533 * MODE_INFORMATION in setfileinfo (I have no
8534 * idea what "mode information" on a file is - it takes a value of 0,
8535 * 2, 4 or 6. What could it be?).
8538 case SMB_FILE_MODE_INFORMATION:
8540 status = smb_file_mode_information(conn,
8547 * CIFS UNIX extensions.
8550 case SMB_SET_FILE_UNIX_BASIC:
8552 status = smb_set_file_unix_basic(conn, req,
8560 case SMB_SET_FILE_UNIX_INFO2:
8562 status = smb_set_file_unix_info2(conn, req,
8570 case SMB_SET_FILE_UNIX_LINK:
8573 /* We must have a pathname for this. */
8574 return NT_STATUS_INVALID_LEVEL;
8576 status = smb_set_file_unix_link(conn, req, pdata,
8577 total_data, smb_fname);
8581 case SMB_SET_FILE_UNIX_HLINK:
8584 /* We must have a pathname for this. */
8585 return NT_STATUS_INVALID_LEVEL;
8587 status = smb_set_file_unix_hlink(conn, req,
8593 case SMB_FILE_RENAME_INFORMATION:
8595 status = smb_file_rename_information(conn, req,
8601 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8603 /* SMB2 rename information. */
8604 status = smb2_file_rename_information(conn, req,
8610 case SMB_FILE_LINK_INFORMATION:
8612 status = smb_file_link_information(conn, req,
8618 #if defined(HAVE_POSIX_ACLS)
8619 case SMB_SET_POSIX_ACL:
8621 status = smb_set_posix_acl(conn,
8630 case SMB_SET_POSIX_LOCK:
8633 return NT_STATUS_INVALID_LEVEL;
8635 status = smb_set_posix_lock(conn, req,
8636 pdata, total_data, fsp);
8640 case SMB_POSIX_PATH_OPEN:
8643 /* We must have a pathname for this. */
8644 return NT_STATUS_INVALID_LEVEL;
8647 status = smb_posix_open(conn, req,
8655 case SMB_POSIX_PATH_UNLINK:
8658 /* We must have a pathname for this. */
8659 return NT_STATUS_INVALID_LEVEL;
8662 status = smb_posix_unlink(conn, req,
8670 return NT_STATUS_INVALID_LEVEL;
8673 if (!NT_STATUS_IS_OK(status)) {
8677 *ret_data_size = data_return_size;
8678 return NT_STATUS_OK;
8681 /****************************************************************************
8682 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8683 ****************************************************************************/
8685 static void call_trans2setfilepathinfo(connection_struct *conn,
8686 struct smb_request *req,
8687 unsigned int tran_call,
8688 char **pparams, int total_params,
8689 char **ppdata, int total_data,
8690 unsigned int max_data_bytes)
8692 char *params = *pparams;
8693 char *pdata = *ppdata;
8694 uint16_t info_level;
8695 struct smb_filename *smb_fname = NULL;
8696 files_struct *fsp = NULL;
8697 NTSTATUS status = NT_STATUS_OK;
8698 int data_return_size = 0;
8701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8705 if (tran_call == TRANSACT2_SETFILEINFO) {
8706 if (total_params < 4) {
8707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8711 fsp = file_fsp(req, SVAL(params,0));
8712 /* Basic check for non-null fsp. */
8713 if (!check_fsp_open(conn, req, fsp)) {
8716 info_level = SVAL(params,2);
8718 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8719 if (smb_fname == NULL) {
8720 reply_nterror(req, NT_STATUS_NO_MEMORY);
8724 if(fsp->fh->fd == -1) {
8726 * This is actually a SETFILEINFO on a directory
8727 * handle (returned from an NT SMB). NT5.0 seems
8728 * to do this call. JRA.
8730 if (INFO_LEVEL_IS_UNIX(info_level)) {
8731 /* Always do lstat for UNIX calls. */
8732 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8733 DEBUG(3,("call_trans2setfilepathinfo: "
8734 "SMB_VFS_LSTAT of %s failed "
8736 smb_fname_str_dbg(smb_fname),
8738 reply_nterror(req, map_nt_error_from_unix(errno));
8742 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8743 DEBUG(3,("call_trans2setfilepathinfo: "
8744 "fileinfo of %s failed (%s)\n",
8745 smb_fname_str_dbg(smb_fname),
8747 reply_nterror(req, map_nt_error_from_unix(errno));
8751 } else if (fsp->print_file) {
8753 * Doing a DELETE_ON_CLOSE should cancel a print job.
8755 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8756 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8758 DEBUG(3,("call_trans2setfilepathinfo: "
8759 "Cancelling print job (%s)\n",
8763 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8769 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8774 * Original code - this is an open file.
8776 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8777 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8778 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8780 reply_nterror(req, map_nt_error_from_unix(errno));
8786 uint32_t ucf_flags = (req->posix_pathnames ?
8787 UCF_POSIX_PATHNAMES : 0);
8790 if (total_params < 7) {
8791 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8795 info_level = SVAL(params,0);
8796 if (req->posix_pathnames) {
8797 srvstr_get_path_posix(req,
8806 srvstr_get_path(req,
8815 if (!NT_STATUS_IS_OK(status)) {
8816 reply_nterror(req, status);
8820 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8821 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8822 info_level == SMB_FILE_RENAME_INFORMATION ||
8823 info_level == SMB_POSIX_PATH_UNLINK) {
8824 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8827 status = filename_convert(req, conn,
8828 req->flags2 & FLAGS2_DFS_PATHNAMES,
8833 if (!NT_STATUS_IS_OK(status)) {
8834 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8835 reply_botherror(req,
8836 NT_STATUS_PATH_NOT_COVERED,
8837 ERRSRV, ERRbadpath);
8840 reply_nterror(req, status);
8844 if (INFO_LEVEL_IS_UNIX(info_level)) {
8846 * For CIFS UNIX extensions the target name may not exist.
8849 /* Always do lstat for UNIX calls. */
8850 SMB_VFS_LSTAT(conn, smb_fname);
8852 } else if (!VALID_STAT(smb_fname->st) &&
8853 SMB_VFS_STAT(conn, smb_fname)) {
8854 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8856 smb_fname_str_dbg(smb_fname),
8858 reply_nterror(req, map_nt_error_from_unix(errno));
8863 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8864 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8866 info_level,total_data));
8868 /* Realloc the parameter size */
8869 *pparams = (char *)SMB_REALLOC(*pparams,2);
8870 if (*pparams == NULL) {
8871 reply_nterror(req, NT_STATUS_NO_MEMORY);
8878 status = smbd_do_setfilepathinfo(conn, req, req,
8884 if (!NT_STATUS_IS_OK(status)) {
8885 if (open_was_deferred(req->xconn, req->mid)) {
8886 /* We have re-scheduled this call. */
8889 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8890 /* We have re-scheduled this call. */
8893 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8894 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8895 ERRSRV, ERRbadpath);
8898 if (info_level == SMB_POSIX_PATH_OPEN) {
8899 reply_openerror(req, status);
8904 * Invalid EA name needs to return 2 param bytes,
8905 * not a zero-length error packet.
8907 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8908 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8911 reply_nterror(req, status);
8916 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8922 /****************************************************************************
8923 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8924 ****************************************************************************/
8926 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8927 char **pparams, int total_params,
8928 char **ppdata, int total_data,
8929 unsigned int max_data_bytes)
8931 struct smb_filename *smb_dname = NULL;
8932 char *params = *pparams;
8933 char *pdata = *ppdata;
8934 char *directory = NULL;
8935 NTSTATUS status = NT_STATUS_OK;
8936 struct ea_list *ea_list = NULL;
8937 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
8938 TALLOC_CTX *ctx = talloc_tos();
8940 if (!CAN_WRITE(conn)) {
8941 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8945 if (total_params < 5) {
8946 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8950 if (req->posix_pathnames) {
8951 srvstr_get_path_posix(ctx,
8960 srvstr_get_path(ctx,
8969 if (!NT_STATUS_IS_OK(status)) {
8970 reply_nterror(req, status);
8974 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8976 status = filename_convert(ctx,
8978 req->flags2 & FLAGS2_DFS_PATHNAMES,
8984 if (!NT_STATUS_IS_OK(status)) {
8985 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8986 reply_botherror(req,
8987 NT_STATUS_PATH_NOT_COVERED,
8988 ERRSRV, ERRbadpath);
8991 reply_nterror(req, status);
8996 * OS/2 workplace shell seems to send SET_EA requests of "null"
8997 * length (4 bytes containing IVAL 4).
8998 * They seem to have no effect. Bug #3212. JRA.
9001 if (total_data && (total_data != 4)) {
9002 /* Any data in this call is an EA list. */
9003 if (total_data < 10) {
9004 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9008 if (IVAL(pdata,0) > total_data) {
9009 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9010 IVAL(pdata,0), (unsigned int)total_data));
9011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9015 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9018 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9022 if (!lp_ea_support(SNUM(conn))) {
9023 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9027 /* If total_data == 4 Windows doesn't care what values
9028 * are placed in that field, it just ignores them.
9029 * The System i QNTC IBM SMB client puts bad values here,
9030 * so ignore them. */
9032 status = create_directory(conn, req, smb_dname);
9034 if (!NT_STATUS_IS_OK(status)) {
9035 reply_nterror(req, status);
9039 /* Try and set any given EA. */
9041 status = set_ea(conn, NULL, smb_dname, ea_list);
9042 if (!NT_STATUS_IS_OK(status)) {
9043 reply_nterror(req, status);
9048 /* Realloc the parameter and data sizes */
9049 *pparams = (char *)SMB_REALLOC(*pparams,2);
9050 if(*pparams == NULL) {
9051 reply_nterror(req, NT_STATUS_NO_MEMORY);
9058 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9061 TALLOC_FREE(smb_dname);
9065 /****************************************************************************
9066 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9067 We don't actually do this - we just send a null response.
9068 ****************************************************************************/
9070 static void call_trans2findnotifyfirst(connection_struct *conn,
9071 struct smb_request *req,
9072 char **pparams, int total_params,
9073 char **ppdata, int total_data,
9074 unsigned int max_data_bytes)
9076 char *params = *pparams;
9077 uint16_t info_level;
9079 if (total_params < 6) {
9080 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9084 info_level = SVAL(params,4);
9085 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9087 switch (info_level) {
9092 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9096 /* Realloc the parameter and data sizes */
9097 *pparams = (char *)SMB_REALLOC(*pparams,6);
9098 if (*pparams == NULL) {
9099 reply_nterror(req, NT_STATUS_NO_MEMORY);
9104 SSVAL(params,0,fnf_handle);
9105 SSVAL(params,2,0); /* No changes */
9106 SSVAL(params,4,0); /* No EA errors */
9113 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9118 /****************************************************************************
9119 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9120 changes). Currently this does nothing.
9121 ****************************************************************************/
9123 static void call_trans2findnotifynext(connection_struct *conn,
9124 struct smb_request *req,
9125 char **pparams, int total_params,
9126 char **ppdata, int total_data,
9127 unsigned int max_data_bytes)
9129 char *params = *pparams;
9131 DEBUG(3,("call_trans2findnotifynext\n"));
9133 /* Realloc the parameter and data sizes */
9134 *pparams = (char *)SMB_REALLOC(*pparams,4);
9135 if (*pparams == NULL) {
9136 reply_nterror(req, NT_STATUS_NO_MEMORY);
9141 SSVAL(params,0,0); /* No changes */
9142 SSVAL(params,2,0); /* No EA errors */
9144 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9149 /****************************************************************************
9150 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9151 ****************************************************************************/
9153 static void call_trans2getdfsreferral(connection_struct *conn,
9154 struct smb_request *req,
9155 char **pparams, int total_params,
9156 char **ppdata, int total_data,
9157 unsigned int max_data_bytes)
9159 char *params = *pparams;
9160 char *pathname = NULL;
9162 int max_referral_level;
9163 NTSTATUS status = NT_STATUS_OK;
9164 TALLOC_CTX *ctx = talloc_tos();
9166 DEBUG(10,("call_trans2getdfsreferral\n"));
9168 if (total_params < 3) {
9169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9173 max_referral_level = SVAL(params,0);
9175 if(!lp_host_msdfs()) {
9176 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9180 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9181 total_params - 2, STR_TERMINATE);
9183 reply_nterror(req, NT_STATUS_NOT_FOUND);
9186 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9187 ppdata,&status)) < 0) {
9188 reply_nterror(req, status);
9192 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9193 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9194 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9199 #define LMCAT_SPL 0x53
9200 #define LMFUNC_GETJOBID 0x60
9202 /****************************************************************************
9203 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9204 ****************************************************************************/
9206 static void call_trans2ioctl(connection_struct *conn,
9207 struct smb_request *req,
9208 char **pparams, int total_params,
9209 char **ppdata, int total_data,
9210 unsigned int max_data_bytes)
9212 char *pdata = *ppdata;
9213 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9217 /* check for an invalid fid before proceeding */
9220 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9224 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9225 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9226 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9227 if (*ppdata == NULL) {
9228 reply_nterror(req, NT_STATUS_NO_MEMORY);
9233 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9234 CAN ACCEPT THIS IN UNICODE. JRA. */
9237 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9239 status = srvstr_push(pdata, req->flags2, pdata + 2,
9240 lp_netbios_name(), 15,
9241 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9242 if (!NT_STATUS_IS_OK(status)) {
9243 reply_nterror(req, status);
9246 status = srvstr_push(pdata, req->flags2, pdata+18,
9247 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9248 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9249 if (!NT_STATUS_IS_OK(status)) {
9250 reply_nterror(req, status);
9253 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9258 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9259 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9262 /****************************************************************************
9263 Reply to a SMBfindclose (stop trans2 directory search).
9264 ****************************************************************************/
9266 void reply_findclose(struct smb_request *req)
9269 struct smbd_server_connection *sconn = req->sconn;
9271 START_PROFILE(SMBfindclose);
9274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9275 END_PROFILE(SMBfindclose);
9279 dptr_num = SVALS(req->vwv+0, 0);
9281 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9283 dptr_close(sconn, &dptr_num);
9285 reply_outbuf(req, 0, 0);
9287 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9289 END_PROFILE(SMBfindclose);
9293 /****************************************************************************
9294 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9295 ****************************************************************************/
9297 void reply_findnclose(struct smb_request *req)
9301 START_PROFILE(SMBfindnclose);
9304 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9305 END_PROFILE(SMBfindnclose);
9309 dptr_num = SVAL(req->vwv+0, 0);
9311 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9313 /* We never give out valid handles for a
9314 findnotifyfirst - so any dptr_num is ok here.
9317 reply_outbuf(req, 0, 0);
9319 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9321 END_PROFILE(SMBfindnclose);
9325 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9326 struct trans_state *state)
9328 if (get_Protocol() >= PROTOCOL_NT1) {
9329 req->flags2 |= 0x40; /* IS_LONG_NAME */
9330 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9333 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9334 if (state->call != TRANSACT2_QFSINFO &&
9335 state->call != TRANSACT2_SETFSINFO) {
9336 DEBUG(0,("handle_trans2: encryption required "
9338 (unsigned int)state->call));
9339 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9344 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9346 /* Now we must call the relevant TRANS2 function */
9347 switch(state->call) {
9348 case TRANSACT2_OPEN:
9350 START_PROFILE(Trans2_open);
9351 call_trans2open(conn, req,
9352 &state->param, state->total_param,
9353 &state->data, state->total_data,
9354 state->max_data_return);
9355 END_PROFILE(Trans2_open);
9359 case TRANSACT2_FINDFIRST:
9361 START_PROFILE(Trans2_findfirst);
9362 call_trans2findfirst(conn, req,
9363 &state->param, state->total_param,
9364 &state->data, state->total_data,
9365 state->max_data_return);
9366 END_PROFILE(Trans2_findfirst);
9370 case TRANSACT2_FINDNEXT:
9372 START_PROFILE(Trans2_findnext);
9373 call_trans2findnext(conn, req,
9374 &state->param, state->total_param,
9375 &state->data, state->total_data,
9376 state->max_data_return);
9377 END_PROFILE(Trans2_findnext);
9381 case TRANSACT2_QFSINFO:
9383 START_PROFILE(Trans2_qfsinfo);
9384 call_trans2qfsinfo(conn, req,
9385 &state->param, state->total_param,
9386 &state->data, state->total_data,
9387 state->max_data_return);
9388 END_PROFILE(Trans2_qfsinfo);
9392 case TRANSACT2_SETFSINFO:
9394 START_PROFILE(Trans2_setfsinfo);
9395 call_trans2setfsinfo(conn, req,
9396 &state->param, state->total_param,
9397 &state->data, state->total_data,
9398 state->max_data_return);
9399 END_PROFILE(Trans2_setfsinfo);
9403 case TRANSACT2_QPATHINFO:
9404 case TRANSACT2_QFILEINFO:
9406 START_PROFILE(Trans2_qpathinfo);
9407 call_trans2qfilepathinfo(conn, req, state->call,
9408 &state->param, state->total_param,
9409 &state->data, state->total_data,
9410 state->max_data_return);
9411 END_PROFILE(Trans2_qpathinfo);
9415 case TRANSACT2_SETPATHINFO:
9416 case TRANSACT2_SETFILEINFO:
9418 START_PROFILE(Trans2_setpathinfo);
9419 call_trans2setfilepathinfo(conn, req, state->call,
9420 &state->param, state->total_param,
9421 &state->data, state->total_data,
9422 state->max_data_return);
9423 END_PROFILE(Trans2_setpathinfo);
9427 case TRANSACT2_FINDNOTIFYFIRST:
9429 START_PROFILE(Trans2_findnotifyfirst);
9430 call_trans2findnotifyfirst(conn, req,
9431 &state->param, state->total_param,
9432 &state->data, state->total_data,
9433 state->max_data_return);
9434 END_PROFILE(Trans2_findnotifyfirst);
9438 case TRANSACT2_FINDNOTIFYNEXT:
9440 START_PROFILE(Trans2_findnotifynext);
9441 call_trans2findnotifynext(conn, req,
9442 &state->param, state->total_param,
9443 &state->data, state->total_data,
9444 state->max_data_return);
9445 END_PROFILE(Trans2_findnotifynext);
9449 case TRANSACT2_MKDIR:
9451 START_PROFILE(Trans2_mkdir);
9452 call_trans2mkdir(conn, req,
9453 &state->param, state->total_param,
9454 &state->data, state->total_data,
9455 state->max_data_return);
9456 END_PROFILE(Trans2_mkdir);
9460 case TRANSACT2_GET_DFS_REFERRAL:
9462 START_PROFILE(Trans2_get_dfs_referral);
9463 call_trans2getdfsreferral(conn, req,
9464 &state->param, state->total_param,
9465 &state->data, state->total_data,
9466 state->max_data_return);
9467 END_PROFILE(Trans2_get_dfs_referral);
9471 case TRANSACT2_IOCTL:
9473 START_PROFILE(Trans2_ioctl);
9474 call_trans2ioctl(conn, req,
9475 &state->param, state->total_param,
9476 &state->data, state->total_data,
9477 state->max_data_return);
9478 END_PROFILE(Trans2_ioctl);
9483 /* Error in request */
9484 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9485 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9489 /****************************************************************************
9490 Reply to a SMBtrans2.
9491 ****************************************************************************/
9493 void reply_trans2(struct smb_request *req)
9495 connection_struct *conn = req->conn;
9500 unsigned int tran_call;
9501 struct trans_state *state;
9504 START_PROFILE(SMBtrans2);
9506 if (req->wct < 14) {
9507 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9508 END_PROFILE(SMBtrans2);
9512 dsoff = SVAL(req->vwv+12, 0);
9513 dscnt = SVAL(req->vwv+11, 0);
9514 psoff = SVAL(req->vwv+10, 0);
9515 pscnt = SVAL(req->vwv+9, 0);
9516 tran_call = SVAL(req->vwv+14, 0);
9518 result = allow_new_trans(conn->pending_trans, req->mid);
9519 if (!NT_STATUS_IS_OK(result)) {
9520 DEBUG(2, ("Got invalid trans2 request: %s\n",
9521 nt_errstr(result)));
9522 reply_nterror(req, result);
9523 END_PROFILE(SMBtrans2);
9528 switch (tran_call) {
9529 /* List the allowed trans2 calls on IPC$ */
9530 case TRANSACT2_OPEN:
9531 case TRANSACT2_GET_DFS_REFERRAL:
9532 case TRANSACT2_QFILEINFO:
9533 case TRANSACT2_QFSINFO:
9534 case TRANSACT2_SETFSINFO:
9537 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9538 END_PROFILE(SMBtrans2);
9543 if ((state = talloc(conn, struct trans_state)) == NULL) {
9544 DEBUG(0, ("talloc failed\n"));
9545 reply_nterror(req, NT_STATUS_NO_MEMORY);
9546 END_PROFILE(SMBtrans2);
9550 state->cmd = SMBtrans2;
9552 state->mid = req->mid;
9553 state->vuid = req->vuid;
9554 state->setup_count = SVAL(req->vwv+13, 0);
9555 state->setup = NULL;
9556 state->total_param = SVAL(req->vwv+0, 0);
9557 state->param = NULL;
9558 state->total_data = SVAL(req->vwv+1, 0);
9560 state->max_param_return = SVAL(req->vwv+2, 0);
9561 state->max_data_return = SVAL(req->vwv+3, 0);
9562 state->max_setup_return = SVAL(req->vwv+4, 0);
9563 state->close_on_completion = BITSETW(req->vwv+5, 0);
9564 state->one_way = BITSETW(req->vwv+5, 1);
9566 state->call = tran_call;
9568 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9569 is so as a sanity check */
9570 if (state->setup_count != 1) {
9572 * Need to have rc=0 for ioctl to get job id for OS/2.
9573 * Network printing will fail if function is not successful.
9574 * Similar function in reply.c will be used if protocol
9575 * is LANMAN1.0 instead of LM1.2X002.
9576 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9577 * outbuf doesn't have to be set(only job id is used).
9579 if ( (state->setup_count == 4)
9580 && (tran_call == TRANSACT2_IOCTL)
9581 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9582 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9583 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9585 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9586 DEBUG(2,("Transaction is %d\n",tran_call));
9588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9589 END_PROFILE(SMBtrans2);
9594 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9597 if (state->total_data) {
9599 if (trans_oob(state->total_data, 0, dscnt)
9600 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9604 /* Can't use talloc here, the core routines do realloc on the
9605 * params and data. */
9606 state->data = (char *)SMB_MALLOC(state->total_data);
9607 if (state->data == NULL) {
9608 DEBUG(0,("reply_trans2: data malloc fail for %u "
9609 "bytes !\n", (unsigned int)state->total_data));
9611 reply_nterror(req, NT_STATUS_NO_MEMORY);
9612 END_PROFILE(SMBtrans2);
9616 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9619 if (state->total_param) {
9621 if (trans_oob(state->total_param, 0, pscnt)
9622 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9626 /* Can't use talloc here, the core routines do realloc on the
9627 * params and data. */
9628 state->param = (char *)SMB_MALLOC(state->total_param);
9629 if (state->param == NULL) {
9630 DEBUG(0,("reply_trans: param malloc fail for %u "
9631 "bytes !\n", (unsigned int)state->total_param));
9632 SAFE_FREE(state->data);
9634 reply_nterror(req, NT_STATUS_NO_MEMORY);
9635 END_PROFILE(SMBtrans2);
9639 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9642 state->received_data = dscnt;
9643 state->received_param = pscnt;
9645 if ((state->received_param == state->total_param) &&
9646 (state->received_data == state->total_data)) {
9648 handle_trans2(conn, req, state);
9650 SAFE_FREE(state->data);
9651 SAFE_FREE(state->param);
9653 END_PROFILE(SMBtrans2);
9657 DLIST_ADD(conn->pending_trans, state);
9659 /* We need to send an interim response then receive the rest
9660 of the parameter/data bytes */
9661 reply_outbuf(req, 0, 0);
9662 show_msg((char *)req->outbuf);
9663 END_PROFILE(SMBtrans2);
9668 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9669 SAFE_FREE(state->data);
9670 SAFE_FREE(state->param);
9672 END_PROFILE(SMBtrans2);
9673 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9677 /****************************************************************************
9678 Reply to a SMBtranss2
9679 ****************************************************************************/
9681 void reply_transs2(struct smb_request *req)
9683 connection_struct *conn = req->conn;
9684 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9685 struct trans_state *state;
9687 START_PROFILE(SMBtranss2);
9689 show_msg((const char *)req->inbuf);
9691 /* Windows clients expect all replies to
9692 a transact secondary (SMBtranss2 0x33)
9693 to have a command code of transact
9694 (SMBtrans2 0x32). See bug #8989
9695 and also [MS-CIFS] section 2.2.4.47.2
9698 req->cmd = SMBtrans2;
9701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9702 END_PROFILE(SMBtranss2);
9706 for (state = conn->pending_trans; state != NULL;
9707 state = state->next) {
9708 if (state->mid == req->mid) {
9713 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9714 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9715 END_PROFILE(SMBtranss2);
9719 /* Revise state->total_param and state->total_data in case they have
9720 changed downwards */
9722 if (SVAL(req->vwv+0, 0) < state->total_param)
9723 state->total_param = SVAL(req->vwv+0, 0);
9724 if (SVAL(req->vwv+1, 0) < state->total_data)
9725 state->total_data = SVAL(req->vwv+1, 0);
9727 pcnt = SVAL(req->vwv+2, 0);
9728 poff = SVAL(req->vwv+3, 0);
9729 pdisp = SVAL(req->vwv+4, 0);
9731 dcnt = SVAL(req->vwv+5, 0);
9732 doff = SVAL(req->vwv+6, 0);
9733 ddisp = SVAL(req->vwv+7, 0);
9735 state->received_param += pcnt;
9736 state->received_data += dcnt;
9738 if ((state->received_data > state->total_data) ||
9739 (state->received_param > state->total_param))
9743 if (trans_oob(state->total_param, pdisp, pcnt)
9744 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9747 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9751 if (trans_oob(state->total_data, ddisp, dcnt)
9752 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9755 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9758 if ((state->received_param < state->total_param) ||
9759 (state->received_data < state->total_data)) {
9760 END_PROFILE(SMBtranss2);
9764 handle_trans2(conn, req, state);
9766 DLIST_REMOVE(conn->pending_trans, state);
9767 SAFE_FREE(state->data);
9768 SAFE_FREE(state->param);
9771 END_PROFILE(SMBtranss2);
9776 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9777 DLIST_REMOVE(conn->pending_trans, state);
9778 SAFE_FREE(state->data);
9779 SAFE_FREE(state->param);
9781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9782 END_PROFILE(SMBtranss2);