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,
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,
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,
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,
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 = ucf_flags_from_smb_request(req);
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,
1296 if (!NT_STATUS_IS_OK(status)) {
1297 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1298 reply_botherror(req,
1299 NT_STATUS_PATH_NOT_COVERED,
1300 ERRSRV, ERRbadpath);
1303 reply_nterror(req, status);
1307 if (open_ofun == 0) {
1308 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1312 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1314 &access_mask, &share_mode,
1315 &create_disposition,
1318 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1322 /* Any data in this call is an EA list. */
1323 if (total_data && (total_data != 4)) {
1324 if (total_data < 10) {
1325 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1329 if (IVAL(pdata,0) > total_data) {
1330 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1331 IVAL(pdata,0), (unsigned int)total_data));
1332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1336 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1343 if (!lp_ea_support(SNUM(conn))) {
1344 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1348 if (!req->posix_pathnames &&
1349 ea_list_has_invalid_name(ea_list)) {
1351 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1352 if(*pparams == NULL ) {
1353 reply_nterror(req, NT_STATUS_NO_MEMORY);
1357 memset(params, '\0', param_len);
1358 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1359 params, param_len, NULL, 0, max_data_bytes);
1364 status = SMB_VFS_CREATE_FILE(
1367 0, /* root_dir_fid */
1368 smb_fname, /* fname */
1369 access_mask, /* access_mask */
1370 share_mode, /* share_access */
1371 create_disposition, /* create_disposition*/
1372 create_options, /* create_options */
1373 open_attr, /* file_attributes */
1374 oplock_request, /* oplock_request */
1376 open_size, /* allocation_size */
1379 ea_list, /* ea_list */
1381 &smb_action, /* psbuf */
1382 NULL, NULL); /* create context */
1384 if (!NT_STATUS_IS_OK(status)) {
1385 if (open_was_deferred(req->xconn, req->mid)) {
1386 /* We have re-scheduled this call. */
1389 reply_openerror(req, status);
1393 size = get_file_size_stat(&smb_fname->st);
1394 fattr = dos_mode(conn, smb_fname);
1395 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1396 inode = smb_fname->st.st_ex_ino;
1397 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1398 close_file(req, fsp, ERROR_CLOSE);
1399 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1403 /* Realloc the size of parameters and data we will return */
1404 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1405 if(*pparams == NULL ) {
1406 reply_nterror(req, NT_STATUS_NO_MEMORY);
1411 SSVAL(params,0,fsp->fnum);
1412 SSVAL(params,2,fattr);
1413 srv_put_dos_date2(params,4, mtime);
1414 SIVAL(params,8, (uint32_t)size);
1415 SSVAL(params,12,deny_mode);
1416 SSVAL(params,14,0); /* open_type - file or directory. */
1417 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1419 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1420 smb_action |= EXTENDED_OPLOCK_GRANTED;
1423 SSVAL(params,18,smb_action);
1426 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1428 SIVAL(params,20,inode);
1429 SSVAL(params,24,0); /* Padding. */
1431 uint32_t ea_size = estimate_ea_size(conn, fsp,
1433 SIVAL(params, 26, ea_size);
1435 SIVAL(params, 26, 0);
1438 /* Send the required number of replies */
1439 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1441 TALLOC_FREE(smb_fname);
1444 /*********************************************************
1445 Routine to check if a given string matches exactly.
1446 as a special case a mask of "." does NOT match. That
1447 is required for correct wildcard semantics
1448 Case can be significant or not.
1449 **********************************************************/
1451 static bool exact_match(bool has_wild,
1452 bool case_sensitive,
1456 if (mask[0] == '.' && mask[1] == 0) {
1464 if (case_sensitive) {
1465 return strcmp(str,mask)==0;
1467 return strcasecmp_m(str,mask) == 0;
1471 /****************************************************************************
1472 Return the filetype for UNIX extensions.
1473 ****************************************************************************/
1475 static uint32_t unix_filetype(mode_t mode)
1478 return UNIX_TYPE_FILE;
1479 else if(S_ISDIR(mode))
1480 return UNIX_TYPE_DIR;
1482 else if(S_ISLNK(mode))
1483 return UNIX_TYPE_SYMLINK;
1486 else if(S_ISCHR(mode))
1487 return UNIX_TYPE_CHARDEV;
1490 else if(S_ISBLK(mode))
1491 return UNIX_TYPE_BLKDEV;
1494 else if(S_ISFIFO(mode))
1495 return UNIX_TYPE_FIFO;
1498 else if(S_ISSOCK(mode))
1499 return UNIX_TYPE_SOCKET;
1502 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1503 return UNIX_TYPE_UNKNOWN;
1506 /****************************************************************************
1507 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1508 ****************************************************************************/
1510 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1512 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1513 const SMB_STRUCT_STAT *psbuf,
1515 enum perm_type ptype,
1520 if (perms == SMB_MODE_NO_CHANGE) {
1521 if (!VALID_STAT(*psbuf)) {
1522 return NT_STATUS_INVALID_PARAMETER;
1524 *ret_perms = psbuf->st_ex_mode;
1525 return NT_STATUS_OK;
1529 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1530 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1531 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1532 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1533 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1534 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1535 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1536 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1537 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1539 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1542 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1545 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1548 if (ptype == PERM_NEW_FILE) {
1550 * "create mask"/"force create mode" are
1551 * only applied to new files, not existing ones.
1553 ret &= lp_create_mask(SNUM(conn));
1554 /* Add in force bits */
1555 ret |= lp_force_create_mode(SNUM(conn));
1556 } else if (ptype == PERM_NEW_DIR) {
1558 * "directory mask"/"force directory mode" are
1559 * only applied to new directories, not existing ones.
1561 ret &= lp_directory_mask(SNUM(conn));
1562 /* Add in force bits */
1563 ret |= lp_force_directory_mode(SNUM(conn));
1567 return NT_STATUS_OK;
1570 /****************************************************************************
1571 Needed to show the msdfs symlinks as directories. Modifies psbuf
1572 to be a directory if it's a msdfs link.
1573 ****************************************************************************/
1575 static bool check_msdfs_link(connection_struct *conn,
1576 const char *pathname,
1577 SMB_STRUCT_STAT *psbuf)
1579 int saved_errno = errno;
1580 if(lp_host_msdfs() &&
1581 lp_msdfs_root(SNUM(conn)) &&
1582 is_msdfs_link(conn, pathname, psbuf)) {
1584 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1587 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1588 errno = saved_errno;
1591 errno = saved_errno;
1596 /****************************************************************************
1597 Get a level dependent lanman2 dir entry.
1598 ****************************************************************************/
1600 struct smbd_dirptr_lanman2_state {
1601 connection_struct *conn;
1602 uint32_t info_level;
1603 bool check_mangled_names;
1605 bool got_exact_match;
1608 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1614 struct smbd_dirptr_lanman2_state *state =
1615 (struct smbd_dirptr_lanman2_state *)private_data;
1617 char mangled_name[13]; /* mangled 8.3 name. */
1621 /* Mangle fname if it's an illegal name. */
1622 if (mangle_must_mangle(dname, state->conn->params)) {
1624 * Slow path - ensure we can push the original name as UCS2. If
1625 * not, then just don't return this name.
1629 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1630 uint8_t *tmp = talloc_array(talloc_tos(),
1634 status = srvstr_push(NULL,
1635 FLAGS2_UNICODE_STRINGS,
1644 if (!NT_STATUS_IS_OK(status)) {
1648 ok = name_to_8_3(dname, mangled_name,
1649 true, state->conn->params);
1653 fname = mangled_name;
1658 got_match = exact_match(state->has_wild,
1659 state->conn->case_sensitive,
1661 state->got_exact_match = got_match;
1663 got_match = mask_match(fname, mask,
1664 state->conn->case_sensitive);
1667 if(!got_match && state->check_mangled_names &&
1668 !mangle_is_8_3(fname, false, state->conn->params)) {
1670 * It turns out that NT matches wildcards against
1671 * both long *and* short names. This may explain some
1672 * of the wildcard wierdness from old DOS clients
1673 * that some people have been seeing.... JRA.
1675 /* Force the mangling into 8.3. */
1676 ok = name_to_8_3(fname, mangled_name,
1677 false, state->conn->params);
1682 got_match = exact_match(state->has_wild,
1683 state->conn->case_sensitive,
1684 mangled_name, mask);
1685 state->got_exact_match = got_match;
1687 got_match = mask_match(mangled_name, mask,
1688 state->conn->case_sensitive);
1696 *_fname = talloc_strdup(ctx, fname);
1697 if (*_fname == NULL) {
1704 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1706 struct smb_filename *smb_fname,
1709 struct smbd_dirptr_lanman2_state *state =
1710 (struct smbd_dirptr_lanman2_state *)private_data;
1711 bool ms_dfs_link = false;
1714 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1715 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1716 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1717 "Couldn't lstat [%s] (%s)\n",
1718 smb_fname_str_dbg(smb_fname),
1722 } else if (!VALID_STAT(smb_fname->st) &&
1723 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1724 /* Needed to show the msdfs symlinks as
1727 ms_dfs_link = check_msdfs_link(state->conn,
1728 smb_fname->base_name,
1731 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1732 "Couldn't stat [%s] (%s)\n",
1733 smb_fname_str_dbg(smb_fname),
1740 mode = dos_mode_msdfs(state->conn, smb_fname);
1742 mode = dos_mode(state->conn, smb_fname);
1749 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1750 connection_struct *conn,
1752 uint32_t info_level,
1753 struct ea_list *name_list,
1754 bool check_mangled_names,
1755 bool requires_resume_key,
1758 const struct smb_filename *smb_fname,
1759 int space_remaining,
1765 uint64_t *last_entry_off)
1767 char *p, *q, *pdata = *ppdata;
1769 uint64_t file_size = 0;
1770 uint64_t allocation_size = 0;
1771 uint64_t file_index = 0;
1773 struct timespec mdate_ts = {0};
1774 struct timespec adate_ts = {0};
1775 struct timespec cdate_ts = {0};
1776 struct timespec create_date_ts = {0};
1777 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1779 char *last_entry_ptr;
1784 struct readdir_attr_data *readdir_attr_data = NULL;
1786 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1787 file_size = get_file_size_stat(&smb_fname->st);
1789 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1791 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1792 if (!NT_STATUS_IS_OK(status)) {
1793 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1798 file_index = get_FileIndex(conn, &smb_fname->st);
1800 mdate_ts = smb_fname->st.st_ex_mtime;
1801 adate_ts = smb_fname->st.st_ex_atime;
1802 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1803 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1805 if (lp_dos_filetime_resolution(SNUM(conn))) {
1806 dos_filetime_timespec(&create_date_ts);
1807 dos_filetime_timespec(&mdate_ts);
1808 dos_filetime_timespec(&adate_ts);
1809 dos_filetime_timespec(&cdate_ts);
1812 create_date = convert_timespec_to_time_t(create_date_ts);
1813 mdate = convert_timespec_to_time_t(mdate_ts);
1814 adate = convert_timespec_to_time_t(adate_ts);
1816 /* align the record */
1817 SMB_ASSERT(align >= 1);
1819 off = (int)PTR_DIFF(pdata, base_data);
1820 pad = (off + (align-1)) & ~(align-1);
1823 if (pad && pad > space_remaining) {
1824 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1825 "for padding (wanted %u, had %d)\n",
1828 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1832 /* initialize padding to 0 */
1834 memset(pdata, 0, pad);
1836 space_remaining -= pad;
1838 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1848 switch (info_level) {
1849 case SMB_FIND_INFO_STANDARD:
1850 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1851 if(requires_resume_key) {
1855 srv_put_dos_date2(p,0,create_date);
1856 srv_put_dos_date2(p,4,adate);
1857 srv_put_dos_date2(p,8,mdate);
1858 SIVAL(p,12,(uint32_t)file_size);
1859 SIVAL(p,16,(uint32_t)allocation_size);
1863 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1864 p += ucs2_align(base_data, p, 0);
1866 status = srvstr_push(base_data, flags2, p,
1867 fname, PTR_DIFF(end_data, p),
1868 STR_TERMINATE, &len);
1869 if (!NT_STATUS_IS_OK(status)) {
1872 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1874 SCVAL(nameptr, -1, len - 2);
1876 SCVAL(nameptr, -1, 0);
1880 SCVAL(nameptr, -1, len - 1);
1882 SCVAL(nameptr, -1, 0);
1888 case SMB_FIND_EA_SIZE:
1889 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1890 if (requires_resume_key) {
1894 srv_put_dos_date2(p,0,create_date);
1895 srv_put_dos_date2(p,4,adate);
1896 srv_put_dos_date2(p,8,mdate);
1897 SIVAL(p,12,(uint32_t)file_size);
1898 SIVAL(p,16,(uint32_t)allocation_size);
1901 unsigned int ea_size = estimate_ea_size(conn, NULL,
1903 SIVAL(p,22,ea_size); /* Extended attributes */
1907 status = srvstr_push(base_data, flags2,
1908 p, fname, PTR_DIFF(end_data, p),
1909 STR_TERMINATE | STR_NOALIGN, &len);
1910 if (!NT_STATUS_IS_OK(status)) {
1913 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1926 SCVAL(nameptr,0,len);
1928 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1931 case SMB_FIND_EA_LIST:
1933 struct ea_list *file_list = NULL;
1936 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1938 return NT_STATUS_INVALID_PARAMETER;
1940 if (requires_resume_key) {
1944 srv_put_dos_date2(p,0,create_date);
1945 srv_put_dos_date2(p,4,adate);
1946 srv_put_dos_date2(p,8,mdate);
1947 SIVAL(p,12,(uint32_t)file_size);
1948 SIVAL(p,16,(uint32_t)allocation_size);
1950 p += 22; /* p now points to the EA area. */
1952 status = get_ea_list_from_file(ctx, conn, NULL,
1954 &ea_len, &file_list);
1955 if (!NT_STATUS_IS_OK(status)) {
1958 name_list = ea_list_union(name_list, file_list, &ea_len);
1960 /* We need to determine if this entry will fit in the space available. */
1961 /* Max string size is 255 bytes. */
1962 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1963 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1964 "(wanted %u, had %d)\n",
1965 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1967 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1970 /* Push the ea_data followed by the name. */
1971 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1973 status = srvstr_push(base_data, flags2,
1974 p + 1, fname, PTR_DIFF(end_data, p+1),
1975 STR_TERMINATE | STR_NOALIGN, &len);
1976 if (!NT_STATUS_IS_OK(status)) {
1979 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1992 SCVAL(nameptr,0,len);
1994 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1998 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1999 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2000 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2002 SIVAL(p,0,reskey); p += 4;
2003 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2004 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2005 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2006 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2007 SOFF_T(p,0,file_size); p += 8;
2008 SOFF_T(p,0,allocation_size); p += 8;
2009 SIVAL(p,0,mode); p += 4;
2010 q = p; p += 4; /* q is placeholder for name length. */
2011 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2012 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2014 unsigned int ea_size = estimate_ea_size(conn, NULL,
2016 SIVAL(p,0,ea_size); /* Extended attributes */
2019 /* Clear the short name buffer. This is
2020 * IMPORTANT as not doing so will trigger
2021 * a Win2k client bug. JRA.
2023 if (!was_8_3 && check_mangled_names) {
2024 char mangled_name[13]; /* mangled 8.3 name. */
2025 if (!name_to_8_3(fname,mangled_name,True,
2027 /* Error - mangle failed ! */
2028 memset(mangled_name,'\0',12);
2030 mangled_name[12] = 0;
2031 status = srvstr_push(base_data, flags2,
2032 p+2, mangled_name, 24,
2033 STR_UPPER|STR_UNICODE, &len);
2034 if (!NT_STATUS_IS_OK(status)) {
2038 memset(p + 2 + len,'\0',24 - len);
2045 status = srvstr_push(base_data, flags2, p,
2046 fname, PTR_DIFF(end_data, p),
2047 STR_TERMINATE_ASCII, &len);
2048 if (!NT_STATUS_IS_OK(status)) {
2054 len = PTR_DIFF(p, pdata);
2055 pad = (len + (align-1)) & ~(align-1);
2057 * offset to the next entry, the caller
2058 * will overwrite it for the last entry
2059 * that's why we always include the padding
2063 * set padding to zero
2066 memset(p, 0, pad - len);
2073 case SMB_FIND_FILE_DIRECTORY_INFO:
2074 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2076 SIVAL(p,0,reskey); p += 4;
2077 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2078 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2079 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2080 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2081 SOFF_T(p,0,file_size); p += 8;
2082 SOFF_T(p,0,allocation_size); p += 8;
2083 SIVAL(p,0,mode); p += 4;
2084 status = srvstr_push(base_data, flags2,
2085 p + 4, fname, PTR_DIFF(end_data, p+4),
2086 STR_TERMINATE_ASCII, &len);
2087 if (!NT_STATUS_IS_OK(status)) {
2093 len = PTR_DIFF(p, pdata);
2094 pad = (len + (align-1)) & ~(align-1);
2096 * offset to the next entry, the caller
2097 * will overwrite it for the last entry
2098 * that's why we always include the padding
2102 * set padding to zero
2105 memset(p, 0, pad - len);
2112 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2113 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2115 SIVAL(p,0,reskey); p += 4;
2116 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2117 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2118 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2119 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2120 SOFF_T(p,0,file_size); p += 8;
2121 SOFF_T(p,0,allocation_size); p += 8;
2122 SIVAL(p,0,mode); p += 4;
2123 q = p; p += 4; /* q is placeholder for name length. */
2125 unsigned int ea_size = estimate_ea_size(conn, NULL,
2127 SIVAL(p,0,ea_size); /* Extended attributes */
2130 status = srvstr_push(base_data, flags2, p,
2131 fname, PTR_DIFF(end_data, p),
2132 STR_TERMINATE_ASCII, &len);
2133 if (!NT_STATUS_IS_OK(status)) {
2139 len = PTR_DIFF(p, pdata);
2140 pad = (len + (align-1)) & ~(align-1);
2142 * offset to the next entry, the caller
2143 * will overwrite it for the last entry
2144 * that's why we always include the padding
2148 * set padding to zero
2151 memset(p, 0, pad - len);
2158 case SMB_FIND_FILE_NAMES_INFO:
2159 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2161 SIVAL(p,0,reskey); p += 4;
2163 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2164 acl on a dir (tridge) */
2165 status = srvstr_push(base_data, flags2, p,
2166 fname, PTR_DIFF(end_data, p),
2167 STR_TERMINATE_ASCII, &len);
2168 if (!NT_STATUS_IS_OK(status)) {
2174 len = PTR_DIFF(p, pdata);
2175 pad = (len + (align-1)) & ~(align-1);
2177 * offset to the next entry, the caller
2178 * will overwrite it for the last entry
2179 * that's why we always include the padding
2183 * set padding to zero
2186 memset(p, 0, pad - len);
2193 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2194 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2196 SIVAL(p,0,reskey); p += 4;
2197 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2198 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2199 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2200 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2201 SOFF_T(p,0,file_size); p += 8;
2202 SOFF_T(p,0,allocation_size); p += 8;
2203 SIVAL(p,0,mode); p += 4;
2204 q = p; p += 4; /* q is placeholder for name length. */
2205 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2206 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2208 unsigned int ea_size = estimate_ea_size(conn, NULL,
2210 SIVAL(p,0,ea_size); /* Extended attributes */
2213 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2214 SBVAL(p,0,file_index); p += 8;
2215 status = srvstr_push(base_data, flags2, p,
2216 fname, PTR_DIFF(end_data, p),
2217 STR_TERMINATE_ASCII, &len);
2218 if (!NT_STATUS_IS_OK(status)) {
2224 len = PTR_DIFF(p, pdata);
2225 pad = (len + (align-1)) & ~(align-1);
2227 * offset to the next entry, the caller
2228 * will overwrite it for the last entry
2229 * that's why we always include the padding
2233 * set padding to zero
2236 memset(p, 0, pad - len);
2243 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2244 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2245 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2247 SIVAL(p,0,reskey); p += 4;
2248 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2249 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2250 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2251 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2252 SOFF_T(p,0,file_size); p += 8;
2253 SOFF_T(p,0,allocation_size); p += 8;
2254 SIVAL(p,0,mode); p += 4;
2255 q = p; p += 4; /* q is placeholder for name length */
2256 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2257 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2258 } else if (readdir_attr_data &&
2259 readdir_attr_data->type == RDATTR_AAPL) {
2261 * OS X specific SMB2 extension negotiated via
2262 * AAPL create context: return max_access in
2265 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2267 unsigned int ea_size = estimate_ea_size(conn, NULL,
2269 SIVAL(p,0,ea_size); /* Extended attributes */
2273 if (readdir_attr_data &&
2274 readdir_attr_data->type == RDATTR_AAPL) {
2276 * OS X specific SMB2 extension negotiated via
2277 * AAPL create context: return resource fork
2278 * length and compressed FinderInfo in
2281 * According to documentation short_name_len
2282 * should be 0, but on the wire behaviour
2283 * shows its set to 24 by clients.
2287 /* Resourefork length */
2288 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2290 /* Compressed FinderInfo */
2291 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2292 } else if (!was_8_3 && check_mangled_names) {
2293 char mangled_name[13]; /* mangled 8.3 name. */
2294 if (!name_to_8_3(fname,mangled_name,True,
2296 /* Error - mangle failed ! */
2297 memset(mangled_name,'\0',12);
2299 mangled_name[12] = 0;
2300 status = srvstr_push(base_data, flags2,
2301 p+2, mangled_name, 24,
2302 STR_UPPER|STR_UNICODE, &len);
2303 if (!NT_STATUS_IS_OK(status)) {
2308 memset(p + 2 + len,'\0',24 - len);
2312 /* Clear the short name buffer. This is
2313 * IMPORTANT as not doing so will trigger
2314 * a Win2k client bug. JRA.
2321 if (readdir_attr_data &&
2322 readdir_attr_data->type == RDATTR_AAPL) {
2324 * OS X specific SMB2 extension negotiated via
2325 * AAPL create context: return UNIX mode in
2328 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2329 SSVAL(p, 0, aapl_mode);
2335 SBVAL(p,0,file_index); p += 8;
2336 status = srvstr_push(base_data, flags2, p,
2337 fname, PTR_DIFF(end_data, p),
2338 STR_TERMINATE_ASCII, &len);
2339 if (!NT_STATUS_IS_OK(status)) {
2345 len = PTR_DIFF(p, pdata);
2346 pad = (len + (align-1)) & ~(align-1);
2348 * offset to the next entry, the caller
2349 * will overwrite it for the last entry
2350 * that's why we always include the padding
2354 * set padding to zero
2357 memset(p, 0, pad - len);
2364 /* CIFS UNIX Extension. */
2366 case SMB_FIND_FILE_UNIX:
2367 case SMB_FIND_FILE_UNIX_INFO2:
2369 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2371 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2373 if (info_level == SMB_FIND_FILE_UNIX) {
2374 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2375 p = store_file_unix_basic(conn, p,
2376 NULL, &smb_fname->st);
2377 status = srvstr_push(base_data, flags2, p,
2378 fname, PTR_DIFF(end_data, p),
2379 STR_TERMINATE, &len);
2380 if (!NT_STATUS_IS_OK(status)) {
2384 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2385 p = store_file_unix_basic_info2(conn, p,
2386 NULL, &smb_fname->st);
2389 status = srvstr_push(base_data, flags2, p, fname,
2390 PTR_DIFF(end_data, p), 0, &len);
2391 if (!NT_STATUS_IS_OK(status)) {
2394 SIVAL(nameptr, 0, len);
2399 len = PTR_DIFF(p, pdata);
2400 pad = (len + (align-1)) & ~(align-1);
2402 * offset to the next entry, the caller
2403 * will overwrite it for the last entry
2404 * that's why we always include the padding
2408 * set padding to zero
2411 memset(p, 0, pad - len);
2416 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2421 return NT_STATUS_INVALID_LEVEL;
2424 if (PTR_DIFF(p,pdata) > space_remaining) {
2425 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2426 "(wanted %u, had %d)\n",
2427 (unsigned int)PTR_DIFF(p,pdata),
2429 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2432 /* Setup the last entry pointer, as an offset from base_data */
2433 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2434 /* Advance the data pointer to the next slot */
2437 return NT_STATUS_OK;
2440 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2441 connection_struct *conn,
2442 struct dptr_struct *dirptr,
2444 const char *path_mask,
2447 int requires_resume_key,
2455 int space_remaining,
2456 bool *got_exact_match,
2457 int *_last_entry_off,
2458 struct ea_list *name_list,
2459 struct file_id *file_id)
2462 const char *mask = NULL;
2463 long prev_dirpos = 0;
2466 struct smb_filename *smb_fname = NULL;
2467 struct smbd_dirptr_lanman2_state state;
2469 uint64_t last_entry_off = 0;
2471 enum mangled_names_options mangled_names;
2472 bool marshall_with_83_names;
2474 mangled_names = lp_mangled_names(conn->params);
2478 state.info_level = info_level;
2479 if (mangled_names != MANGLED_NAMES_NO) {
2480 state.check_mangled_names = true;
2482 state.has_wild = dptr_has_wild(dirptr);
2483 state.got_exact_match = false;
2485 *got_exact_match = false;
2487 p = strrchr_m(path_mask,'/');
2498 ok = smbd_dirptr_get_entry(ctx,
2504 smbd_dirptr_lanman2_match_fn,
2505 smbd_dirptr_lanman2_mode_fn,
2512 return NT_STATUS_END_OF_FILE;
2515 *got_exact_match = state.got_exact_match;
2517 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2519 status = smbd_marshall_dir_entry(ctx,
2524 marshall_with_83_names,
2525 requires_resume_key,
2536 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2537 DEBUG(1,("Conversion error: illegal character: %s\n",
2538 smb_fname_str_dbg(smb_fname)));
2541 if (file_id != NULL) {
2542 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2546 TALLOC_FREE(smb_fname);
2547 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2548 dptr_SeekDir(dirptr, prev_dirpos);
2551 if (!NT_STATUS_IS_OK(status)) {
2555 *_last_entry_off = last_entry_off;
2556 return NT_STATUS_OK;
2559 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2560 connection_struct *conn,
2561 struct dptr_struct *dirptr,
2563 const char *path_mask,
2566 bool requires_resume_key,
2572 int space_remaining,
2573 bool *got_exact_match,
2574 int *last_entry_off,
2575 struct ea_list *name_list)
2578 const bool do_pad = true;
2580 if (info_level >= 1 && info_level <= 3) {
2581 /* No alignment on earlier info levels. */
2585 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2586 path_mask, dirtype, info_level,
2587 requires_resume_key, dont_descend, ask_sharemode,
2589 ppdata, base_data, end_data,
2592 last_entry_off, name_list, NULL);
2595 /****************************************************************************
2596 Reply to a TRANS2_FINDFIRST.
2597 ****************************************************************************/
2599 static void call_trans2findfirst(connection_struct *conn,
2600 struct smb_request *req,
2601 char **pparams, int total_params,
2602 char **ppdata, int total_data,
2603 unsigned int max_data_bytes)
2605 /* We must be careful here that we don't return more than the
2606 allowed number of data bytes. If this means returning fewer than
2607 maxentries then so be it. We assume that the redirector has
2608 enough room for the fixed number of parameter bytes it has
2610 struct smb_filename *smb_dname = NULL;
2611 char *params = *pparams;
2612 char *pdata = *ppdata;
2616 uint16_t findfirst_flags;
2617 bool close_after_first;
2619 bool requires_resume_key;
2621 char *directory = NULL;
2624 int last_entry_off=0;
2628 bool finished = False;
2629 bool dont_descend = False;
2630 bool out_of_space = False;
2631 int space_remaining;
2632 bool mask_contains_wcard = False;
2633 struct ea_list *ea_list = NULL;
2634 NTSTATUS ntstatus = NT_STATUS_OK;
2635 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2636 struct dptr_struct *dirptr = NULL;
2637 struct smbd_server_connection *sconn = req->sconn;
2638 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2639 ucf_flags_from_smb_request(req);
2640 bool backup_priv = false;
2641 bool as_root = false;
2643 if (total_params < 13) {
2644 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2648 dirtype = SVAL(params,0);
2649 maxentries = SVAL(params,2);
2650 findfirst_flags = SVAL(params,4);
2651 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2652 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2653 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2654 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2655 security_token_has_privilege(get_current_nttok(conn),
2658 info_level = SVAL(params,6);
2660 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2661 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2662 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2664 info_level, max_data_bytes));
2667 /* W2K3 seems to treat zero as 1. */
2671 switch (info_level) {
2672 case SMB_FIND_INFO_STANDARD:
2673 case SMB_FIND_EA_SIZE:
2674 case SMB_FIND_EA_LIST:
2675 case SMB_FIND_FILE_DIRECTORY_INFO:
2676 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2677 case SMB_FIND_FILE_NAMES_INFO:
2678 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2679 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2680 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2682 case SMB_FIND_FILE_UNIX:
2683 case SMB_FIND_FILE_UNIX_INFO2:
2684 /* Always use filesystem for UNIX mtime query. */
2685 ask_sharemode = false;
2686 if (!lp_unix_extensions()) {
2687 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2690 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2693 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2697 if (req->posix_pathnames) {
2698 srvstr_get_path_wcard_posix(talloc_tos(),
2706 &mask_contains_wcard);
2708 srvstr_get_path_wcard(talloc_tos(),
2716 &mask_contains_wcard);
2718 if (!NT_STATUS_IS_OK(ntstatus)) {
2719 reply_nterror(req, ntstatus);
2726 ntstatus = filename_convert_with_privilege(talloc_tos(),
2731 &mask_contains_wcard,
2734 ntstatus = filename_convert(talloc_tos(), conn,
2737 &mask_contains_wcard,
2741 if (!NT_STATUS_IS_OK(ntstatus)) {
2742 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2743 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2744 ERRSRV, ERRbadpath);
2747 reply_nterror(req, ntstatus);
2751 mask = smb_dname->original_lcomp;
2753 directory = smb_dname->base_name;
2755 p = strrchr_m(directory,'/');
2757 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2758 if((directory[0] == '.') && (directory[1] == '\0')) {
2759 mask = talloc_strdup(talloc_tos(),"*");
2761 reply_nterror(req, NT_STATUS_NO_MEMORY);
2764 mask_contains_wcard = True;
2770 if (p == NULL || p == directory) {
2771 /* Ensure we don't have a directory name of "". */
2772 directory = talloc_strdup(talloc_tos(), ".");
2774 reply_nterror(req, NT_STATUS_NO_MEMORY);
2777 /* Ensure smb_dname->base_name matches. */
2778 smb_dname->base_name = directory;
2781 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2783 if (info_level == SMB_FIND_EA_LIST) {
2786 if (total_data < 4) {
2787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2791 ea_size = IVAL(pdata,0);
2792 if (ea_size != total_data) {
2793 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2794 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2799 if (!lp_ea_support(SNUM(conn))) {
2800 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2804 /* Pull out the list of names. */
2805 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2807 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2812 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2813 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2817 *ppdata = (char *)SMB_REALLOC(
2818 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2819 if(*ppdata == NULL ) {
2820 reply_nterror(req, NT_STATUS_NO_MEMORY);
2824 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2826 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2829 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2830 /* Realloc the params space */
2831 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2832 if (*pparams == NULL) {
2833 reply_nterror(req, NT_STATUS_NO_MEMORY);
2838 /* Save the wildcard match and attribs we are using on this directory -
2839 needed as lanman2 assumes these are being saved between calls */
2841 ntstatus = dptr_create(conn,
2849 mask_contains_wcard,
2853 if (!NT_STATUS_IS_OK(ntstatus)) {
2854 reply_nterror(req, ntstatus);
2859 /* Remember this in case we have
2860 to do a findnext. */
2861 dptr_set_priv(dirptr);
2864 dptr_num = dptr_dnum(dirptr);
2865 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2867 /* Initialize per TRANS2_FIND_FIRST operation data */
2868 dptr_init_search_op(dirptr);
2870 /* We don't need to check for VOL here as this is returned by
2871 a different TRANS2 call. */
2873 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2874 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2875 if (in_list(directory,
2876 lp_dont_descend(talloc_tos(), SNUM(conn)),
2877 conn->case_sensitive)) {
2878 dont_descend = True;
2882 space_remaining = max_data_bytes;
2883 out_of_space = False;
2885 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2886 bool got_exact_match = False;
2888 /* this is a heuristic to avoid seeking the dirptr except when
2889 absolutely necessary. It allows for a filename of about 40 chars */
2890 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2891 out_of_space = True;
2894 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2898 mask,dirtype,info_level,
2899 requires_resume_key,dont_descend,
2904 &last_entry_off, ea_list);
2905 if (NT_STATUS_EQUAL(ntstatus,
2906 NT_STATUS_ILLEGAL_CHARACTER)) {
2908 * Bad character conversion on name. Ignore this
2913 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2914 out_of_space = true;
2916 finished = !NT_STATUS_IS_OK(ntstatus);
2920 if (!finished && !out_of_space)
2924 * As an optimisation if we know we aren't looking
2925 * for a wildcard name (ie. the name matches the wildcard exactly)
2926 * then we can finish on any (first) match.
2927 * This speeds up large directory searches. JRA.
2933 /* Ensure space_remaining never goes -ve. */
2934 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2935 space_remaining = 0;
2936 out_of_space = true;
2938 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2942 /* Check if we can close the dirptr */
2943 if(close_after_first || (finished && close_if_end)) {
2944 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2945 dptr_close(sconn, &dptr_num);
2949 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2950 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2951 * the protocol level is less than NT1. Tested with smbclient. JRA.
2952 * This should fix the OS/2 client bug #2335.
2955 if(numentries == 0) {
2956 dptr_close(sconn, &dptr_num);
2957 if (get_Protocol() < PROTOCOL_NT1) {
2958 reply_force_doserror(req, ERRDOS, ERRnofiles);
2961 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2962 ERRDOS, ERRbadfile);
2967 /* At this point pdata points to numentries directory entries. */
2969 /* Set up the return parameter block */
2970 SSVAL(params,0,dptr_num);
2971 SSVAL(params,2,numentries);
2972 SSVAL(params,4,finished);
2973 SSVAL(params,6,0); /* Never an EA error */
2974 SSVAL(params,8,last_entry_off);
2976 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2979 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2980 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2982 reply_nterror(req, NT_STATUS_NO_MEMORY);
2986 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2987 smb_fn_name(req->cmd),
2988 mask, directory, dirtype, numentries ) );
2991 * Force a name mangle here to ensure that the
2992 * mask as an 8.3 name is top of the mangled cache.
2993 * The reasons for this are subtle. Don't remove
2994 * this code unless you know what you are doing
2995 * (see PR#13758). JRA.
2998 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2999 char mangled_name[13];
3000 name_to_8_3(mask, mangled_name, True, conn->params);
3008 TALLOC_FREE(smb_dname);
3012 /****************************************************************************
3013 Reply to a TRANS2_FINDNEXT.
3014 ****************************************************************************/
3016 static void call_trans2findnext(connection_struct *conn,
3017 struct smb_request *req,
3018 char **pparams, int total_params,
3019 char **ppdata, int total_data,
3020 unsigned int max_data_bytes)
3022 /* We must be careful here that we don't return more than the
3023 allowed number of data bytes. If this means returning fewer than
3024 maxentries then so be it. We assume that the redirector has
3025 enough room for the fixed number of parameter bytes it has
3027 char *params = *pparams;
3028 char *pdata = *ppdata;
3032 uint16_t info_level;
3033 uint32_t resume_key;
3034 uint16_t findnext_flags;
3035 bool close_after_request;
3037 bool requires_resume_key;
3039 bool mask_contains_wcard = False;
3040 char *resume_name = NULL;
3041 const char *mask = NULL;
3042 const char *directory = NULL;
3046 int i, last_entry_off=0;
3047 bool finished = False;
3048 bool dont_descend = False;
3049 bool out_of_space = False;
3050 int space_remaining;
3051 struct ea_list *ea_list = NULL;
3052 NTSTATUS ntstatus = NT_STATUS_OK;
3053 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3054 TALLOC_CTX *ctx = talloc_tos();
3055 struct dptr_struct *dirptr;
3056 struct smbd_server_connection *sconn = req->sconn;
3057 bool backup_priv = false;
3058 bool as_root = false;
3060 if (total_params < 13) {
3061 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3065 dptr_num = SVAL(params,0);
3066 maxentries = SVAL(params,2);
3067 info_level = SVAL(params,4);
3068 resume_key = IVAL(params,6);
3069 findnext_flags = SVAL(params,10);
3070 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3071 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3072 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3073 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3075 if (!continue_bit) {
3076 /* We only need resume_name if continue_bit is zero. */
3077 if (req->posix_pathnames) {
3078 srvstr_get_path_wcard_posix(ctx,
3086 &mask_contains_wcard);
3088 srvstr_get_path_wcard(ctx,
3096 &mask_contains_wcard);
3098 if (!NT_STATUS_IS_OK(ntstatus)) {
3099 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3100 complain (it thinks we're asking for the directory above the shared
3101 path or an invalid name). Catch this as the resume name is only compared, never used in
3102 a file access. JRA. */
3103 srvstr_pull_talloc(ctx, params, req->flags2,
3104 &resume_name, params+12,
3108 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3109 reply_nterror(req, ntstatus);
3115 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3116 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3117 resume_key = %d resume name = %s continue=%d level = %d\n",
3118 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3119 requires_resume_key, resume_key,
3120 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3123 /* W2K3 seems to treat zero as 1. */
3127 switch (info_level) {
3128 case SMB_FIND_INFO_STANDARD:
3129 case SMB_FIND_EA_SIZE:
3130 case SMB_FIND_EA_LIST:
3131 case SMB_FIND_FILE_DIRECTORY_INFO:
3132 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3133 case SMB_FIND_FILE_NAMES_INFO:
3134 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3135 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3136 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3138 case SMB_FIND_FILE_UNIX:
3139 case SMB_FIND_FILE_UNIX_INFO2:
3140 /* Always use filesystem for UNIX mtime query. */
3141 ask_sharemode = false;
3142 if (!lp_unix_extensions()) {
3143 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3148 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3152 if (info_level == SMB_FIND_EA_LIST) {
3155 if (total_data < 4) {
3156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3160 ea_size = IVAL(pdata,0);
3161 if (ea_size != total_data) {
3162 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3163 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3168 if (!lp_ea_support(SNUM(conn))) {
3169 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3173 /* Pull out the list of names. */
3174 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3181 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3186 *ppdata = (char *)SMB_REALLOC(
3187 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3188 if(*ppdata == NULL) {
3189 reply_nterror(req, NT_STATUS_NO_MEMORY);
3194 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3197 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3200 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3201 /* Realloc the params space */
3202 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3203 if(*pparams == NULL ) {
3204 reply_nterror(req, NT_STATUS_NO_MEMORY);
3210 /* Check that the dptr is valid */
3211 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3212 reply_nterror(req, STATUS_NO_MORE_FILES);
3216 directory = dptr_path(sconn, dptr_num);
3218 /* Get the wildcard mask from the dptr */
3219 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3220 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3221 reply_nterror(req, STATUS_NO_MORE_FILES);
3225 /* Get the attr mask from the dptr */
3226 dirtype = dptr_attr(sconn, dptr_num);
3228 backup_priv = dptr_get_priv(dirptr);
3230 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3231 "backup_priv = %d\n",
3232 dptr_num, mask, dirtype,
3234 dptr_TellDir(dirptr),
3237 /* Initialize per TRANS2_FIND_NEXT operation data */
3238 dptr_init_search_op(dirptr);
3240 /* We don't need to check for VOL here as this is returned by
3241 a different TRANS2 call. */
3243 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3244 directory,lp_dont_descend(ctx, SNUM(conn))));
3245 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3246 dont_descend = True;
3249 space_remaining = max_data_bytes;
3250 out_of_space = False;
3258 * Seek to the correct position. We no longer use the resume key but
3259 * depend on the last file name instead.
3262 if(!continue_bit && resume_name && *resume_name) {
3265 long current_pos = 0;
3267 * Remember, name_to_8_3 is called by
3268 * get_lanman2_dir_entry(), so the resume name
3269 * could be mangled. Ensure we check the unmangled name.
3272 if (mangle_is_mangled(resume_name, conn->params)) {
3273 char *new_resume_name = NULL;
3274 mangle_lookup_name_from_8_3(ctx,
3278 if (new_resume_name) {
3279 resume_name = new_resume_name;
3284 * Fix for NT redirector problem triggered by resume key indexes
3285 * changing between directory scans. We now return a resume key of 0
3286 * and instead look for the filename to continue from (also given
3287 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3288 * findfirst/findnext (as is usual) then the directory pointer
3289 * should already be at the correct place.
3292 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3293 } /* end if resume_name && !continue_bit */
3295 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3296 bool got_exact_match = False;
3298 /* this is a heuristic to avoid seeking the dirptr except when
3299 absolutely necessary. It allows for a filename of about 40 chars */
3300 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3301 out_of_space = True;
3304 ntstatus = get_lanman2_dir_entry(ctx,
3308 mask,dirtype,info_level,
3309 requires_resume_key,dont_descend,
3314 &last_entry_off, ea_list);
3315 if (NT_STATUS_EQUAL(ntstatus,
3316 NT_STATUS_ILLEGAL_CHARACTER)) {
3318 * Bad character conversion on name. Ignore this
3323 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3324 out_of_space = true;
3326 finished = !NT_STATUS_IS_OK(ntstatus);
3330 if (!finished && !out_of_space)
3334 * As an optimisation if we know we aren't looking
3335 * for a wildcard name (ie. the name matches the wildcard exactly)
3336 * then we can finish on any (first) match.
3337 * This speeds up large directory searches. JRA.
3343 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3346 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3347 smb_fn_name(req->cmd),
3348 mask, directory, dirtype, numentries ) );
3350 /* Check if we can close the dirptr */
3351 if(close_after_request || (finished && close_if_end)) {
3352 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3353 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3360 /* Set up the return parameter block */
3361 SSVAL(params,0,numentries);
3362 SSVAL(params,2,finished);
3363 SSVAL(params,4,0); /* Never an EA error */
3364 SSVAL(params,6,last_entry_off);
3366 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3372 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3374 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3378 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3380 SMB_ASSERT(extended_info != NULL);
3382 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3383 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3384 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3385 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3386 #ifdef SAMBA_VERSION_REVISION
3387 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3389 extended_info->samba_subversion = 0;
3390 #ifdef SAMBA_VERSION_RC_RELEASE
3391 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3393 #ifdef SAMBA_VERSION_PRE_RELEASE
3394 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3397 #ifdef SAMBA_VERSION_VENDOR_PATCH
3398 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3400 extended_info->samba_gitcommitdate = 0;
3401 #ifdef SAMBA_VERSION_COMMIT_TIME
3402 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3405 memset(extended_info->samba_version_string, 0,
3406 sizeof(extended_info->samba_version_string));
3408 snprintf (extended_info->samba_version_string,
3409 sizeof(extended_info->samba_version_string),
3410 "%s", samba_version_string());
3413 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3414 connection_struct *conn,
3415 TALLOC_CTX *mem_ctx,
3416 uint16_t info_level,
3418 unsigned int max_data_bytes,
3419 size_t *fixed_portion,
3420 struct smb_filename *fname,
3424 char *pdata, *end_data;
3427 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3428 int snum = SNUM(conn);
3429 const char *fstype = lp_fstype(SNUM(conn));
3430 const char *filename = NULL;
3431 const uint64_t bytes_per_sector = 512;
3432 uint32_t additional_flags = 0;
3433 struct smb_filename smb_fname;
3435 NTSTATUS status = NT_STATUS_OK;
3438 if (fname == NULL || fname->base_name == NULL) {
3441 filename = fname->base_name;
3445 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3446 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3447 "info level (0x%x) on IPC$.\n",
3448 (unsigned int)info_level));
3449 return NT_STATUS_ACCESS_DENIED;
3453 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3455 ZERO_STRUCT(smb_fname);
3456 smb_fname.base_name = discard_const_p(char, filename);
3458 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3459 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3460 return map_nt_error_from_unix(errno);
3465 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3466 return NT_STATUS_INVALID_PARAMETER;
3469 *ppdata = (char *)SMB_REALLOC(
3470 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3471 if (*ppdata == NULL) {
3472 return NT_STATUS_NO_MEMORY;
3476 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3477 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3481 switch (info_level) {
3482 case SMB_INFO_ALLOCATION:
3484 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3486 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3488 if (df_ret == (uint64_t)-1) {
3489 return map_nt_error_from_unix(errno);
3492 block_size = lp_block_size(snum);
3493 if (bsize < block_size) {
3494 uint64_t factor = block_size/bsize;
3499 if (bsize > block_size) {
3500 uint64_t factor = bsize/block_size;
3505 sectors_per_unit = bsize/bytes_per_sector;
3507 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3508 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3509 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3512 * For large drives, return max values and not modulo.
3514 dsize = MIN(dsize, UINT32_MAX);
3515 dfree = MIN(dfree, UINT32_MAX);
3517 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3518 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3519 SIVAL(pdata,l1_cUnit,dsize);
3520 SIVAL(pdata,l1_cUnitAvail,dfree);
3521 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3525 case SMB_INFO_VOLUME:
3526 /* Return volume name */
3528 * Add volume serial number - hash of a combination of
3529 * the called hostname and the service name.
3531 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3533 * Win2k3 and previous mess this up by sending a name length
3534 * one byte short. I believe only older clients (OS/2 Win9x) use
3535 * this call so try fixing this by adding a terminating null to
3536 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3538 status = srvstr_push(
3540 pdata+l2_vol_szVolLabel, vname,
3541 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3542 STR_NOALIGN|STR_TERMINATE, &len);
3543 if (!NT_STATUS_IS_OK(status)) {
3546 SCVAL(pdata,l2_vol_cch,len);
3547 data_len = l2_vol_szVolLabel + len;
3548 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3549 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3550 (unsigned)len, vname));
3553 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3554 case SMB_FS_ATTRIBUTE_INFORMATION:
3556 additional_flags = 0;
3557 #if defined(HAVE_SYS_QUOTAS)
3558 additional_flags |= FILE_VOLUME_QUOTAS;
3561 if(lp_nt_acl_support(SNUM(conn))) {
3562 additional_flags |= FILE_PERSISTENT_ACLS;
3565 /* Capabilities are filled in at connection time through STATVFS call */
3566 additional_flags |= conn->fs_capabilities;
3567 additional_flags |= lp_parm_int(conn->params->service,
3568 "share", "fake_fscaps",
3571 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3572 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3573 additional_flags); /* FS ATTRIBUTES */
3575 SIVAL(pdata,4,255); /* Max filename component length */
3576 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3577 and will think we can't do long filenames */
3578 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3579 PTR_DIFF(end_data, pdata+12),
3581 if (!NT_STATUS_IS_OK(status)) {
3585 data_len = 12 + len;
3586 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3587 /* the client only requested a portion of the
3589 data_len = max_data_bytes;
3590 status = STATUS_BUFFER_OVERFLOW;
3592 *fixed_portion = 16;
3595 case SMB_QUERY_FS_LABEL_INFO:
3596 case SMB_FS_LABEL_INFORMATION:
3597 status = srvstr_push(pdata, flags2, pdata+4, vname,
3598 PTR_DIFF(end_data, pdata+4), 0, &len);
3599 if (!NT_STATUS_IS_OK(status)) {
3606 case SMB_QUERY_FS_VOLUME_INFO:
3607 case SMB_FS_VOLUME_INFORMATION:
3610 * Add volume serial number - hash of a combination of
3611 * the called hostname and the service name.
3613 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3614 (str_checksum(get_local_machine_name())<<16));
3616 /* Max label len is 32 characters. */
3617 status = srvstr_push(pdata, flags2, pdata+18, vname,
3618 PTR_DIFF(end_data, pdata+18),
3620 if (!NT_STATUS_IS_OK(status)) {
3623 SIVAL(pdata,12,len);
3626 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3627 (int)strlen(vname),vname,
3628 lp_servicename(talloc_tos(), snum)));
3629 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3630 /* the client only requested a portion of the
3632 data_len = max_data_bytes;
3633 status = STATUS_BUFFER_OVERFLOW;
3635 *fixed_portion = 24;
3638 case SMB_QUERY_FS_SIZE_INFO:
3639 case SMB_FS_SIZE_INFORMATION:
3641 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3643 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3645 if (df_ret == (uint64_t)-1) {
3646 return map_nt_error_from_unix(errno);
3648 block_size = lp_block_size(snum);
3649 if (bsize < block_size) {
3650 uint64_t factor = block_size/bsize;
3655 if (bsize > block_size) {
3656 uint64_t factor = bsize/block_size;
3661 sectors_per_unit = bsize/bytes_per_sector;
3662 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3663 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3664 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3665 SBIG_UINT(pdata,0,dsize);
3666 SBIG_UINT(pdata,8,dfree);
3667 SIVAL(pdata,16,sectors_per_unit);
3668 SIVAL(pdata,20,bytes_per_sector);
3669 *fixed_portion = 24;
3673 case SMB_FS_FULL_SIZE_INFORMATION:
3675 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3677 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3679 if (df_ret == (uint64_t)-1) {
3680 return map_nt_error_from_unix(errno);
3682 block_size = lp_block_size(snum);
3683 if (bsize < block_size) {
3684 uint64_t factor = block_size/bsize;
3689 if (bsize > block_size) {
3690 uint64_t factor = bsize/block_size;
3695 sectors_per_unit = bsize/bytes_per_sector;
3696 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3697 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3698 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3699 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3700 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3701 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3702 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3703 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3704 *fixed_portion = 32;
3708 case SMB_QUERY_FS_DEVICE_INFO:
3709 case SMB_FS_DEVICE_INFORMATION:
3711 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3713 if (!CAN_WRITE(conn)) {
3714 characteristics |= FILE_READ_ONLY_DEVICE;
3717 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3718 SIVAL(pdata,4,characteristics);
3723 #ifdef HAVE_SYS_QUOTAS
3724 case SMB_FS_QUOTA_INFORMATION:
3726 * what we have to send --metze:
3728 * Unknown1: 24 NULL bytes
3729 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3730 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3731 * Quota Flags: 2 byte :
3732 * Unknown3: 6 NULL bytes
3736 * details for Quota Flags:
3738 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3739 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3740 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3741 * 0x0001 Enable Quotas: enable quota for this fs
3745 /* we need to fake up a fsp here,
3746 * because its not send in this call
3749 SMB_NTQUOTA_STRUCT quotas;
3752 ZERO_STRUCT(quotas);
3755 fsp.fnum = FNUM_FIELD_INVALID;
3758 if (get_current_uid(conn) != 0) {
3759 DEBUG(0,("get_user_quota: access_denied "
3760 "service [%s] user [%s]\n",
3761 lp_servicename(talloc_tos(), SNUM(conn)),
3762 conn->session_info->unix_info->unix_name));
3763 return NT_STATUS_ACCESS_DENIED;
3766 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3768 if (!NT_STATUS_IS_OK(status)) {
3769 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3775 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3776 lp_servicename(talloc_tos(), SNUM(conn))));
3778 /* Unknown1 24 NULL bytes*/
3779 SBIG_UINT(pdata,0,(uint64_t)0);
3780 SBIG_UINT(pdata,8,(uint64_t)0);
3781 SBIG_UINT(pdata,16,(uint64_t)0);
3783 /* Default Soft Quota 8 bytes */
3784 SBIG_UINT(pdata,24,quotas.softlim);
3786 /* Default Hard Quota 8 bytes */
3787 SBIG_UINT(pdata,32,quotas.hardlim);
3789 /* Quota flag 2 bytes */
3790 SSVAL(pdata,40,quotas.qflags);
3792 /* Unknown3 6 NULL bytes */
3798 #endif /* HAVE_SYS_QUOTAS */
3799 case SMB_FS_OBJECTID_INFORMATION:
3801 unsigned char objid[16];
3802 struct smb_extended_info extended_info;
3803 memcpy(pdata,create_volume_objectid(conn, objid),16);
3804 samba_extended_info_version (&extended_info);
3805 SIVAL(pdata,16,extended_info.samba_magic);
3806 SIVAL(pdata,20,extended_info.samba_version);
3807 SIVAL(pdata,24,extended_info.samba_subversion);
3808 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3809 memcpy(pdata+36,extended_info.samba_version_string,28);
3814 case SMB_FS_SECTOR_SIZE_INFORMATION:
3818 * These values match a physical Windows Server 2012
3819 * share backed by NTFS atop spinning rust.
3821 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3822 /* logical_bytes_per_sector */
3823 SIVAL(pdata, 0, bytes_per_sector);
3824 /* phys_bytes_per_sector_atomic */
3825 SIVAL(pdata, 4, bytes_per_sector);
3826 /* phys_bytes_per_sector_perf */
3827 SIVAL(pdata, 8, bytes_per_sector);
3828 /* fs_effective_phys_bytes_per_sector_atomic */
3829 SIVAL(pdata, 12, bytes_per_sector);
3831 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3832 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3833 /* byte_off_sector_align */
3834 SIVAL(pdata, 20, 0);
3835 /* byte_off_partition_align */
3836 SIVAL(pdata, 24, 0);
3837 *fixed_portion = 28;
3843 * Query the version and capabilities of the CIFS UNIX extensions
3847 case SMB_QUERY_CIFS_UNIX_INFO:
3849 bool large_write = lp_min_receive_file_size() &&
3850 !srv_is_signing_active(xconn);
3851 bool large_read = !srv_is_signing_active(xconn);
3852 int encrypt_caps = 0;
3854 if (!lp_unix_extensions()) {
3855 return NT_STATUS_INVALID_LEVEL;
3858 switch (conn->encrypt_level) {
3859 case SMB_SIGNING_OFF:
3862 case SMB_SIGNING_DESIRED:
3863 case SMB_SIGNING_IF_REQUIRED:
3864 case SMB_SIGNING_DEFAULT:
3865 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3867 case SMB_SIGNING_REQUIRED:
3868 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3869 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3870 large_write = false;
3876 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3877 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3879 /* We have POSIX ACLs, pathname, encryption,
3880 * large read/write, and locking capability. */
3882 SBIG_UINT(pdata,4,((uint64_t)(
3883 CIFS_UNIX_POSIX_ACLS_CAP|
3884 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3885 CIFS_UNIX_FCNTL_LOCKS_CAP|
3886 CIFS_UNIX_EXTATTR_CAP|
3887 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3889 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3891 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3895 case SMB_QUERY_POSIX_FS_INFO:
3898 vfs_statvfs_struct svfs;
3900 if (!lp_unix_extensions()) {
3901 return NT_STATUS_INVALID_LEVEL;
3904 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3908 SIVAL(pdata,0,svfs.OptimalTransferSize);
3909 SIVAL(pdata,4,svfs.BlockSize);
3910 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3911 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3912 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3913 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3914 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3915 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3916 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3918 } else if (rc == EOPNOTSUPP) {
3919 return NT_STATUS_INVALID_LEVEL;
3920 #endif /* EOPNOTSUPP */
3922 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3923 return NT_STATUS_DOS(ERRSRV, ERRerror);
3928 case SMB_QUERY_POSIX_WHOAMI:
3934 if (!lp_unix_extensions()) {
3935 return NT_STATUS_INVALID_LEVEL;
3938 if (max_data_bytes < 40) {
3939 return NT_STATUS_BUFFER_TOO_SMALL;
3942 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3943 flags |= SMB_WHOAMI_GUEST;
3946 /* NOTE: 8 bytes for UID/GID, irrespective of native
3947 * platform size. This matches
3948 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3950 data_len = 4 /* flags */
3957 + 4 /* pad/reserved */
3958 + (conn->session_info->unix_token->ngroups * 8)
3960 + (conn->session_info->security_token->num_sids *
3964 SIVAL(pdata, 0, flags);
3965 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3967 (uint64_t)conn->session_info->unix_token->uid);
3968 SBIG_UINT(pdata, 16,
3969 (uint64_t)conn->session_info->unix_token->gid);
3972 if (data_len >= max_data_bytes) {
3973 /* Potential overflow, skip the GIDs and SIDs. */
3975 SIVAL(pdata, 24, 0); /* num_groups */
3976 SIVAL(pdata, 28, 0); /* num_sids */
3977 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3978 SIVAL(pdata, 36, 0); /* reserved */
3984 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3985 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3987 /* We walk the SID list twice, but this call is fairly
3988 * infrequent, and I don't expect that it's performance
3989 * sensitive -- jpeach
3991 for (i = 0, sid_bytes = 0;
3992 i < conn->session_info->security_token->num_sids; ++i) {
3993 sid_bytes += ndr_size_dom_sid(
3994 &conn->session_info->security_token->sids[i],
3998 /* SID list byte count */
3999 SIVAL(pdata, 32, sid_bytes);
4001 /* 4 bytes pad/reserved - must be zero */
4002 SIVAL(pdata, 36, 0);
4006 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4007 SBIG_UINT(pdata, data_len,
4008 (uint64_t)conn->session_info->unix_token->groups[i]);
4014 i < conn->session_info->security_token->num_sids; ++i) {
4015 int sid_len = ndr_size_dom_sid(
4016 &conn->session_info->security_token->sids[i],
4019 sid_linearize((uint8_t *)(pdata + data_len),
4021 &conn->session_info->security_token->sids[i]);
4022 data_len += sid_len;
4028 case SMB_MAC_QUERY_FS_INFO:
4030 * Thursby MAC extension... ONLY on NTFS filesystems
4031 * once we do streams then we don't need this
4033 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4035 SIVAL(pdata,84,0x100); /* Don't support mac... */
4040 return NT_STATUS_INVALID_LEVEL;
4043 *ret_data_len = data_len;
4047 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4048 struct smb_request *req,
4050 const DATA_BLOB *qdata)
4053 SMB_NTQUOTA_STRUCT quotas;
4055 ZERO_STRUCT(quotas);
4058 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4059 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4060 lp_servicename(talloc_tos(), SNUM(conn)),
4061 conn->session_info->unix_info->unix_name));
4062 return NT_STATUS_ACCESS_DENIED;
4065 if (!check_fsp_ntquota_handle(conn, req,
4067 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4068 return NT_STATUS_INVALID_HANDLE;
4071 /* note: normally there're 48 bytes,
4072 * but we didn't use the last 6 bytes for now
4075 if (qdata->length < 42) {
4076 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4077 (unsigned int)qdata->length));
4078 return NT_STATUS_INVALID_PARAMETER;
4081 /* unknown_1 24 NULL bytes in pdata*/
4083 /* the soft quotas 8 bytes (uint64_t)*/
4084 quotas.softlim = BVAL(qdata->data,24);
4086 /* the hard quotas 8 bytes (uint64_t)*/
4087 quotas.hardlim = BVAL(qdata->data,32);
4089 /* quota_flags 2 bytes **/
4090 quotas.qflags = SVAL(qdata->data,40);
4092 /* unknown_2 6 NULL bytes follow*/
4094 /* now set the quotas */
4095 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4096 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4097 lp_servicename(talloc_tos(), SNUM(conn))));
4098 status = map_nt_error_from_unix(errno);
4100 status = NT_STATUS_OK;
4105 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4106 struct smb_request *req,
4107 TALLOC_CTX *mem_ctx,
4108 uint16_t info_level,
4110 const DATA_BLOB *pdata)
4112 switch (info_level) {
4113 case SMB_FS_QUOTA_INFORMATION:
4115 return smb_set_fsquota(conn,
4124 return NT_STATUS_INVALID_LEVEL;
4127 /****************************************************************************
4128 Reply to a TRANS2_QFSINFO (query filesystem info).
4129 ****************************************************************************/
4131 static void call_trans2qfsinfo(connection_struct *conn,
4132 struct smb_request *req,
4133 char **pparams, int total_params,
4134 char **ppdata, int total_data,
4135 unsigned int max_data_bytes)
4137 char *params = *pparams;
4138 uint16_t info_level;
4140 size_t fixed_portion;
4143 if (total_params < 2) {
4144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4148 info_level = SVAL(params,0);
4150 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4151 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4152 DEBUG(0,("call_trans2qfsinfo: encryption required "
4153 "and info level 0x%x sent.\n",
4154 (unsigned int)info_level));
4155 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4160 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4162 status = smbd_do_qfsinfo(req->xconn, conn, req,
4169 if (!NT_STATUS_IS_OK(status)) {
4170 reply_nterror(req, status);
4174 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4177 DEBUG( 4, ( "%s info_level = %d\n",
4178 smb_fn_name(req->cmd), info_level) );
4183 /****************************************************************************
4184 Reply to a TRANS2_SETFSINFO (set filesystem info).
4185 ****************************************************************************/
4187 static void call_trans2setfsinfo(connection_struct *conn,
4188 struct smb_request *req,
4189 char **pparams, int total_params,
4190 char **ppdata, int total_data,
4191 unsigned int max_data_bytes)
4193 struct smbXsrv_connection *xconn = req->xconn;
4194 char *pdata = *ppdata;
4195 char *params = *pparams;
4196 uint16_t info_level;
4198 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4199 lp_servicename(talloc_tos(), SNUM(conn))));
4202 if (total_params < 4) {
4203 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4205 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4209 info_level = SVAL(params,2);
4212 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4213 info_level != SMB_SET_CIFS_UNIX_INFO) {
4214 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4215 "info level (0x%x) on IPC$.\n",
4216 (unsigned int)info_level));
4217 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4222 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4223 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4224 DEBUG(0,("call_trans2setfsinfo: encryption required "
4225 "and info level 0x%x sent.\n",
4226 (unsigned int)info_level));
4227 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4232 switch(info_level) {
4233 case SMB_SET_CIFS_UNIX_INFO:
4234 if (!lp_unix_extensions()) {
4235 DEBUG(2,("call_trans2setfsinfo: "
4236 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4237 "unix extensions off\n"));
4239 NT_STATUS_INVALID_LEVEL);
4243 /* There should be 12 bytes of capabilities set. */
4244 if (total_data < 12) {
4247 NT_STATUS_INVALID_PARAMETER);
4250 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4251 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4252 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4253 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4254 /* Just print these values for now. */
4255 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4256 "major = %u, minor = %u cap_low = 0x%x, "
4258 (unsigned int)xconn->
4259 smb1.unix_info.client_major,
4260 (unsigned int)xconn->
4261 smb1.unix_info.client_minor,
4262 (unsigned int)xconn->
4263 smb1.unix_info.client_cap_low,
4264 (unsigned int)xconn->
4265 smb1.unix_info.client_cap_high));
4267 /* Here is where we must switch to posix pathname processing... */
4268 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4269 lp_set_posix_pathnames();
4270 mangle_change_to_posix();
4273 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4274 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4275 /* Client that knows how to do posix locks,
4276 * but not posix open/mkdir operations. Set a
4277 * default type for read/write checks. */
4279 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4284 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4287 size_t param_len = 0;
4288 size_t data_len = total_data;
4290 if (!lp_unix_extensions()) {
4293 NT_STATUS_INVALID_LEVEL);
4297 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4300 NT_STATUS_NOT_SUPPORTED);
4304 if (xconn->smb1.echo_handler.trusted_fde) {
4305 DEBUG( 2,("call_trans2setfsinfo: "
4306 "request transport encryption disabled"
4307 "with 'fork echo handler = yes'\n"));
4310 NT_STATUS_NOT_SUPPORTED);
4314 DEBUG( 4,("call_trans2setfsinfo: "
4315 "request transport encryption.\n"));
4317 status = srv_request_encryption_setup(conn,
4318 (unsigned char **)ppdata,
4320 (unsigned char **)pparams,
4323 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4324 !NT_STATUS_IS_OK(status)) {
4325 reply_nterror(req, status);
4329 send_trans2_replies(conn, req,
4337 if (NT_STATUS_IS_OK(status)) {
4338 /* Server-side transport
4339 * encryption is now *on*. */
4340 status = srv_encryption_start(conn);
4341 if (!NT_STATUS_IS_OK(status)) {
4342 char *reason = talloc_asprintf(talloc_tos(),
4343 "Failure in setting "
4344 "up encrypted transport: %s",
4346 exit_server_cleanly(reason);
4352 case SMB_FS_QUOTA_INFORMATION:
4356 .data = (uint8_t *)pdata,
4357 .length = total_data
4359 files_struct *fsp = NULL;
4360 fsp = file_fsp(req, SVAL(params,0));
4362 status = smb_set_fsquota(conn,
4366 if (!NT_STATUS_IS_OK(status)) {
4367 reply_nterror(req, status);
4373 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4375 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4381 * sending this reply works fine,
4382 * but I'm not sure it's the same
4383 * like windows do...
4386 reply_outbuf(req, 10, 0);
4389 #if defined(HAVE_POSIX_ACLS)
4390 /****************************************************************************
4391 Utility function to count the number of entries in a POSIX acl.
4392 ****************************************************************************/
4394 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4396 unsigned int ace_count = 0;
4397 int entry_id = SMB_ACL_FIRST_ENTRY;
4398 SMB_ACL_ENTRY_T entry;
4400 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4402 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4403 entry_id = SMB_ACL_NEXT_ENTRY;
4410 /****************************************************************************
4411 Utility function to marshall a POSIX acl into wire format.
4412 ****************************************************************************/
4414 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4416 int entry_id = SMB_ACL_FIRST_ENTRY;
4417 SMB_ACL_ENTRY_T entry;
4419 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4420 SMB_ACL_TAG_T tagtype;
4421 SMB_ACL_PERMSET_T permset;
4422 unsigned char perms = 0;
4423 unsigned int own_grp;
4426 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4427 entry_id = SMB_ACL_NEXT_ENTRY;
4430 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4431 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4435 if (sys_acl_get_permset(entry, &permset) == -1) {
4436 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4440 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4441 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4442 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4444 SCVAL(pdata,1,perms);
4447 case SMB_ACL_USER_OBJ:
4448 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4449 own_grp = (unsigned int)pst->st_ex_uid;
4450 SIVAL(pdata,2,own_grp);
4455 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4457 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4460 own_grp = (unsigned int)*puid;
4461 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4462 SIVAL(pdata,2,own_grp);
4466 case SMB_ACL_GROUP_OBJ:
4467 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4468 own_grp = (unsigned int)pst->st_ex_gid;
4469 SIVAL(pdata,2,own_grp);
4474 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4476 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4479 own_grp = (unsigned int)*pgid;
4480 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4481 SIVAL(pdata,2,own_grp);
4486 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4487 SIVAL(pdata,2,0xFFFFFFFF);
4488 SIVAL(pdata,6,0xFFFFFFFF);
4491 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4492 SIVAL(pdata,2,0xFFFFFFFF);
4493 SIVAL(pdata,6,0xFFFFFFFF);
4496 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4499 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4506 /****************************************************************************
4507 Store the FILE_UNIX_BASIC info.
4508 ****************************************************************************/
4510 static char *store_file_unix_basic(connection_struct *conn,
4513 const SMB_STRUCT_STAT *psbuf)
4515 uint64_t file_index = get_FileIndex(conn, psbuf);
4518 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4519 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4521 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4524 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4527 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4528 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4529 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4532 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4536 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4540 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4543 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4544 devno = psbuf->st_ex_rdev;
4546 devno = psbuf->st_ex_dev;
4549 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4553 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4557 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4560 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4564 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4571 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4572 * the chflags(2) (or equivalent) flags.
4574 * XXX: this really should be behind the VFS interface. To do this, we would
4575 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4576 * Each VFS module could then implement its own mapping as appropriate for the
4577 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4579 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4583 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4587 { UF_IMMUTABLE, EXT_IMMUTABLE },
4591 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4595 { UF_HIDDEN, EXT_HIDDEN },
4598 /* Do not remove. We need to guarantee that this array has at least one
4599 * entry to build on HP-UX.
4605 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4606 uint32_t *smb_fflags, uint32_t *smb_fmask)
4610 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4611 *smb_fmask |= info2_flags_map[i].smb_fflag;
4612 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4613 *smb_fflags |= info2_flags_map[i].smb_fflag;
4618 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4619 const uint32_t smb_fflags,
4620 const uint32_t smb_fmask,
4623 uint32_t max_fmask = 0;
4626 *stat_fflags = psbuf->st_ex_flags;
4628 /* For each flags requested in smb_fmask, check the state of the
4629 * corresponding flag in smb_fflags and set or clear the matching
4633 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4634 max_fmask |= info2_flags_map[i].smb_fflag;
4635 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4636 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4637 *stat_fflags |= info2_flags_map[i].stat_fflag;
4639 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4644 /* If smb_fmask is asking to set any bits that are not supported by
4645 * our flag mappings, we should fail.
4647 if ((smb_fmask & max_fmask) != smb_fmask) {
4655 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4656 * of file flags and birth (create) time.
4658 static char *store_file_unix_basic_info2(connection_struct *conn,
4661 const SMB_STRUCT_STAT *psbuf)
4663 uint32_t file_flags = 0;
4664 uint32_t flags_mask = 0;
4666 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4668 /* Create (birth) time 64 bit */
4669 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4672 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4673 SIVAL(pdata, 0, file_flags); /* flags */
4674 SIVAL(pdata, 4, flags_mask); /* mask */
4680 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4681 const struct stream_struct *streams,
4683 unsigned int max_data_bytes,
4684 unsigned int *data_size)
4687 unsigned int ofs = 0;
4689 if (max_data_bytes < 32) {
4690 return NT_STATUS_INFO_LENGTH_MISMATCH;
4693 for (i = 0; i < num_streams; i++) {
4694 unsigned int next_offset;
4696 smb_ucs2_t *namebuf;
4698 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4699 streams[i].name, &namelen) ||
4702 return NT_STATUS_INVALID_PARAMETER;
4706 * name_buf is now null-terminated, we need to marshall as not
4713 * We cannot overflow ...
4715 if ((ofs + 24 + namelen) > max_data_bytes) {
4716 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4718 TALLOC_FREE(namebuf);
4719 return STATUS_BUFFER_OVERFLOW;
4722 SIVAL(data, ofs+4, namelen);
4723 SOFF_T(data, ofs+8, streams[i].size);
4724 SOFF_T(data, ofs+16, streams[i].alloc_size);
4725 memcpy(data+ofs+24, namebuf, namelen);
4726 TALLOC_FREE(namebuf);
4728 next_offset = ofs + 24 + namelen;
4730 if (i == num_streams-1) {
4731 SIVAL(data, ofs, 0);
4734 unsigned int align = ndr_align_size(next_offset, 8);
4736 if ((next_offset + align) > max_data_bytes) {
4737 DEBUG(10, ("refusing to overflow align "
4738 "reply at stream %u\n",
4740 TALLOC_FREE(namebuf);
4741 return STATUS_BUFFER_OVERFLOW;
4744 memset(data+next_offset, 0, align);
4745 next_offset += align;
4747 SIVAL(data, ofs, next_offset - ofs);
4754 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4758 return NT_STATUS_OK;
4761 /****************************************************************************
4762 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4763 ****************************************************************************/
4765 static void call_trans2qpipeinfo(connection_struct *conn,
4766 struct smb_request *req,
4767 unsigned int tran_call,
4768 char **pparams, int total_params,
4769 char **ppdata, int total_data,
4770 unsigned int max_data_bytes)
4772 char *params = *pparams;
4773 char *pdata = *ppdata;
4774 unsigned int data_size = 0;
4775 unsigned int param_size = 2;
4776 uint16_t info_level;
4780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4784 if (total_params < 4) {
4785 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4789 fsp = file_fsp(req, SVAL(params,0));
4790 if (!fsp_is_np(fsp)) {
4791 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4795 info_level = SVAL(params,2);
4797 *pparams = (char *)SMB_REALLOC(*pparams,2);
4798 if (*pparams == NULL) {
4799 reply_nterror(req, NT_STATUS_NO_MEMORY);
4804 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4805 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4808 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4809 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4810 if (*ppdata == NULL ) {
4811 reply_nterror(req, NT_STATUS_NO_MEMORY);
4816 switch (info_level) {
4817 case SMB_FILE_STANDARD_INFORMATION:
4819 SOFF_T(pdata,0,4096LL);
4826 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4830 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4836 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4837 TALLOC_CTX *mem_ctx,
4838 uint16_t info_level,
4840 struct smb_filename *smb_fname,
4841 bool delete_pending,
4842 struct timespec write_time_ts,
4843 struct ea_list *ea_list,
4844 int lock_data_count,
4847 unsigned int max_data_bytes,
4848 size_t *fixed_portion,
4850 unsigned int *pdata_size)
4852 char *pdata = *ppdata;
4853 char *dstart, *dend;
4854 unsigned int data_size;
4855 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4856 time_t create_time, mtime, atime, c_time;
4857 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4864 uint64_t file_size = 0;
4866 uint64_t allocation_size = 0;
4867 uint64_t file_index = 0;
4868 uint32_t access_mask = 0;
4871 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4872 return NT_STATUS_INVALID_LEVEL;
4875 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4876 smb_fname_str_dbg(smb_fname),
4878 info_level, max_data_bytes));
4880 mode = dos_mode(conn, smb_fname);
4881 nlink = psbuf->st_ex_nlink;
4883 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4887 if ((nlink > 0) && delete_pending) {
4891 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4892 return NT_STATUS_INVALID_PARAMETER;
4895 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4896 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4897 if (*ppdata == NULL) {
4898 return NT_STATUS_NO_MEMORY;
4902 dend = dstart + data_size - 1;
4904 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4905 update_stat_ex_mtime(psbuf, write_time_ts);
4908 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4909 mtime_ts = psbuf->st_ex_mtime;
4910 atime_ts = psbuf->st_ex_atime;
4911 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4913 if (lp_dos_filetime_resolution(SNUM(conn))) {
4914 dos_filetime_timespec(&create_time_ts);
4915 dos_filetime_timespec(&mtime_ts);
4916 dos_filetime_timespec(&atime_ts);
4917 dos_filetime_timespec(&ctime_ts);
4920 create_time = convert_timespec_to_time_t(create_time_ts);
4921 mtime = convert_timespec_to_time_t(mtime_ts);
4922 atime = convert_timespec_to_time_t(atime_ts);
4923 c_time = convert_timespec_to_time_t(ctime_ts);
4925 p = strrchr_m(smb_fname->base_name,'/');
4927 base_name = smb_fname->base_name;
4931 /* NT expects the name to be in an exact form of the *full*
4932 filename. See the trans2 torture test */
4933 if (ISDOT(base_name)) {
4934 dos_fname = talloc_strdup(mem_ctx, "\\");
4936 return NT_STATUS_NO_MEMORY;
4939 dos_fname = talloc_asprintf(mem_ctx,
4941 smb_fname->base_name);
4943 return NT_STATUS_NO_MEMORY;
4945 if (is_ntfs_stream_smb_fname(smb_fname)) {
4946 dos_fname = talloc_asprintf(dos_fname, "%s",
4947 smb_fname->stream_name);
4949 return NT_STATUS_NO_MEMORY;
4953 string_replace(dos_fname, '/', '\\');
4956 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4959 /* Do we have this path open ? */
4961 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4962 fsp1 = file_find_di_first(conn->sconn, fileid);
4963 if (fsp1 && fsp1->initial_allocation_size) {
4964 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4968 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4969 file_size = get_file_size_stat(psbuf);
4973 pos = fsp->fh->position_information;
4977 access_mask = fsp->access_mask;
4979 /* GENERIC_EXECUTE mapping from Windows */
4980 access_mask = 0x12019F;
4983 /* This should be an index number - looks like
4986 I think this causes us to fail the IFSKIT
4987 BasicFileInformationTest. -tpot */
4988 file_index = get_FileIndex(conn, psbuf);
4992 switch (info_level) {
4993 case SMB_INFO_STANDARD:
4994 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4996 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4997 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4998 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4999 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5000 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5001 SSVAL(pdata,l1_attrFile,mode);
5004 case SMB_INFO_QUERY_EA_SIZE:
5006 unsigned int ea_size =
5007 estimate_ea_size(conn, fsp,
5009 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5011 srv_put_dos_date2(pdata,0,create_time);
5012 srv_put_dos_date2(pdata,4,atime);
5013 srv_put_dos_date2(pdata,8,mtime); /* write time */
5014 SIVAL(pdata,12,(uint32_t)file_size);
5015 SIVAL(pdata,16,(uint32_t)allocation_size);
5016 SSVAL(pdata,20,mode);
5017 SIVAL(pdata,22,ea_size);
5021 case SMB_INFO_IS_NAME_VALID:
5022 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5024 /* os/2 needs this ? really ?*/
5025 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5027 /* This is only reached for qpathinfo */
5031 case SMB_INFO_QUERY_EAS_FROM_LIST:
5033 size_t total_ea_len = 0;
5034 struct ea_list *ea_file_list = NULL;
5035 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5038 get_ea_list_from_file(mem_ctx, conn, fsp,
5040 &total_ea_len, &ea_file_list);
5041 if (!NT_STATUS_IS_OK(status)) {
5045 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5047 if (!ea_list || (total_ea_len > data_size)) {
5049 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5053 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5057 case SMB_INFO_QUERY_ALL_EAS:
5059 /* We have data_size bytes to put EA's into. */
5060 size_t total_ea_len = 0;
5061 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5063 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5065 &total_ea_len, &ea_list);
5066 if (!NT_STATUS_IS_OK(status)) {
5070 if (!ea_list || (total_ea_len > data_size)) {
5072 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5076 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5080 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5082 /* This is FileFullEaInformation - 0xF which maps to
5083 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5085 /* We have data_size bytes to put EA's into. */
5086 size_t total_ea_len = 0;
5087 struct ea_list *ea_file_list = NULL;
5089 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5091 /*TODO: add filtering and index handling */
5094 get_ea_list_from_file(mem_ctx, conn, fsp,
5096 &total_ea_len, &ea_file_list);
5097 if (!NT_STATUS_IS_OK(status)) {
5100 if (!ea_file_list) {
5101 return NT_STATUS_NO_EAS_ON_FILE;
5104 status = fill_ea_chained_buffer(mem_ctx,
5108 conn, ea_file_list);
5109 if (!NT_STATUS_IS_OK(status)) {
5115 case SMB_FILE_BASIC_INFORMATION:
5116 case SMB_QUERY_FILE_BASIC_INFO:
5118 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5119 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5120 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5122 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5126 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5127 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5128 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5129 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5130 SIVAL(pdata,32,mode);
5132 DEBUG(5,("SMB_QFBI - "));
5133 DEBUG(5,("create: %s ", ctime(&create_time)));
5134 DEBUG(5,("access: %s ", ctime(&atime)));
5135 DEBUG(5,("write: %s ", ctime(&mtime)));
5136 DEBUG(5,("change: %s ", ctime(&c_time)));
5137 DEBUG(5,("mode: %x\n", mode));
5138 *fixed_portion = data_size;
5141 case SMB_FILE_STANDARD_INFORMATION:
5142 case SMB_QUERY_FILE_STANDARD_INFO:
5144 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5146 SOFF_T(pdata,0,allocation_size);
5147 SOFF_T(pdata,8,file_size);
5148 SIVAL(pdata,16,nlink);
5149 SCVAL(pdata,20,delete_pending?1:0);
5150 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5151 SSVAL(pdata,22,0); /* Padding. */
5152 *fixed_portion = 24;
5155 case SMB_FILE_EA_INFORMATION:
5156 case SMB_QUERY_FILE_EA_INFO:
5158 unsigned int ea_size =
5159 estimate_ea_size(conn, fsp, smb_fname);
5160 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5163 SIVAL(pdata,0,ea_size);
5167 /* Get the 8.3 name - used if NT SMB was negotiated. */
5168 case SMB_QUERY_FILE_ALT_NAME_INFO:
5169 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5171 char mangled_name[13];
5172 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5173 if (!name_to_8_3(base_name,mangled_name,
5174 True,conn->params)) {
5175 return NT_STATUS_NO_MEMORY;
5177 status = srvstr_push(dstart, flags2,
5178 pdata+4, mangled_name,
5179 PTR_DIFF(dend, pdata+4),
5181 if (!NT_STATUS_IS_OK(status)) {
5184 data_size = 4 + len;
5190 case SMB_QUERY_FILE_NAME_INFO:
5193 this must be *exactly* right for ACLs on mapped drives to work
5195 status = srvstr_push(dstart, flags2,
5197 PTR_DIFF(dend, pdata+4),
5199 if (!NT_STATUS_IS_OK(status)) {
5202 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5203 data_size = 4 + len;
5208 case SMB_FILE_ALLOCATION_INFORMATION:
5209 case SMB_QUERY_FILE_ALLOCATION_INFO:
5210 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5212 SOFF_T(pdata,0,allocation_size);
5215 case SMB_FILE_END_OF_FILE_INFORMATION:
5216 case SMB_QUERY_FILE_END_OF_FILEINFO:
5217 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5219 SOFF_T(pdata,0,file_size);
5222 case SMB_QUERY_FILE_ALL_INFO:
5223 case SMB_FILE_ALL_INFORMATION:
5225 unsigned int ea_size =
5226 estimate_ea_size(conn, fsp, smb_fname);
5227 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5228 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5229 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5230 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5231 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5232 SIVAL(pdata,32,mode);
5233 SIVAL(pdata,36,0); /* padding. */
5235 SOFF_T(pdata,0,allocation_size);
5236 SOFF_T(pdata,8,file_size);
5237 SIVAL(pdata,16,nlink);
5238 SCVAL(pdata,20,delete_pending);
5239 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5242 SIVAL(pdata,0,ea_size);
5243 pdata += 4; /* EA info */
5244 status = srvstr_push(dstart, flags2,
5246 PTR_DIFF(dend, pdata+4),
5248 if (!NT_STATUS_IS_OK(status)) {
5253 data_size = PTR_DIFF(pdata,(*ppdata));
5254 *fixed_portion = 10;
5258 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5260 unsigned int ea_size =
5261 estimate_ea_size(conn, fsp, smb_fname);
5262 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5263 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5264 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5265 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5266 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5267 SIVAL(pdata, 0x20, mode);
5268 SIVAL(pdata, 0x24, 0); /* padding. */
5269 SBVAL(pdata, 0x28, allocation_size);
5270 SBVAL(pdata, 0x30, file_size);
5271 SIVAL(pdata, 0x38, nlink);
5272 SCVAL(pdata, 0x3C, delete_pending);
5273 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5274 SSVAL(pdata, 0x3E, 0); /* padding */
5275 SBVAL(pdata, 0x40, file_index);
5276 SIVAL(pdata, 0x48, ea_size);
5277 SIVAL(pdata, 0x4C, access_mask);
5278 SBVAL(pdata, 0x50, pos);
5279 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5280 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5284 status = srvstr_push(dstart, flags2,
5286 PTR_DIFF(dend, pdata+4),
5288 if (!NT_STATUS_IS_OK(status)) {
5293 data_size = PTR_DIFF(pdata,(*ppdata));
5294 *fixed_portion = 104;
5297 case SMB_FILE_INTERNAL_INFORMATION:
5299 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5300 SBVAL(pdata, 0, file_index);
5305 case SMB_FILE_ACCESS_INFORMATION:
5306 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5307 SIVAL(pdata, 0, access_mask);
5312 case SMB_FILE_NAME_INFORMATION:
5313 /* Pathname with leading '\'. */
5316 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5317 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5318 SIVAL(pdata,0,byte_len);
5319 data_size = 4 + byte_len;
5323 case SMB_FILE_DISPOSITION_INFORMATION:
5324 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5326 SCVAL(pdata,0,delete_pending);
5330 case SMB_FILE_POSITION_INFORMATION:
5331 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5333 SOFF_T(pdata,0,pos);
5337 case SMB_FILE_MODE_INFORMATION:
5338 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5339 SIVAL(pdata,0,mode);
5344 case SMB_FILE_ALIGNMENT_INFORMATION:
5345 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5346 SIVAL(pdata,0,0); /* No alignment needed. */
5352 * NT4 server just returns "invalid query" to this - if we try
5353 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5356 /* The first statement above is false - verified using Thursby
5357 * client against NT4 -- gcolley.
5359 case SMB_QUERY_FILE_STREAM_INFO:
5360 case SMB_FILE_STREAM_INFORMATION: {
5361 unsigned int num_streams = 0;
5362 struct stream_struct *streams = NULL;
5364 DEBUG(10,("smbd_do_qfilepathinfo: "
5365 "SMB_FILE_STREAM_INFORMATION\n"));
5367 if (is_ntfs_stream_smb_fname(smb_fname)) {
5368 return NT_STATUS_INVALID_PARAMETER;
5371 status = vfs_streaminfo(conn,
5378 if (!NT_STATUS_IS_OK(status)) {
5379 DEBUG(10, ("could not get stream info: %s\n",
5380 nt_errstr(status)));
5384 status = marshall_stream_info(num_streams, streams,
5385 pdata, max_data_bytes,
5388 if (!NT_STATUS_IS_OK(status)) {
5389 DEBUG(10, ("marshall_stream_info failed: %s\n",
5390 nt_errstr(status)));
5391 TALLOC_FREE(streams);
5395 TALLOC_FREE(streams);
5397 *fixed_portion = 32;
5401 case SMB_QUERY_COMPRESSION_INFO:
5402 case SMB_FILE_COMPRESSION_INFORMATION:
5403 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5404 SOFF_T(pdata,0,file_size);
5405 SIVAL(pdata,8,0); /* ??? */
5406 SIVAL(pdata,12,0); /* ??? */
5408 *fixed_portion = 16;
5411 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5412 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5413 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5414 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5415 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5416 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5417 SOFF_T(pdata,32,allocation_size);
5418 SOFF_T(pdata,40,file_size);
5419 SIVAL(pdata,48,mode);
5420 SIVAL(pdata,52,0); /* ??? */
5422 *fixed_portion = 56;
5425 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5426 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5427 SIVAL(pdata,0,mode);
5434 * CIFS UNIX Extensions.
5437 case SMB_QUERY_FILE_UNIX_BASIC:
5439 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5440 data_size = PTR_DIFF(pdata,(*ppdata));
5442 DEBUG(4,("smbd_do_qfilepathinfo: "
5443 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5444 dump_data(4, (uint8_t *)(*ppdata), data_size);
5448 case SMB_QUERY_FILE_UNIX_INFO2:
5450 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5451 data_size = PTR_DIFF(pdata,(*ppdata));
5455 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5457 for (i=0; i<100; i++)
5458 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5464 case SMB_QUERY_FILE_UNIX_LINK:
5467 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5470 return NT_STATUS_NO_MEMORY;
5473 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5475 if(!S_ISLNK(psbuf->st_ex_mode)) {
5476 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5479 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5481 link_len = SMB_VFS_READLINK(conn,
5482 smb_fname->base_name,
5484 if (link_len == -1) {
5485 return map_nt_error_from_unix(errno);
5487 buffer[link_len] = 0;
5488 status = srvstr_push(dstart, flags2,
5490 PTR_DIFF(dend, pdata),
5491 STR_TERMINATE, &len);
5492 if (!NT_STATUS_IS_OK(status)) {
5496 data_size = PTR_DIFF(pdata,(*ppdata));
5501 #if defined(HAVE_POSIX_ACLS)
5502 case SMB_QUERY_POSIX_ACL:
5504 SMB_ACL_T file_acl = NULL;
5505 SMB_ACL_T def_acl = NULL;
5506 uint16_t num_file_acls = 0;
5507 uint16_t num_def_acls = 0;
5509 status = refuse_symlink(conn,
5512 if (!NT_STATUS_IS_OK(status)) {
5516 if (fsp && fsp->fh->fd != -1) {
5517 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5521 SMB_VFS_SYS_ACL_GET_FILE(conn,
5523 SMB_ACL_TYPE_ACCESS,
5527 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5528 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5529 "not implemented on "
5530 "filesystem containing %s\n",
5531 smb_fname->base_name));
5532 return NT_STATUS_NOT_IMPLEMENTED;
5535 if (S_ISDIR(psbuf->st_ex_mode)) {
5536 if (fsp && fsp->is_directory) {
5538 SMB_VFS_SYS_ACL_GET_FILE(
5541 SMB_ACL_TYPE_DEFAULT,
5545 SMB_VFS_SYS_ACL_GET_FILE(
5548 SMB_ACL_TYPE_DEFAULT,
5551 def_acl = free_empty_sys_acl(conn, def_acl);
5554 num_file_acls = count_acl_entries(conn, file_acl);
5555 num_def_acls = count_acl_entries(conn, def_acl);
5557 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5558 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5560 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5561 SMB_POSIX_ACL_HEADER_SIZE) ));
5563 TALLOC_FREE(file_acl);
5566 TALLOC_FREE(def_acl);
5568 return NT_STATUS_BUFFER_TOO_SMALL;
5571 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5572 SSVAL(pdata,2,num_file_acls);
5573 SSVAL(pdata,4,num_def_acls);
5574 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5576 TALLOC_FREE(file_acl);
5579 TALLOC_FREE(def_acl);
5581 return NT_STATUS_INTERNAL_ERROR;
5583 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5585 TALLOC_FREE(file_acl);
5588 TALLOC_FREE(def_acl);
5590 return NT_STATUS_INTERNAL_ERROR;
5594 TALLOC_FREE(file_acl);
5597 TALLOC_FREE(def_acl);
5599 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5605 case SMB_QUERY_POSIX_LOCK:
5610 enum brl_type lock_type;
5612 /* We need an open file with a real fd for this. */
5613 if (!fsp || fsp->fh->fd == -1) {
5614 return NT_STATUS_INVALID_LEVEL;
5617 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5618 return NT_STATUS_INVALID_PARAMETER;
5621 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5622 case POSIX_LOCK_TYPE_READ:
5623 lock_type = READ_LOCK;
5625 case POSIX_LOCK_TYPE_WRITE:
5626 lock_type = WRITE_LOCK;
5628 case POSIX_LOCK_TYPE_UNLOCK:
5630 /* There's no point in asking for an unlock... */
5631 return NT_STATUS_INVALID_PARAMETER;
5634 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5635 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5636 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5638 status = query_lock(fsp,
5645 if (ERROR_WAS_LOCK_DENIED(status)) {
5646 /* Here we need to report who has it locked... */
5647 data_size = POSIX_LOCK_DATA_SIZE;
5649 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5650 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5651 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5652 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5653 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5655 } else if (NT_STATUS_IS_OK(status)) {
5656 /* For success we just return a copy of what we sent
5657 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5658 data_size = POSIX_LOCK_DATA_SIZE;
5659 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5660 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5668 return NT_STATUS_INVALID_LEVEL;
5671 *pdata_size = data_size;
5672 return NT_STATUS_OK;
5675 /****************************************************************************
5676 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5677 file name or file id).
5678 ****************************************************************************/
5680 static void call_trans2qfilepathinfo(connection_struct *conn,
5681 struct smb_request *req,
5682 unsigned int tran_call,
5683 char **pparams, int total_params,
5684 char **ppdata, int total_data,
5685 unsigned int max_data_bytes)
5687 char *params = *pparams;
5688 char *pdata = *ppdata;
5689 uint16_t info_level;
5690 unsigned int data_size = 0;
5691 unsigned int param_size = 2;
5692 struct smb_filename *smb_fname = NULL;
5693 bool delete_pending = False;
5694 struct timespec write_time_ts;
5695 files_struct *fsp = NULL;
5696 struct file_id fileid;
5697 struct ea_list *ea_list = NULL;
5698 int lock_data_count = 0;
5699 char *lock_data = NULL;
5700 size_t fixed_portion;
5701 NTSTATUS status = NT_STATUS_OK;
5704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5708 ZERO_STRUCT(write_time_ts);
5710 if (tran_call == TRANSACT2_QFILEINFO) {
5711 if (total_params < 4) {
5712 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5717 call_trans2qpipeinfo(conn, req, tran_call,
5718 pparams, total_params,
5724 fsp = file_fsp(req, SVAL(params,0));
5725 info_level = SVAL(params,2);
5727 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5729 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5730 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5734 /* Initial check for valid fsp ptr. */
5735 if (!check_fsp_open(conn, req, fsp)) {
5739 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5740 if (smb_fname == NULL) {
5741 reply_nterror(req, NT_STATUS_NO_MEMORY);
5745 if(fsp->fake_file_handle) {
5747 * This is actually for the QUOTA_FAKE_FILE --metze
5750 /* We know this name is ok, it's already passed the checks. */
5752 } else if(fsp->fh->fd == -1) {
5754 * This is actually a QFILEINFO on a directory
5755 * handle (returned from an NT SMB). NT5.0 seems
5756 * to do this call. JRA.
5759 if (INFO_LEVEL_IS_UNIX(info_level)) {
5760 /* Always do lstat for UNIX calls. */
5761 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5762 DEBUG(3,("call_trans2qfilepathinfo: "
5763 "SMB_VFS_LSTAT of %s failed "
5765 smb_fname_str_dbg(smb_fname),
5768 map_nt_error_from_unix(errno));
5771 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5772 DEBUG(3,("call_trans2qfilepathinfo: "
5773 "SMB_VFS_STAT of %s failed (%s)\n",
5774 smb_fname_str_dbg(smb_fname),
5777 map_nt_error_from_unix(errno));
5781 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5782 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5785 * Original code - this is an open file.
5787 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5788 DEBUG(3, ("fstat of %s failed (%s)\n",
5789 fsp_fnum_dbg(fsp), strerror(errno)));
5791 map_nt_error_from_unix(errno));
5794 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5795 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5801 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5804 if (total_params < 7) {
5805 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5809 info_level = SVAL(params,0);
5811 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5813 if (INFO_LEVEL_IS_UNIX(info_level)) {
5814 if (!lp_unix_extensions()) {
5815 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5818 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5819 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5820 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5821 req->posix_pathnames) {
5822 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5826 if (req->posix_pathnames) {
5827 srvstr_get_path_posix(req,
5836 srvstr_get_path(req,
5845 if (!NT_STATUS_IS_OK(status)) {
5846 reply_nterror(req, status);
5850 status = filename_convert(req,
5856 if (!NT_STATUS_IS_OK(status)) {
5857 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5858 reply_botherror(req,
5859 NT_STATUS_PATH_NOT_COVERED,
5860 ERRSRV, ERRbadpath);
5863 reply_nterror(req, status);
5867 /* If this is a stream, check if there is a delete_pending. */
5868 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5869 && is_ntfs_stream_smb_fname(smb_fname)) {
5870 struct smb_filename *smb_fname_base;
5872 /* Create an smb_filename with stream_name == NULL. */
5873 smb_fname_base = synthetic_smb_fname(
5875 smb_fname->base_name,
5879 if (smb_fname_base == NULL) {
5880 reply_nterror(req, NT_STATUS_NO_MEMORY);
5884 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5885 /* Always do lstat for UNIX calls. */
5886 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5887 DEBUG(3,("call_trans2qfilepathinfo: "
5888 "SMB_VFS_LSTAT of %s failed "
5890 smb_fname_str_dbg(smb_fname_base),
5892 TALLOC_FREE(smb_fname_base);
5894 map_nt_error_from_unix(errno));
5898 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5899 DEBUG(3,("call_trans2qfilepathinfo: "
5900 "fileinfo of %s failed "
5902 smb_fname_str_dbg(smb_fname_base),
5904 TALLOC_FREE(smb_fname_base);
5906 map_nt_error_from_unix(errno));
5911 status = file_name_hash(conn,
5912 smb_fname_str_dbg(smb_fname_base),
5914 if (!NT_STATUS_IS_OK(status)) {
5915 TALLOC_FREE(smb_fname_base);
5916 reply_nterror(req, status);
5920 fileid = vfs_file_id_from_sbuf(conn,
5921 &smb_fname_base->st);
5922 TALLOC_FREE(smb_fname_base);
5923 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5924 if (delete_pending) {
5925 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5930 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5931 /* Always do lstat for UNIX calls. */
5932 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5933 DEBUG(3,("call_trans2qfilepathinfo: "
5934 "SMB_VFS_LSTAT of %s failed (%s)\n",
5935 smb_fname_str_dbg(smb_fname),
5938 map_nt_error_from_unix(errno));
5943 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5944 DEBUG(3,("call_trans2qfilepathinfo: "
5945 "SMB_VFS_STAT of %s failed (%s)\n",
5946 smb_fname_str_dbg(smb_fname),
5949 map_nt_error_from_unix(errno));
5954 status = file_name_hash(conn,
5955 smb_fname_str_dbg(smb_fname),
5957 if (!NT_STATUS_IS_OK(status)) {
5958 reply_nterror(req, status);
5962 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5963 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5964 if (delete_pending) {
5965 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5970 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5971 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5973 info_level,tran_call,total_data));
5975 /* Pull out any data sent here before we realloc. */
5976 switch (info_level) {
5977 case SMB_INFO_QUERY_EAS_FROM_LIST:
5979 /* Pull any EA list from the data portion. */
5982 if (total_data < 4) {
5984 req, NT_STATUS_INVALID_PARAMETER);
5987 ea_size = IVAL(pdata,0);
5989 if (total_data > 0 && ea_size != total_data) {
5990 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5991 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5993 req, NT_STATUS_INVALID_PARAMETER);
5997 if (!lp_ea_support(SNUM(conn))) {
5998 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6002 /* Pull out the list of names. */
6003 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6006 req, NT_STATUS_INVALID_PARAMETER);
6012 case SMB_QUERY_POSIX_LOCK:
6014 if (fsp == NULL || fsp->fh->fd == -1) {
6015 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6019 if (total_data != POSIX_LOCK_DATA_SIZE) {
6021 req, NT_STATUS_INVALID_PARAMETER);
6025 /* Copy the lock range data. */
6026 lock_data = (char *)talloc_memdup(
6027 req, pdata, total_data);
6029 reply_nterror(req, NT_STATUS_NO_MEMORY);
6032 lock_data_count = total_data;
6038 *pparams = (char *)SMB_REALLOC(*pparams,2);
6039 if (*pparams == NULL) {
6040 reply_nterror(req, NT_STATUS_NO_MEMORY);
6047 * draft-leach-cifs-v1-spec-02.txt
6048 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6051 * The requested information is placed in the Data portion of the
6052 * transaction response. For the information levels greater than 0x100,
6053 * the transaction response has 1 parameter word which should be
6054 * ignored by the client.
6056 * However Windows only follows this rule for the IS_NAME_VALID call.
6058 switch (info_level) {
6059 case SMB_INFO_IS_NAME_VALID:
6064 if ((info_level & 0xFF00) == 0xFF00) {
6066 * We use levels that start with 0xFF00
6067 * internally to represent SMB2 specific levels
6069 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6073 status = smbd_do_qfilepathinfo(conn, req, info_level,
6075 delete_pending, write_time_ts,
6077 lock_data_count, lock_data,
6078 req->flags2, max_data_bytes,
6080 ppdata, &data_size);
6081 if (!NT_STATUS_IS_OK(status)) {
6082 reply_nterror(req, status);
6085 if (fixed_portion > max_data_bytes) {
6086 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6090 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6096 /****************************************************************************
6097 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6099 ****************************************************************************/
6101 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6102 connection_struct *conn,
6103 struct smb_request *req,
6104 bool overwrite_if_exists,
6105 const struct smb_filename *smb_fname_old,
6106 struct smb_filename *smb_fname_new)
6108 NTSTATUS status = NT_STATUS_OK;
6110 /* source must already exist. */
6111 if (!VALID_STAT(smb_fname_old->st)) {
6112 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6115 if (VALID_STAT(smb_fname_new->st)) {
6116 if (overwrite_if_exists) {
6117 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6118 return NT_STATUS_FILE_IS_A_DIRECTORY;
6120 status = unlink_internals(conn,
6122 FILE_ATTRIBUTE_NORMAL,
6125 if (!NT_STATUS_IS_OK(status)) {
6129 /* Disallow if newname already exists. */
6130 return NT_STATUS_OBJECT_NAME_COLLISION;
6134 /* No links from a directory. */
6135 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6136 return NT_STATUS_FILE_IS_A_DIRECTORY;
6139 /* Setting a hardlink to/from a stream isn't currently supported. */
6140 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6141 is_ntfs_stream_smb_fname(smb_fname_new)) {
6142 return NT_STATUS_INVALID_PARAMETER;
6145 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6146 smb_fname_old->base_name, smb_fname_new->base_name));
6148 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
6149 smb_fname_new->base_name) != 0) {
6150 status = map_nt_error_from_unix(errno);
6151 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6152 nt_errstr(status), smb_fname_old->base_name,
6153 smb_fname_new->base_name));
6158 /****************************************************************************
6159 Deal with setting the time from any of the setfilepathinfo functions.
6160 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6161 calling this function.
6162 ****************************************************************************/
6164 NTSTATUS smb_set_file_time(connection_struct *conn,
6166 const struct smb_filename *smb_fname,
6167 struct smb_file_time *ft,
6168 bool setting_write_time)
6170 struct smb_filename smb_fname_base;
6172 FILE_NOTIFY_CHANGE_LAST_ACCESS
6173 |FILE_NOTIFY_CHANGE_LAST_WRITE
6174 |FILE_NOTIFY_CHANGE_CREATION;
6176 if (!VALID_STAT(smb_fname->st)) {
6177 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6180 /* get some defaults (no modifications) if any info is zero or -1. */
6181 if (null_timespec(ft->create_time)) {
6182 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6185 if (null_timespec(ft->atime)) {
6186 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6189 if (null_timespec(ft->mtime)) {
6190 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6193 if (!setting_write_time) {
6194 /* ft->mtime comes from change time, not write time. */
6195 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6198 /* Ensure the resolution is the correct for
6199 * what we can store on this filesystem. */
6201 round_timespec(conn->ts_res, &ft->create_time);
6202 round_timespec(conn->ts_res, &ft->ctime);
6203 round_timespec(conn->ts_res, &ft->atime);
6204 round_timespec(conn->ts_res, &ft->mtime);
6206 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6207 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6208 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6209 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6210 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6211 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6212 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6213 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6215 if (setting_write_time) {
6217 * This was a Windows setfileinfo on an open file.
6218 * NT does this a lot. We also need to
6219 * set the time here, as it can be read by
6220 * FindFirst/FindNext and with the patch for bug #2045
6221 * in smbd/fileio.c it ensures that this timestamp is
6222 * kept sticky even after a write. We save the request
6223 * away and will set it on file close and after a write. JRA.
6226 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6227 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6230 if (fsp->base_fsp) {
6231 set_sticky_write_time_fsp(fsp->base_fsp,
6234 set_sticky_write_time_fsp(fsp, ft->mtime);
6237 set_sticky_write_time_path(
6238 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6243 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6245 /* Always call ntimes on the base, even if a stream was passed in. */
6246 smb_fname_base = *smb_fname;
6247 smb_fname_base.stream_name = NULL;
6249 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6250 return map_nt_error_from_unix(errno);
6253 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6254 smb_fname->base_name);
6255 return NT_STATUS_OK;
6258 /****************************************************************************
6259 Deal with setting the dosmode from any of the setfilepathinfo functions.
6260 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6261 done before calling this function.
6262 ****************************************************************************/
6264 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6265 const struct smb_filename *smb_fname,
6268 struct smb_filename *smb_fname_base;
6271 if (!VALID_STAT(smb_fname->st)) {
6272 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6275 /* Always operate on the base_name, even if a stream was passed in. */
6276 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6277 smb_fname->base_name,
6281 if (smb_fname_base == NULL) {
6282 return NT_STATUS_NO_MEMORY;
6286 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6287 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6289 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6293 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6295 /* check the mode isn't different, before changing it */
6296 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6297 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6298 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6299 (unsigned int)dosmode));
6301 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6303 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6305 smb_fname_str_dbg(smb_fname_base),
6307 status = map_nt_error_from_unix(errno);
6311 status = NT_STATUS_OK;
6313 TALLOC_FREE(smb_fname_base);
6317 /****************************************************************************
6318 Deal with setting the size from any of the setfilepathinfo functions.
6319 ****************************************************************************/
6321 static NTSTATUS smb_set_file_size(connection_struct *conn,
6322 struct smb_request *req,
6324 const struct smb_filename *smb_fname,
6325 const SMB_STRUCT_STAT *psbuf,
6327 bool fail_after_createfile)
6329 NTSTATUS status = NT_STATUS_OK;
6330 struct smb_filename *smb_fname_tmp = NULL;
6331 files_struct *new_fsp = NULL;
6333 if (!VALID_STAT(*psbuf)) {
6334 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6337 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6339 if (size == get_file_size_stat(psbuf)) {
6340 return NT_STATUS_OK;
6343 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6344 smb_fname_str_dbg(smb_fname), (double)size));
6346 if (fsp && fsp->fh->fd != -1) {
6347 /* Handle based call. */
6348 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6349 return NT_STATUS_ACCESS_DENIED;
6352 if (vfs_set_filelen(fsp, size) == -1) {
6353 return map_nt_error_from_unix(errno);
6355 trigger_write_time_update_immediate(fsp);
6356 return NT_STATUS_OK;
6359 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6360 if (smb_fname_tmp == NULL) {
6361 return NT_STATUS_NO_MEMORY;
6364 smb_fname_tmp->st = *psbuf;
6366 status = SMB_VFS_CREATE_FILE(
6369 0, /* root_dir_fid */
6370 smb_fname_tmp, /* fname */
6371 FILE_WRITE_DATA, /* access_mask */
6372 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6374 FILE_OPEN, /* create_disposition*/
6375 0, /* create_options */
6376 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6377 0, /* oplock_request */
6379 0, /* allocation_size */
6380 0, /* private_flags */
6383 &new_fsp, /* result */
6385 NULL, NULL); /* create context */
6387 TALLOC_FREE(smb_fname_tmp);
6389 if (!NT_STATUS_IS_OK(status)) {
6390 /* NB. We check for open_was_deferred in the caller. */
6394 /* See RAW-SFILEINFO-END-OF-FILE */
6395 if (fail_after_createfile) {
6396 close_file(req, new_fsp,NORMAL_CLOSE);
6397 return NT_STATUS_INVALID_LEVEL;
6400 if (vfs_set_filelen(new_fsp, size) == -1) {
6401 status = map_nt_error_from_unix(errno);
6402 close_file(req, new_fsp,NORMAL_CLOSE);
6406 trigger_write_time_update_immediate(new_fsp);
6407 close_file(req, new_fsp,NORMAL_CLOSE);
6408 return NT_STATUS_OK;
6411 /****************************************************************************
6412 Deal with SMB_INFO_SET_EA.
6413 ****************************************************************************/
6415 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6419 const struct smb_filename *smb_fname)
6421 struct ea_list *ea_list = NULL;
6422 TALLOC_CTX *ctx = NULL;
6423 NTSTATUS status = NT_STATUS_OK;
6425 if (total_data < 10) {
6427 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6428 length. They seem to have no effect. Bug #3212. JRA */
6430 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6431 /* We're done. We only get EA info in this call. */
6432 return NT_STATUS_OK;
6435 return NT_STATUS_INVALID_PARAMETER;
6438 if (IVAL(pdata,0) > total_data) {
6439 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6440 IVAL(pdata,0), (unsigned int)total_data));
6441 return NT_STATUS_INVALID_PARAMETER;
6445 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6447 return NT_STATUS_INVALID_PARAMETER;
6450 status = set_ea(conn, fsp, smb_fname, ea_list);
6455 /****************************************************************************
6456 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6457 ****************************************************************************/
6459 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6464 struct ea_list *ea_list = NULL;
6468 return NT_STATUS_INVALID_HANDLE;
6471 if (!lp_ea_support(SNUM(conn))) {
6472 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6473 "EA's not supported.\n",
6474 (unsigned int)total_data));
6475 return NT_STATUS_EAS_NOT_SUPPORTED;
6478 if (total_data < 10) {
6479 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6481 (unsigned int)total_data));
6482 return NT_STATUS_INVALID_PARAMETER;
6485 ea_list = read_nttrans_ea_list(talloc_tos(),
6490 return NT_STATUS_INVALID_PARAMETER;
6493 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6495 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6496 smb_fname_str_dbg(fsp->fsp_name),
6497 nt_errstr(status) ));
6503 /****************************************************************************
6504 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6505 ****************************************************************************/
6507 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6511 struct smb_filename *smb_fname)
6513 NTSTATUS status = NT_STATUS_OK;
6514 bool delete_on_close;
6515 uint32_t dosmode = 0;
6517 if (total_data < 1) {
6518 return NT_STATUS_INVALID_PARAMETER;
6522 return NT_STATUS_INVALID_HANDLE;
6525 delete_on_close = (CVAL(pdata,0) ? True : False);
6526 dosmode = dos_mode(conn, smb_fname);
6528 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6529 "delete_on_close = %u\n",
6530 smb_fname_str_dbg(smb_fname),
6531 (unsigned int)dosmode,
6532 (unsigned int)delete_on_close ));
6534 if (delete_on_close) {
6535 status = can_set_delete_on_close(fsp, dosmode);
6536 if (!NT_STATUS_IS_OK(status)) {
6541 /* The set is across all open files on this dev/inode pair. */
6542 if (!set_delete_on_close(fsp, delete_on_close,
6543 conn->session_info->security_token,
6544 conn->session_info->unix_token)) {
6545 return NT_STATUS_ACCESS_DENIED;
6547 return NT_STATUS_OK;
6550 /****************************************************************************
6551 Deal with SMB_FILE_POSITION_INFORMATION.
6552 ****************************************************************************/
6554 static NTSTATUS smb_file_position_information(connection_struct *conn,
6559 uint64_t position_information;
6561 if (total_data < 8) {
6562 return NT_STATUS_INVALID_PARAMETER;
6566 /* Ignore on pathname based set. */
6567 return NT_STATUS_OK;
6570 position_information = (uint64_t)IVAL(pdata,0);
6571 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6573 DEBUG(10,("smb_file_position_information: Set file position "
6574 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6575 (double)position_information));
6576 fsp->fh->position_information = position_information;
6577 return NT_STATUS_OK;
6580 /****************************************************************************
6581 Deal with SMB_FILE_MODE_INFORMATION.
6582 ****************************************************************************/
6584 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6590 if (total_data < 4) {
6591 return NT_STATUS_INVALID_PARAMETER;
6593 mode = IVAL(pdata,0);
6594 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6595 return NT_STATUS_INVALID_PARAMETER;
6597 return NT_STATUS_OK;
6600 /****************************************************************************
6601 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6602 ****************************************************************************/
6604 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6605 struct smb_request *req,
6608 const struct smb_filename *smb_fname)
6610 char *link_target = NULL;
6611 const char *newname = smb_fname->base_name;
6612 TALLOC_CTX *ctx = talloc_tos();
6614 /* Set a symbolic link. */
6615 /* Don't allow this if follow links is false. */
6617 if (total_data == 0) {
6618 return NT_STATUS_INVALID_PARAMETER;
6621 if (!lp_follow_symlinks(SNUM(conn))) {
6622 return NT_STATUS_ACCESS_DENIED;
6625 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6626 total_data, STR_TERMINATE);
6629 return NT_STATUS_INVALID_PARAMETER;
6632 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6633 newname, link_target ));
6635 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6636 return map_nt_error_from_unix(errno);
6639 return NT_STATUS_OK;
6642 /****************************************************************************
6643 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6644 ****************************************************************************/
6646 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6647 struct smb_request *req,
6648 const char *pdata, int total_data,
6649 struct smb_filename *smb_fname_new)
6651 char *oldname = NULL;
6652 struct smb_filename *smb_fname_old = NULL;
6653 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6654 TALLOC_CTX *ctx = talloc_tos();
6655 NTSTATUS status = NT_STATUS_OK;
6657 /* Set a hard link. */
6658 if (total_data == 0) {
6659 return NT_STATUS_INVALID_PARAMETER;
6662 if (req->posix_pathnames) {
6663 srvstr_get_path_posix(ctx,
6672 srvstr_get_path(ctx,
6681 if (!NT_STATUS_IS_OK(status)) {
6685 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6686 smb_fname_str_dbg(smb_fname_new), oldname));
6688 status = filename_convert(ctx,
6694 if (!NT_STATUS_IS_OK(status)) {
6698 return hardlink_internals(ctx, conn, req, false,
6699 smb_fname_old, smb_fname_new);
6702 /****************************************************************************
6703 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6704 ****************************************************************************/
6706 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6707 struct smb_request *req,
6711 struct smb_filename *smb_fname_src)
6715 char *newname = NULL;
6716 struct smb_filename *smb_fname_dst = NULL;
6717 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6718 ucf_flags_from_smb_request(req);
6719 NTSTATUS status = NT_STATUS_OK;
6720 TALLOC_CTX *ctx = talloc_tos();
6723 return NT_STATUS_INVALID_HANDLE;
6726 if (total_data < 20) {
6727 return NT_STATUS_INVALID_PARAMETER;
6730 overwrite = (CVAL(pdata,0) ? True : False);
6731 len = IVAL(pdata,16);
6733 if (len > (total_data - 20) || (len == 0)) {
6734 return NT_STATUS_INVALID_PARAMETER;
6737 if (req->posix_pathnames) {
6738 srvstr_get_path_posix(ctx,
6747 srvstr_get_path(ctx,
6756 if (!NT_STATUS_IS_OK(status)) {
6760 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6763 status = filename_convert(ctx,
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 ucf_flags_from_smb_request(req);
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,
6879 if (!NT_STATUS_IS_OK(status)) {
6883 if (fsp->base_fsp) {
6884 /* No stream names. */
6885 return NT_STATUS_NOT_SUPPORTED;
6888 DEBUG(10,("smb_file_link_information: "
6889 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6890 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6891 smb_fname_str_dbg(smb_fname_dst)));
6892 status = hardlink_internals(ctx,
6899 TALLOC_FREE(smb_fname_dst);
6903 /****************************************************************************
6904 Deal with SMB_FILE_RENAME_INFORMATION.
6905 ****************************************************************************/
6907 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6908 struct smb_request *req,
6912 struct smb_filename *smb_fname_src)
6917 char *newname = NULL;
6918 struct smb_filename *smb_fname_dst = NULL;
6919 bool dest_has_wcard = False;
6920 NTSTATUS status = NT_STATUS_OK;
6922 TALLOC_CTX *ctx = talloc_tos();
6924 if (total_data < 13) {
6925 return NT_STATUS_INVALID_PARAMETER;
6928 overwrite = (CVAL(pdata,0) ? True : False);
6929 root_fid = IVAL(pdata,4);
6930 len = IVAL(pdata,8);
6932 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6933 return NT_STATUS_INVALID_PARAMETER;
6936 if (req->posix_pathnames) {
6937 srvstr_get_path_wcard_posix(ctx,
6947 srvstr_get_path_wcard(ctx,
6957 if (!NT_STATUS_IS_OK(status)) {
6961 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6964 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
6965 status = resolve_dfspath_wcard(ctx, conn,
6967 UCF_COND_ALLOW_WCARD_LCOMP,
6968 !conn->sconn->using_smb2,
6971 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;
7016 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7017 ucf_flags_from_smb_request(req);
7019 if (dest_has_wcard) {
7020 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7023 /* newname must *not* be a stream name. */
7024 if (newname[0] == ':') {
7025 return NT_STATUS_NOT_SUPPORTED;
7029 * Strip off the last component (filename) of the path passed
7032 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7034 return NT_STATUS_NO_MEMORY;
7036 p = strrchr_m(base_name, '/');
7040 base_name = talloc_strdup(ctx, "");
7042 return NT_STATUS_NO_MEMORY;
7045 /* Append the new name. */
7046 base_name = talloc_asprintf_append(base_name,
7050 return NT_STATUS_NO_MEMORY;
7053 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7056 /* If an error we expect this to be
7057 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7059 if (!NT_STATUS_IS_OK(status)) {
7060 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7064 /* Create an smb_fname to call rename_internals_fsp() */
7065 smb_fname_dst = synthetic_smb_fname(ctx,
7069 smb_fname_src->flags);
7070 if (smb_fname_dst == NULL) {
7071 status = NT_STATUS_NO_MEMORY;
7078 DEBUG(10,("smb_file_rename_information: "
7079 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7080 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7081 smb_fname_str_dbg(smb_fname_dst)));
7082 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7085 DEBUG(10,("smb_file_rename_information: "
7086 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7087 smb_fname_str_dbg(smb_fname_src),
7088 smb_fname_str_dbg(smb_fname_dst)));
7089 status = rename_internals(ctx, conn, req, smb_fname_src,
7090 smb_fname_dst, 0, overwrite, false,
7092 FILE_WRITE_ATTRIBUTES);
7095 TALLOC_FREE(smb_fname_dst);
7099 /****************************************************************************
7100 Deal with SMB_SET_POSIX_ACL.
7101 ****************************************************************************/
7103 #if defined(HAVE_POSIX_ACLS)
7104 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7108 const struct smb_filename *smb_fname)
7110 uint16_t posix_acl_version;
7111 uint16_t num_file_acls;
7112 uint16_t num_def_acls;
7113 bool valid_file_acls = True;
7114 bool valid_def_acls = True;
7117 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7118 return NT_STATUS_INVALID_PARAMETER;
7120 posix_acl_version = SVAL(pdata,0);
7121 num_file_acls = SVAL(pdata,2);
7122 num_def_acls = SVAL(pdata,4);
7124 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7125 valid_file_acls = False;
7129 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7130 valid_def_acls = False;
7134 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7135 return NT_STATUS_INVALID_PARAMETER;
7138 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7139 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7140 return NT_STATUS_INVALID_PARAMETER;
7143 status = refuse_symlink(conn, fsp, smb_fname);
7144 if (!NT_STATUS_IS_OK(status)) {
7148 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7149 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7150 (unsigned int)num_file_acls,
7151 (unsigned int)num_def_acls));
7153 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7154 smb_fname, num_file_acls,
7155 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7156 return map_nt_error_from_unix(errno);
7159 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7160 smb_fname, num_def_acls,
7161 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7162 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7163 return map_nt_error_from_unix(errno);
7165 return NT_STATUS_OK;
7169 /****************************************************************************
7170 Deal with SMB_SET_POSIX_LOCK.
7171 ****************************************************************************/
7173 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7174 struct smb_request *req,
7182 bool blocking_lock = False;
7183 enum brl_type lock_type;
7185 NTSTATUS status = NT_STATUS_OK;
7187 if (fsp == NULL || fsp->fh->fd == -1) {
7188 return NT_STATUS_INVALID_HANDLE;
7191 if (total_data != POSIX_LOCK_DATA_SIZE) {
7192 return NT_STATUS_INVALID_PARAMETER;
7195 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7196 case POSIX_LOCK_TYPE_READ:
7197 lock_type = READ_LOCK;
7199 case POSIX_LOCK_TYPE_WRITE:
7200 /* Return the right POSIX-mappable error code for files opened read-only. */
7201 if (!fsp->can_write) {
7202 return NT_STATUS_INVALID_HANDLE;
7204 lock_type = WRITE_LOCK;
7206 case POSIX_LOCK_TYPE_UNLOCK:
7207 lock_type = UNLOCK_LOCK;
7210 return NT_STATUS_INVALID_PARAMETER;
7213 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7214 blocking_lock = False;
7215 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7216 blocking_lock = True;
7218 return NT_STATUS_INVALID_PARAMETER;
7221 if (!lp_blocking_locks(SNUM(conn))) {
7222 blocking_lock = False;
7225 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7226 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7227 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7228 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7229 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7231 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7232 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7234 (unsigned int)lock_type,
7235 (unsigned long long)smblctx,
7239 if (lock_type == UNLOCK_LOCK) {
7240 status = do_unlock(req->sconn->msg_ctx,
7247 uint64_t block_smblctx;
7249 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7260 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7262 * A blocking lock was requested. Package up
7263 * this smb into a queued request and push it
7264 * onto the blocking lock queue.
7266 if(push_blocking_lock_request(br_lck,
7269 -1, /* infinite timeout. */
7277 TALLOC_FREE(br_lck);
7281 TALLOC_FREE(br_lck);
7287 /****************************************************************************
7288 Deal with SMB_SET_FILE_BASIC_INFO.
7289 ****************************************************************************/
7291 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7295 const struct smb_filename *smb_fname)
7297 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7298 struct smb_file_time ft;
7299 uint32_t dosmode = 0;
7300 NTSTATUS status = NT_STATUS_OK;
7304 if (total_data < 36) {
7305 return NT_STATUS_INVALID_PARAMETER;
7308 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7309 if (!NT_STATUS_IS_OK(status)) {
7313 /* Set the attributes */
7314 dosmode = IVAL(pdata,32);
7315 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7316 if (!NT_STATUS_IS_OK(status)) {
7321 ft.create_time = interpret_long_date(pdata);
7324 ft.atime = interpret_long_date(pdata+8);
7327 ft.mtime = interpret_long_date(pdata+16);
7330 ft.ctime = interpret_long_date(pdata+24);
7332 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7333 smb_fname_str_dbg(smb_fname)));
7335 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7339 /****************************************************************************
7340 Deal with SMB_INFO_STANDARD.
7341 ****************************************************************************/
7343 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7347 const struct smb_filename *smb_fname)
7350 struct smb_file_time ft;
7354 if (total_data < 12) {
7355 return NT_STATUS_INVALID_PARAMETER;
7359 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7361 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7363 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7365 DEBUG(10,("smb_set_info_standard: file %s\n",
7366 smb_fname_str_dbg(smb_fname)));
7368 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7369 if (!NT_STATUS_IS_OK(status)) {
7373 return smb_set_file_time(conn,
7380 /****************************************************************************
7381 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7382 ****************************************************************************/
7384 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7385 struct smb_request *req,
7389 struct smb_filename *smb_fname)
7391 uint64_t allocation_size = 0;
7392 NTSTATUS status = NT_STATUS_OK;
7393 files_struct *new_fsp = NULL;
7395 if (!VALID_STAT(smb_fname->st)) {
7396 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7399 if (total_data < 8) {
7400 return NT_STATUS_INVALID_PARAMETER;
7403 allocation_size = (uint64_t)IVAL(pdata,0);
7404 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7405 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7406 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7407 (double)allocation_size));
7409 if (allocation_size) {
7410 allocation_size = smb_roundup(conn, allocation_size);
7413 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7414 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7415 (double)allocation_size));
7417 if (fsp && fsp->fh->fd != -1) {
7418 /* Open file handle. */
7419 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7420 return NT_STATUS_ACCESS_DENIED;
7423 /* Only change if needed. */
7424 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7425 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7426 return map_nt_error_from_unix(errno);
7429 /* But always update the time. */
7431 * This is equivalent to a write. Ensure it's seen immediately
7432 * if there are no pending writes.
7434 trigger_write_time_update_immediate(fsp);
7435 return NT_STATUS_OK;
7438 /* Pathname or stat or directory file. */
7439 status = SMB_VFS_CREATE_FILE(
7442 0, /* root_dir_fid */
7443 smb_fname, /* fname */
7444 FILE_WRITE_DATA, /* access_mask */
7445 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7447 FILE_OPEN, /* create_disposition*/
7448 0, /* create_options */
7449 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7450 0, /* oplock_request */
7452 0, /* allocation_size */
7453 0, /* private_flags */
7456 &new_fsp, /* result */
7458 NULL, NULL); /* create context */
7460 if (!NT_STATUS_IS_OK(status)) {
7461 /* NB. We check for open_was_deferred in the caller. */
7465 /* Only change if needed. */
7466 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7467 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7468 status = map_nt_error_from_unix(errno);
7469 close_file(req, new_fsp, NORMAL_CLOSE);
7474 /* Changing the allocation size should set the last mod time. */
7476 * This is equivalent to a write. Ensure it's seen immediately
7477 * if there are no pending writes.
7479 trigger_write_time_update_immediate(new_fsp);
7480 close_file(req, new_fsp, NORMAL_CLOSE);
7481 return NT_STATUS_OK;
7484 /****************************************************************************
7485 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7486 ****************************************************************************/
7488 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7489 struct smb_request *req,
7493 const struct smb_filename *smb_fname,
7494 bool fail_after_createfile)
7498 if (total_data < 8) {
7499 return NT_STATUS_INVALID_PARAMETER;
7502 size = IVAL(pdata,0);
7503 size |= (((off_t)IVAL(pdata,4)) << 32);
7504 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7505 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7508 return smb_set_file_size(conn, req,
7513 fail_after_createfile);
7516 /****************************************************************************
7517 Allow a UNIX info mknod.
7518 ****************************************************************************/
7520 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7523 const struct smb_filename *smb_fname)
7525 uint32_t file_type = IVAL(pdata,56);
7526 #if defined(HAVE_MAKEDEV)
7527 uint32_t dev_major = IVAL(pdata,60);
7528 uint32_t dev_minor = IVAL(pdata,68);
7530 SMB_DEV_T dev = (SMB_DEV_T)0;
7531 uint32_t raw_unixmode = IVAL(pdata,84);
7535 if (total_data < 100) {
7536 return NT_STATUS_INVALID_PARAMETER;
7539 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7540 PERM_NEW_FILE, &unixmode);
7541 if (!NT_STATUS_IS_OK(status)) {
7545 #if defined(HAVE_MAKEDEV)
7546 dev = makedev(dev_major, dev_minor);
7549 switch (file_type) {
7550 #if defined(S_IFIFO)
7551 case UNIX_TYPE_FIFO:
7552 unixmode |= S_IFIFO;
7555 #if defined(S_IFSOCK)
7556 case UNIX_TYPE_SOCKET:
7557 unixmode |= S_IFSOCK;
7560 #if defined(S_IFCHR)
7561 case UNIX_TYPE_CHARDEV:
7562 unixmode |= S_IFCHR;
7565 #if defined(S_IFBLK)
7566 case UNIX_TYPE_BLKDEV:
7567 unixmode |= S_IFBLK;
7571 return NT_STATUS_INVALID_PARAMETER;
7574 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7575 "%.0f mode 0%o for file %s\n", (double)dev,
7576 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7578 /* Ok - do the mknod. */
7579 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7580 return map_nt_error_from_unix(errno);
7583 /* If any of the other "set" calls fail we
7584 * don't want to end up with a half-constructed mknod.
7587 if (lp_inherit_permissions(SNUM(conn))) {
7589 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7591 return NT_STATUS_NO_MEMORY;
7593 inherit_access_posix_acl(conn, parent, smb_fname,
7595 TALLOC_FREE(parent);
7598 return NT_STATUS_OK;
7601 /****************************************************************************
7602 Deal with SMB_SET_FILE_UNIX_BASIC.
7603 ****************************************************************************/
7605 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7606 struct smb_request *req,
7610 const struct smb_filename *smb_fname)
7612 struct smb_file_time ft;
7613 uint32_t raw_unixmode;
7616 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7617 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7618 NTSTATUS status = NT_STATUS_OK;
7619 bool delete_on_fail = False;
7620 enum perm_type ptype;
7621 files_struct *all_fsps = NULL;
7622 bool modify_mtime = true;
7624 struct smb_filename *smb_fname_tmp = NULL;
7625 SMB_STRUCT_STAT sbuf;
7629 if (total_data < 100) {
7630 return NT_STATUS_INVALID_PARAMETER;
7633 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7634 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7635 size=IVAL(pdata,0); /* first 8 Bytes are size */
7636 size |= (((off_t)IVAL(pdata,4)) << 32);
7639 ft.atime = interpret_long_date(pdata+24); /* access_time */
7640 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7641 set_owner = (uid_t)IVAL(pdata,40);
7642 set_grp = (gid_t)IVAL(pdata,48);
7643 raw_unixmode = IVAL(pdata,84);
7645 if (VALID_STAT(smb_fname->st)) {
7646 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7647 ptype = PERM_EXISTING_DIR;
7649 ptype = PERM_EXISTING_FILE;
7652 ptype = PERM_NEW_FILE;
7655 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7657 if (!NT_STATUS_IS_OK(status)) {
7661 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7662 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7663 smb_fname_str_dbg(smb_fname), (double)size,
7664 (unsigned int)set_owner, (unsigned int)set_grp,
7665 (int)raw_unixmode));
7667 sbuf = smb_fname->st;
7669 if (!VALID_STAT(sbuf)) {
7671 * The only valid use of this is to create character and block
7672 * devices, and named pipes. This is deprecated (IMHO) and
7673 * a new info level should be used for mknod. JRA.
7676 status = smb_unix_mknod(conn,
7680 if (!NT_STATUS_IS_OK(status)) {
7684 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7685 if (smb_fname_tmp == NULL) {
7686 return NT_STATUS_NO_MEMORY;
7689 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7690 status = map_nt_error_from_unix(errno);
7691 TALLOC_FREE(smb_fname_tmp);
7692 SMB_VFS_UNLINK(conn, smb_fname);
7696 sbuf = smb_fname_tmp->st;
7697 smb_fname = smb_fname_tmp;
7699 /* Ensure we don't try and change anything else. */
7700 raw_unixmode = SMB_MODE_NO_CHANGE;
7701 size = get_file_size_stat(&sbuf);
7702 ft.atime = sbuf.st_ex_atime;
7703 ft.mtime = sbuf.st_ex_mtime;
7705 * We continue here as we might want to change the
7708 delete_on_fail = True;
7712 /* Horrible backwards compatibility hack as an old server bug
7713 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7717 size = get_file_size_stat(&sbuf);
7722 * Deal with the UNIX specific mode set.
7725 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7728 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7729 "setting mode 0%o for file %s\n",
7730 (unsigned int)unixmode,
7731 smb_fname_str_dbg(smb_fname)));
7732 if (fsp && fsp->fh->fd != -1) {
7733 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7735 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7738 return map_nt_error_from_unix(errno);
7743 * Deal with the UNIX specific uid set.
7746 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7747 (sbuf.st_ex_uid != set_owner)) {
7750 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7751 "changing owner %u for path %s\n",
7752 (unsigned int)set_owner,
7753 smb_fname_str_dbg(smb_fname)));
7755 if (fsp && fsp->fh->fd != -1) {
7756 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7759 * UNIX extensions calls must always operate
7762 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7763 set_owner, (gid_t)-1);
7767 status = map_nt_error_from_unix(errno);
7768 if (delete_on_fail) {
7769 SMB_VFS_UNLINK(conn, smb_fname);
7776 * Deal with the UNIX specific gid set.
7779 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7780 (sbuf.st_ex_gid != set_grp)) {
7783 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7784 "changing group %u for file %s\n",
7785 (unsigned int)set_owner,
7786 smb_fname_str_dbg(smb_fname)));
7787 if (fsp && fsp->fh->fd != -1) {
7788 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7791 * UNIX extensions calls must always operate
7794 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7798 status = map_nt_error_from_unix(errno);
7799 if (delete_on_fail) {
7800 SMB_VFS_UNLINK(conn, smb_fname);
7806 /* Deal with any size changes. */
7808 status = smb_set_file_size(conn, req,
7814 if (!NT_STATUS_IS_OK(status)) {
7818 /* Deal with any time changes. */
7819 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7820 /* No change, don't cancel anything. */
7824 id = vfs_file_id_from_sbuf(conn, &sbuf);
7825 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7826 all_fsps = file_find_di_next(all_fsps)) {
7828 * We're setting the time explicitly for UNIX.
7829 * Cancel any pending changes over all handles.
7831 all_fsps->update_write_time_on_close = false;
7832 TALLOC_FREE(all_fsps->update_write_time_event);
7836 * Override the "setting_write_time"
7837 * parameter here as it almost does what
7838 * we need. Just remember if we modified
7839 * mtime and send the notify ourselves.
7841 if (null_timespec(ft.mtime)) {
7842 modify_mtime = false;
7845 status = smb_set_file_time(conn,
7851 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7852 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7857 /****************************************************************************
7858 Deal with SMB_SET_FILE_UNIX_INFO2.
7859 ****************************************************************************/
7861 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7862 struct smb_request *req,
7866 const struct smb_filename *smb_fname)
7869 uint32_t smb_fflags;
7872 if (total_data < 116) {
7873 return NT_STATUS_INVALID_PARAMETER;
7876 /* Start by setting all the fields that are common between UNIX_BASIC
7879 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7881 if (!NT_STATUS_IS_OK(status)) {
7885 smb_fflags = IVAL(pdata, 108);
7886 smb_fmask = IVAL(pdata, 112);
7888 /* NB: We should only attempt to alter the file flags if the client
7889 * sends a non-zero mask.
7891 if (smb_fmask != 0) {
7892 int stat_fflags = 0;
7894 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7895 smb_fmask, &stat_fflags)) {
7896 /* Client asked to alter a flag we don't understand. */
7897 return NT_STATUS_INVALID_PARAMETER;
7900 if (fsp && fsp->fh->fd != -1) {
7901 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7902 return NT_STATUS_NOT_SUPPORTED;
7904 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7905 stat_fflags) != 0) {
7906 return map_nt_error_from_unix(errno);
7911 /* XXX: need to add support for changing the create_time here. You
7912 * can do this for paths on Darwin with setattrlist(2). The right way
7913 * to hook this up is probably by extending the VFS utimes interface.
7916 return NT_STATUS_OK;
7919 /****************************************************************************
7920 Create a directory with POSIX semantics.
7921 ****************************************************************************/
7923 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7924 struct smb_request *req,
7927 struct smb_filename *smb_fname,
7928 int *pdata_return_size)
7930 NTSTATUS status = NT_STATUS_OK;
7931 uint32_t raw_unixmode = 0;
7932 uint32_t mod_unixmode = 0;
7933 mode_t unixmode = (mode_t)0;
7934 files_struct *fsp = NULL;
7935 uint16_t info_level_return = 0;
7937 char *pdata = *ppdata;
7939 if (total_data < 18) {
7940 return NT_STATUS_INVALID_PARAMETER;
7943 raw_unixmode = IVAL(pdata,8);
7944 /* Next 4 bytes are not yet defined. */
7946 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7947 PERM_NEW_DIR, &unixmode);
7948 if (!NT_STATUS_IS_OK(status)) {
7952 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7954 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7955 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7957 status = SMB_VFS_CREATE_FILE(
7960 0, /* root_dir_fid */
7961 smb_fname, /* fname */
7962 FILE_READ_ATTRIBUTES, /* access_mask */
7963 FILE_SHARE_NONE, /* share_access */
7964 FILE_CREATE, /* create_disposition*/
7965 FILE_DIRECTORY_FILE, /* create_options */
7966 mod_unixmode, /* file_attributes */
7967 0, /* oplock_request */
7969 0, /* allocation_size */
7970 0, /* private_flags */
7975 NULL, NULL); /* create context */
7977 if (NT_STATUS_IS_OK(status)) {
7978 close_file(req, fsp, NORMAL_CLOSE);
7981 info_level_return = SVAL(pdata,16);
7983 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7984 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7985 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7986 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7988 *pdata_return_size = 12;
7991 /* Realloc the data size */
7992 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7993 if (*ppdata == NULL) {
7994 *pdata_return_size = 0;
7995 return NT_STATUS_NO_MEMORY;
7999 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8000 SSVAL(pdata,2,0); /* No fnum. */
8001 SIVAL(pdata,4,info); /* Was directory created. */
8003 switch (info_level_return) {
8004 case SMB_QUERY_FILE_UNIX_BASIC:
8005 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8006 SSVAL(pdata,10,0); /* Padding. */
8007 store_file_unix_basic(conn, pdata + 12, fsp,
8010 case SMB_QUERY_FILE_UNIX_INFO2:
8011 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8012 SSVAL(pdata,10,0); /* Padding. */
8013 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8017 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8018 SSVAL(pdata,10,0); /* Padding. */
8025 /****************************************************************************
8026 Open/Create a file with POSIX semantics.
8027 ****************************************************************************/
8029 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8030 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8032 static NTSTATUS smb_posix_open(connection_struct *conn,
8033 struct smb_request *req,
8036 struct smb_filename *smb_fname,
8037 int *pdata_return_size)
8039 bool extended_oplock_granted = False;
8040 char *pdata = *ppdata;
8042 uint32_t wire_open_mode = 0;
8043 uint32_t raw_unixmode = 0;
8044 uint32_t mod_unixmode = 0;
8045 uint32_t create_disp = 0;
8046 uint32_t access_mask = 0;
8047 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8048 NTSTATUS status = NT_STATUS_OK;
8049 mode_t unixmode = (mode_t)0;
8050 files_struct *fsp = NULL;
8051 int oplock_request = 0;
8053 uint16_t info_level_return = 0;
8055 if (total_data < 18) {
8056 return NT_STATUS_INVALID_PARAMETER;
8059 flags = IVAL(pdata,0);
8060 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8061 if (oplock_request) {
8062 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8065 wire_open_mode = IVAL(pdata,4);
8067 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8068 return smb_posix_mkdir(conn, req,
8075 switch (wire_open_mode & SMB_ACCMODE) {
8077 access_mask = SMB_O_RDONLY_MAPPING;
8080 access_mask = SMB_O_WRONLY_MAPPING;
8083 access_mask = (SMB_O_RDONLY_MAPPING|
8084 SMB_O_WRONLY_MAPPING);
8087 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8088 (unsigned int)wire_open_mode ));
8089 return NT_STATUS_INVALID_PARAMETER;
8092 wire_open_mode &= ~SMB_ACCMODE;
8094 /* First take care of O_CREAT|O_EXCL interactions. */
8095 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8096 case (SMB_O_CREAT | SMB_O_EXCL):
8097 /* File exists fail. File not exist create. */
8098 create_disp = FILE_CREATE;
8101 /* File exists open. File not exist create. */
8102 create_disp = FILE_OPEN_IF;
8105 /* O_EXCL on its own without O_CREAT is undefined.
8106 We deliberately ignore it as some versions of
8107 Linux CIFSFS can send a bare O_EXCL on the
8108 wire which other filesystems in the kernel
8109 ignore. See bug 9519 for details. */
8114 /* File exists open. File not exist fail. */
8115 create_disp = FILE_OPEN;
8118 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8119 (unsigned int)wire_open_mode ));
8120 return NT_STATUS_INVALID_PARAMETER;
8123 /* Next factor in the effects of O_TRUNC. */
8124 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8126 if (wire_open_mode & SMB_O_TRUNC) {
8127 switch (create_disp) {
8129 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8130 /* Leave create_disp alone as
8131 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8133 /* File exists fail. File not exist create. */
8136 /* SMB_O_CREAT | SMB_O_TRUNC */
8137 /* File exists overwrite. File not exist create. */
8138 create_disp = FILE_OVERWRITE_IF;
8142 /* File exists overwrite. File not exist fail. */
8143 create_disp = FILE_OVERWRITE;
8146 /* Cannot get here. */
8147 smb_panic("smb_posix_open: logic error");
8148 return NT_STATUS_INVALID_PARAMETER;
8152 raw_unixmode = IVAL(pdata,8);
8153 /* Next 4 bytes are not yet defined. */
8155 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8156 (VALID_STAT(smb_fname->st) ?
8157 PERM_EXISTING_FILE : PERM_NEW_FILE),
8160 if (!NT_STATUS_IS_OK(status)) {
8164 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8166 if (wire_open_mode & SMB_O_SYNC) {
8167 create_options |= FILE_WRITE_THROUGH;
8169 if (wire_open_mode & SMB_O_APPEND) {
8170 access_mask |= FILE_APPEND_DATA;
8172 if (wire_open_mode & SMB_O_DIRECT) {
8173 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8176 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8177 VALID_STAT_OF_DIR(smb_fname->st)) {
8178 if (access_mask != SMB_O_RDONLY_MAPPING) {
8179 return NT_STATUS_FILE_IS_A_DIRECTORY;
8181 create_options &= ~FILE_NON_DIRECTORY_FILE;
8182 create_options |= FILE_DIRECTORY_FILE;
8185 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8186 smb_fname_str_dbg(smb_fname),
8187 (unsigned int)wire_open_mode,
8188 (unsigned int)unixmode ));
8190 status = SMB_VFS_CREATE_FILE(
8193 0, /* root_dir_fid */
8194 smb_fname, /* fname */
8195 access_mask, /* access_mask */
8196 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8198 create_disp, /* create_disposition*/
8199 create_options, /* create_options */
8200 mod_unixmode, /* file_attributes */
8201 oplock_request, /* oplock_request */
8203 0, /* allocation_size */
8204 0, /* private_flags */
8209 NULL, NULL); /* create context */
8211 if (!NT_STATUS_IS_OK(status)) {
8215 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8216 extended_oplock_granted = True;
8219 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8220 extended_oplock_granted = True;
8223 info_level_return = SVAL(pdata,16);
8225 /* Allocate the correct return size. */
8227 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8228 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8229 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8230 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8232 *pdata_return_size = 12;
8235 /* Realloc the data size */
8236 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8237 if (*ppdata == NULL) {
8238 close_file(req, fsp, ERROR_CLOSE);
8239 *pdata_return_size = 0;
8240 return NT_STATUS_NO_MEMORY;
8244 if (extended_oplock_granted) {
8245 if (flags & REQUEST_BATCH_OPLOCK) {
8246 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8248 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8250 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8251 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8253 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8256 SSVAL(pdata,2,fsp->fnum);
8257 SIVAL(pdata,4,info); /* Was file created etc. */
8259 switch (info_level_return) {
8260 case SMB_QUERY_FILE_UNIX_BASIC:
8261 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8262 SSVAL(pdata,10,0); /* padding. */
8263 store_file_unix_basic(conn, pdata + 12, fsp,
8266 case SMB_QUERY_FILE_UNIX_INFO2:
8267 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8268 SSVAL(pdata,10,0); /* padding. */
8269 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8273 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8274 SSVAL(pdata,10,0); /* padding. */
8277 return NT_STATUS_OK;
8280 /****************************************************************************
8281 Delete a file with POSIX semantics.
8282 ****************************************************************************/
8284 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8285 struct smb_request *req,
8288 struct smb_filename *smb_fname)
8290 NTSTATUS status = NT_STATUS_OK;
8291 files_struct *fsp = NULL;
8295 int create_options = 0;
8297 struct share_mode_lock *lck = NULL;
8299 if (total_data < 2) {
8300 return NT_STATUS_INVALID_PARAMETER;
8303 flags = SVAL(pdata,0);
8305 if (!VALID_STAT(smb_fname->st)) {
8306 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8309 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8310 !VALID_STAT_OF_DIR(smb_fname->st)) {
8311 return NT_STATUS_NOT_A_DIRECTORY;
8314 DEBUG(10,("smb_posix_unlink: %s %s\n",
8315 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8316 smb_fname_str_dbg(smb_fname)));
8318 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8319 create_options |= FILE_DIRECTORY_FILE;
8322 status = SMB_VFS_CREATE_FILE(
8325 0, /* root_dir_fid */
8326 smb_fname, /* fname */
8327 DELETE_ACCESS, /* access_mask */
8328 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8330 FILE_OPEN, /* create_disposition*/
8331 create_options, /* create_options */
8332 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8333 0, /* oplock_request */
8335 0, /* allocation_size */
8336 0, /* private_flags */
8341 NULL, NULL); /* create context */
8343 if (!NT_STATUS_IS_OK(status)) {
8348 * Don't lie to client. If we can't really delete due to
8349 * non-POSIX opens return SHARING_VIOLATION.
8352 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8354 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8355 "lock for file %s\n", fsp_str_dbg(fsp)));
8356 close_file(req, fsp, NORMAL_CLOSE);
8357 return NT_STATUS_INVALID_PARAMETER;
8361 * See if others still have the file open. If this is the case, then
8362 * don't delete. If all opens are POSIX delete we can set the delete
8363 * on close disposition.
8365 for (i=0; i<lck->data->num_share_modes; i++) {
8366 struct share_mode_entry *e = &lck->data->share_modes[i];
8367 if (is_valid_share_mode_entry(e)) {
8368 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8371 if (share_mode_stale_pid(lck->data, i)) {
8374 /* Fail with sharing violation. */
8376 close_file(req, fsp, NORMAL_CLOSE);
8377 return NT_STATUS_SHARING_VIOLATION;
8382 * Set the delete on close.
8384 status = smb_set_file_disposition_info(conn,
8392 if (!NT_STATUS_IS_OK(status)) {
8393 close_file(req, fsp, NORMAL_CLOSE);
8396 return close_file(req, fsp, NORMAL_CLOSE);
8399 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8400 struct smb_request *req,
8401 TALLOC_CTX *mem_ctx,
8402 uint16_t info_level,
8404 struct smb_filename *smb_fname,
8405 char **ppdata, int total_data,
8408 char *pdata = *ppdata;
8409 NTSTATUS status = NT_STATUS_OK;
8410 int data_return_size = 0;
8414 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8415 return NT_STATUS_INVALID_LEVEL;
8418 if (!CAN_WRITE(conn)) {
8419 /* Allow POSIX opens. The open path will deny
8420 * any non-readonly opens. */
8421 if (info_level != SMB_POSIX_PATH_OPEN) {
8422 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8426 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8427 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8429 info_level, total_data));
8431 switch (info_level) {
8433 case SMB_INFO_STANDARD:
8435 status = smb_set_info_standard(conn,
8443 case SMB_INFO_SET_EA:
8445 status = smb_info_set_ea(conn,
8453 case SMB_SET_FILE_BASIC_INFO:
8454 case SMB_FILE_BASIC_INFORMATION:
8456 status = smb_set_file_basic_info(conn,
8464 case SMB_FILE_ALLOCATION_INFORMATION:
8465 case SMB_SET_FILE_ALLOCATION_INFO:
8467 status = smb_set_file_allocation_info(conn, req,
8475 case SMB_FILE_END_OF_FILE_INFORMATION:
8476 case SMB_SET_FILE_END_OF_FILE_INFO:
8479 * XP/Win7 both fail after the createfile with
8480 * SMB_SET_FILE_END_OF_FILE_INFO but not
8481 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8482 * The level is known here, so pass it down
8486 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8488 status = smb_set_file_end_of_file_info(conn, req,
8497 case SMB_FILE_DISPOSITION_INFORMATION:
8498 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8501 /* JRA - We used to just ignore this on a path ?
8502 * Shouldn't this be invalid level on a pathname
8505 if (tran_call != TRANSACT2_SETFILEINFO) {
8506 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8509 status = smb_set_file_disposition_info(conn,
8517 case SMB_FILE_POSITION_INFORMATION:
8519 status = smb_file_position_information(conn,
8526 case SMB_FILE_FULL_EA_INFORMATION:
8528 status = smb_set_file_full_ea_info(conn,
8535 /* From tridge Samba4 :
8536 * MODE_INFORMATION in setfileinfo (I have no
8537 * idea what "mode information" on a file is - it takes a value of 0,
8538 * 2, 4 or 6. What could it be?).
8541 case SMB_FILE_MODE_INFORMATION:
8543 status = smb_file_mode_information(conn,
8550 * CIFS UNIX extensions.
8553 case SMB_SET_FILE_UNIX_BASIC:
8555 status = smb_set_file_unix_basic(conn, req,
8563 case SMB_SET_FILE_UNIX_INFO2:
8565 status = smb_set_file_unix_info2(conn, req,
8573 case SMB_SET_FILE_UNIX_LINK:
8576 /* We must have a pathname for this. */
8577 return NT_STATUS_INVALID_LEVEL;
8579 status = smb_set_file_unix_link(conn, req, pdata,
8580 total_data, smb_fname);
8584 case SMB_SET_FILE_UNIX_HLINK:
8587 /* We must have a pathname for this. */
8588 return NT_STATUS_INVALID_LEVEL;
8590 status = smb_set_file_unix_hlink(conn, req,
8596 case SMB_FILE_RENAME_INFORMATION:
8598 status = smb_file_rename_information(conn, req,
8604 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8606 /* SMB2 rename information. */
8607 status = smb2_file_rename_information(conn, req,
8613 case SMB_FILE_LINK_INFORMATION:
8615 status = smb_file_link_information(conn, req,
8621 #if defined(HAVE_POSIX_ACLS)
8622 case SMB_SET_POSIX_ACL:
8624 status = smb_set_posix_acl(conn,
8633 case SMB_SET_POSIX_LOCK:
8636 return NT_STATUS_INVALID_LEVEL;
8638 status = smb_set_posix_lock(conn, req,
8639 pdata, total_data, fsp);
8643 case SMB_POSIX_PATH_OPEN:
8646 /* We must have a pathname for this. */
8647 return NT_STATUS_INVALID_LEVEL;
8650 status = smb_posix_open(conn, req,
8658 case SMB_POSIX_PATH_UNLINK:
8661 /* We must have a pathname for this. */
8662 return NT_STATUS_INVALID_LEVEL;
8665 status = smb_posix_unlink(conn, req,
8673 return NT_STATUS_INVALID_LEVEL;
8676 if (!NT_STATUS_IS_OK(status)) {
8680 *ret_data_size = data_return_size;
8681 return NT_STATUS_OK;
8684 /****************************************************************************
8685 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8686 ****************************************************************************/
8688 static void call_trans2setfilepathinfo(connection_struct *conn,
8689 struct smb_request *req,
8690 unsigned int tran_call,
8691 char **pparams, int total_params,
8692 char **ppdata, int total_data,
8693 unsigned int max_data_bytes)
8695 char *params = *pparams;
8696 char *pdata = *ppdata;
8697 uint16_t info_level;
8698 struct smb_filename *smb_fname = NULL;
8699 files_struct *fsp = NULL;
8700 NTSTATUS status = NT_STATUS_OK;
8701 int data_return_size = 0;
8704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8708 if (tran_call == TRANSACT2_SETFILEINFO) {
8709 if (total_params < 4) {
8710 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8714 fsp = file_fsp(req, SVAL(params,0));
8715 /* Basic check for non-null fsp. */
8716 if (!check_fsp_open(conn, req, fsp)) {
8719 info_level = SVAL(params,2);
8721 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8722 if (smb_fname == NULL) {
8723 reply_nterror(req, NT_STATUS_NO_MEMORY);
8727 if(fsp->fh->fd == -1) {
8729 * This is actually a SETFILEINFO on a directory
8730 * handle (returned from an NT SMB). NT5.0 seems
8731 * to do this call. JRA.
8733 if (INFO_LEVEL_IS_UNIX(info_level)) {
8734 /* Always do lstat for UNIX calls. */
8735 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8736 DEBUG(3,("call_trans2setfilepathinfo: "
8737 "SMB_VFS_LSTAT of %s failed "
8739 smb_fname_str_dbg(smb_fname),
8741 reply_nterror(req, map_nt_error_from_unix(errno));
8745 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8746 DEBUG(3,("call_trans2setfilepathinfo: "
8747 "fileinfo of %s failed (%s)\n",
8748 smb_fname_str_dbg(smb_fname),
8750 reply_nterror(req, map_nt_error_from_unix(errno));
8754 } else if (fsp->print_file) {
8756 * Doing a DELETE_ON_CLOSE should cancel a print job.
8758 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8759 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8761 DEBUG(3,("call_trans2setfilepathinfo: "
8762 "Cancelling print job (%s)\n",
8766 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8772 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8777 * Original code - this is an open file.
8779 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8780 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8781 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8783 reply_nterror(req, map_nt_error_from_unix(errno));
8789 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8792 if (total_params < 7) {
8793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8797 info_level = SVAL(params,0);
8798 if (req->posix_pathnames) {
8799 srvstr_get_path_posix(req,
8808 srvstr_get_path(req,
8817 if (!NT_STATUS_IS_OK(status)) {
8818 reply_nterror(req, status);
8822 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8823 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8824 info_level == SMB_FILE_RENAME_INFORMATION ||
8825 info_level == SMB_POSIX_PATH_UNLINK) {
8826 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8829 status = filename_convert(req, conn,
8834 if (!NT_STATUS_IS_OK(status)) {
8835 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8836 reply_botherror(req,
8837 NT_STATUS_PATH_NOT_COVERED,
8838 ERRSRV, ERRbadpath);
8841 reply_nterror(req, status);
8845 if (INFO_LEVEL_IS_UNIX(info_level)) {
8847 * For CIFS UNIX extensions the target name may not exist.
8850 /* Always do lstat for UNIX calls. */
8851 SMB_VFS_LSTAT(conn, smb_fname);
8853 } else if (!VALID_STAT(smb_fname->st) &&
8854 SMB_VFS_STAT(conn, smb_fname)) {
8855 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8857 smb_fname_str_dbg(smb_fname),
8859 reply_nterror(req, map_nt_error_from_unix(errno));
8864 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8865 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8867 info_level,total_data));
8869 /* Realloc the parameter size */
8870 *pparams = (char *)SMB_REALLOC(*pparams,2);
8871 if (*pparams == NULL) {
8872 reply_nterror(req, NT_STATUS_NO_MEMORY);
8879 status = smbd_do_setfilepathinfo(conn, req, req,
8885 if (!NT_STATUS_IS_OK(status)) {
8886 if (open_was_deferred(req->xconn, req->mid)) {
8887 /* We have re-scheduled this call. */
8890 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8891 /* We have re-scheduled this call. */
8894 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8895 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8896 ERRSRV, ERRbadpath);
8899 if (info_level == SMB_POSIX_PATH_OPEN) {
8900 reply_openerror(req, status);
8905 * Invalid EA name needs to return 2 param bytes,
8906 * not a zero-length error packet.
8908 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8909 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8912 reply_nterror(req, status);
8917 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8923 /****************************************************************************
8924 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8925 ****************************************************************************/
8927 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8928 char **pparams, int total_params,
8929 char **ppdata, int total_data,
8930 unsigned int max_data_bytes)
8932 struct smb_filename *smb_dname = NULL;
8933 char *params = *pparams;
8934 char *pdata = *ppdata;
8935 char *directory = NULL;
8936 NTSTATUS status = NT_STATUS_OK;
8937 struct ea_list *ea_list = NULL;
8938 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8939 TALLOC_CTX *ctx = talloc_tos();
8941 if (!CAN_WRITE(conn)) {
8942 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8946 if (total_params < 5) {
8947 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8951 if (req->posix_pathnames) {
8952 srvstr_get_path_posix(ctx,
8961 srvstr_get_path(ctx,
8970 if (!NT_STATUS_IS_OK(status)) {
8971 reply_nterror(req, status);
8975 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8977 status = filename_convert(ctx,
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);