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->base_share_dev == psbuf->st_ex_dev) {
150 return (uint64_t)psbuf->st_ex_ino;
152 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
153 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
157 /****************************************************************************
158 Utility functions for dealing with extended attributes.
159 ****************************************************************************/
161 /****************************************************************************
162 Refuse to allow clients to overwrite our private xattrs.
163 ****************************************************************************/
165 bool samba_private_attr_name(const char *unix_ea_name)
167 static const char * const prohibited_ea_names[] = {
168 SAMBA_POSIX_INHERITANCE_EA_NAME,
169 SAMBA_XATTR_DOS_ATTRIB,
177 for (i = 0; prohibited_ea_names[i]; i++) {
178 if (strequal( prohibited_ea_names[i], unix_ea_name))
181 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
182 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
188 /****************************************************************************
189 Get one EA value. Fill in a struct ea_struct.
190 ****************************************************************************/
192 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
193 files_struct *fsp, const char *fname,
194 const char *ea_name, struct ea_struct *pea)
196 /* Get the value of this xattr. Max size is 64k. */
197 size_t attr_size = 256;
203 val = talloc_realloc(mem_ctx, val, char, attr_size);
205 return NT_STATUS_NO_MEMORY;
208 if (fsp && fsp->fh->fd != -1) {
209 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
211 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
214 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
220 return map_nt_error_from_unix(errno);
223 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
224 dump_data(10, (uint8_t *)val, sizeret);
227 if (strnequal(ea_name, "user.", 5)) {
228 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
230 pea->name = talloc_strdup(mem_ctx, ea_name);
232 if (pea->name == NULL) {
234 return NT_STATUS_NO_MEMORY;
236 pea->value.data = (unsigned char *)val;
237 pea->value.length = (size_t)sizeret;
241 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
242 connection_struct *conn,
244 const struct smb_filename *smb_fname,
249 /* Get a list of all xattrs. Max namesize is 64k. */
250 size_t ea_namelist_size = 1024;
251 char *ea_namelist = smallbuf;
252 char *to_free = NULL;
257 ssize_t sizeret = -1;
265 status = refuse_symlink(conn, fsp, smb_fname);
266 if (!NT_STATUS_IS_OK(status)) {
268 * Just return no EA's on a symlink.
273 if (fsp && fsp->fh->fd != -1) {
274 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
277 sizeret = SMB_VFS_LISTXATTR(conn,
278 smb_fname->base_name,
283 if ((sizeret == -1) && (errno == ERANGE)) {
284 ea_namelist_size = 65536;
285 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
286 if (ea_namelist == NULL) {
287 return NT_STATUS_NO_MEMORY;
289 to_free = ea_namelist;
291 if (fsp && fsp->fh->fd != -1) {
292 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
295 sizeret = SMB_VFS_LISTXATTR(conn,
296 smb_fname->base_name,
303 status = map_nt_error_from_unix(errno);
304 TALLOC_FREE(to_free);
308 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
311 TALLOC_FREE(to_free);
316 * Ensure the result is 0-terminated
319 if (ea_namelist[sizeret-1] != '\0') {
320 TALLOC_FREE(to_free);
321 return NT_STATUS_INTERNAL_ERROR;
329 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
333 *pnum_names = num_names;
335 if (pnames == NULL) {
336 TALLOC_FREE(to_free);
340 names = talloc_array(mem_ctx, char *, num_names);
342 DEBUG(0, ("talloc failed\n"));
343 TALLOC_FREE(to_free);
344 return NT_STATUS_NO_MEMORY;
347 if (ea_namelist == smallbuf) {
348 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
349 if (ea_namelist == NULL) {
351 return NT_STATUS_NO_MEMORY;
354 talloc_steal(names, ea_namelist);
356 ea_namelist = talloc_realloc(names, ea_namelist, char,
358 if (ea_namelist == NULL) {
360 return NT_STATUS_NO_MEMORY;
366 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
367 names[num_names++] = p;
375 /****************************************************************************
376 Return a linked list of the total EA's. Plus the total size
377 ****************************************************************************/
379 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
380 connection_struct *conn,
382 const struct smb_filename *smb_fname,
383 size_t *pea_total_len,
384 struct ea_list **ea_list)
386 /* Get a list of all xattrs. Max namesize is 64k. */
389 struct ea_list *ea_list_head = NULL;
390 bool posix_pathnames = false;
396 if (!lp_ea_support(SNUM(conn))) {
402 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
404 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
407 status = get_ea_names_from_file(talloc_tos(),
414 if (!NT_STATUS_IS_OK(status)) {
418 if (num_names == 0) {
422 for (i=0; i<num_names; i++) {
423 struct ea_list *listp;
426 if (strnequal(names[i], "system.", 7)
427 || samba_private_attr_name(names[i]))
431 * Filter out any underlying POSIX EA names
432 * that a Windows client can't handle.
434 if (!posix_pathnames &&
435 is_invalid_windows_ea_name(names[i])) {
439 listp = talloc(mem_ctx, struct ea_list);
441 return NT_STATUS_NO_MEMORY;
444 status = get_ea_value(listp,
447 smb_fname->base_name,
451 if (!NT_STATUS_IS_OK(status)) {
456 if (listp->ea.value.length == 0) {
458 * We can never return a zero length EA.
459 * Windows reports the EA's as corrupted.
465 push_ascii_fstring(dos_ea_name, listp->ea.name);
468 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
470 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
471 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
472 (unsigned int)listp->ea.value.length));
474 DLIST_ADD_END(ea_list_head, listp);
478 /* Add on 4 for total length. */
479 if (*pea_total_len) {
483 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
484 (unsigned int)*pea_total_len));
486 *ea_list = ea_list_head;
490 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
491 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
496 if (!lp_ea_support(SNUM(conn))) {
500 if (is_ntfs_stream_smb_fname(smb_fname)) {
501 return NT_STATUS_INVALID_PARAMETER;
504 return get_ea_list_from_file_path(mem_ctx,
512 /****************************************************************************
513 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
515 ****************************************************************************/
517 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
518 connection_struct *conn, struct ea_list *ea_list)
520 unsigned int ret_data_size = 4;
523 SMB_ASSERT(total_data_size >= 4);
525 if (!lp_ea_support(SNUM(conn))) {
530 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
533 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
534 dos_namelen = strlen(dos_ea_name);
535 if (dos_namelen > 255 || dos_namelen == 0) {
538 if (ea_list->ea.value.length > 65535) {
541 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
545 /* We know we have room. */
546 SCVAL(p,0,ea_list->ea.flags);
547 SCVAL(p,1,dos_namelen);
548 SSVAL(p,2,ea_list->ea.value.length);
549 strlcpy(p+4, dos_ea_name, dos_namelen+1);
550 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
552 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
553 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
556 ret_data_size = PTR_DIFF(p, pdata);
557 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
558 SIVAL(pdata,0,ret_data_size);
559 return ret_data_size;
562 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
564 unsigned int total_data_size,
565 unsigned int *ret_data_size,
566 connection_struct *conn,
567 struct ea_list *ea_list)
569 uint8_t *p = (uint8_t *)pdata;
570 uint8_t *last_start = NULL;
571 bool do_store_data = (pdata != NULL);
575 if (!lp_ea_support(SNUM(conn))) {
576 return NT_STATUS_NO_EAS_ON_FILE;
579 for (; ea_list; ea_list = ea_list->next) {
585 if (last_start != NULL && do_store_data) {
586 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
590 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
591 dos_namelen = strlen(dos_ea_name);
592 if (dos_namelen > 255 || dos_namelen == 0) {
593 return NT_STATUS_INTERNAL_ERROR;
595 if (ea_list->ea.value.length > 65535) {
596 return NT_STATUS_INTERNAL_ERROR;
599 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
602 pad = (4 - (this_size % 4)) % 4;
607 if (this_size > total_data_size) {
608 return NT_STATUS_INFO_LENGTH_MISMATCH;
611 /* We know we have room. */
612 SIVAL(p, 0x00, 0); /* next offset */
613 SCVAL(p, 0x04, ea_list->ea.flags);
614 SCVAL(p, 0x05, dos_namelen);
615 SSVAL(p, 0x06, ea_list->ea.value.length);
616 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
617 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
619 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
623 total_data_size -= this_size;
629 *ret_data_size = PTR_DIFF(p, pdata);
630 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
634 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
636 size_t total_ea_len = 0;
638 struct ea_list *ea_list = NULL;
640 if (!lp_ea_support(SNUM(conn))) {
643 mem_ctx = talloc_stackframe();
645 /* If this is a stream fsp, then we need to instead find the
646 * estimated ea len from the main file, not the stream
647 * (streams cannot have EAs), but the estimate isn't just 0 in
649 if (is_ntfs_stream_smb_fname(smb_fname)) {
652 (void)get_ea_list_from_file_path(mem_ctx,
658 if(conn->sconn->using_smb2) {
660 unsigned int ret_data_size;
662 * We're going to be using fill_ea_chained_buffer() to
663 * marshall EA's - this size is significantly larger
664 * than the SMB1 buffer. Re-calculate the size without
667 status = fill_ea_chained_buffer(mem_ctx,
673 if (!NT_STATUS_IS_OK(status)) {
676 total_ea_len = ret_data_size;
678 TALLOC_FREE(mem_ctx);
682 /****************************************************************************
683 Ensure the EA name is case insensitive by matching any existing EA name.
684 ****************************************************************************/
686 static void canonicalize_ea_name(connection_struct *conn,
688 const struct smb_filename *smb_fname,
689 fstring unix_ea_name)
692 TALLOC_CTX *mem_ctx = talloc_tos();
693 struct ea_list *ea_list;
694 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
700 if (!NT_STATUS_IS_OK(status)) {
704 for (; ea_list; ea_list = ea_list->next) {
705 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
706 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
707 &unix_ea_name[5], ea_list->ea.name));
708 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
714 /****************************************************************************
715 Set or delete an extended attribute.
716 ****************************************************************************/
718 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
719 const struct smb_filename *smb_fname, struct ea_list *ea_list)
722 bool posix_pathnames = false;
724 if (!lp_ea_support(SNUM(conn))) {
725 return NT_STATUS_EAS_NOT_SUPPORTED;
730 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
732 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
735 status = refuse_symlink(conn, fsp, smb_fname);
736 if (!NT_STATUS_IS_OK(status)) {
740 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
741 if (!NT_STATUS_IS_OK(status)) {
745 /* Setting EAs on streams isn't supported. */
746 if (is_ntfs_stream_smb_fname(smb_fname)) {
747 return NT_STATUS_INVALID_PARAMETER;
751 * Filter out invalid Windows EA names - before
752 * we set *any* of them.
755 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
756 return STATUS_INVALID_EA_NAME;
759 for (;ea_list; ea_list = ea_list->next) {
761 fstring unix_ea_name;
763 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
764 fstrcat(unix_ea_name, ea_list->ea.name);
766 canonicalize_ea_name(conn,
771 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
773 if (samba_private_attr_name(unix_ea_name)) {
774 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
775 return NT_STATUS_ACCESS_DENIED;
778 if (ea_list->ea.value.length == 0) {
779 /* Remove the attribute. */
780 if (fsp && (fsp->fh->fd != -1)) {
781 DEBUG(10,("set_ea: deleting ea name %s on "
782 "file %s by file descriptor.\n",
783 unix_ea_name, fsp_str_dbg(fsp)));
784 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
786 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
787 unix_ea_name, smb_fname->base_name));
788 ret = SMB_VFS_REMOVEXATTR(conn,
789 smb_fname->base_name,
793 /* Removing a non existent attribute always succeeds. */
794 if (ret == -1 && errno == ENOATTR) {
795 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
801 if (fsp && (fsp->fh->fd != -1)) {
802 DEBUG(10,("set_ea: setting ea name %s on file "
803 "%s by file descriptor.\n",
804 unix_ea_name, fsp_str_dbg(fsp)));
805 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
806 ea_list->ea.value.data, ea_list->ea.value.length, 0);
808 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
809 unix_ea_name, smb_fname->base_name));
810 ret = SMB_VFS_SETXATTR(conn,
811 smb_fname->base_name,
813 ea_list->ea.value.data,
814 ea_list->ea.value.length,
821 if (errno == ENOTSUP) {
822 return NT_STATUS_EAS_NOT_SUPPORTED;
825 return map_nt_error_from_unix(errno);
831 /****************************************************************************
832 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
833 ****************************************************************************/
835 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
837 struct ea_list *ea_list_head = NULL;
838 size_t converted_size, offset = 0;
840 while (offset + 2 < data_size) {
841 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
842 unsigned int namelen = CVAL(pdata,offset);
844 offset++; /* Go past the namelen byte. */
846 /* integer wrap paranioa. */
847 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
848 (offset > data_size) || (namelen > data_size) ||
849 (offset + namelen >= data_size)) {
852 /* Ensure the name is null terminated. */
853 if (pdata[offset + namelen] != '\0') {
856 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
858 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
859 "failed: %s", strerror(errno)));
865 offset += (namelen + 1); /* Go past the name + terminating zero. */
866 DLIST_ADD_END(ea_list_head, eal);
867 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
873 /****************************************************************************
874 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
875 ****************************************************************************/
877 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
879 struct ea_list *ea_list_head = NULL;
881 size_t bytes_used = 0;
883 while (offset < data_size) {
884 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
890 DLIST_ADD_END(ea_list_head, eal);
891 offset += bytes_used;
897 /****************************************************************************
898 Count the total EA size needed.
899 ****************************************************************************/
901 static size_t ea_list_size(struct ea_list *ealist)
904 struct ea_list *listp;
907 for (listp = ealist; listp; listp = listp->next) {
908 push_ascii_fstring(dos_ea_name, listp->ea.name);
909 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
911 /* Add on 4 for total length. */
919 /****************************************************************************
920 Return a union of EA's from a file list and a list of names.
921 The TALLOC context for the two lists *MUST* be identical as we steal
922 memory from one list to add to another. JRA.
923 ****************************************************************************/
925 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
927 struct ea_list *nlistp, *flistp;
929 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
930 for (flistp = file_list; flistp; flistp = flistp->next) {
931 if (strequal(nlistp->ea.name, flistp->ea.name)) {
937 /* Copy the data from this entry. */
938 nlistp->ea.flags = flistp->ea.flags;
939 nlistp->ea.value = flistp->ea.value;
942 nlistp->ea.flags = 0;
943 ZERO_STRUCT(nlistp->ea.value);
947 *total_ea_len = ea_list_size(name_list);
951 /****************************************************************************
952 Send the required number of replies back.
953 We assume all fields other than the data fields are
954 set correctly for the type of call.
955 HACK ! Always assumes smb_setup field is zero.
956 ****************************************************************************/
958 void send_trans2_replies(connection_struct *conn,
959 struct smb_request *req,
967 /* As we are using a protocol > LANMAN1 then the max_send
968 variable must have been set in the sessetupX call.
969 This takes precedence over the max_xmit field in the
970 global struct. These different max_xmit variables should
971 be merged as this is now too confusing */
973 int data_to_send = datasize;
974 int params_to_send = paramsize;
976 const char *pp = params;
977 const char *pd = pdata;
978 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
979 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
980 int data_alignment_offset = 0;
981 bool overflow = False;
982 struct smbXsrv_connection *xconn = req->xconn;
983 int max_send = xconn->smb1.sessions.max_send;
985 /* Modify the data_to_send and datasize and set the error if
986 we're trying to send more than max_data_bytes. We still send
987 the part of the packet(s) that fit. Strange, but needed
990 if (max_data_bytes > 0 && datasize > max_data_bytes) {
991 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
992 max_data_bytes, datasize ));
993 datasize = data_to_send = max_data_bytes;
997 /* If there genuinely are no parameters or data to send just send the empty packet */
999 if(params_to_send == 0 && data_to_send == 0) {
1000 reply_outbuf(req, 10, 0);
1001 if (NT_STATUS_V(status)) {
1004 ntstatus_to_dos(status, &eclass, &ecode);
1005 error_packet_set((char *)req->outbuf,
1006 eclass, ecode, status,
1009 show_msg((char *)req->outbuf);
1010 if (!srv_send_smb(xconn,
1011 (char *)req->outbuf,
1012 true, req->seqnum+1,
1013 IS_CONN_ENCRYPTED(conn),
1015 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1017 TALLOC_FREE(req->outbuf);
1021 /* When sending params and data ensure that both are nicely aligned */
1022 /* Only do this alignment when there is also data to send - else
1023 can cause NT redirector problems. */
1025 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1026 data_alignment_offset = 4 - (params_to_send % 4);
1028 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1029 /* The alignment_offset is to align the param bytes on an even byte
1030 boundary. NT 4.0 Beta needs this to work correctly. */
1032 useable_space = max_send - (smb_size
1035 + data_alignment_offset);
1037 if (useable_space < 0) {
1038 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1039 "= %d!!!", useable_space));
1040 exit_server_cleanly("send_trans2_replies: Not enough space");
1043 while (params_to_send || data_to_send) {
1044 /* Calculate whether we will totally or partially fill this packet */
1046 total_sent_thistime = params_to_send + data_to_send;
1048 /* We can never send more than useable_space */
1050 * Note that 'useable_space' does not include the alignment offsets,
1051 * but we must include the alignment offsets in the calculation of
1052 * the length of the data we send over the wire, as the alignment offsets
1053 * are sent here. Fix from Marc_Jacobsen@hp.com.
1056 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1058 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1059 + data_alignment_offset);
1061 /* Set total params and data to be sent */
1062 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1063 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1065 /* Calculate how many parameters and data we can fit into
1066 * this packet. Parameters get precedence
1069 params_sent_thistime = MIN(params_to_send,useable_space);
1070 data_sent_thistime = useable_space - params_sent_thistime;
1071 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1073 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1075 /* smb_proff is the offset from the start of the SMB header to the
1076 parameter bytes, however the first 4 bytes of outbuf are
1077 the Netbios over TCP header. Thus use smb_base() to subtract
1078 them from the calculation */
1080 SSVAL(req->outbuf,smb_proff,
1081 ((smb_buf(req->outbuf)+alignment_offset)
1082 - smb_base(req->outbuf)));
1084 if(params_sent_thistime == 0)
1085 SSVAL(req->outbuf,smb_prdisp,0);
1087 /* Absolute displacement of param bytes sent in this packet */
1088 SSVAL(req->outbuf,smb_prdisp,pp - params);
1090 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1091 if(data_sent_thistime == 0) {
1092 SSVAL(req->outbuf,smb_droff,0);
1093 SSVAL(req->outbuf,smb_drdisp, 0);
1095 /* The offset of the data bytes is the offset of the
1096 parameter bytes plus the number of parameters being sent this time */
1097 SSVAL(req->outbuf, smb_droff,
1098 ((smb_buf(req->outbuf)+alignment_offset)
1099 - smb_base(req->outbuf))
1100 + params_sent_thistime + data_alignment_offset);
1101 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1104 /* Initialize the padding for alignment */
1106 if (alignment_offset != 0) {
1107 memset(smb_buf(req->outbuf), 0, alignment_offset);
1110 /* Copy the param bytes into the packet */
1112 if(params_sent_thistime) {
1113 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1114 params_sent_thistime);
1117 /* Copy in the data bytes */
1118 if(data_sent_thistime) {
1119 if (data_alignment_offset != 0) {
1120 memset((smb_buf(req->outbuf)+alignment_offset+
1121 params_sent_thistime), 0,
1122 data_alignment_offset);
1124 memcpy(smb_buf(req->outbuf)+alignment_offset
1125 +params_sent_thistime+data_alignment_offset,
1126 pd,data_sent_thistime);
1129 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1130 params_sent_thistime, data_sent_thistime, useable_space));
1131 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1132 params_to_send, data_to_send, paramsize, datasize));
1135 error_packet_set((char *)req->outbuf,
1136 ERRDOS,ERRbufferoverflow,
1137 STATUS_BUFFER_OVERFLOW,
1139 } else if (NT_STATUS_V(status)) {
1142 ntstatus_to_dos(status, &eclass, &ecode);
1143 error_packet_set((char *)req->outbuf,
1144 eclass, ecode, status,
1148 /* Send the packet */
1149 show_msg((char *)req->outbuf);
1150 if (!srv_send_smb(xconn,
1151 (char *)req->outbuf,
1152 true, req->seqnum+1,
1153 IS_CONN_ENCRYPTED(conn),
1155 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1157 TALLOC_FREE(req->outbuf);
1159 pp += params_sent_thistime;
1160 pd += data_sent_thistime;
1162 params_to_send -= params_sent_thistime;
1163 data_to_send -= data_sent_thistime;
1166 if(params_to_send < 0 || data_to_send < 0) {
1167 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1168 params_to_send, data_to_send));
1176 /****************************************************************************
1177 Reply to a TRANSACT2_OPEN.
1178 ****************************************************************************/
1180 static void call_trans2open(connection_struct *conn,
1181 struct smb_request *req,
1182 char **pparams, int total_params,
1183 char **ppdata, int total_data,
1184 unsigned int max_data_bytes)
1186 struct smb_filename *smb_fname = NULL;
1187 char *params = *pparams;
1188 char *pdata = *ppdata;
1191 bool oplock_request;
1193 bool return_additional_info;
1202 int fattr=0,mtime=0;
1203 SMB_INO_T inode = 0;
1206 struct ea_list *ea_list = NULL;
1209 uint32_t access_mask;
1210 uint32_t share_mode;
1211 uint32_t create_disposition;
1212 uint32_t create_options = 0;
1213 uint32_t private_flags = 0;
1214 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1215 TALLOC_CTX *ctx = talloc_tos();
1218 * Ensure we have enough parameters to perform the operation.
1221 if (total_params < 29) {
1222 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1226 flags = SVAL(params, 0);
1227 deny_mode = SVAL(params, 2);
1228 open_attr = SVAL(params,6);
1229 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1230 if (oplock_request) {
1231 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1235 return_additional_info = BITSETW(params,0);
1236 open_sattr = SVAL(params, 4);
1237 open_time = make_unix_date3(params+8);
1239 open_ofun = SVAL(params,12);
1240 open_size = IVAL(params,14);
1241 pname = ¶ms[28];
1244 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1248 if (req->posix_pathnames) {
1249 srvstr_get_path_posix(ctx,
1258 srvstr_get_path(ctx,
1267 if (!NT_STATUS_IS_OK(status)) {
1268 reply_nterror(req, status);
1272 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1273 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1274 (unsigned int)open_ofun, open_size));
1276 status = filename_convert(ctx,
1278 req->flags2 & FLAGS2_DFS_PATHNAMES,
1283 if (!NT_STATUS_IS_OK(status)) {
1284 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1285 reply_botherror(req,
1286 NT_STATUS_PATH_NOT_COVERED,
1287 ERRSRV, ERRbadpath);
1290 reply_nterror(req, status);
1294 if (open_ofun == 0) {
1295 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1299 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1301 &access_mask, &share_mode,
1302 &create_disposition,
1305 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1309 /* Any data in this call is an EA list. */
1310 if (total_data && (total_data != 4)) {
1311 if (total_data < 10) {
1312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1316 if (IVAL(pdata,0) > total_data) {
1317 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1318 IVAL(pdata,0), (unsigned int)total_data));
1319 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1323 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1330 if (!lp_ea_support(SNUM(conn))) {
1331 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1335 if (!req->posix_pathnames &&
1336 ea_list_has_invalid_name(ea_list)) {
1338 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1339 if(*pparams == NULL ) {
1340 reply_nterror(req, NT_STATUS_NO_MEMORY);
1344 memset(params, '\0', param_len);
1345 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1346 params, param_len, NULL, 0, max_data_bytes);
1351 status = SMB_VFS_CREATE_FILE(
1354 0, /* root_dir_fid */
1355 smb_fname, /* fname */
1356 access_mask, /* access_mask */
1357 share_mode, /* share_access */
1358 create_disposition, /* create_disposition*/
1359 create_options, /* create_options */
1360 open_attr, /* file_attributes */
1361 oplock_request, /* oplock_request */
1363 open_size, /* allocation_size */
1366 ea_list, /* ea_list */
1368 &smb_action, /* psbuf */
1369 NULL, NULL); /* create context */
1371 if (!NT_STATUS_IS_OK(status)) {
1372 if (open_was_deferred(req->xconn, req->mid)) {
1373 /* We have re-scheduled this call. */
1376 reply_openerror(req, status);
1380 size = get_file_size_stat(&smb_fname->st);
1381 fattr = dos_mode(conn, smb_fname);
1382 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1383 inode = smb_fname->st.st_ex_ino;
1384 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1385 close_file(req, fsp, ERROR_CLOSE);
1386 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1390 /* Realloc the size of parameters and data we will return */
1391 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1392 if(*pparams == NULL ) {
1393 reply_nterror(req, NT_STATUS_NO_MEMORY);
1398 SSVAL(params,0,fsp->fnum);
1399 SSVAL(params,2,fattr);
1400 srv_put_dos_date2(params,4, mtime);
1401 SIVAL(params,8, (uint32_t)size);
1402 SSVAL(params,12,deny_mode);
1403 SSVAL(params,14,0); /* open_type - file or directory. */
1404 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1406 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1407 smb_action |= EXTENDED_OPLOCK_GRANTED;
1410 SSVAL(params,18,smb_action);
1413 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1415 SIVAL(params,20,inode);
1416 SSVAL(params,24,0); /* Padding. */
1418 uint32_t ea_size = estimate_ea_size(conn, fsp,
1420 SIVAL(params, 26, ea_size);
1422 SIVAL(params, 26, 0);
1425 /* Send the required number of replies */
1426 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1428 TALLOC_FREE(smb_fname);
1431 /*********************************************************
1432 Routine to check if a given string matches exactly.
1433 as a special case a mask of "." does NOT match. That
1434 is required for correct wildcard semantics
1435 Case can be significant or not.
1436 **********************************************************/
1438 static bool exact_match(bool has_wild,
1439 bool case_sensitive,
1443 if (mask[0] == '.' && mask[1] == 0) {
1451 if (case_sensitive) {
1452 return strcmp(str,mask)==0;
1454 return strcasecmp_m(str,mask) == 0;
1458 /****************************************************************************
1459 Return the filetype for UNIX extensions.
1460 ****************************************************************************/
1462 static uint32_t unix_filetype(mode_t mode)
1465 return UNIX_TYPE_FILE;
1466 else if(S_ISDIR(mode))
1467 return UNIX_TYPE_DIR;
1469 else if(S_ISLNK(mode))
1470 return UNIX_TYPE_SYMLINK;
1473 else if(S_ISCHR(mode))
1474 return UNIX_TYPE_CHARDEV;
1477 else if(S_ISBLK(mode))
1478 return UNIX_TYPE_BLKDEV;
1481 else if(S_ISFIFO(mode))
1482 return UNIX_TYPE_FIFO;
1485 else if(S_ISSOCK(mode))
1486 return UNIX_TYPE_SOCKET;
1489 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1490 return UNIX_TYPE_UNKNOWN;
1493 /****************************************************************************
1494 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1495 ****************************************************************************/
1497 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1499 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1500 const SMB_STRUCT_STAT *psbuf,
1502 enum perm_type ptype,
1507 if (perms == SMB_MODE_NO_CHANGE) {
1508 if (!VALID_STAT(*psbuf)) {
1509 return NT_STATUS_INVALID_PARAMETER;
1511 *ret_perms = psbuf->st_ex_mode;
1512 return NT_STATUS_OK;
1516 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1517 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1518 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1519 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1520 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1521 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1522 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1523 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1524 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1526 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1529 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1532 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1535 if (ptype == PERM_NEW_FILE) {
1537 * "create mask"/"force create mode" are
1538 * only applied to new files, not existing ones.
1540 ret &= lp_create_mask(SNUM(conn));
1541 /* Add in force bits */
1542 ret |= lp_force_create_mode(SNUM(conn));
1543 } else if (ptype == PERM_NEW_DIR) {
1545 * "directory mask"/"force directory mode" are
1546 * only applied to new directories, not existing ones.
1548 ret &= lp_directory_mask(SNUM(conn));
1549 /* Add in force bits */
1550 ret |= lp_force_directory_mode(SNUM(conn));
1554 return NT_STATUS_OK;
1557 /****************************************************************************
1558 Needed to show the msdfs symlinks as directories. Modifies psbuf
1559 to be a directory if it's a msdfs link.
1560 ****************************************************************************/
1562 static bool check_msdfs_link(connection_struct *conn,
1563 const char *pathname,
1564 SMB_STRUCT_STAT *psbuf)
1566 int saved_errno = errno;
1567 if(lp_host_msdfs() &&
1568 lp_msdfs_root(SNUM(conn)) &&
1569 is_msdfs_link(conn, pathname, psbuf)) {
1571 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1574 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1575 errno = saved_errno;
1578 errno = saved_errno;
1583 /****************************************************************************
1584 Get a level dependent lanman2 dir entry.
1585 ****************************************************************************/
1587 struct smbd_dirptr_lanman2_state {
1588 connection_struct *conn;
1589 uint32_t info_level;
1590 bool check_mangled_names;
1592 bool got_exact_match;
1595 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1601 struct smbd_dirptr_lanman2_state *state =
1602 (struct smbd_dirptr_lanman2_state *)private_data;
1604 char mangled_name[13]; /* mangled 8.3 name. */
1608 /* Mangle fname if it's an illegal name. */
1609 if (mangle_must_mangle(dname, state->conn->params)) {
1611 * Slow path - ensure we can push the original name as UCS2. If
1612 * not, then just don't return this name.
1616 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1617 uint8_t *tmp = talloc_array(talloc_tos(),
1621 status = srvstr_push(NULL,
1622 FLAGS2_UNICODE_STRINGS,
1631 if (!NT_STATUS_IS_OK(status)) {
1635 ok = name_to_8_3(dname, mangled_name,
1636 true, state->conn->params);
1640 fname = mangled_name;
1645 got_match = exact_match(state->has_wild,
1646 state->conn->case_sensitive,
1648 state->got_exact_match = got_match;
1650 got_match = mask_match(fname, mask,
1651 state->conn->case_sensitive);
1654 if(!got_match && state->check_mangled_names &&
1655 !mangle_is_8_3(fname, false, state->conn->params)) {
1657 * It turns out that NT matches wildcards against
1658 * both long *and* short names. This may explain some
1659 * of the wildcard wierdness from old DOS clients
1660 * that some people have been seeing.... JRA.
1662 /* Force the mangling into 8.3. */
1663 ok = name_to_8_3(fname, mangled_name,
1664 false, state->conn->params);
1669 got_match = exact_match(state->has_wild,
1670 state->conn->case_sensitive,
1671 mangled_name, mask);
1672 state->got_exact_match = got_match;
1674 got_match = mask_match(mangled_name, mask,
1675 state->conn->case_sensitive);
1683 *_fname = talloc_strdup(ctx, fname);
1684 if (*_fname == NULL) {
1691 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1693 struct smb_filename *smb_fname,
1696 struct smbd_dirptr_lanman2_state *state =
1697 (struct smbd_dirptr_lanman2_state *)private_data;
1698 bool ms_dfs_link = false;
1701 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1702 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1703 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1704 "Couldn't lstat [%s] (%s)\n",
1705 smb_fname_str_dbg(smb_fname),
1709 } else if (!VALID_STAT(smb_fname->st) &&
1710 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1711 /* Needed to show the msdfs symlinks as
1714 ms_dfs_link = check_msdfs_link(state->conn,
1715 smb_fname->base_name,
1718 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1719 "Couldn't stat [%s] (%s)\n",
1720 smb_fname_str_dbg(smb_fname),
1727 mode = dos_mode_msdfs(state->conn, smb_fname);
1729 mode = dos_mode(state->conn, smb_fname);
1736 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1737 connection_struct *conn,
1739 uint32_t info_level,
1740 struct ea_list *name_list,
1741 bool check_mangled_names,
1742 bool requires_resume_key,
1745 const struct smb_filename *smb_fname,
1746 int space_remaining,
1752 uint64_t *last_entry_off)
1754 char *p, *q, *pdata = *ppdata;
1756 uint64_t file_size = 0;
1757 uint64_t allocation_size = 0;
1758 uint64_t file_index = 0;
1760 struct timespec mdate_ts = {0};
1761 struct timespec adate_ts = {0};
1762 struct timespec cdate_ts = {0};
1763 struct timespec create_date_ts = {0};
1764 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1766 char *last_entry_ptr;
1771 struct readdir_attr_data *readdir_attr_data = NULL;
1773 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1774 file_size = get_file_size_stat(&smb_fname->st);
1776 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1778 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1779 if (!NT_STATUS_IS_OK(status)) {
1780 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1785 file_index = get_FileIndex(conn, &smb_fname->st);
1787 mdate_ts = smb_fname->st.st_ex_mtime;
1788 adate_ts = smb_fname->st.st_ex_atime;
1789 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1790 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1792 if (lp_dos_filetime_resolution(SNUM(conn))) {
1793 dos_filetime_timespec(&create_date_ts);
1794 dos_filetime_timespec(&mdate_ts);
1795 dos_filetime_timespec(&adate_ts);
1796 dos_filetime_timespec(&cdate_ts);
1799 create_date = convert_timespec_to_time_t(create_date_ts);
1800 mdate = convert_timespec_to_time_t(mdate_ts);
1801 adate = convert_timespec_to_time_t(adate_ts);
1803 /* align the record */
1804 SMB_ASSERT(align >= 1);
1806 off = (int)PTR_DIFF(pdata, base_data);
1807 pad = (off + (align-1)) & ~(align-1);
1810 if (pad && pad > space_remaining) {
1811 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1812 "for padding (wanted %u, had %d)\n",
1815 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1819 /* initialize padding to 0 */
1821 memset(pdata, 0, pad);
1823 space_remaining -= pad;
1825 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1835 switch (info_level) {
1836 case SMB_FIND_INFO_STANDARD:
1837 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1838 if(requires_resume_key) {
1842 srv_put_dos_date2(p,0,create_date);
1843 srv_put_dos_date2(p,4,adate);
1844 srv_put_dos_date2(p,8,mdate);
1845 SIVAL(p,12,(uint32_t)file_size);
1846 SIVAL(p,16,(uint32_t)allocation_size);
1850 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1851 p += ucs2_align(base_data, p, 0);
1853 status = srvstr_push(base_data, flags2, p,
1854 fname, PTR_DIFF(end_data, p),
1855 STR_TERMINATE, &len);
1856 if (!NT_STATUS_IS_OK(status)) {
1859 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1861 SCVAL(nameptr, -1, len - 2);
1863 SCVAL(nameptr, -1, 0);
1867 SCVAL(nameptr, -1, len - 1);
1869 SCVAL(nameptr, -1, 0);
1875 case SMB_FIND_EA_SIZE:
1876 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1877 if (requires_resume_key) {
1881 srv_put_dos_date2(p,0,create_date);
1882 srv_put_dos_date2(p,4,adate);
1883 srv_put_dos_date2(p,8,mdate);
1884 SIVAL(p,12,(uint32_t)file_size);
1885 SIVAL(p,16,(uint32_t)allocation_size);
1888 unsigned int ea_size = estimate_ea_size(conn, NULL,
1890 SIVAL(p,22,ea_size); /* Extended attributes */
1894 status = srvstr_push(base_data, flags2,
1895 p, fname, PTR_DIFF(end_data, p),
1896 STR_TERMINATE | STR_NOALIGN, &len);
1897 if (!NT_STATUS_IS_OK(status)) {
1900 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1913 SCVAL(nameptr,0,len);
1915 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1918 case SMB_FIND_EA_LIST:
1920 struct ea_list *file_list = NULL;
1923 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1925 return NT_STATUS_INVALID_PARAMETER;
1927 if (requires_resume_key) {
1931 srv_put_dos_date2(p,0,create_date);
1932 srv_put_dos_date2(p,4,adate);
1933 srv_put_dos_date2(p,8,mdate);
1934 SIVAL(p,12,(uint32_t)file_size);
1935 SIVAL(p,16,(uint32_t)allocation_size);
1937 p += 22; /* p now points to the EA area. */
1939 status = get_ea_list_from_file(ctx, conn, NULL,
1941 &ea_len, &file_list);
1942 if (!NT_STATUS_IS_OK(status)) {
1945 name_list = ea_list_union(name_list, file_list, &ea_len);
1947 /* We need to determine if this entry will fit in the space available. */
1948 /* Max string size is 255 bytes. */
1949 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1950 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1951 "(wanted %u, had %d)\n",
1952 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1954 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1957 /* Push the ea_data followed by the name. */
1958 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1960 status = srvstr_push(base_data, flags2,
1961 p + 1, fname, PTR_DIFF(end_data, p+1),
1962 STR_TERMINATE | STR_NOALIGN, &len);
1963 if (!NT_STATUS_IS_OK(status)) {
1966 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1979 SCVAL(nameptr,0,len);
1981 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1985 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1986 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1987 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1989 SIVAL(p,0,reskey); p += 4;
1990 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1991 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1992 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1993 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1994 SOFF_T(p,0,file_size); p += 8;
1995 SOFF_T(p,0,allocation_size); p += 8;
1996 SIVAL(p,0,mode); p += 4;
1997 q = p; p += 4; /* q is placeholder for name length. */
1998 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1999 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2001 unsigned int ea_size = estimate_ea_size(conn, NULL,
2003 SIVAL(p,0,ea_size); /* Extended attributes */
2006 /* Clear the short name buffer. This is
2007 * IMPORTANT as not doing so will trigger
2008 * a Win2k client bug. JRA.
2010 if (!was_8_3 && check_mangled_names) {
2011 char mangled_name[13]; /* mangled 8.3 name. */
2012 if (!name_to_8_3(fname,mangled_name,True,
2014 /* Error - mangle failed ! */
2015 memset(mangled_name,'\0',12);
2017 mangled_name[12] = 0;
2018 status = srvstr_push(base_data, flags2,
2019 p+2, mangled_name, 24,
2020 STR_UPPER|STR_UNICODE, &len);
2021 if (!NT_STATUS_IS_OK(status)) {
2025 memset(p + 2 + len,'\0',24 - len);
2032 status = srvstr_push(base_data, flags2, p,
2033 fname, PTR_DIFF(end_data, p),
2034 STR_TERMINATE_ASCII, &len);
2035 if (!NT_STATUS_IS_OK(status)) {
2041 len = PTR_DIFF(p, pdata);
2042 pad = (len + (align-1)) & ~(align-1);
2044 * offset to the next entry, the caller
2045 * will overwrite it for the last entry
2046 * that's why we always include the padding
2050 * set padding to zero
2053 memset(p, 0, pad - len);
2060 case SMB_FIND_FILE_DIRECTORY_INFO:
2061 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2063 SIVAL(p,0,reskey); p += 4;
2064 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2065 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2066 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2067 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2068 SOFF_T(p,0,file_size); p += 8;
2069 SOFF_T(p,0,allocation_size); p += 8;
2070 SIVAL(p,0,mode); p += 4;
2071 status = srvstr_push(base_data, flags2,
2072 p + 4, fname, PTR_DIFF(end_data, p+4),
2073 STR_TERMINATE_ASCII, &len);
2074 if (!NT_STATUS_IS_OK(status)) {
2080 len = PTR_DIFF(p, pdata);
2081 pad = (len + (align-1)) & ~(align-1);
2083 * offset to the next entry, the caller
2084 * will overwrite it for the last entry
2085 * that's why we always include the padding
2089 * set padding to zero
2092 memset(p, 0, pad - len);
2099 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2100 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2102 SIVAL(p,0,reskey); p += 4;
2103 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2104 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2105 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2106 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2107 SOFF_T(p,0,file_size); p += 8;
2108 SOFF_T(p,0,allocation_size); p += 8;
2109 SIVAL(p,0,mode); p += 4;
2110 q = p; p += 4; /* q is placeholder for name length. */
2112 unsigned int ea_size = estimate_ea_size(conn, NULL,
2114 SIVAL(p,0,ea_size); /* Extended attributes */
2117 status = srvstr_push(base_data, flags2, p,
2118 fname, PTR_DIFF(end_data, p),
2119 STR_TERMINATE_ASCII, &len);
2120 if (!NT_STATUS_IS_OK(status)) {
2126 len = PTR_DIFF(p, pdata);
2127 pad = (len + (align-1)) & ~(align-1);
2129 * offset to the next entry, the caller
2130 * will overwrite it for the last entry
2131 * that's why we always include the padding
2135 * set padding to zero
2138 memset(p, 0, pad - len);
2145 case SMB_FIND_FILE_NAMES_INFO:
2146 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2148 SIVAL(p,0,reskey); p += 4;
2150 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2151 acl on a dir (tridge) */
2152 status = srvstr_push(base_data, flags2, p,
2153 fname, PTR_DIFF(end_data, p),
2154 STR_TERMINATE_ASCII, &len);
2155 if (!NT_STATUS_IS_OK(status)) {
2161 len = PTR_DIFF(p, pdata);
2162 pad = (len + (align-1)) & ~(align-1);
2164 * offset to the next entry, the caller
2165 * will overwrite it for the last entry
2166 * that's why we always include the padding
2170 * set padding to zero
2173 memset(p, 0, pad - len);
2180 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2181 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2183 SIVAL(p,0,reskey); p += 4;
2184 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2185 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2186 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2187 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2188 SOFF_T(p,0,file_size); p += 8;
2189 SOFF_T(p,0,allocation_size); p += 8;
2190 SIVAL(p,0,mode); p += 4;
2191 q = p; p += 4; /* q is placeholder for name length. */
2192 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2193 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2195 unsigned int ea_size = estimate_ea_size(conn, NULL,
2197 SIVAL(p,0,ea_size); /* Extended attributes */
2200 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2201 SBVAL(p,0,file_index); p += 8;
2202 status = srvstr_push(base_data, flags2, p,
2203 fname, PTR_DIFF(end_data, p),
2204 STR_TERMINATE_ASCII, &len);
2205 if (!NT_STATUS_IS_OK(status)) {
2211 len = PTR_DIFF(p, pdata);
2212 pad = (len + (align-1)) & ~(align-1);
2214 * offset to the next entry, the caller
2215 * will overwrite it for the last entry
2216 * that's why we always include the padding
2220 * set padding to zero
2223 memset(p, 0, pad - len);
2230 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2231 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2232 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2234 SIVAL(p,0,reskey); p += 4;
2235 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2236 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2237 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2238 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2239 SOFF_T(p,0,file_size); p += 8;
2240 SOFF_T(p,0,allocation_size); p += 8;
2241 SIVAL(p,0,mode); p += 4;
2242 q = p; p += 4; /* q is placeholder for name length */
2243 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2244 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2245 } else if (readdir_attr_data &&
2246 readdir_attr_data->type == RDATTR_AAPL) {
2248 * OS X specific SMB2 extension negotiated via
2249 * AAPL create context: return max_access in
2252 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2254 unsigned int ea_size = estimate_ea_size(conn, NULL,
2256 SIVAL(p,0,ea_size); /* Extended attributes */
2260 if (readdir_attr_data &&
2261 readdir_attr_data->type == RDATTR_AAPL) {
2263 * OS X specific SMB2 extension negotiated via
2264 * AAPL create context: return resource fork
2265 * length and compressed FinderInfo in
2268 * According to documentation short_name_len
2269 * should be 0, but on the wire behaviour
2270 * shows its set to 24 by clients.
2274 /* Resourefork length */
2275 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2277 /* Compressed FinderInfo */
2278 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2279 } else if (!was_8_3 && check_mangled_names) {
2280 char mangled_name[13]; /* mangled 8.3 name. */
2281 if (!name_to_8_3(fname,mangled_name,True,
2283 /* Error - mangle failed ! */
2284 memset(mangled_name,'\0',12);
2286 mangled_name[12] = 0;
2287 status = srvstr_push(base_data, flags2,
2288 p+2, mangled_name, 24,
2289 STR_UPPER|STR_UNICODE, &len);
2290 if (!NT_STATUS_IS_OK(status)) {
2295 memset(p + 2 + len,'\0',24 - len);
2299 /* Clear the short name buffer. This is
2300 * IMPORTANT as not doing so will trigger
2301 * a Win2k client bug. JRA.
2308 if (readdir_attr_data &&
2309 readdir_attr_data->type == RDATTR_AAPL) {
2311 * OS X specific SMB2 extension negotiated via
2312 * AAPL create context: return UNIX mode in
2315 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2316 SSVAL(p, 0, aapl_mode);
2322 SBVAL(p,0,file_index); p += 8;
2323 status = srvstr_push(base_data, flags2, p,
2324 fname, PTR_DIFF(end_data, p),
2325 STR_TERMINATE_ASCII, &len);
2326 if (!NT_STATUS_IS_OK(status)) {
2332 len = PTR_DIFF(p, pdata);
2333 pad = (len + (align-1)) & ~(align-1);
2335 * offset to the next entry, the caller
2336 * will overwrite it for the last entry
2337 * that's why we always include the padding
2341 * set padding to zero
2344 memset(p, 0, pad - len);
2351 /* CIFS UNIX Extension. */
2353 case SMB_FIND_FILE_UNIX:
2354 case SMB_FIND_FILE_UNIX_INFO2:
2356 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2358 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2360 if (info_level == SMB_FIND_FILE_UNIX) {
2361 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2362 p = store_file_unix_basic(conn, p,
2363 NULL, &smb_fname->st);
2364 status = srvstr_push(base_data, flags2, p,
2365 fname, PTR_DIFF(end_data, p),
2366 STR_TERMINATE, &len);
2367 if (!NT_STATUS_IS_OK(status)) {
2371 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2372 p = store_file_unix_basic_info2(conn, p,
2373 NULL, &smb_fname->st);
2376 status = srvstr_push(base_data, flags2, p, fname,
2377 PTR_DIFF(end_data, p), 0, &len);
2378 if (!NT_STATUS_IS_OK(status)) {
2381 SIVAL(nameptr, 0, len);
2386 len = PTR_DIFF(p, pdata);
2387 pad = (len + (align-1)) & ~(align-1);
2389 * offset to the next entry, the caller
2390 * will overwrite it for the last entry
2391 * that's why we always include the padding
2395 * set padding to zero
2398 memset(p, 0, pad - len);
2403 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2408 return NT_STATUS_INVALID_LEVEL;
2411 if (PTR_DIFF(p,pdata) > space_remaining) {
2412 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2413 "(wanted %u, had %d)\n",
2414 (unsigned int)PTR_DIFF(p,pdata),
2416 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2419 /* Setup the last entry pointer, as an offset from base_data */
2420 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2421 /* Advance the data pointer to the next slot */
2424 return NT_STATUS_OK;
2427 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2428 connection_struct *conn,
2429 struct dptr_struct *dirptr,
2431 const char *path_mask,
2434 int requires_resume_key,
2442 int space_remaining,
2443 bool *got_exact_match,
2444 int *_last_entry_off,
2445 struct ea_list *name_list)
2448 const char *mask = NULL;
2449 long prev_dirpos = 0;
2452 struct smb_filename *smb_fname = NULL;
2453 struct smbd_dirptr_lanman2_state state;
2455 uint64_t last_entry_off = 0;
2457 enum mangled_names_options mangled_names;
2458 bool marshall_with_83_names;
2460 mangled_names = lp_mangled_names(conn->params);
2464 state.info_level = info_level;
2465 if (mangled_names != MANGLED_NAMES_NO) {
2466 state.check_mangled_names = true;
2468 state.has_wild = dptr_has_wild(dirptr);
2469 state.got_exact_match = false;
2471 *got_exact_match = false;
2473 p = strrchr_m(path_mask,'/');
2484 ok = smbd_dirptr_get_entry(ctx,
2490 smbd_dirptr_lanman2_match_fn,
2491 smbd_dirptr_lanman2_mode_fn,
2498 return NT_STATUS_END_OF_FILE;
2501 *got_exact_match = state.got_exact_match;
2503 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2505 status = smbd_marshall_dir_entry(ctx,
2510 marshall_with_83_names,
2511 requires_resume_key,
2522 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2523 DEBUG(1,("Conversion error: illegal character: %s\n",
2524 smb_fname_str_dbg(smb_fname)));
2527 TALLOC_FREE(smb_fname);
2528 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2529 dptr_SeekDir(dirptr, prev_dirpos);
2532 if (!NT_STATUS_IS_OK(status)) {
2536 *_last_entry_off = last_entry_off;
2537 return NT_STATUS_OK;
2540 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2541 connection_struct *conn,
2542 struct dptr_struct *dirptr,
2544 const char *path_mask,
2547 bool requires_resume_key,
2553 int space_remaining,
2554 bool *got_exact_match,
2555 int *last_entry_off,
2556 struct ea_list *name_list)
2559 const bool do_pad = true;
2561 if (info_level >= 1 && info_level <= 3) {
2562 /* No alignment on earlier info levels. */
2566 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2567 path_mask, dirtype, info_level,
2568 requires_resume_key, dont_descend, ask_sharemode,
2570 ppdata, base_data, end_data,
2573 last_entry_off, name_list);
2576 /****************************************************************************
2577 Reply to a TRANS2_FINDFIRST.
2578 ****************************************************************************/
2580 static void call_trans2findfirst(connection_struct *conn,
2581 struct smb_request *req,
2582 char **pparams, int total_params,
2583 char **ppdata, int total_data,
2584 unsigned int max_data_bytes)
2586 /* We must be careful here that we don't return more than the
2587 allowed number of data bytes. If this means returning fewer than
2588 maxentries then so be it. We assume that the redirector has
2589 enough room for the fixed number of parameter bytes it has
2591 struct smb_filename *smb_dname = NULL;
2592 char *params = *pparams;
2593 char *pdata = *ppdata;
2597 uint16_t findfirst_flags;
2598 bool close_after_first;
2600 bool requires_resume_key;
2602 char *directory = NULL;
2605 int last_entry_off=0;
2609 bool finished = False;
2610 bool dont_descend = False;
2611 bool out_of_space = False;
2612 int space_remaining;
2613 bool mask_contains_wcard = False;
2614 struct ea_list *ea_list = NULL;
2615 NTSTATUS ntstatus = NT_STATUS_OK;
2616 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2617 struct dptr_struct *dirptr = NULL;
2618 struct smbd_server_connection *sconn = req->sconn;
2619 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2620 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2621 bool backup_priv = false;
2622 bool as_root = false;
2624 if (total_params < 13) {
2625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2629 dirtype = SVAL(params,0);
2630 maxentries = SVAL(params,2);
2631 findfirst_flags = SVAL(params,4);
2632 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2633 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2634 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2635 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2636 security_token_has_privilege(get_current_nttok(conn),
2639 info_level = SVAL(params,6);
2641 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2642 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2643 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2645 info_level, max_data_bytes));
2648 /* W2K3 seems to treat zero as 1. */
2652 switch (info_level) {
2653 case SMB_FIND_INFO_STANDARD:
2654 case SMB_FIND_EA_SIZE:
2655 case SMB_FIND_EA_LIST:
2656 case SMB_FIND_FILE_DIRECTORY_INFO:
2657 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2658 case SMB_FIND_FILE_NAMES_INFO:
2659 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2660 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2661 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2663 case SMB_FIND_FILE_UNIX:
2664 case SMB_FIND_FILE_UNIX_INFO2:
2665 /* Always use filesystem for UNIX mtime query. */
2666 ask_sharemode = false;
2667 if (!lp_unix_extensions()) {
2668 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2671 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2674 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2678 if (req->posix_pathnames) {
2679 srvstr_get_path_wcard_posix(talloc_tos(),
2687 &mask_contains_wcard);
2689 srvstr_get_path_wcard(talloc_tos(),
2697 &mask_contains_wcard);
2699 if (!NT_STATUS_IS_OK(ntstatus)) {
2700 reply_nterror(req, ntstatus);
2707 ntstatus = filename_convert_with_privilege(talloc_tos(),
2712 &mask_contains_wcard,
2715 ntstatus = filename_convert(talloc_tos(), conn,
2716 req->flags2 & FLAGS2_DFS_PATHNAMES,
2719 &mask_contains_wcard,
2723 if (!NT_STATUS_IS_OK(ntstatus)) {
2724 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2725 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2726 ERRSRV, ERRbadpath);
2729 reply_nterror(req, ntstatus);
2733 mask = smb_dname->original_lcomp;
2735 directory = smb_dname->base_name;
2737 p = strrchr_m(directory,'/');
2739 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2740 if((directory[0] == '.') && (directory[1] == '\0')) {
2741 mask = talloc_strdup(talloc_tos(),"*");
2743 reply_nterror(req, NT_STATUS_NO_MEMORY);
2746 mask_contains_wcard = True;
2752 if (p == NULL || p == directory) {
2753 /* Ensure we don't have a directory name of "". */
2754 directory = talloc_strdup(talloc_tos(), ".");
2756 reply_nterror(req, NT_STATUS_NO_MEMORY);
2759 /* Ensure smb_dname->base_name matches. */
2760 smb_dname->base_name = directory;
2763 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2765 if (info_level == SMB_FIND_EA_LIST) {
2768 if (total_data < 4) {
2769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2773 ea_size = IVAL(pdata,0);
2774 if (ea_size != total_data) {
2775 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2776 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2777 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2781 if (!lp_ea_support(SNUM(conn))) {
2782 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2786 /* Pull out the list of names. */
2787 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2794 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2795 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2799 *ppdata = (char *)SMB_REALLOC(
2800 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2801 if(*ppdata == NULL ) {
2802 reply_nterror(req, NT_STATUS_NO_MEMORY);
2806 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2808 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2811 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2812 /* Realloc the params space */
2813 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2814 if (*pparams == NULL) {
2815 reply_nterror(req, NT_STATUS_NO_MEMORY);
2820 /* Save the wildcard match and attribs we are using on this directory -
2821 needed as lanman2 assumes these are being saved between calls */
2823 ntstatus = dptr_create(conn,
2831 mask_contains_wcard,
2835 if (!NT_STATUS_IS_OK(ntstatus)) {
2836 reply_nterror(req, ntstatus);
2841 /* Remember this in case we have
2842 to do a findnext. */
2843 dptr_set_priv(dirptr);
2846 dptr_num = dptr_dnum(dirptr);
2847 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2849 /* Initialize per TRANS2_FIND_FIRST operation data */
2850 dptr_init_search_op(dirptr);
2852 /* We don't need to check for VOL here as this is returned by
2853 a different TRANS2 call. */
2855 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2856 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2857 if (in_list(directory,
2858 lp_dont_descend(talloc_tos(), SNUM(conn)),
2859 conn->case_sensitive)) {
2860 dont_descend = True;
2864 space_remaining = max_data_bytes;
2865 out_of_space = False;
2867 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2868 bool got_exact_match = False;
2870 /* this is a heuristic to avoid seeking the dirptr except when
2871 absolutely necessary. It allows for a filename of about 40 chars */
2872 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2873 out_of_space = True;
2876 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2880 mask,dirtype,info_level,
2881 requires_resume_key,dont_descend,
2886 &last_entry_off, ea_list);
2887 if (NT_STATUS_EQUAL(ntstatus,
2888 NT_STATUS_ILLEGAL_CHARACTER)) {
2890 * Bad character conversion on name. Ignore this
2895 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2896 out_of_space = true;
2898 finished = !NT_STATUS_IS_OK(ntstatus);
2902 if (!finished && !out_of_space)
2906 * As an optimisation if we know we aren't looking
2907 * for a wildcard name (ie. the name matches the wildcard exactly)
2908 * then we can finish on any (first) match.
2909 * This speeds up large directory searches. JRA.
2915 /* Ensure space_remaining never goes -ve. */
2916 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2917 space_remaining = 0;
2918 out_of_space = true;
2920 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2924 /* Check if we can close the dirptr */
2925 if(close_after_first || (finished && close_if_end)) {
2926 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2927 dptr_close(sconn, &dptr_num);
2931 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2932 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2933 * the protocol level is less than NT1. Tested with smbclient. JRA.
2934 * This should fix the OS/2 client bug #2335.
2937 if(numentries == 0) {
2938 dptr_close(sconn, &dptr_num);
2939 if (get_Protocol() < PROTOCOL_NT1) {
2940 reply_force_doserror(req, ERRDOS, ERRnofiles);
2943 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2944 ERRDOS, ERRbadfile);
2949 /* At this point pdata points to numentries directory entries. */
2951 /* Set up the return parameter block */
2952 SSVAL(params,0,dptr_num);
2953 SSVAL(params,2,numentries);
2954 SSVAL(params,4,finished);
2955 SSVAL(params,6,0); /* Never an EA error */
2956 SSVAL(params,8,last_entry_off);
2958 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2961 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2962 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2964 reply_nterror(req, NT_STATUS_NO_MEMORY);
2968 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2969 smb_fn_name(req->cmd),
2970 mask, directory, dirtype, numentries ) );
2973 * Force a name mangle here to ensure that the
2974 * mask as an 8.3 name is top of the mangled cache.
2975 * The reasons for this are subtle. Don't remove
2976 * this code unless you know what you are doing
2977 * (see PR#13758). JRA.
2980 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2981 char mangled_name[13];
2982 name_to_8_3(mask, mangled_name, True, conn->params);
2990 TALLOC_FREE(smb_dname);
2994 /****************************************************************************
2995 Reply to a TRANS2_FINDNEXT.
2996 ****************************************************************************/
2998 static void call_trans2findnext(connection_struct *conn,
2999 struct smb_request *req,
3000 char **pparams, int total_params,
3001 char **ppdata, int total_data,
3002 unsigned int max_data_bytes)
3004 /* We must be careful here that we don't return more than the
3005 allowed number of data bytes. If this means returning fewer than
3006 maxentries then so be it. We assume that the redirector has
3007 enough room for the fixed number of parameter bytes it has
3009 char *params = *pparams;
3010 char *pdata = *ppdata;
3014 uint16_t info_level;
3015 uint32_t resume_key;
3016 uint16_t findnext_flags;
3017 bool close_after_request;
3019 bool requires_resume_key;
3021 bool mask_contains_wcard = False;
3022 char *resume_name = NULL;
3023 const char *mask = NULL;
3024 const char *directory = NULL;
3028 int i, last_entry_off=0;
3029 bool finished = False;
3030 bool dont_descend = False;
3031 bool out_of_space = False;
3032 int space_remaining;
3033 struct ea_list *ea_list = NULL;
3034 NTSTATUS ntstatus = NT_STATUS_OK;
3035 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3036 TALLOC_CTX *ctx = talloc_tos();
3037 struct dptr_struct *dirptr;
3038 struct smbd_server_connection *sconn = req->sconn;
3039 bool backup_priv = false;
3040 bool as_root = false;
3042 if (total_params < 13) {
3043 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3047 dptr_num = SVAL(params,0);
3048 maxentries = SVAL(params,2);
3049 info_level = SVAL(params,4);
3050 resume_key = IVAL(params,6);
3051 findnext_flags = SVAL(params,10);
3052 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3053 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3054 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3055 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3057 if (!continue_bit) {
3058 /* We only need resume_name if continue_bit is zero. */
3059 if (req->posix_pathnames) {
3060 srvstr_get_path_wcard_posix(ctx,
3068 &mask_contains_wcard);
3070 srvstr_get_path_wcard(ctx,
3078 &mask_contains_wcard);
3080 if (!NT_STATUS_IS_OK(ntstatus)) {
3081 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3082 complain (it thinks we're asking for the directory above the shared
3083 path or an invalid name). Catch this as the resume name is only compared, never used in
3084 a file access. JRA. */
3085 srvstr_pull_talloc(ctx, params, req->flags2,
3086 &resume_name, params+12,
3090 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3091 reply_nterror(req, ntstatus);
3097 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3098 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3099 resume_key = %d resume name = %s continue=%d level = %d\n",
3100 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3101 requires_resume_key, resume_key,
3102 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3105 /* W2K3 seems to treat zero as 1. */
3109 switch (info_level) {
3110 case SMB_FIND_INFO_STANDARD:
3111 case SMB_FIND_EA_SIZE:
3112 case SMB_FIND_EA_LIST:
3113 case SMB_FIND_FILE_DIRECTORY_INFO:
3114 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3115 case SMB_FIND_FILE_NAMES_INFO:
3116 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3117 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3118 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3120 case SMB_FIND_FILE_UNIX:
3121 case SMB_FIND_FILE_UNIX_INFO2:
3122 /* Always use filesystem for UNIX mtime query. */
3123 ask_sharemode = false;
3124 if (!lp_unix_extensions()) {
3125 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3130 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3134 if (info_level == SMB_FIND_EA_LIST) {
3137 if (total_data < 4) {
3138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3142 ea_size = IVAL(pdata,0);
3143 if (ea_size != total_data) {
3144 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3145 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3146 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3150 if (!lp_ea_support(SNUM(conn))) {
3151 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3155 /* Pull out the list of names. */
3156 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3158 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3163 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3168 *ppdata = (char *)SMB_REALLOC(
3169 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3170 if(*ppdata == NULL) {
3171 reply_nterror(req, NT_STATUS_NO_MEMORY);
3176 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3179 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3182 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3183 /* Realloc the params space */
3184 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3185 if(*pparams == NULL ) {
3186 reply_nterror(req, NT_STATUS_NO_MEMORY);
3192 /* Check that the dptr is valid */
3193 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3194 reply_nterror(req, STATUS_NO_MORE_FILES);
3198 directory = dptr_path(sconn, dptr_num);
3200 /* Get the wildcard mask from the dptr */
3201 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3202 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3203 reply_nterror(req, STATUS_NO_MORE_FILES);
3207 /* Get the attr mask from the dptr */
3208 dirtype = dptr_attr(sconn, dptr_num);
3210 backup_priv = dptr_get_priv(dirptr);
3212 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3213 "backup_priv = %d\n",
3214 dptr_num, mask, dirtype,
3216 dptr_TellDir(dirptr),
3219 /* Initialize per TRANS2_FIND_NEXT operation data */
3220 dptr_init_search_op(dirptr);
3222 /* We don't need to check for VOL here as this is returned by
3223 a different TRANS2 call. */
3225 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3226 directory,lp_dont_descend(ctx, SNUM(conn))));
3227 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3228 dont_descend = True;
3231 space_remaining = max_data_bytes;
3232 out_of_space = False;
3240 * Seek to the correct position. We no longer use the resume key but
3241 * depend on the last file name instead.
3244 if(!continue_bit && resume_name && *resume_name) {
3247 long current_pos = 0;
3249 * Remember, name_to_8_3 is called by
3250 * get_lanman2_dir_entry(), so the resume name
3251 * could be mangled. Ensure we check the unmangled name.
3254 if (mangle_is_mangled(resume_name, conn->params)) {
3255 char *new_resume_name = NULL;
3256 mangle_lookup_name_from_8_3(ctx,
3260 if (new_resume_name) {
3261 resume_name = new_resume_name;
3266 * Fix for NT redirector problem triggered by resume key indexes
3267 * changing between directory scans. We now return a resume key of 0
3268 * and instead look for the filename to continue from (also given
3269 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3270 * findfirst/findnext (as is usual) then the directory pointer
3271 * should already be at the correct place.
3274 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3275 } /* end if resume_name && !continue_bit */
3277 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3278 bool got_exact_match = False;
3280 /* this is a heuristic to avoid seeking the dirptr except when
3281 absolutely necessary. It allows for a filename of about 40 chars */
3282 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3283 out_of_space = True;
3286 ntstatus = get_lanman2_dir_entry(ctx,
3290 mask,dirtype,info_level,
3291 requires_resume_key,dont_descend,
3296 &last_entry_off, ea_list);
3297 if (NT_STATUS_EQUAL(ntstatus,
3298 NT_STATUS_ILLEGAL_CHARACTER)) {
3300 * Bad character conversion on name. Ignore this
3305 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3306 out_of_space = true;
3308 finished = !NT_STATUS_IS_OK(ntstatus);
3312 if (!finished && !out_of_space)
3316 * As an optimisation if we know we aren't looking
3317 * for a wildcard name (ie. the name matches the wildcard exactly)
3318 * then we can finish on any (first) match.
3319 * This speeds up large directory searches. JRA.
3325 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3328 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3329 smb_fn_name(req->cmd),
3330 mask, directory, dirtype, numentries ) );
3332 /* Check if we can close the dirptr */
3333 if(close_after_request || (finished && close_if_end)) {
3334 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3335 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3342 /* Set up the return parameter block */
3343 SSVAL(params,0,numentries);
3344 SSVAL(params,2,finished);
3345 SSVAL(params,4,0); /* Never an EA error */
3346 SSVAL(params,6,last_entry_off);
3348 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3354 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3356 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3360 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3362 SMB_ASSERT(extended_info != NULL);
3364 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3365 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3366 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3367 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3368 #ifdef SAMBA_VERSION_REVISION
3369 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3371 extended_info->samba_subversion = 0;
3372 #ifdef SAMBA_VERSION_RC_RELEASE
3373 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3375 #ifdef SAMBA_VERSION_PRE_RELEASE
3376 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3379 #ifdef SAMBA_VERSION_VENDOR_PATCH
3380 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3382 extended_info->samba_gitcommitdate = 0;
3383 #ifdef SAMBA_VERSION_COMMIT_TIME
3384 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3387 memset(extended_info->samba_version_string, 0,
3388 sizeof(extended_info->samba_version_string));
3390 snprintf (extended_info->samba_version_string,
3391 sizeof(extended_info->samba_version_string),
3392 "%s", samba_version_string());
3395 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3396 connection_struct *conn,
3397 TALLOC_CTX *mem_ctx,
3398 uint16_t info_level,
3400 unsigned int max_data_bytes,
3401 size_t *fixed_portion,
3402 struct smb_filename *fname,
3406 char *pdata, *end_data;
3409 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3410 int snum = SNUM(conn);
3411 const char *fstype = lp_fstype(SNUM(conn));
3412 const char *filename = NULL;
3413 const uint64_t bytes_per_sector = 512;
3414 uint32_t additional_flags = 0;
3415 struct smb_filename smb_fname;
3417 NTSTATUS status = NT_STATUS_OK;
3420 if (fname == NULL || fname->base_name == NULL) {
3423 filename = fname->base_name;
3427 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3428 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3429 "info level (0x%x) on IPC$.\n",
3430 (unsigned int)info_level));
3431 return NT_STATUS_ACCESS_DENIED;
3435 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3437 ZERO_STRUCT(smb_fname);
3438 smb_fname.base_name = discard_const_p(char, filename);
3440 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3441 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3442 return map_nt_error_from_unix(errno);
3447 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3448 return NT_STATUS_INVALID_PARAMETER;
3451 *ppdata = (char *)SMB_REALLOC(
3452 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3453 if (*ppdata == NULL) {
3454 return NT_STATUS_NO_MEMORY;
3458 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3459 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3463 switch (info_level) {
3464 case SMB_INFO_ALLOCATION:
3466 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3468 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3470 if (df_ret == (uint64_t)-1) {
3471 return map_nt_error_from_unix(errno);
3474 block_size = lp_block_size(snum);
3475 if (bsize < block_size) {
3476 uint64_t factor = block_size/bsize;
3481 if (bsize > block_size) {
3482 uint64_t factor = bsize/block_size;
3487 sectors_per_unit = bsize/bytes_per_sector;
3489 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3490 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3491 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3493 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3494 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3495 SIVAL(pdata,l1_cUnit,dsize);
3496 SIVAL(pdata,l1_cUnitAvail,dfree);
3497 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3501 case SMB_INFO_VOLUME:
3502 /* Return volume name */
3504 * Add volume serial number - hash of a combination of
3505 * the called hostname and the service name.
3507 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3509 * Win2k3 and previous mess this up by sending a name length
3510 * one byte short. I believe only older clients (OS/2 Win9x) use
3511 * this call so try fixing this by adding a terminating null to
3512 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3514 status = srvstr_push(
3516 pdata+l2_vol_szVolLabel, vname,
3517 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3518 STR_NOALIGN|STR_TERMINATE, &len);
3519 if (!NT_STATUS_IS_OK(status)) {
3522 SCVAL(pdata,l2_vol_cch,len);
3523 data_len = l2_vol_szVolLabel + len;
3524 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3525 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3526 (unsigned)len, vname));
3529 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3530 case SMB_FS_ATTRIBUTE_INFORMATION:
3532 additional_flags = 0;
3533 #if defined(HAVE_SYS_QUOTAS)
3534 additional_flags |= FILE_VOLUME_QUOTAS;
3537 if(lp_nt_acl_support(SNUM(conn))) {
3538 additional_flags |= FILE_PERSISTENT_ACLS;
3541 /* Capabilities are filled in at connection time through STATVFS call */
3542 additional_flags |= conn->fs_capabilities;
3543 additional_flags |= lp_parm_int(conn->params->service,
3544 "share", "fake_fscaps",
3547 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3548 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3549 additional_flags); /* FS ATTRIBUTES */
3551 SIVAL(pdata,4,255); /* Max filename component length */
3552 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3553 and will think we can't do long filenames */
3554 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3555 PTR_DIFF(end_data, pdata+12),
3557 if (!NT_STATUS_IS_OK(status)) {
3561 data_len = 12 + len;
3562 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3563 /* the client only requested a portion of the
3565 data_len = max_data_bytes;
3566 status = STATUS_BUFFER_OVERFLOW;
3568 *fixed_portion = 16;
3571 case SMB_QUERY_FS_LABEL_INFO:
3572 case SMB_FS_LABEL_INFORMATION:
3573 status = srvstr_push(pdata, flags2, pdata+4, vname,
3574 PTR_DIFF(end_data, pdata+4), 0, &len);
3575 if (!NT_STATUS_IS_OK(status)) {
3582 case SMB_QUERY_FS_VOLUME_INFO:
3583 case SMB_FS_VOLUME_INFORMATION:
3586 * Add volume serial number - hash of a combination of
3587 * the called hostname and the service name.
3589 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3590 (str_checksum(get_local_machine_name())<<16));
3592 /* Max label len is 32 characters. */
3593 status = srvstr_push(pdata, flags2, pdata+18, vname,
3594 PTR_DIFF(end_data, pdata+18),
3596 if (!NT_STATUS_IS_OK(status)) {
3599 SIVAL(pdata,12,len);
3602 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3603 (int)strlen(vname),vname,
3604 lp_servicename(talloc_tos(), snum)));
3605 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3606 /* the client only requested a portion of the
3608 data_len = max_data_bytes;
3609 status = STATUS_BUFFER_OVERFLOW;
3611 *fixed_portion = 24;
3614 case SMB_QUERY_FS_SIZE_INFO:
3615 case SMB_FS_SIZE_INFORMATION:
3617 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3619 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3621 if (df_ret == (uint64_t)-1) {
3622 return map_nt_error_from_unix(errno);
3624 block_size = lp_block_size(snum);
3625 if (bsize < block_size) {
3626 uint64_t factor = block_size/bsize;
3631 if (bsize > block_size) {
3632 uint64_t factor = bsize/block_size;
3637 sectors_per_unit = bsize/bytes_per_sector;
3638 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3639 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3640 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3641 SBIG_UINT(pdata,0,dsize);
3642 SBIG_UINT(pdata,8,dfree);
3643 SIVAL(pdata,16,sectors_per_unit);
3644 SIVAL(pdata,20,bytes_per_sector);
3645 *fixed_portion = 24;
3649 case SMB_FS_FULL_SIZE_INFORMATION:
3651 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3653 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3655 if (df_ret == (uint64_t)-1) {
3656 return map_nt_error_from_unix(errno);
3658 block_size = lp_block_size(snum);
3659 if (bsize < block_size) {
3660 uint64_t factor = block_size/bsize;
3665 if (bsize > block_size) {
3666 uint64_t factor = bsize/block_size;
3671 sectors_per_unit = bsize/bytes_per_sector;
3672 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3673 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3674 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3675 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3676 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3677 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3678 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3679 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3680 *fixed_portion = 32;
3684 case SMB_QUERY_FS_DEVICE_INFO:
3685 case SMB_FS_DEVICE_INFORMATION:
3687 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3689 if (!CAN_WRITE(conn)) {
3690 characteristics |= FILE_READ_ONLY_DEVICE;
3693 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3694 SIVAL(pdata,4,characteristics);
3699 #ifdef HAVE_SYS_QUOTAS
3700 case SMB_FS_QUOTA_INFORMATION:
3702 * what we have to send --metze:
3704 * Unknown1: 24 NULL bytes
3705 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3706 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3707 * Quota Flags: 2 byte :
3708 * Unknown3: 6 NULL bytes
3712 * details for Quota Flags:
3714 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3715 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3716 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3717 * 0x0001 Enable Quotas: enable quota for this fs
3721 /* we need to fake up a fsp here,
3722 * because its not send in this call
3725 SMB_NTQUOTA_STRUCT quotas;
3728 ZERO_STRUCT(quotas);
3731 fsp.fnum = FNUM_FIELD_INVALID;
3734 if (get_current_uid(conn) != 0) {
3735 DEBUG(0,("get_user_quota: access_denied "
3736 "service [%s] user [%s]\n",
3737 lp_servicename(talloc_tos(), SNUM(conn)),
3738 conn->session_info->unix_info->unix_name));
3739 return NT_STATUS_ACCESS_DENIED;
3742 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3744 if (!NT_STATUS_IS_OK(status)) {
3745 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3751 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3752 lp_servicename(talloc_tos(), SNUM(conn))));
3754 /* Unknown1 24 NULL bytes*/
3755 SBIG_UINT(pdata,0,(uint64_t)0);
3756 SBIG_UINT(pdata,8,(uint64_t)0);
3757 SBIG_UINT(pdata,16,(uint64_t)0);
3759 /* Default Soft Quota 8 bytes */
3760 SBIG_UINT(pdata,24,quotas.softlim);
3762 /* Default Hard Quota 8 bytes */
3763 SBIG_UINT(pdata,32,quotas.hardlim);
3765 /* Quota flag 2 bytes */
3766 SSVAL(pdata,40,quotas.qflags);
3768 /* Unknown3 6 NULL bytes */
3774 #endif /* HAVE_SYS_QUOTAS */
3775 case SMB_FS_OBJECTID_INFORMATION:
3777 unsigned char objid[16];
3778 struct smb_extended_info extended_info;
3779 memcpy(pdata,create_volume_objectid(conn, objid),16);
3780 samba_extended_info_version (&extended_info);
3781 SIVAL(pdata,16,extended_info.samba_magic);
3782 SIVAL(pdata,20,extended_info.samba_version);
3783 SIVAL(pdata,24,extended_info.samba_subversion);
3784 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3785 memcpy(pdata+36,extended_info.samba_version_string,28);
3790 case SMB_FS_SECTOR_SIZE_INFORMATION:
3794 * These values match a physical Windows Server 2012
3795 * share backed by NTFS atop spinning rust.
3797 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3798 /* logical_bytes_per_sector */
3799 SIVAL(pdata, 0, bytes_per_sector);
3800 /* phys_bytes_per_sector_atomic */
3801 SIVAL(pdata, 4, bytes_per_sector);
3802 /* phys_bytes_per_sector_perf */
3803 SIVAL(pdata, 8, bytes_per_sector);
3804 /* fs_effective_phys_bytes_per_sector_atomic */
3805 SIVAL(pdata, 12, bytes_per_sector);
3807 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3808 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3809 /* byte_off_sector_align */
3810 SIVAL(pdata, 20, 0);
3811 /* byte_off_partition_align */
3812 SIVAL(pdata, 24, 0);
3813 *fixed_portion = 28;
3819 * Query the version and capabilities of the CIFS UNIX extensions
3823 case SMB_QUERY_CIFS_UNIX_INFO:
3825 bool large_write = lp_min_receive_file_size() &&
3826 !srv_is_signing_active(xconn);
3827 bool large_read = !srv_is_signing_active(xconn);
3828 int encrypt_caps = 0;
3830 if (!lp_unix_extensions()) {
3831 return NT_STATUS_INVALID_LEVEL;
3834 switch (conn->encrypt_level) {
3835 case SMB_SIGNING_OFF:
3838 case SMB_SIGNING_DESIRED:
3839 case SMB_SIGNING_IF_REQUIRED:
3840 case SMB_SIGNING_DEFAULT:
3841 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3843 case SMB_SIGNING_REQUIRED:
3844 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3845 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3846 large_write = false;
3852 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3853 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3855 /* We have POSIX ACLs, pathname, encryption,
3856 * large read/write, and locking capability. */
3858 SBIG_UINT(pdata,4,((uint64_t)(
3859 CIFS_UNIX_POSIX_ACLS_CAP|
3860 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3861 CIFS_UNIX_FCNTL_LOCKS_CAP|
3862 CIFS_UNIX_EXTATTR_CAP|
3863 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3865 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3867 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3871 case SMB_QUERY_POSIX_FS_INFO:
3874 vfs_statvfs_struct svfs;
3876 if (!lp_unix_extensions()) {
3877 return NT_STATUS_INVALID_LEVEL;
3880 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3884 SIVAL(pdata,0,svfs.OptimalTransferSize);
3885 SIVAL(pdata,4,svfs.BlockSize);
3886 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3887 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3888 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3889 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3890 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3891 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3892 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3894 } else if (rc == EOPNOTSUPP) {
3895 return NT_STATUS_INVALID_LEVEL;
3896 #endif /* EOPNOTSUPP */
3898 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3899 return NT_STATUS_DOS(ERRSRV, ERRerror);
3904 case SMB_QUERY_POSIX_WHOAMI:
3910 if (!lp_unix_extensions()) {
3911 return NT_STATUS_INVALID_LEVEL;
3914 if (max_data_bytes < 40) {
3915 return NT_STATUS_BUFFER_TOO_SMALL;
3918 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3919 flags |= SMB_WHOAMI_GUEST;
3922 /* NOTE: 8 bytes for UID/GID, irrespective of native
3923 * platform size. This matches
3924 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3926 data_len = 4 /* flags */
3933 + 4 /* pad/reserved */
3934 + (conn->session_info->unix_token->ngroups * 8)
3936 + (conn->session_info->security_token->num_sids *
3940 SIVAL(pdata, 0, flags);
3941 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3943 (uint64_t)conn->session_info->unix_token->uid);
3944 SBIG_UINT(pdata, 16,
3945 (uint64_t)conn->session_info->unix_token->gid);
3948 if (data_len >= max_data_bytes) {
3949 /* Potential overflow, skip the GIDs and SIDs. */
3951 SIVAL(pdata, 24, 0); /* num_groups */
3952 SIVAL(pdata, 28, 0); /* num_sids */
3953 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3954 SIVAL(pdata, 36, 0); /* reserved */
3960 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3961 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3963 /* We walk the SID list twice, but this call is fairly
3964 * infrequent, and I don't expect that it's performance
3965 * sensitive -- jpeach
3967 for (i = 0, sid_bytes = 0;
3968 i < conn->session_info->security_token->num_sids; ++i) {
3969 sid_bytes += ndr_size_dom_sid(
3970 &conn->session_info->security_token->sids[i],
3974 /* SID list byte count */
3975 SIVAL(pdata, 32, sid_bytes);
3977 /* 4 bytes pad/reserved - must be zero */
3978 SIVAL(pdata, 36, 0);
3982 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3983 SBIG_UINT(pdata, data_len,
3984 (uint64_t)conn->session_info->unix_token->groups[i]);
3990 i < conn->session_info->security_token->num_sids; ++i) {
3991 int sid_len = ndr_size_dom_sid(
3992 &conn->session_info->security_token->sids[i],
3995 sid_linearize((uint8_t *)(pdata + data_len),
3997 &conn->session_info->security_token->sids[i]);
3998 data_len += sid_len;
4004 case SMB_MAC_QUERY_FS_INFO:
4006 * Thursby MAC extension... ONLY on NTFS filesystems
4007 * once we do streams then we don't need this
4009 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4011 SIVAL(pdata,84,0x100); /* Don't support mac... */
4016 return NT_STATUS_INVALID_LEVEL;
4019 *ret_data_len = data_len;
4023 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4024 struct smb_request *req,
4026 const DATA_BLOB *qdata)
4029 SMB_NTQUOTA_STRUCT quotas;
4031 ZERO_STRUCT(quotas);
4034 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4035 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4036 lp_servicename(talloc_tos(), SNUM(conn)),
4037 conn->session_info->unix_info->unix_name));
4038 return NT_STATUS_ACCESS_DENIED;
4041 if (!check_fsp_ntquota_handle(conn, req,
4043 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4044 return NT_STATUS_INVALID_HANDLE;
4047 /* note: normally there're 48 bytes,
4048 * but we didn't use the last 6 bytes for now
4051 if (qdata->length < 42) {
4052 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4053 (unsigned int)qdata->length));
4054 return NT_STATUS_INVALID_PARAMETER;
4057 /* unknown_1 24 NULL bytes in pdata*/
4059 /* the soft quotas 8 bytes (uint64_t)*/
4060 quotas.softlim = BVAL(qdata->data,24);
4062 /* the hard quotas 8 bytes (uint64_t)*/
4063 quotas.hardlim = BVAL(qdata->data,32);
4065 /* quota_flags 2 bytes **/
4066 quotas.qflags = SVAL(qdata->data,40);
4068 /* unknown_2 6 NULL bytes follow*/
4070 /* now set the quotas */
4071 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4072 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4073 lp_servicename(talloc_tos(), SNUM(conn))));
4074 status = map_nt_error_from_unix(errno);
4076 status = NT_STATUS_OK;
4081 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4082 struct smb_request *req,
4083 TALLOC_CTX *mem_ctx,
4084 uint16_t info_level,
4086 const DATA_BLOB *pdata)
4088 switch (info_level) {
4089 case SMB_FS_QUOTA_INFORMATION:
4091 return smb_set_fsquota(conn,
4100 return NT_STATUS_INVALID_LEVEL;
4103 /****************************************************************************
4104 Reply to a TRANS2_QFSINFO (query filesystem info).
4105 ****************************************************************************/
4107 static void call_trans2qfsinfo(connection_struct *conn,
4108 struct smb_request *req,
4109 char **pparams, int total_params,
4110 char **ppdata, int total_data,
4111 unsigned int max_data_bytes)
4113 char *params = *pparams;
4114 uint16_t info_level;
4116 size_t fixed_portion;
4119 if (total_params < 2) {
4120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4124 info_level = SVAL(params,0);
4126 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4127 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4128 DEBUG(0,("call_trans2qfsinfo: encryption required "
4129 "and info level 0x%x sent.\n",
4130 (unsigned int)info_level));
4131 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4136 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4138 status = smbd_do_qfsinfo(req->xconn, conn, req,
4145 if (!NT_STATUS_IS_OK(status)) {
4146 reply_nterror(req, status);
4150 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4153 DEBUG( 4, ( "%s info_level = %d\n",
4154 smb_fn_name(req->cmd), info_level) );
4159 /****************************************************************************
4160 Reply to a TRANS2_SETFSINFO (set filesystem info).
4161 ****************************************************************************/
4163 static void call_trans2setfsinfo(connection_struct *conn,
4164 struct smb_request *req,
4165 char **pparams, int total_params,
4166 char **ppdata, int total_data,
4167 unsigned int max_data_bytes)
4169 struct smbXsrv_connection *xconn = req->xconn;
4170 char *pdata = *ppdata;
4171 char *params = *pparams;
4172 uint16_t info_level;
4174 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4175 lp_servicename(talloc_tos(), SNUM(conn))));
4178 if (total_params < 4) {
4179 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4181 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4185 info_level = SVAL(params,2);
4188 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4189 info_level != SMB_SET_CIFS_UNIX_INFO) {
4190 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4191 "info level (0x%x) on IPC$.\n",
4192 (unsigned int)info_level));
4193 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4198 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4199 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4200 DEBUG(0,("call_trans2setfsinfo: encryption required "
4201 "and info level 0x%x sent.\n",
4202 (unsigned int)info_level));
4203 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4208 switch(info_level) {
4209 case SMB_SET_CIFS_UNIX_INFO:
4210 if (!lp_unix_extensions()) {
4211 DEBUG(2,("call_trans2setfsinfo: "
4212 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4213 "unix extensions off\n"));
4215 NT_STATUS_INVALID_LEVEL);
4219 /* There should be 12 bytes of capabilities set. */
4220 if (total_data < 12) {
4223 NT_STATUS_INVALID_PARAMETER);
4226 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4227 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4228 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4229 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4230 /* Just print these values for now. */
4231 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4232 "major = %u, minor = %u cap_low = 0x%x, "
4234 (unsigned int)xconn->
4235 smb1.unix_info.client_major,
4236 (unsigned int)xconn->
4237 smb1.unix_info.client_minor,
4238 (unsigned int)xconn->
4239 smb1.unix_info.client_cap_low,
4240 (unsigned int)xconn->
4241 smb1.unix_info.client_cap_high));
4243 /* Here is where we must switch to posix pathname processing... */
4244 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4245 lp_set_posix_pathnames();
4246 mangle_change_to_posix();
4249 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4250 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4251 /* Client that knows how to do posix locks,
4252 * but not posix open/mkdir operations. Set a
4253 * default type for read/write checks. */
4255 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4260 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4263 size_t param_len = 0;
4264 size_t data_len = total_data;
4266 if (!lp_unix_extensions()) {
4269 NT_STATUS_INVALID_LEVEL);
4273 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4276 NT_STATUS_NOT_SUPPORTED);
4280 if (xconn->smb1.echo_handler.trusted_fde) {
4281 DEBUG( 2,("call_trans2setfsinfo: "
4282 "request transport encryption disabled"
4283 "with 'fork echo handler = yes'\n"));
4286 NT_STATUS_NOT_SUPPORTED);
4290 DEBUG( 4,("call_trans2setfsinfo: "
4291 "request transport encryption.\n"));
4293 status = srv_request_encryption_setup(conn,
4294 (unsigned char **)ppdata,
4296 (unsigned char **)pparams,
4299 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4300 !NT_STATUS_IS_OK(status)) {
4301 reply_nterror(req, status);
4305 send_trans2_replies(conn, req,
4313 if (NT_STATUS_IS_OK(status)) {
4314 /* Server-side transport
4315 * encryption is now *on*. */
4316 status = srv_encryption_start(conn);
4317 if (!NT_STATUS_IS_OK(status)) {
4318 char *reason = talloc_asprintf(talloc_tos(),
4319 "Failure in setting "
4320 "up encrypted transport: %s",
4322 exit_server_cleanly(reason);
4328 case SMB_FS_QUOTA_INFORMATION:
4332 .data = (uint8_t *)pdata,
4333 .length = total_data
4335 files_struct *fsp = NULL;
4336 fsp = file_fsp(req, SVAL(params,0));
4338 status = smb_set_fsquota(conn,
4342 if (!NT_STATUS_IS_OK(status)) {
4343 reply_nterror(req, status);
4349 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4351 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4357 * sending this reply works fine,
4358 * but I'm not sure it's the same
4359 * like windows do...
4362 reply_outbuf(req, 10, 0);
4365 #if defined(HAVE_POSIX_ACLS)
4366 /****************************************************************************
4367 Utility function to count the number of entries in a POSIX acl.
4368 ****************************************************************************/
4370 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4372 unsigned int ace_count = 0;
4373 int entry_id = SMB_ACL_FIRST_ENTRY;
4374 SMB_ACL_ENTRY_T entry;
4376 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4378 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4379 entry_id = SMB_ACL_NEXT_ENTRY;
4386 /****************************************************************************
4387 Utility function to marshall a POSIX acl into wire format.
4388 ****************************************************************************/
4390 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4392 int entry_id = SMB_ACL_FIRST_ENTRY;
4393 SMB_ACL_ENTRY_T entry;
4395 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4396 SMB_ACL_TAG_T tagtype;
4397 SMB_ACL_PERMSET_T permset;
4398 unsigned char perms = 0;
4399 unsigned int own_grp;
4402 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4403 entry_id = SMB_ACL_NEXT_ENTRY;
4406 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4407 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4411 if (sys_acl_get_permset(entry, &permset) == -1) {
4412 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4416 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4417 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4418 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4420 SCVAL(pdata,1,perms);
4423 case SMB_ACL_USER_OBJ:
4424 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4425 own_grp = (unsigned int)pst->st_ex_uid;
4426 SIVAL(pdata,2,own_grp);
4431 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4433 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4436 own_grp = (unsigned int)*puid;
4437 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4438 SIVAL(pdata,2,own_grp);
4442 case SMB_ACL_GROUP_OBJ:
4443 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4444 own_grp = (unsigned int)pst->st_ex_gid;
4445 SIVAL(pdata,2,own_grp);
4450 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4452 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4455 own_grp = (unsigned int)*pgid;
4456 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4457 SIVAL(pdata,2,own_grp);
4462 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4463 SIVAL(pdata,2,0xFFFFFFFF);
4464 SIVAL(pdata,6,0xFFFFFFFF);
4467 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4468 SIVAL(pdata,2,0xFFFFFFFF);
4469 SIVAL(pdata,6,0xFFFFFFFF);
4472 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4475 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4482 /****************************************************************************
4483 Store the FILE_UNIX_BASIC info.
4484 ****************************************************************************/
4486 static char *store_file_unix_basic(connection_struct *conn,
4489 const SMB_STRUCT_STAT *psbuf)
4491 uint64_t file_index = get_FileIndex(conn, psbuf);
4494 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4495 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4497 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4500 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4503 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4504 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4505 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4508 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4512 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4516 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4519 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4520 devno = psbuf->st_ex_rdev;
4522 devno = psbuf->st_ex_dev;
4525 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4529 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4533 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4536 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4540 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4547 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4548 * the chflags(2) (or equivalent) flags.
4550 * XXX: this really should be behind the VFS interface. To do this, we would
4551 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4552 * Each VFS module could then implement its own mapping as appropriate for the
4553 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4555 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4559 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4563 { UF_IMMUTABLE, EXT_IMMUTABLE },
4567 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4571 { UF_HIDDEN, EXT_HIDDEN },
4574 /* Do not remove. We need to guarantee that this array has at least one
4575 * entry to build on HP-UX.
4581 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4582 uint32_t *smb_fflags, uint32_t *smb_fmask)
4586 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4587 *smb_fmask |= info2_flags_map[i].smb_fflag;
4588 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4589 *smb_fflags |= info2_flags_map[i].smb_fflag;
4594 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4595 const uint32_t smb_fflags,
4596 const uint32_t smb_fmask,
4599 uint32_t max_fmask = 0;
4602 *stat_fflags = psbuf->st_ex_flags;
4604 /* For each flags requested in smb_fmask, check the state of the
4605 * corresponding flag in smb_fflags and set or clear the matching
4609 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4610 max_fmask |= info2_flags_map[i].smb_fflag;
4611 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4612 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4613 *stat_fflags |= info2_flags_map[i].stat_fflag;
4615 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4620 /* If smb_fmask is asking to set any bits that are not supported by
4621 * our flag mappings, we should fail.
4623 if ((smb_fmask & max_fmask) != smb_fmask) {
4631 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4632 * of file flags and birth (create) time.
4634 static char *store_file_unix_basic_info2(connection_struct *conn,
4637 const SMB_STRUCT_STAT *psbuf)
4639 uint32_t file_flags = 0;
4640 uint32_t flags_mask = 0;
4642 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4644 /* Create (birth) time 64 bit */
4645 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4648 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4649 SIVAL(pdata, 0, file_flags); /* flags */
4650 SIVAL(pdata, 4, flags_mask); /* mask */
4656 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4657 const struct stream_struct *streams,
4659 unsigned int max_data_bytes,
4660 unsigned int *data_size)
4663 unsigned int ofs = 0;
4665 if (max_data_bytes < 32) {
4666 return NT_STATUS_INFO_LENGTH_MISMATCH;
4669 for (i = 0; i < num_streams; i++) {
4670 unsigned int next_offset;
4672 smb_ucs2_t *namebuf;
4674 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4675 streams[i].name, &namelen) ||
4678 return NT_STATUS_INVALID_PARAMETER;
4682 * name_buf is now null-terminated, we need to marshall as not
4689 * We cannot overflow ...
4691 if ((ofs + 24 + namelen) > max_data_bytes) {
4692 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4694 TALLOC_FREE(namebuf);
4695 return STATUS_BUFFER_OVERFLOW;
4698 SIVAL(data, ofs+4, namelen);
4699 SOFF_T(data, ofs+8, streams[i].size);
4700 SOFF_T(data, ofs+16, streams[i].alloc_size);
4701 memcpy(data+ofs+24, namebuf, namelen);
4702 TALLOC_FREE(namebuf);
4704 next_offset = ofs + 24 + namelen;
4706 if (i == num_streams-1) {
4707 SIVAL(data, ofs, 0);
4710 unsigned int align = ndr_align_size(next_offset, 8);
4712 if ((next_offset + align) > max_data_bytes) {
4713 DEBUG(10, ("refusing to overflow align "
4714 "reply at stream %u\n",
4716 TALLOC_FREE(namebuf);
4717 return STATUS_BUFFER_OVERFLOW;
4720 memset(data+next_offset, 0, align);
4721 next_offset += align;
4723 SIVAL(data, ofs, next_offset - ofs);
4730 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4734 return NT_STATUS_OK;
4737 /****************************************************************************
4738 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4739 ****************************************************************************/
4741 static void call_trans2qpipeinfo(connection_struct *conn,
4742 struct smb_request *req,
4743 unsigned int tran_call,
4744 char **pparams, int total_params,
4745 char **ppdata, int total_data,
4746 unsigned int max_data_bytes)
4748 char *params = *pparams;
4749 char *pdata = *ppdata;
4750 unsigned int data_size = 0;
4751 unsigned int param_size = 2;
4752 uint16_t info_level;
4756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4760 if (total_params < 4) {
4761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4765 fsp = file_fsp(req, SVAL(params,0));
4766 if (!fsp_is_np(fsp)) {
4767 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4771 info_level = SVAL(params,2);
4773 *pparams = (char *)SMB_REALLOC(*pparams,2);
4774 if (*pparams == NULL) {
4775 reply_nterror(req, NT_STATUS_NO_MEMORY);
4780 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4781 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4784 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4785 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4786 if (*ppdata == NULL ) {
4787 reply_nterror(req, NT_STATUS_NO_MEMORY);
4792 switch (info_level) {
4793 case SMB_FILE_STANDARD_INFORMATION:
4795 SOFF_T(pdata,0,4096LL);
4802 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4806 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4812 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4813 TALLOC_CTX *mem_ctx,
4814 uint16_t info_level,
4816 struct smb_filename *smb_fname,
4817 bool delete_pending,
4818 struct timespec write_time_ts,
4819 struct ea_list *ea_list,
4820 int lock_data_count,
4823 unsigned int max_data_bytes,
4824 size_t *fixed_portion,
4826 unsigned int *pdata_size)
4828 char *pdata = *ppdata;
4829 char *dstart, *dend;
4830 unsigned int data_size;
4831 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4832 time_t create_time, mtime, atime, c_time;
4833 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4840 uint64_t file_size = 0;
4842 uint64_t allocation_size = 0;
4843 uint64_t file_index = 0;
4844 uint32_t access_mask = 0;
4847 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4848 return NT_STATUS_INVALID_LEVEL;
4851 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4852 smb_fname_str_dbg(smb_fname),
4854 info_level, max_data_bytes));
4856 mode = dos_mode(conn, smb_fname);
4857 nlink = psbuf->st_ex_nlink;
4859 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4863 if ((nlink > 0) && delete_pending) {
4867 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4868 return NT_STATUS_INVALID_PARAMETER;
4871 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4872 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4873 if (*ppdata == NULL) {
4874 return NT_STATUS_NO_MEMORY;
4878 dend = dstart + data_size - 1;
4880 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4881 update_stat_ex_mtime(psbuf, write_time_ts);
4884 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4885 mtime_ts = psbuf->st_ex_mtime;
4886 atime_ts = psbuf->st_ex_atime;
4887 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4889 if (lp_dos_filetime_resolution(SNUM(conn))) {
4890 dos_filetime_timespec(&create_time_ts);
4891 dos_filetime_timespec(&mtime_ts);
4892 dos_filetime_timespec(&atime_ts);
4893 dos_filetime_timespec(&ctime_ts);
4896 create_time = convert_timespec_to_time_t(create_time_ts);
4897 mtime = convert_timespec_to_time_t(mtime_ts);
4898 atime = convert_timespec_to_time_t(atime_ts);
4899 c_time = convert_timespec_to_time_t(ctime_ts);
4901 p = strrchr_m(smb_fname->base_name,'/');
4903 base_name = smb_fname->base_name;
4907 /* NT expects the name to be in an exact form of the *full*
4908 filename. See the trans2 torture test */
4909 if (ISDOT(base_name)) {
4910 dos_fname = talloc_strdup(mem_ctx, "\\");
4912 return NT_STATUS_NO_MEMORY;
4915 dos_fname = talloc_asprintf(mem_ctx,
4917 smb_fname->base_name);
4919 return NT_STATUS_NO_MEMORY;
4921 if (is_ntfs_stream_smb_fname(smb_fname)) {
4922 dos_fname = talloc_asprintf(dos_fname, "%s",
4923 smb_fname->stream_name);
4925 return NT_STATUS_NO_MEMORY;
4929 string_replace(dos_fname, '/', '\\');
4932 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4935 /* Do we have this path open ? */
4937 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4938 fsp1 = file_find_di_first(conn->sconn, fileid);
4939 if (fsp1 && fsp1->initial_allocation_size) {
4940 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4944 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4945 file_size = get_file_size_stat(psbuf);
4949 pos = fsp->fh->position_information;
4953 access_mask = fsp->access_mask;
4955 /* GENERIC_EXECUTE mapping from Windows */
4956 access_mask = 0x12019F;
4959 /* This should be an index number - looks like
4962 I think this causes us to fail the IFSKIT
4963 BasicFileInformationTest. -tpot */
4964 file_index = get_FileIndex(conn, psbuf);
4968 switch (info_level) {
4969 case SMB_INFO_STANDARD:
4970 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4972 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4973 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4974 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4975 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4976 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4977 SSVAL(pdata,l1_attrFile,mode);
4980 case SMB_INFO_QUERY_EA_SIZE:
4982 unsigned int ea_size =
4983 estimate_ea_size(conn, fsp,
4985 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4987 srv_put_dos_date2(pdata,0,create_time);
4988 srv_put_dos_date2(pdata,4,atime);
4989 srv_put_dos_date2(pdata,8,mtime); /* write time */
4990 SIVAL(pdata,12,(uint32_t)file_size);
4991 SIVAL(pdata,16,(uint32_t)allocation_size);
4992 SSVAL(pdata,20,mode);
4993 SIVAL(pdata,22,ea_size);
4997 case SMB_INFO_IS_NAME_VALID:
4998 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5000 /* os/2 needs this ? really ?*/
5001 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5003 /* This is only reached for qpathinfo */
5007 case SMB_INFO_QUERY_EAS_FROM_LIST:
5009 size_t total_ea_len = 0;
5010 struct ea_list *ea_file_list = NULL;
5011 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5014 get_ea_list_from_file(mem_ctx, conn, fsp,
5016 &total_ea_len, &ea_file_list);
5017 if (!NT_STATUS_IS_OK(status)) {
5021 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5023 if (!ea_list || (total_ea_len > data_size)) {
5025 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5029 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5033 case SMB_INFO_QUERY_ALL_EAS:
5035 /* We have data_size bytes to put EA's into. */
5036 size_t total_ea_len = 0;
5037 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5039 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5041 &total_ea_len, &ea_list);
5042 if (!NT_STATUS_IS_OK(status)) {
5046 if (!ea_list || (total_ea_len > data_size)) {
5048 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5052 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5056 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5058 /* This is FileFullEaInformation - 0xF which maps to
5059 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5061 /* We have data_size bytes to put EA's into. */
5062 size_t total_ea_len = 0;
5063 struct ea_list *ea_file_list = NULL;
5065 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5067 /*TODO: add filtering and index handling */
5070 get_ea_list_from_file(mem_ctx, conn, fsp,
5072 &total_ea_len, &ea_file_list);
5073 if (!NT_STATUS_IS_OK(status)) {
5076 if (!ea_file_list) {
5077 return NT_STATUS_NO_EAS_ON_FILE;
5080 status = fill_ea_chained_buffer(mem_ctx,
5084 conn, ea_file_list);
5085 if (!NT_STATUS_IS_OK(status)) {
5091 case SMB_FILE_BASIC_INFORMATION:
5092 case SMB_QUERY_FILE_BASIC_INFO:
5094 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5095 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5096 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5098 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5102 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5103 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5104 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5105 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5106 SIVAL(pdata,32,mode);
5108 DEBUG(5,("SMB_QFBI - "));
5109 DEBUG(5,("create: %s ", ctime(&create_time)));
5110 DEBUG(5,("access: %s ", ctime(&atime)));
5111 DEBUG(5,("write: %s ", ctime(&mtime)));
5112 DEBUG(5,("change: %s ", ctime(&c_time)));
5113 DEBUG(5,("mode: %x\n", mode));
5114 *fixed_portion = data_size;
5117 case SMB_FILE_STANDARD_INFORMATION:
5118 case SMB_QUERY_FILE_STANDARD_INFO:
5120 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5122 SOFF_T(pdata,0,allocation_size);
5123 SOFF_T(pdata,8,file_size);
5124 SIVAL(pdata,16,nlink);
5125 SCVAL(pdata,20,delete_pending?1:0);
5126 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5127 SSVAL(pdata,22,0); /* Padding. */
5128 *fixed_portion = 24;
5131 case SMB_FILE_EA_INFORMATION:
5132 case SMB_QUERY_FILE_EA_INFO:
5134 unsigned int ea_size =
5135 estimate_ea_size(conn, fsp, smb_fname);
5136 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5139 SIVAL(pdata,0,ea_size);
5143 /* Get the 8.3 name - used if NT SMB was negotiated. */
5144 case SMB_QUERY_FILE_ALT_NAME_INFO:
5145 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5147 char mangled_name[13];
5148 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5149 if (!name_to_8_3(base_name,mangled_name,
5150 True,conn->params)) {
5151 return NT_STATUS_NO_MEMORY;
5153 status = srvstr_push(dstart, flags2,
5154 pdata+4, mangled_name,
5155 PTR_DIFF(dend, pdata+4),
5157 if (!NT_STATUS_IS_OK(status)) {
5160 data_size = 4 + len;
5166 case SMB_QUERY_FILE_NAME_INFO:
5169 this must be *exactly* right for ACLs on mapped drives to work
5171 status = srvstr_push(dstart, flags2,
5173 PTR_DIFF(dend, pdata+4),
5175 if (!NT_STATUS_IS_OK(status)) {
5178 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5179 data_size = 4 + len;
5184 case SMB_FILE_ALLOCATION_INFORMATION:
5185 case SMB_QUERY_FILE_ALLOCATION_INFO:
5186 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5188 SOFF_T(pdata,0,allocation_size);
5191 case SMB_FILE_END_OF_FILE_INFORMATION:
5192 case SMB_QUERY_FILE_END_OF_FILEINFO:
5193 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5195 SOFF_T(pdata,0,file_size);
5198 case SMB_QUERY_FILE_ALL_INFO:
5199 case SMB_FILE_ALL_INFORMATION:
5201 unsigned int ea_size =
5202 estimate_ea_size(conn, fsp, smb_fname);
5203 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5204 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5205 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5206 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5207 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5208 SIVAL(pdata,32,mode);
5209 SIVAL(pdata,36,0); /* padding. */
5211 SOFF_T(pdata,0,allocation_size);
5212 SOFF_T(pdata,8,file_size);
5213 SIVAL(pdata,16,nlink);
5214 SCVAL(pdata,20,delete_pending);
5215 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5218 SIVAL(pdata,0,ea_size);
5219 pdata += 4; /* EA info */
5220 status = srvstr_push(dstart, flags2,
5222 PTR_DIFF(dend, pdata+4),
5224 if (!NT_STATUS_IS_OK(status)) {
5229 data_size = PTR_DIFF(pdata,(*ppdata));
5230 *fixed_portion = 10;
5234 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5236 unsigned int ea_size =
5237 estimate_ea_size(conn, fsp, smb_fname);
5238 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5239 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5240 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5241 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5242 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5243 SIVAL(pdata, 0x20, mode);
5244 SIVAL(pdata, 0x24, 0); /* padding. */
5245 SBVAL(pdata, 0x28, allocation_size);
5246 SBVAL(pdata, 0x30, file_size);
5247 SIVAL(pdata, 0x38, nlink);
5248 SCVAL(pdata, 0x3C, delete_pending);
5249 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5250 SSVAL(pdata, 0x3E, 0); /* padding */
5251 SBVAL(pdata, 0x40, file_index);
5252 SIVAL(pdata, 0x48, ea_size);
5253 SIVAL(pdata, 0x4C, access_mask);
5254 SBVAL(pdata, 0x50, pos);
5255 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5256 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5260 status = srvstr_push(dstart, flags2,
5262 PTR_DIFF(dend, pdata+4),
5264 if (!NT_STATUS_IS_OK(status)) {
5269 data_size = PTR_DIFF(pdata,(*ppdata));
5270 *fixed_portion = 104;
5273 case SMB_FILE_INTERNAL_INFORMATION:
5275 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5276 SBVAL(pdata, 0, file_index);
5281 case SMB_FILE_ACCESS_INFORMATION:
5282 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5283 SIVAL(pdata, 0, access_mask);
5288 case SMB_FILE_NAME_INFORMATION:
5289 /* Pathname with leading '\'. */
5292 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5293 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5294 SIVAL(pdata,0,byte_len);
5295 data_size = 4 + byte_len;
5299 case SMB_FILE_DISPOSITION_INFORMATION:
5300 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5302 SCVAL(pdata,0,delete_pending);
5306 case SMB_FILE_POSITION_INFORMATION:
5307 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5309 SOFF_T(pdata,0,pos);
5313 case SMB_FILE_MODE_INFORMATION:
5314 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5315 SIVAL(pdata,0,mode);
5320 case SMB_FILE_ALIGNMENT_INFORMATION:
5321 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5322 SIVAL(pdata,0,0); /* No alignment needed. */
5328 * NT4 server just returns "invalid query" to this - if we try
5329 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5332 /* The first statement above is false - verified using Thursby
5333 * client against NT4 -- gcolley.
5335 case SMB_QUERY_FILE_STREAM_INFO:
5336 case SMB_FILE_STREAM_INFORMATION: {
5337 unsigned int num_streams = 0;
5338 struct stream_struct *streams = NULL;
5340 DEBUG(10,("smbd_do_qfilepathinfo: "
5341 "SMB_FILE_STREAM_INFORMATION\n"));
5343 if (is_ntfs_stream_smb_fname(smb_fname)) {
5344 return NT_STATUS_INVALID_PARAMETER;
5347 status = vfs_streaminfo(conn,
5354 if (!NT_STATUS_IS_OK(status)) {
5355 DEBUG(10, ("could not get stream info: %s\n",
5356 nt_errstr(status)));
5360 status = marshall_stream_info(num_streams, streams,
5361 pdata, max_data_bytes,
5364 if (!NT_STATUS_IS_OK(status)) {
5365 DEBUG(10, ("marshall_stream_info failed: %s\n",
5366 nt_errstr(status)));
5367 TALLOC_FREE(streams);
5371 TALLOC_FREE(streams);
5373 *fixed_portion = 32;
5377 case SMB_QUERY_COMPRESSION_INFO:
5378 case SMB_FILE_COMPRESSION_INFORMATION:
5379 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5380 SOFF_T(pdata,0,file_size);
5381 SIVAL(pdata,8,0); /* ??? */
5382 SIVAL(pdata,12,0); /* ??? */
5384 *fixed_portion = 16;
5387 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5388 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5389 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5390 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5391 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5392 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5393 SOFF_T(pdata,32,allocation_size);
5394 SOFF_T(pdata,40,file_size);
5395 SIVAL(pdata,48,mode);
5396 SIVAL(pdata,52,0); /* ??? */
5398 *fixed_portion = 56;
5401 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5402 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5403 SIVAL(pdata,0,mode);
5410 * CIFS UNIX Extensions.
5413 case SMB_QUERY_FILE_UNIX_BASIC:
5415 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5416 data_size = PTR_DIFF(pdata,(*ppdata));
5418 DEBUG(4,("smbd_do_qfilepathinfo: "
5419 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5420 dump_data(4, (uint8_t *)(*ppdata), data_size);
5424 case SMB_QUERY_FILE_UNIX_INFO2:
5426 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5427 data_size = PTR_DIFF(pdata,(*ppdata));
5431 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5433 for (i=0; i<100; i++)
5434 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5440 case SMB_QUERY_FILE_UNIX_LINK:
5443 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5446 return NT_STATUS_NO_MEMORY;
5449 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5451 if(!S_ISLNK(psbuf->st_ex_mode)) {
5452 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5455 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5457 link_len = SMB_VFS_READLINK(conn,
5458 smb_fname->base_name,
5460 if (link_len == -1) {
5461 return map_nt_error_from_unix(errno);
5463 buffer[link_len] = 0;
5464 status = srvstr_push(dstart, flags2,
5466 PTR_DIFF(dend, pdata),
5467 STR_TERMINATE, &len);
5468 if (!NT_STATUS_IS_OK(status)) {
5472 data_size = PTR_DIFF(pdata,(*ppdata));
5477 #if defined(HAVE_POSIX_ACLS)
5478 case SMB_QUERY_POSIX_ACL:
5480 SMB_ACL_T file_acl = NULL;
5481 SMB_ACL_T def_acl = NULL;
5482 uint16_t num_file_acls = 0;
5483 uint16_t num_def_acls = 0;
5485 status = refuse_symlink(conn,
5488 if (!NT_STATUS_IS_OK(status)) {
5492 if (fsp && fsp->fh->fd != -1) {
5493 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5497 SMB_VFS_SYS_ACL_GET_FILE(conn,
5498 smb_fname->base_name,
5499 SMB_ACL_TYPE_ACCESS,
5503 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5504 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5505 "not implemented on "
5506 "filesystem containing %s\n",
5507 smb_fname->base_name));
5508 return NT_STATUS_NOT_IMPLEMENTED;
5511 if (S_ISDIR(psbuf->st_ex_mode)) {
5512 if (fsp && fsp->is_directory) {
5514 SMB_VFS_SYS_ACL_GET_FILE(
5516 fsp->fsp_name->base_name,
5517 SMB_ACL_TYPE_DEFAULT,
5521 SMB_VFS_SYS_ACL_GET_FILE(
5523 smb_fname->base_name,
5524 SMB_ACL_TYPE_DEFAULT,
5527 def_acl = free_empty_sys_acl(conn, def_acl);
5530 num_file_acls = count_acl_entries(conn, file_acl);
5531 num_def_acls = count_acl_entries(conn, def_acl);
5533 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5534 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5536 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5537 SMB_POSIX_ACL_HEADER_SIZE) ));
5539 TALLOC_FREE(file_acl);
5542 TALLOC_FREE(def_acl);
5544 return NT_STATUS_BUFFER_TOO_SMALL;
5547 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5548 SSVAL(pdata,2,num_file_acls);
5549 SSVAL(pdata,4,num_def_acls);
5550 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5552 TALLOC_FREE(file_acl);
5555 TALLOC_FREE(def_acl);
5557 return NT_STATUS_INTERNAL_ERROR;
5559 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5561 TALLOC_FREE(file_acl);
5564 TALLOC_FREE(def_acl);
5566 return NT_STATUS_INTERNAL_ERROR;
5570 TALLOC_FREE(file_acl);
5573 TALLOC_FREE(def_acl);
5575 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5581 case SMB_QUERY_POSIX_LOCK:
5586 enum brl_type lock_type;
5588 /* We need an open file with a real fd for this. */
5589 if (!fsp || fsp->fh->fd == -1) {
5590 return NT_STATUS_INVALID_LEVEL;
5593 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5594 return NT_STATUS_INVALID_PARAMETER;
5597 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5598 case POSIX_LOCK_TYPE_READ:
5599 lock_type = READ_LOCK;
5601 case POSIX_LOCK_TYPE_WRITE:
5602 lock_type = WRITE_LOCK;
5604 case POSIX_LOCK_TYPE_UNLOCK:
5606 /* There's no point in asking for an unlock... */
5607 return NT_STATUS_INVALID_PARAMETER;
5610 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5611 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5612 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5614 status = query_lock(fsp,
5621 if (ERROR_WAS_LOCK_DENIED(status)) {
5622 /* Here we need to report who has it locked... */
5623 data_size = POSIX_LOCK_DATA_SIZE;
5625 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5626 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5627 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5628 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5629 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5631 } else if (NT_STATUS_IS_OK(status)) {
5632 /* For success we just return a copy of what we sent
5633 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5634 data_size = POSIX_LOCK_DATA_SIZE;
5635 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5636 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5644 return NT_STATUS_INVALID_LEVEL;
5647 *pdata_size = data_size;
5648 return NT_STATUS_OK;
5651 /****************************************************************************
5652 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5653 file name or file id).
5654 ****************************************************************************/
5656 static void call_trans2qfilepathinfo(connection_struct *conn,
5657 struct smb_request *req,
5658 unsigned int tran_call,
5659 char **pparams, int total_params,
5660 char **ppdata, int total_data,
5661 unsigned int max_data_bytes)
5663 char *params = *pparams;
5664 char *pdata = *ppdata;
5665 uint16_t info_level;
5666 unsigned int data_size = 0;
5667 unsigned int param_size = 2;
5668 struct smb_filename *smb_fname = NULL;
5669 bool delete_pending = False;
5670 struct timespec write_time_ts;
5671 files_struct *fsp = NULL;
5672 struct file_id fileid;
5673 struct ea_list *ea_list = NULL;
5674 int lock_data_count = 0;
5675 char *lock_data = NULL;
5676 size_t fixed_portion;
5677 NTSTATUS status = NT_STATUS_OK;
5680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5684 ZERO_STRUCT(write_time_ts);
5686 if (tran_call == TRANSACT2_QFILEINFO) {
5687 if (total_params < 4) {
5688 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5693 call_trans2qpipeinfo(conn, req, tran_call,
5694 pparams, total_params,
5700 fsp = file_fsp(req, SVAL(params,0));
5701 info_level = SVAL(params,2);
5703 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5705 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5706 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5710 /* Initial check for valid fsp ptr. */
5711 if (!check_fsp_open(conn, req, fsp)) {
5715 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5716 if (smb_fname == NULL) {
5717 reply_nterror(req, NT_STATUS_NO_MEMORY);
5721 if(fsp->fake_file_handle) {
5723 * This is actually for the QUOTA_FAKE_FILE --metze
5726 /* We know this name is ok, it's already passed the checks. */
5728 } else if(fsp->fh->fd == -1) {
5730 * This is actually a QFILEINFO on a directory
5731 * handle (returned from an NT SMB). NT5.0 seems
5732 * to do this call. JRA.
5735 if (INFO_LEVEL_IS_UNIX(info_level)) {
5736 /* Always do lstat for UNIX calls. */
5737 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5738 DEBUG(3,("call_trans2qfilepathinfo: "
5739 "SMB_VFS_LSTAT of %s failed "
5741 smb_fname_str_dbg(smb_fname),
5744 map_nt_error_from_unix(errno));
5747 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5748 DEBUG(3,("call_trans2qfilepathinfo: "
5749 "SMB_VFS_STAT of %s failed (%s)\n",
5750 smb_fname_str_dbg(smb_fname),
5753 map_nt_error_from_unix(errno));
5757 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5758 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5761 * Original code - this is an open file.
5763 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5764 DEBUG(3, ("fstat of %s failed (%s)\n",
5765 fsp_fnum_dbg(fsp), strerror(errno)));
5767 map_nt_error_from_unix(errno));
5770 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5771 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5777 uint32_t ucf_flags = (req->posix_pathnames ?
5778 UCF_POSIX_PATHNAMES : 0);
5781 if (total_params < 7) {
5782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5786 info_level = SVAL(params,0);
5788 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5790 if (INFO_LEVEL_IS_UNIX(info_level)) {
5791 if (!lp_unix_extensions()) {
5792 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5795 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5796 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5797 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5798 req->posix_pathnames) {
5799 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5803 if (req->posix_pathnames) {
5804 srvstr_get_path_posix(req,
5813 srvstr_get_path(req,
5822 if (!NT_STATUS_IS_OK(status)) {
5823 reply_nterror(req, status);
5827 status = filename_convert(req,
5829 req->flags2 & FLAGS2_DFS_PATHNAMES,
5834 if (!NT_STATUS_IS_OK(status)) {
5835 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5836 reply_botherror(req,
5837 NT_STATUS_PATH_NOT_COVERED,
5838 ERRSRV, ERRbadpath);
5841 reply_nterror(req, status);
5845 /* If this is a stream, check if there is a delete_pending. */
5846 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5847 && is_ntfs_stream_smb_fname(smb_fname)) {
5848 struct smb_filename *smb_fname_base;
5850 /* Create an smb_filename with stream_name == NULL. */
5851 smb_fname_base = synthetic_smb_fname(
5853 smb_fname->base_name,
5857 if (smb_fname_base == NULL) {
5858 reply_nterror(req, NT_STATUS_NO_MEMORY);
5862 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5863 /* Always do lstat for UNIX calls. */
5864 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5865 DEBUG(3,("call_trans2qfilepathinfo: "
5866 "SMB_VFS_LSTAT of %s failed "
5868 smb_fname_str_dbg(smb_fname_base),
5870 TALLOC_FREE(smb_fname_base);
5872 map_nt_error_from_unix(errno));
5876 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5877 DEBUG(3,("call_trans2qfilepathinfo: "
5878 "fileinfo of %s failed "
5880 smb_fname_str_dbg(smb_fname_base),
5882 TALLOC_FREE(smb_fname_base);
5884 map_nt_error_from_unix(errno));
5889 status = file_name_hash(conn,
5890 smb_fname_str_dbg(smb_fname_base),
5892 if (!NT_STATUS_IS_OK(status)) {
5893 TALLOC_FREE(smb_fname_base);
5894 reply_nterror(req, status);
5898 fileid = vfs_file_id_from_sbuf(conn,
5899 &smb_fname_base->st);
5900 TALLOC_FREE(smb_fname_base);
5901 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5902 if (delete_pending) {
5903 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5908 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5909 /* Always do lstat for UNIX calls. */
5910 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5911 DEBUG(3,("call_trans2qfilepathinfo: "
5912 "SMB_VFS_LSTAT of %s failed (%s)\n",
5913 smb_fname_str_dbg(smb_fname),
5916 map_nt_error_from_unix(errno));
5921 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5922 DEBUG(3,("call_trans2qfilepathinfo: "
5923 "SMB_VFS_STAT of %s failed (%s)\n",
5924 smb_fname_str_dbg(smb_fname),
5927 map_nt_error_from_unix(errno));
5932 status = file_name_hash(conn,
5933 smb_fname_str_dbg(smb_fname),
5935 if (!NT_STATUS_IS_OK(status)) {
5936 reply_nterror(req, status);
5940 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5941 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5942 if (delete_pending) {
5943 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5948 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5949 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5951 info_level,tran_call,total_data));
5953 /* Pull out any data sent here before we realloc. */
5954 switch (info_level) {
5955 case SMB_INFO_QUERY_EAS_FROM_LIST:
5957 /* Pull any EA list from the data portion. */
5960 if (total_data < 4) {
5962 req, NT_STATUS_INVALID_PARAMETER);
5965 ea_size = IVAL(pdata,0);
5967 if (total_data > 0 && ea_size != total_data) {
5968 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5969 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5971 req, NT_STATUS_INVALID_PARAMETER);
5975 if (!lp_ea_support(SNUM(conn))) {
5976 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5980 /* Pull out the list of names. */
5981 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5984 req, NT_STATUS_INVALID_PARAMETER);
5990 case SMB_QUERY_POSIX_LOCK:
5992 if (fsp == NULL || fsp->fh->fd == -1) {
5993 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5997 if (total_data != POSIX_LOCK_DATA_SIZE) {
5999 req, NT_STATUS_INVALID_PARAMETER);
6003 /* Copy the lock range data. */
6004 lock_data = (char *)talloc_memdup(
6005 req, pdata, total_data);
6007 reply_nterror(req, NT_STATUS_NO_MEMORY);
6010 lock_data_count = total_data;
6016 *pparams = (char *)SMB_REALLOC(*pparams,2);
6017 if (*pparams == NULL) {
6018 reply_nterror(req, NT_STATUS_NO_MEMORY);
6025 * draft-leach-cifs-v1-spec-02.txt
6026 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6029 * The requested information is placed in the Data portion of the
6030 * transaction response. For the information levels greater than 0x100,
6031 * the transaction response has 1 parameter word which should be
6032 * ignored by the client.
6034 * However Windows only follows this rule for the IS_NAME_VALID call.
6036 switch (info_level) {
6037 case SMB_INFO_IS_NAME_VALID:
6042 if ((info_level & 0xFF00) == 0xFF00) {
6044 * We use levels that start with 0xFF00
6045 * internally to represent SMB2 specific levels
6047 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6051 status = smbd_do_qfilepathinfo(conn, req, info_level,
6053 delete_pending, write_time_ts,
6055 lock_data_count, lock_data,
6056 req->flags2, max_data_bytes,
6058 ppdata, &data_size);
6059 if (!NT_STATUS_IS_OK(status)) {
6060 reply_nterror(req, status);
6063 if (fixed_portion > max_data_bytes) {
6064 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6068 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6074 /****************************************************************************
6075 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6077 ****************************************************************************/
6079 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6080 connection_struct *conn,
6081 struct smb_request *req,
6082 bool overwrite_if_exists,
6083 const struct smb_filename *smb_fname_old,
6084 struct smb_filename *smb_fname_new)
6086 NTSTATUS status = NT_STATUS_OK;
6088 /* source must already exist. */
6089 if (!VALID_STAT(smb_fname_old->st)) {
6090 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6093 if (VALID_STAT(smb_fname_new->st)) {
6094 if (overwrite_if_exists) {
6095 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6096 return NT_STATUS_FILE_IS_A_DIRECTORY;
6098 status = unlink_internals(conn,
6100 FILE_ATTRIBUTE_NORMAL,
6103 if (!NT_STATUS_IS_OK(status)) {
6107 /* Disallow if newname already exists. */
6108 return NT_STATUS_OBJECT_NAME_COLLISION;
6112 /* No links from a directory. */
6113 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6114 return NT_STATUS_FILE_IS_A_DIRECTORY;
6117 /* Setting a hardlink to/from a stream isn't currently supported. */
6118 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6119 is_ntfs_stream_smb_fname(smb_fname_new)) {
6120 return NT_STATUS_INVALID_PARAMETER;
6123 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6124 smb_fname_old->base_name, smb_fname_new->base_name));
6126 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
6127 smb_fname_new->base_name) != 0) {
6128 status = map_nt_error_from_unix(errno);
6129 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6130 nt_errstr(status), smb_fname_old->base_name,
6131 smb_fname_new->base_name));
6136 /****************************************************************************
6137 Deal with setting the time from any of the setfilepathinfo functions.
6138 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6139 calling this function.
6140 ****************************************************************************/
6142 NTSTATUS smb_set_file_time(connection_struct *conn,
6144 const struct smb_filename *smb_fname,
6145 struct smb_file_time *ft,
6146 bool setting_write_time)
6148 struct smb_filename smb_fname_base;
6150 FILE_NOTIFY_CHANGE_LAST_ACCESS
6151 |FILE_NOTIFY_CHANGE_LAST_WRITE
6152 |FILE_NOTIFY_CHANGE_CREATION;
6154 if (!VALID_STAT(smb_fname->st)) {
6155 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6158 /* get some defaults (no modifications) if any info is zero or -1. */
6159 if (null_timespec(ft->create_time)) {
6160 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6163 if (null_timespec(ft->atime)) {
6164 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6167 if (null_timespec(ft->mtime)) {
6168 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6171 if (!setting_write_time) {
6172 /* ft->mtime comes from change time, not write time. */
6173 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6176 /* Ensure the resolution is the correct for
6177 * what we can store on this filesystem. */
6179 round_timespec(conn->ts_res, &ft->create_time);
6180 round_timespec(conn->ts_res, &ft->ctime);
6181 round_timespec(conn->ts_res, &ft->atime);
6182 round_timespec(conn->ts_res, &ft->mtime);
6184 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6185 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6186 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6187 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6188 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6189 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6190 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6191 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6193 if (setting_write_time) {
6195 * This was a Windows setfileinfo on an open file.
6196 * NT does this a lot. We also need to
6197 * set the time here, as it can be read by
6198 * FindFirst/FindNext and with the patch for bug #2045
6199 * in smbd/fileio.c it ensures that this timestamp is
6200 * kept sticky even after a write. We save the request
6201 * away and will set it on file close and after a write. JRA.
6204 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6205 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6208 if (fsp->base_fsp) {
6209 set_sticky_write_time_fsp(fsp->base_fsp,
6212 set_sticky_write_time_fsp(fsp, ft->mtime);
6215 set_sticky_write_time_path(
6216 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6221 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6223 /* Always call ntimes on the base, even if a stream was passed in. */
6224 smb_fname_base = *smb_fname;
6225 smb_fname_base.stream_name = NULL;
6227 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6228 return map_nt_error_from_unix(errno);
6231 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6232 smb_fname->base_name);
6233 return NT_STATUS_OK;
6236 /****************************************************************************
6237 Deal with setting the dosmode from any of the setfilepathinfo functions.
6238 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6239 done before calling this function.
6240 ****************************************************************************/
6242 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6243 const struct smb_filename *smb_fname,
6246 struct smb_filename *smb_fname_base;
6249 if (!VALID_STAT(smb_fname->st)) {
6250 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6253 /* Always operate on the base_name, even if a stream was passed in. */
6254 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6255 smb_fname->base_name,
6259 if (smb_fname_base == NULL) {
6260 return NT_STATUS_NO_MEMORY;
6264 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6265 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6267 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6271 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6273 /* check the mode isn't different, before changing it */
6274 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6275 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6276 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6277 (unsigned int)dosmode));
6279 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6281 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6283 smb_fname_str_dbg(smb_fname_base),
6285 status = map_nt_error_from_unix(errno);
6289 status = NT_STATUS_OK;
6291 TALLOC_FREE(smb_fname_base);
6295 /****************************************************************************
6296 Deal with setting the size from any of the setfilepathinfo functions.
6297 ****************************************************************************/
6299 static NTSTATUS smb_set_file_size(connection_struct *conn,
6300 struct smb_request *req,
6302 const struct smb_filename *smb_fname,
6303 const SMB_STRUCT_STAT *psbuf,
6305 bool fail_after_createfile)
6307 NTSTATUS status = NT_STATUS_OK;
6308 struct smb_filename *smb_fname_tmp = NULL;
6309 files_struct *new_fsp = NULL;
6311 if (!VALID_STAT(*psbuf)) {
6312 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6315 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6317 if (size == get_file_size_stat(psbuf)) {
6318 return NT_STATUS_OK;
6321 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6322 smb_fname_str_dbg(smb_fname), (double)size));
6324 if (fsp && fsp->fh->fd != -1) {
6325 /* Handle based call. */
6326 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6327 return NT_STATUS_ACCESS_DENIED;
6330 if (vfs_set_filelen(fsp, size) == -1) {
6331 return map_nt_error_from_unix(errno);
6333 trigger_write_time_update_immediate(fsp);
6334 return NT_STATUS_OK;
6337 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6338 if (smb_fname_tmp == NULL) {
6339 return NT_STATUS_NO_MEMORY;
6342 smb_fname_tmp->st = *psbuf;
6344 status = SMB_VFS_CREATE_FILE(
6347 0, /* root_dir_fid */
6348 smb_fname_tmp, /* fname */
6349 FILE_WRITE_DATA, /* access_mask */
6350 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6352 FILE_OPEN, /* create_disposition*/
6353 0, /* create_options */
6354 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6355 0, /* oplock_request */
6357 0, /* allocation_size */
6358 0, /* private_flags */
6361 &new_fsp, /* result */
6363 NULL, NULL); /* create context */
6365 TALLOC_FREE(smb_fname_tmp);
6367 if (!NT_STATUS_IS_OK(status)) {
6368 /* NB. We check for open_was_deferred in the caller. */
6372 /* See RAW-SFILEINFO-END-OF-FILE */
6373 if (fail_after_createfile) {
6374 close_file(req, new_fsp,NORMAL_CLOSE);
6375 return NT_STATUS_INVALID_LEVEL;
6378 if (vfs_set_filelen(new_fsp, size) == -1) {
6379 status = map_nt_error_from_unix(errno);
6380 close_file(req, new_fsp,NORMAL_CLOSE);
6384 trigger_write_time_update_immediate(new_fsp);
6385 close_file(req, new_fsp,NORMAL_CLOSE);
6386 return NT_STATUS_OK;
6389 /****************************************************************************
6390 Deal with SMB_INFO_SET_EA.
6391 ****************************************************************************/
6393 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6397 const struct smb_filename *smb_fname)
6399 struct ea_list *ea_list = NULL;
6400 TALLOC_CTX *ctx = NULL;
6401 NTSTATUS status = NT_STATUS_OK;
6403 if (total_data < 10) {
6405 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6406 length. They seem to have no effect. Bug #3212. JRA */
6408 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6409 /* We're done. We only get EA info in this call. */
6410 return NT_STATUS_OK;
6413 return NT_STATUS_INVALID_PARAMETER;
6416 if (IVAL(pdata,0) > total_data) {
6417 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6418 IVAL(pdata,0), (unsigned int)total_data));
6419 return NT_STATUS_INVALID_PARAMETER;
6423 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6425 return NT_STATUS_INVALID_PARAMETER;
6428 status = set_ea(conn, fsp, smb_fname, ea_list);
6433 /****************************************************************************
6434 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6435 ****************************************************************************/
6437 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6442 struct ea_list *ea_list = NULL;
6446 return NT_STATUS_INVALID_HANDLE;
6449 if (!lp_ea_support(SNUM(conn))) {
6450 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6451 "EA's not supported.\n",
6452 (unsigned int)total_data));
6453 return NT_STATUS_EAS_NOT_SUPPORTED;
6456 if (total_data < 10) {
6457 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6459 (unsigned int)total_data));
6460 return NT_STATUS_INVALID_PARAMETER;
6463 ea_list = read_nttrans_ea_list(talloc_tos(),
6468 return NT_STATUS_INVALID_PARAMETER;
6471 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6473 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6474 smb_fname_str_dbg(fsp->fsp_name),
6475 nt_errstr(status) ));
6481 /****************************************************************************
6482 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6483 ****************************************************************************/
6485 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6489 struct smb_filename *smb_fname)
6491 NTSTATUS status = NT_STATUS_OK;
6492 bool delete_on_close;
6493 uint32_t dosmode = 0;
6495 if (total_data < 1) {
6496 return NT_STATUS_INVALID_PARAMETER;
6500 return NT_STATUS_INVALID_HANDLE;
6503 delete_on_close = (CVAL(pdata,0) ? True : False);
6504 dosmode = dos_mode(conn, smb_fname);
6506 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6507 "delete_on_close = %u\n",
6508 smb_fname_str_dbg(smb_fname),
6509 (unsigned int)dosmode,
6510 (unsigned int)delete_on_close ));
6512 if (delete_on_close) {
6513 status = can_set_delete_on_close(fsp, dosmode);
6514 if (!NT_STATUS_IS_OK(status)) {
6519 /* The set is across all open files on this dev/inode pair. */
6520 if (!set_delete_on_close(fsp, delete_on_close,
6521 conn->session_info->security_token,
6522 conn->session_info->unix_token)) {
6523 return NT_STATUS_ACCESS_DENIED;
6525 return NT_STATUS_OK;
6528 /****************************************************************************
6529 Deal with SMB_FILE_POSITION_INFORMATION.
6530 ****************************************************************************/
6532 static NTSTATUS smb_file_position_information(connection_struct *conn,
6537 uint64_t position_information;
6539 if (total_data < 8) {
6540 return NT_STATUS_INVALID_PARAMETER;
6544 /* Ignore on pathname based set. */
6545 return NT_STATUS_OK;
6548 position_information = (uint64_t)IVAL(pdata,0);
6549 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6551 DEBUG(10,("smb_file_position_information: Set file position "
6552 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6553 (double)position_information));
6554 fsp->fh->position_information = position_information;
6555 return NT_STATUS_OK;
6558 /****************************************************************************
6559 Deal with SMB_FILE_MODE_INFORMATION.
6560 ****************************************************************************/
6562 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6568 if (total_data < 4) {
6569 return NT_STATUS_INVALID_PARAMETER;
6571 mode = IVAL(pdata,0);
6572 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6573 return NT_STATUS_INVALID_PARAMETER;
6575 return NT_STATUS_OK;
6578 /****************************************************************************
6579 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6580 ****************************************************************************/
6582 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6583 struct smb_request *req,
6586 const struct smb_filename *smb_fname)
6588 char *link_target = NULL;
6589 const char *newname = smb_fname->base_name;
6590 TALLOC_CTX *ctx = talloc_tos();
6592 /* Set a symbolic link. */
6593 /* Don't allow this if follow links is false. */
6595 if (total_data == 0) {
6596 return NT_STATUS_INVALID_PARAMETER;
6599 if (!lp_follow_symlinks(SNUM(conn))) {
6600 return NT_STATUS_ACCESS_DENIED;
6603 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6604 total_data, STR_TERMINATE);
6607 return NT_STATUS_INVALID_PARAMETER;
6610 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6611 newname, link_target ));
6613 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6614 return map_nt_error_from_unix(errno);
6617 return NT_STATUS_OK;
6620 /****************************************************************************
6621 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6622 ****************************************************************************/
6624 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6625 struct smb_request *req,
6626 const char *pdata, int total_data,
6627 struct smb_filename *smb_fname_new)
6629 char *oldname = NULL;
6630 struct smb_filename *smb_fname_old = NULL;
6631 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6632 TALLOC_CTX *ctx = talloc_tos();
6633 NTSTATUS status = NT_STATUS_OK;
6635 /* Set a hard link. */
6636 if (total_data == 0) {
6637 return NT_STATUS_INVALID_PARAMETER;
6640 if (req->posix_pathnames) {
6641 srvstr_get_path_posix(ctx,
6650 srvstr_get_path(ctx,
6659 if (!NT_STATUS_IS_OK(status)) {
6663 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6664 smb_fname_str_dbg(smb_fname_new), oldname));
6666 status = filename_convert(ctx,
6668 req->flags2 & FLAGS2_DFS_PATHNAMES,
6673 if (!NT_STATUS_IS_OK(status)) {
6677 return hardlink_internals(ctx, conn, req, false,
6678 smb_fname_old, smb_fname_new);
6681 /****************************************************************************
6682 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6683 ****************************************************************************/
6685 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6686 struct smb_request *req,
6690 struct smb_filename *smb_fname_src)
6694 char *newname = NULL;
6695 struct smb_filename *smb_fname_dst = NULL;
6696 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6697 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6698 NTSTATUS status = NT_STATUS_OK;
6699 TALLOC_CTX *ctx = talloc_tos();
6702 return NT_STATUS_INVALID_HANDLE;
6705 if (total_data < 20) {
6706 return NT_STATUS_INVALID_PARAMETER;
6709 overwrite = (CVAL(pdata,0) ? True : False);
6710 len = IVAL(pdata,16);
6712 if (len > (total_data - 20) || (len == 0)) {
6713 return NT_STATUS_INVALID_PARAMETER;
6716 if (req->posix_pathnames) {
6717 srvstr_get_path_posix(ctx,
6726 srvstr_get_path(ctx,
6735 if (!NT_STATUS_IS_OK(status)) {
6739 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6742 status = filename_convert(ctx,
6744 req->flags2 & FLAGS2_DFS_PATHNAMES,
6749 if (!NT_STATUS_IS_OK(status)) {
6753 if (fsp->base_fsp) {
6754 /* newname must be a stream name. */
6755 if (newname[0] != ':') {
6756 return NT_STATUS_NOT_SUPPORTED;
6759 /* Create an smb_fname to call rename_internals_fsp() with. */
6760 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6761 fsp->base_fsp->fsp_name->base_name,
6764 fsp->base_fsp->fsp_name->flags);
6765 if (smb_fname_dst == NULL) {
6766 status = NT_STATUS_NO_MEMORY;
6771 * Set the original last component, since
6772 * rename_internals_fsp() requires it.
6774 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6776 if (smb_fname_dst->original_lcomp == NULL) {
6777 status = NT_STATUS_NO_MEMORY;
6783 DEBUG(10,("smb2_file_rename_information: "
6784 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6785 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6786 smb_fname_str_dbg(smb_fname_dst)));
6787 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6788 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6792 TALLOC_FREE(smb_fname_dst);
6796 static NTSTATUS smb_file_link_information(connection_struct *conn,
6797 struct smb_request *req,
6801 struct smb_filename *smb_fname_src)
6805 char *newname = NULL;
6806 struct smb_filename *smb_fname_dst = NULL;
6807 NTSTATUS status = NT_STATUS_OK;
6808 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6809 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6810 TALLOC_CTX *ctx = talloc_tos();
6813 return NT_STATUS_INVALID_HANDLE;
6816 if (total_data < 20) {
6817 return NT_STATUS_INVALID_PARAMETER;
6820 overwrite = (CVAL(pdata,0) ? true : false);
6821 len = IVAL(pdata,16);
6823 if (len > (total_data - 20) || (len == 0)) {
6824 return NT_STATUS_INVALID_PARAMETER;
6827 if (req->posix_pathnames) {
6828 srvstr_get_path_posix(ctx,
6837 srvstr_get_path(ctx,
6846 if (!NT_STATUS_IS_OK(status)) {
6850 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6853 status = filename_convert(ctx,
6855 req->flags2 & FLAGS2_DFS_PATHNAMES,
6860 if (!NT_STATUS_IS_OK(status)) {
6864 if (fsp->base_fsp) {
6865 /* No stream names. */
6866 return NT_STATUS_NOT_SUPPORTED;
6869 DEBUG(10,("smb_file_link_information: "
6870 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6871 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6872 smb_fname_str_dbg(smb_fname_dst)));
6873 status = hardlink_internals(ctx,
6880 TALLOC_FREE(smb_fname_dst);
6884 /****************************************************************************
6885 Deal with SMB_FILE_RENAME_INFORMATION.
6886 ****************************************************************************/
6888 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6889 struct smb_request *req,
6893 struct smb_filename *smb_fname_src)
6898 char *newname = NULL;
6899 struct smb_filename *smb_fname_dst = NULL;
6900 bool dest_has_wcard = False;
6901 NTSTATUS status = NT_STATUS_OK;
6903 TALLOC_CTX *ctx = talloc_tos();
6905 if (total_data < 13) {
6906 return NT_STATUS_INVALID_PARAMETER;
6909 overwrite = (CVAL(pdata,0) ? True : False);
6910 root_fid = IVAL(pdata,4);
6911 len = IVAL(pdata,8);
6913 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6914 return NT_STATUS_INVALID_PARAMETER;
6917 if (req->posix_pathnames) {
6918 srvstr_get_path_wcard_posix(ctx,
6928 srvstr_get_path_wcard(ctx,
6938 if (!NT_STATUS_IS_OK(status)) {
6942 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6945 status = resolve_dfspath_wcard(ctx, conn,
6946 req->flags2 & FLAGS2_DFS_PATHNAMES,
6948 UCF_COND_ALLOW_WCARD_LCOMP,
6949 !conn->sconn->using_smb2,
6952 if (!NT_STATUS_IS_OK(status)) {
6956 /* Check the new name has no '/' characters. */
6957 if (strchr_m(newname, '/')) {
6958 return NT_STATUS_NOT_SUPPORTED;
6961 if (fsp && fsp->base_fsp) {
6962 /* newname must be a stream name. */
6963 if (newname[0] != ':') {
6964 return NT_STATUS_NOT_SUPPORTED;
6967 /* Create an smb_fname to call rename_internals_fsp() with. */
6968 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6969 fsp->base_fsp->fsp_name->base_name,
6972 fsp->base_fsp->fsp_name->flags);
6973 if (smb_fname_dst == NULL) {
6974 status = NT_STATUS_NO_MEMORY;
6979 * Set the original last component, since
6980 * rename_internals_fsp() requires it.
6982 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6984 if (smb_fname_dst->original_lcomp == NULL) {
6985 status = NT_STATUS_NO_MEMORY;
6991 * Build up an smb_fname_dst based on the filename passed in.
6992 * We basically just strip off the last component, and put on
6993 * the newname instead.
6995 char *base_name = NULL;
6997 /* newname must *not* be a stream name. */
6998 if (newname[0] == ':') {
6999 return NT_STATUS_NOT_SUPPORTED;
7003 * Strip off the last component (filename) of the path passed
7006 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7008 return NT_STATUS_NO_MEMORY;
7010 p = strrchr_m(base_name, '/');
7014 base_name = talloc_strdup(ctx, "");
7016 return NT_STATUS_NO_MEMORY;
7019 /* Append the new name. */
7020 base_name = talloc_asprintf_append(base_name,
7024 return NT_STATUS_NO_MEMORY;
7027 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7030 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
7033 /* If an error we expect this to be
7034 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7036 if (!NT_STATUS_IS_OK(status)) {
7037 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7041 /* Create an smb_fname to call rename_internals_fsp() */
7042 smb_fname_dst = synthetic_smb_fname(ctx,
7046 smb_fname_src->flags);
7047 if (smb_fname_dst == NULL) {
7048 status = NT_STATUS_NO_MEMORY;
7055 DEBUG(10,("smb_file_rename_information: "
7056 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7057 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7058 smb_fname_str_dbg(smb_fname_dst)));
7059 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7062 DEBUG(10,("smb_file_rename_information: "
7063 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7064 smb_fname_str_dbg(smb_fname_src),
7065 smb_fname_str_dbg(smb_fname_dst)));
7066 status = rename_internals(ctx, conn, req, smb_fname_src,
7067 smb_fname_dst, 0, overwrite, false,
7069 FILE_WRITE_ATTRIBUTES);
7072 TALLOC_FREE(smb_fname_dst);
7076 /****************************************************************************
7077 Deal with SMB_SET_POSIX_ACL.
7078 ****************************************************************************/
7080 #if defined(HAVE_POSIX_ACLS)
7081 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7085 const struct smb_filename *smb_fname)
7087 uint16_t posix_acl_version;
7088 uint16_t num_file_acls;
7089 uint16_t num_def_acls;
7090 bool valid_file_acls = True;
7091 bool valid_def_acls = True;
7094 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7095 return NT_STATUS_INVALID_PARAMETER;
7097 posix_acl_version = SVAL(pdata,0);
7098 num_file_acls = SVAL(pdata,2);
7099 num_def_acls = SVAL(pdata,4);
7101 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7102 valid_file_acls = False;
7106 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7107 valid_def_acls = False;
7111 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7112 return NT_STATUS_INVALID_PARAMETER;
7115 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7116 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7117 return NT_STATUS_INVALID_PARAMETER;
7120 status = refuse_symlink(conn, fsp, smb_fname);
7121 if (!NT_STATUS_IS_OK(status)) {
7125 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7126 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7127 (unsigned int)num_file_acls,
7128 (unsigned int)num_def_acls));
7130 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7131 smb_fname->base_name, num_file_acls,
7132 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7133 return map_nt_error_from_unix(errno);
7136 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7137 smb_fname->base_name, &smb_fname->st, num_def_acls,
7138 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7139 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7140 return map_nt_error_from_unix(errno);
7142 return NT_STATUS_OK;
7146 /****************************************************************************
7147 Deal with SMB_SET_POSIX_LOCK.
7148 ****************************************************************************/
7150 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7151 struct smb_request *req,
7159 bool blocking_lock = False;
7160 enum brl_type lock_type;
7162 NTSTATUS status = NT_STATUS_OK;
7164 if (fsp == NULL || fsp->fh->fd == -1) {
7165 return NT_STATUS_INVALID_HANDLE;
7168 if (total_data != POSIX_LOCK_DATA_SIZE) {
7169 return NT_STATUS_INVALID_PARAMETER;
7172 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7173 case POSIX_LOCK_TYPE_READ:
7174 lock_type = READ_LOCK;
7176 case POSIX_LOCK_TYPE_WRITE:
7177 /* Return the right POSIX-mappable error code for files opened read-only. */
7178 if (!fsp->can_write) {
7179 return NT_STATUS_INVALID_HANDLE;
7181 lock_type = WRITE_LOCK;
7183 case POSIX_LOCK_TYPE_UNLOCK:
7184 lock_type = UNLOCK_LOCK;
7187 return NT_STATUS_INVALID_PARAMETER;
7190 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7191 blocking_lock = False;
7192 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7193 blocking_lock = True;
7195 return NT_STATUS_INVALID_PARAMETER;
7198 if (!lp_blocking_locks(SNUM(conn))) {
7199 blocking_lock = False;
7202 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7203 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7204 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7205 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7206 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7208 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7209 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7211 (unsigned int)lock_type,
7212 (unsigned long long)smblctx,
7216 if (lock_type == UNLOCK_LOCK) {
7217 status = do_unlock(req->sconn->msg_ctx,
7224 uint64_t block_smblctx;
7226 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7237 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7239 * A blocking lock was requested. Package up
7240 * this smb into a queued request and push it
7241 * onto the blocking lock queue.
7243 if(push_blocking_lock_request(br_lck,
7246 -1, /* infinite timeout. */
7254 TALLOC_FREE(br_lck);
7258 TALLOC_FREE(br_lck);
7264 /****************************************************************************
7265 Deal with SMB_SET_FILE_BASIC_INFO.
7266 ****************************************************************************/
7268 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7272 const struct smb_filename *smb_fname)
7274 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7275 struct smb_file_time ft;
7276 uint32_t dosmode = 0;
7277 NTSTATUS status = NT_STATUS_OK;
7281 if (total_data < 36) {
7282 return NT_STATUS_INVALID_PARAMETER;
7285 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7286 if (!NT_STATUS_IS_OK(status)) {
7290 /* Set the attributes */
7291 dosmode = IVAL(pdata,32);
7292 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7293 if (!NT_STATUS_IS_OK(status)) {
7298 ft.create_time = interpret_long_date(pdata);
7301 ft.atime = interpret_long_date(pdata+8);
7304 ft.mtime = interpret_long_date(pdata+16);
7307 ft.ctime = interpret_long_date(pdata+24);
7309 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7310 smb_fname_str_dbg(smb_fname)));
7312 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7316 /****************************************************************************
7317 Deal with SMB_INFO_STANDARD.
7318 ****************************************************************************/
7320 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7324 const struct smb_filename *smb_fname)
7327 struct smb_file_time ft;
7331 if (total_data < 12) {
7332 return NT_STATUS_INVALID_PARAMETER;
7336 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7338 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7340 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7342 DEBUG(10,("smb_set_info_standard: file %s\n",
7343 smb_fname_str_dbg(smb_fname)));
7345 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7346 if (!NT_STATUS_IS_OK(status)) {
7350 return smb_set_file_time(conn,
7357 /****************************************************************************
7358 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7359 ****************************************************************************/
7361 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7362 struct smb_request *req,
7366 struct smb_filename *smb_fname)
7368 uint64_t allocation_size = 0;
7369 NTSTATUS status = NT_STATUS_OK;
7370 files_struct *new_fsp = NULL;
7372 if (!VALID_STAT(smb_fname->st)) {
7373 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7376 if (total_data < 8) {
7377 return NT_STATUS_INVALID_PARAMETER;
7380 allocation_size = (uint64_t)IVAL(pdata,0);
7381 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7382 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7383 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7384 (double)allocation_size));
7386 if (allocation_size) {
7387 allocation_size = smb_roundup(conn, allocation_size);
7390 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7391 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7392 (double)allocation_size));
7394 if (fsp && fsp->fh->fd != -1) {
7395 /* Open file handle. */
7396 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7397 return NT_STATUS_ACCESS_DENIED;
7400 /* Only change if needed. */
7401 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7402 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7403 return map_nt_error_from_unix(errno);
7406 /* But always update the time. */
7408 * This is equivalent to a write. Ensure it's seen immediately
7409 * if there are no pending writes.
7411 trigger_write_time_update_immediate(fsp);
7412 return NT_STATUS_OK;
7415 /* Pathname or stat or directory file. */
7416 status = SMB_VFS_CREATE_FILE(
7419 0, /* root_dir_fid */
7420 smb_fname, /* fname */
7421 FILE_WRITE_DATA, /* access_mask */
7422 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7424 FILE_OPEN, /* create_disposition*/
7425 0, /* create_options */
7426 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7427 0, /* oplock_request */
7429 0, /* allocation_size */
7430 0, /* private_flags */
7433 &new_fsp, /* result */
7435 NULL, NULL); /* create context */
7437 if (!NT_STATUS_IS_OK(status)) {
7438 /* NB. We check for open_was_deferred in the caller. */
7442 /* Only change if needed. */
7443 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7444 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7445 status = map_nt_error_from_unix(errno);
7446 close_file(req, new_fsp, NORMAL_CLOSE);
7451 /* Changing the allocation size should set the last mod time. */
7453 * This is equivalent to a write. Ensure it's seen immediately
7454 * if there are no pending writes.
7456 trigger_write_time_update_immediate(new_fsp);
7457 close_file(req, new_fsp, NORMAL_CLOSE);
7458 return NT_STATUS_OK;
7461 /****************************************************************************
7462 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7463 ****************************************************************************/
7465 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7466 struct smb_request *req,
7470 const struct smb_filename *smb_fname,
7471 bool fail_after_createfile)
7475 if (total_data < 8) {
7476 return NT_STATUS_INVALID_PARAMETER;
7479 size = IVAL(pdata,0);
7480 size |= (((off_t)IVAL(pdata,4)) << 32);
7481 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7482 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7485 return smb_set_file_size(conn, req,
7490 fail_after_createfile);
7493 /****************************************************************************
7494 Allow a UNIX info mknod.
7495 ****************************************************************************/
7497 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7500 const struct smb_filename *smb_fname)
7502 uint32_t file_type = IVAL(pdata,56);
7503 #if defined(HAVE_MAKEDEV)
7504 uint32_t dev_major = IVAL(pdata,60);
7505 uint32_t dev_minor = IVAL(pdata,68);
7507 SMB_DEV_T dev = (SMB_DEV_T)0;
7508 uint32_t raw_unixmode = IVAL(pdata,84);
7512 if (total_data < 100) {
7513 return NT_STATUS_INVALID_PARAMETER;
7516 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7517 PERM_NEW_FILE, &unixmode);
7518 if (!NT_STATUS_IS_OK(status)) {
7522 #if defined(HAVE_MAKEDEV)
7523 dev = makedev(dev_major, dev_minor);
7526 switch (file_type) {
7527 #if defined(S_IFIFO)
7528 case UNIX_TYPE_FIFO:
7529 unixmode |= S_IFIFO;
7532 #if defined(S_IFSOCK)
7533 case UNIX_TYPE_SOCKET:
7534 unixmode |= S_IFSOCK;
7537 #if defined(S_IFCHR)
7538 case UNIX_TYPE_CHARDEV:
7539 unixmode |= S_IFCHR;
7542 #if defined(S_IFBLK)
7543 case UNIX_TYPE_BLKDEV:
7544 unixmode |= S_IFBLK;
7548 return NT_STATUS_INVALID_PARAMETER;
7551 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7552 "%.0f mode 0%o for file %s\n", (double)dev,
7553 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7555 /* Ok - do the mknod. */
7556 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7557 return map_nt_error_from_unix(errno);
7560 /* If any of the other "set" calls fail we
7561 * don't want to end up with a half-constructed mknod.
7564 if (lp_inherit_permissions(SNUM(conn))) {
7566 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7568 return NT_STATUS_NO_MEMORY;
7570 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7572 TALLOC_FREE(parent);
7575 return NT_STATUS_OK;
7578 /****************************************************************************
7579 Deal with SMB_SET_FILE_UNIX_BASIC.
7580 ****************************************************************************/
7582 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7583 struct smb_request *req,
7587 const struct smb_filename *smb_fname)
7589 struct smb_file_time ft;
7590 uint32_t raw_unixmode;
7593 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7594 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7595 NTSTATUS status = NT_STATUS_OK;
7596 bool delete_on_fail = False;
7597 enum perm_type ptype;
7598 files_struct *all_fsps = NULL;
7599 bool modify_mtime = true;
7601 struct smb_filename *smb_fname_tmp = NULL;
7602 SMB_STRUCT_STAT sbuf;
7606 if (total_data < 100) {
7607 return NT_STATUS_INVALID_PARAMETER;
7610 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7611 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7612 size=IVAL(pdata,0); /* first 8 Bytes are size */
7613 size |= (((off_t)IVAL(pdata,4)) << 32);
7616 ft.atime = interpret_long_date(pdata+24); /* access_time */
7617 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7618 set_owner = (uid_t)IVAL(pdata,40);
7619 set_grp = (gid_t)IVAL(pdata,48);
7620 raw_unixmode = IVAL(pdata,84);
7622 if (VALID_STAT(smb_fname->st)) {
7623 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7624 ptype = PERM_EXISTING_DIR;
7626 ptype = PERM_EXISTING_FILE;
7629 ptype = PERM_NEW_FILE;
7632 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7634 if (!NT_STATUS_IS_OK(status)) {
7638 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7639 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7640 smb_fname_str_dbg(smb_fname), (double)size,
7641 (unsigned int)set_owner, (unsigned int)set_grp,
7642 (int)raw_unixmode));
7644 sbuf = smb_fname->st;
7646 if (!VALID_STAT(sbuf)) {
7648 * The only valid use of this is to create character and block
7649 * devices, and named pipes. This is deprecated (IMHO) and
7650 * a new info level should be used for mknod. JRA.
7653 status = smb_unix_mknod(conn,
7657 if (!NT_STATUS_IS_OK(status)) {
7661 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7662 if (smb_fname_tmp == NULL) {
7663 return NT_STATUS_NO_MEMORY;
7666 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7667 status = map_nt_error_from_unix(errno);
7668 TALLOC_FREE(smb_fname_tmp);
7669 SMB_VFS_UNLINK(conn, smb_fname);
7673 sbuf = smb_fname_tmp->st;
7674 smb_fname = smb_fname_tmp;
7676 /* Ensure we don't try and change anything else. */
7677 raw_unixmode = SMB_MODE_NO_CHANGE;
7678 size = get_file_size_stat(&sbuf);
7679 ft.atime = sbuf.st_ex_atime;
7680 ft.mtime = sbuf.st_ex_mtime;
7682 * We continue here as we might want to change the
7685 delete_on_fail = True;
7689 /* Horrible backwards compatibility hack as an old server bug
7690 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7694 size = get_file_size_stat(&sbuf);
7699 * Deal with the UNIX specific mode set.
7702 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7705 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7706 "setting mode 0%o for file %s\n",
7707 (unsigned int)unixmode,
7708 smb_fname_str_dbg(smb_fname)));
7709 if (fsp && fsp->fh->fd != -1) {
7710 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7712 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7715 return map_nt_error_from_unix(errno);
7720 * Deal with the UNIX specific uid set.
7723 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7724 (sbuf.st_ex_uid != set_owner)) {
7727 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7728 "changing owner %u for path %s\n",
7729 (unsigned int)set_owner,
7730 smb_fname_str_dbg(smb_fname)));
7732 if (fsp && fsp->fh->fd != -1) {
7733 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7736 * UNIX extensions calls must always operate
7739 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7740 set_owner, (gid_t)-1);
7744 status = map_nt_error_from_unix(errno);
7745 if (delete_on_fail) {
7746 SMB_VFS_UNLINK(conn, smb_fname);
7753 * Deal with the UNIX specific gid set.
7756 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7757 (sbuf.st_ex_gid != set_grp)) {
7760 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7761 "changing group %u for file %s\n",
7762 (unsigned int)set_owner,
7763 smb_fname_str_dbg(smb_fname)));
7764 if (fsp && fsp->fh->fd != -1) {
7765 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7768 * UNIX extensions calls must always operate
7771 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7775 status = map_nt_error_from_unix(errno);
7776 if (delete_on_fail) {
7777 SMB_VFS_UNLINK(conn, smb_fname);
7783 /* Deal with any size changes. */
7785 status = smb_set_file_size(conn, req,
7791 if (!NT_STATUS_IS_OK(status)) {
7795 /* Deal with any time changes. */
7796 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7797 /* No change, don't cancel anything. */
7801 id = vfs_file_id_from_sbuf(conn, &sbuf);
7802 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7803 all_fsps = file_find_di_next(all_fsps)) {
7805 * We're setting the time explicitly for UNIX.
7806 * Cancel any pending changes over all handles.
7808 all_fsps->update_write_time_on_close = false;
7809 TALLOC_FREE(all_fsps->update_write_time_event);
7813 * Override the "setting_write_time"
7814 * parameter here as it almost does what
7815 * we need. Just remember if we modified
7816 * mtime and send the notify ourselves.
7818 if (null_timespec(ft.mtime)) {
7819 modify_mtime = false;
7822 status = smb_set_file_time(conn,
7828 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7829 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7834 /****************************************************************************
7835 Deal with SMB_SET_FILE_UNIX_INFO2.
7836 ****************************************************************************/
7838 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7839 struct smb_request *req,
7843 const struct smb_filename *smb_fname)
7846 uint32_t smb_fflags;
7849 if (total_data < 116) {
7850 return NT_STATUS_INVALID_PARAMETER;
7853 /* Start by setting all the fields that are common between UNIX_BASIC
7856 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7858 if (!NT_STATUS_IS_OK(status)) {
7862 smb_fflags = IVAL(pdata, 108);
7863 smb_fmask = IVAL(pdata, 112);
7865 /* NB: We should only attempt to alter the file flags if the client
7866 * sends a non-zero mask.
7868 if (smb_fmask != 0) {
7869 int stat_fflags = 0;
7871 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7872 smb_fmask, &stat_fflags)) {
7873 /* Client asked to alter a flag we don't understand. */
7874 return NT_STATUS_INVALID_PARAMETER;
7877 if (fsp && fsp->fh->fd != -1) {
7878 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7879 return NT_STATUS_NOT_SUPPORTED;
7881 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7882 stat_fflags) != 0) {
7883 return map_nt_error_from_unix(errno);
7888 /* XXX: need to add support for changing the create_time here. You
7889 * can do this for paths on Darwin with setattrlist(2). The right way
7890 * to hook this up is probably by extending the VFS utimes interface.
7893 return NT_STATUS_OK;
7896 /****************************************************************************
7897 Create a directory with POSIX semantics.
7898 ****************************************************************************/
7900 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7901 struct smb_request *req,
7904 struct smb_filename *smb_fname,
7905 int *pdata_return_size)
7907 NTSTATUS status = NT_STATUS_OK;
7908 uint32_t raw_unixmode = 0;
7909 uint32_t mod_unixmode = 0;
7910 mode_t unixmode = (mode_t)0;
7911 files_struct *fsp = NULL;
7912 uint16_t info_level_return = 0;
7914 char *pdata = *ppdata;
7916 if (total_data < 18) {
7917 return NT_STATUS_INVALID_PARAMETER;
7920 raw_unixmode = IVAL(pdata,8);
7921 /* Next 4 bytes are not yet defined. */
7923 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7924 PERM_NEW_DIR, &unixmode);
7925 if (!NT_STATUS_IS_OK(status)) {
7929 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7931 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7932 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7934 status = SMB_VFS_CREATE_FILE(
7937 0, /* root_dir_fid */
7938 smb_fname, /* fname */
7939 FILE_READ_ATTRIBUTES, /* access_mask */
7940 FILE_SHARE_NONE, /* share_access */
7941 FILE_CREATE, /* create_disposition*/
7942 FILE_DIRECTORY_FILE, /* create_options */
7943 mod_unixmode, /* file_attributes */
7944 0, /* oplock_request */
7946 0, /* allocation_size */
7947 0, /* private_flags */
7952 NULL, NULL); /* create context */
7954 if (NT_STATUS_IS_OK(status)) {
7955 close_file(req, fsp, NORMAL_CLOSE);
7958 info_level_return = SVAL(pdata,16);
7960 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7961 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7962 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7963 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7965 *pdata_return_size = 12;
7968 /* Realloc the data size */
7969 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7970 if (*ppdata == NULL) {
7971 *pdata_return_size = 0;
7972 return NT_STATUS_NO_MEMORY;
7976 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7977 SSVAL(pdata,2,0); /* No fnum. */
7978 SIVAL(pdata,4,info); /* Was directory created. */
7980 switch (info_level_return) {
7981 case SMB_QUERY_FILE_UNIX_BASIC:
7982 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7983 SSVAL(pdata,10,0); /* Padding. */
7984 store_file_unix_basic(conn, pdata + 12, fsp,
7987 case SMB_QUERY_FILE_UNIX_INFO2:
7988 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7989 SSVAL(pdata,10,0); /* Padding. */
7990 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7994 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7995 SSVAL(pdata,10,0); /* Padding. */
8002 /****************************************************************************
8003 Open/Create a file with POSIX semantics.
8004 ****************************************************************************/
8006 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8007 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8009 static NTSTATUS smb_posix_open(connection_struct *conn,
8010 struct smb_request *req,
8013 struct smb_filename *smb_fname,
8014 int *pdata_return_size)
8016 bool extended_oplock_granted = False;
8017 char *pdata = *ppdata;
8019 uint32_t wire_open_mode = 0;
8020 uint32_t raw_unixmode = 0;
8021 uint32_t mod_unixmode = 0;
8022 uint32_t create_disp = 0;
8023 uint32_t access_mask = 0;
8024 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8025 NTSTATUS status = NT_STATUS_OK;
8026 mode_t unixmode = (mode_t)0;
8027 files_struct *fsp = NULL;
8028 int oplock_request = 0;
8030 uint16_t info_level_return = 0;
8032 if (total_data < 18) {
8033 return NT_STATUS_INVALID_PARAMETER;
8036 flags = IVAL(pdata,0);
8037 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8038 if (oplock_request) {
8039 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8042 wire_open_mode = IVAL(pdata,4);
8044 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8045 return smb_posix_mkdir(conn, req,
8052 switch (wire_open_mode & SMB_ACCMODE) {
8054 access_mask = SMB_O_RDONLY_MAPPING;
8057 access_mask = SMB_O_WRONLY_MAPPING;
8060 access_mask = (SMB_O_RDONLY_MAPPING|
8061 SMB_O_WRONLY_MAPPING);
8064 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8065 (unsigned int)wire_open_mode ));
8066 return NT_STATUS_INVALID_PARAMETER;
8069 wire_open_mode &= ~SMB_ACCMODE;
8071 /* First take care of O_CREAT|O_EXCL interactions. */
8072 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8073 case (SMB_O_CREAT | SMB_O_EXCL):
8074 /* File exists fail. File not exist create. */
8075 create_disp = FILE_CREATE;
8078 /* File exists open. File not exist create. */
8079 create_disp = FILE_OPEN_IF;
8082 /* O_EXCL on its own without O_CREAT is undefined.
8083 We deliberately ignore it as some versions of
8084 Linux CIFSFS can send a bare O_EXCL on the
8085 wire which other filesystems in the kernel
8086 ignore. See bug 9519 for details. */
8091 /* File exists open. File not exist fail. */
8092 create_disp = FILE_OPEN;
8095 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8096 (unsigned int)wire_open_mode ));
8097 return NT_STATUS_INVALID_PARAMETER;
8100 /* Next factor in the effects of O_TRUNC. */
8101 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8103 if (wire_open_mode & SMB_O_TRUNC) {
8104 switch (create_disp) {
8106 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8107 /* Leave create_disp alone as
8108 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8110 /* File exists fail. File not exist create. */
8113 /* SMB_O_CREAT | SMB_O_TRUNC */
8114 /* File exists overwrite. File not exist create. */
8115 create_disp = FILE_OVERWRITE_IF;
8119 /* File exists overwrite. File not exist fail. */
8120 create_disp = FILE_OVERWRITE;
8123 /* Cannot get here. */
8124 smb_panic("smb_posix_open: logic error");
8125 return NT_STATUS_INVALID_PARAMETER;
8129 raw_unixmode = IVAL(pdata,8);
8130 /* Next 4 bytes are not yet defined. */
8132 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8133 (VALID_STAT(smb_fname->st) ?
8134 PERM_EXISTING_FILE : PERM_NEW_FILE),
8137 if (!NT_STATUS_IS_OK(status)) {
8141 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8143 if (wire_open_mode & SMB_O_SYNC) {
8144 create_options |= FILE_WRITE_THROUGH;
8146 if (wire_open_mode & SMB_O_APPEND) {
8147 access_mask |= FILE_APPEND_DATA;
8149 if (wire_open_mode & SMB_O_DIRECT) {
8150 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8153 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8154 VALID_STAT_OF_DIR(smb_fname->st)) {
8155 if (access_mask != SMB_O_RDONLY_MAPPING) {
8156 return NT_STATUS_FILE_IS_A_DIRECTORY;
8158 create_options &= ~FILE_NON_DIRECTORY_FILE;
8159 create_options |= FILE_DIRECTORY_FILE;
8162 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8163 smb_fname_str_dbg(smb_fname),
8164 (unsigned int)wire_open_mode,
8165 (unsigned int)unixmode ));
8167 status = SMB_VFS_CREATE_FILE(
8170 0, /* root_dir_fid */
8171 smb_fname, /* fname */
8172 access_mask, /* access_mask */
8173 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8175 create_disp, /* create_disposition*/
8176 create_options, /* create_options */
8177 mod_unixmode, /* file_attributes */
8178 oplock_request, /* oplock_request */
8180 0, /* allocation_size */
8181 0, /* private_flags */
8186 NULL, NULL); /* create context */
8188 if (!NT_STATUS_IS_OK(status)) {
8192 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8193 extended_oplock_granted = True;
8196 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8197 extended_oplock_granted = True;
8200 info_level_return = SVAL(pdata,16);
8202 /* Allocate the correct return size. */
8204 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8205 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8206 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8207 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8209 *pdata_return_size = 12;
8212 /* Realloc the data size */
8213 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8214 if (*ppdata == NULL) {
8215 close_file(req, fsp, ERROR_CLOSE);
8216 *pdata_return_size = 0;
8217 return NT_STATUS_NO_MEMORY;
8221 if (extended_oplock_granted) {
8222 if (flags & REQUEST_BATCH_OPLOCK) {
8223 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8225 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8227 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8228 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8230 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8233 SSVAL(pdata,2,fsp->fnum);
8234 SIVAL(pdata,4,info); /* Was file created etc. */
8236 switch (info_level_return) {
8237 case SMB_QUERY_FILE_UNIX_BASIC:
8238 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8239 SSVAL(pdata,10,0); /* padding. */
8240 store_file_unix_basic(conn, pdata + 12, fsp,
8243 case SMB_QUERY_FILE_UNIX_INFO2:
8244 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8245 SSVAL(pdata,10,0); /* padding. */
8246 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8250 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8251 SSVAL(pdata,10,0); /* padding. */
8254 return NT_STATUS_OK;
8257 /****************************************************************************
8258 Delete a file with POSIX semantics.
8259 ****************************************************************************/
8261 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8262 struct smb_request *req,
8265 struct smb_filename *smb_fname)
8267 NTSTATUS status = NT_STATUS_OK;
8268 files_struct *fsp = NULL;
8272 int create_options = 0;
8274 struct share_mode_lock *lck = NULL;
8276 if (total_data < 2) {
8277 return NT_STATUS_INVALID_PARAMETER;
8280 flags = SVAL(pdata,0);
8282 if (!VALID_STAT(smb_fname->st)) {
8283 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8286 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8287 !VALID_STAT_OF_DIR(smb_fname->st)) {
8288 return NT_STATUS_NOT_A_DIRECTORY;
8291 DEBUG(10,("smb_posix_unlink: %s %s\n",
8292 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8293 smb_fname_str_dbg(smb_fname)));
8295 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8296 create_options |= FILE_DIRECTORY_FILE;
8299 status = SMB_VFS_CREATE_FILE(
8302 0, /* root_dir_fid */
8303 smb_fname, /* fname */
8304 DELETE_ACCESS, /* access_mask */
8305 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8307 FILE_OPEN, /* create_disposition*/
8308 create_options, /* create_options */
8309 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8310 0, /* oplock_request */
8312 0, /* allocation_size */
8313 0, /* private_flags */
8318 NULL, NULL); /* create context */
8320 if (!NT_STATUS_IS_OK(status)) {
8325 * Don't lie to client. If we can't really delete due to
8326 * non-POSIX opens return SHARING_VIOLATION.
8329 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8331 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8332 "lock for file %s\n", fsp_str_dbg(fsp)));
8333 close_file(req, fsp, NORMAL_CLOSE);
8334 return NT_STATUS_INVALID_PARAMETER;
8338 * See if others still have the file open. If this is the case, then
8339 * don't delete. If all opens are POSIX delete we can set the delete
8340 * on close disposition.
8342 for (i=0; i<lck->data->num_share_modes; i++) {
8343 struct share_mode_entry *e = &lck->data->share_modes[i];
8344 if (is_valid_share_mode_entry(e)) {
8345 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8348 if (share_mode_stale_pid(lck->data, i)) {
8351 /* Fail with sharing violation. */
8353 close_file(req, fsp, NORMAL_CLOSE);
8354 return NT_STATUS_SHARING_VIOLATION;
8359 * Set the delete on close.
8361 status = smb_set_file_disposition_info(conn,
8369 if (!NT_STATUS_IS_OK(status)) {
8370 close_file(req, fsp, NORMAL_CLOSE);
8373 return close_file(req, fsp, NORMAL_CLOSE);
8376 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8377 struct smb_request *req,
8378 TALLOC_CTX *mem_ctx,
8379 uint16_t info_level,
8381 struct smb_filename *smb_fname,
8382 char **ppdata, int total_data,
8385 char *pdata = *ppdata;
8386 NTSTATUS status = NT_STATUS_OK;
8387 int data_return_size = 0;
8391 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8392 return NT_STATUS_INVALID_LEVEL;
8395 if (!CAN_WRITE(conn)) {
8396 /* Allow POSIX opens. The open path will deny
8397 * any non-readonly opens. */
8398 if (info_level != SMB_POSIX_PATH_OPEN) {
8399 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8403 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8404 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8406 info_level, total_data));
8408 switch (info_level) {
8410 case SMB_INFO_STANDARD:
8412 status = smb_set_info_standard(conn,
8420 case SMB_INFO_SET_EA:
8422 status = smb_info_set_ea(conn,
8430 case SMB_SET_FILE_BASIC_INFO:
8431 case SMB_FILE_BASIC_INFORMATION:
8433 status = smb_set_file_basic_info(conn,
8441 case SMB_FILE_ALLOCATION_INFORMATION:
8442 case SMB_SET_FILE_ALLOCATION_INFO:
8444 status = smb_set_file_allocation_info(conn, req,
8452 case SMB_FILE_END_OF_FILE_INFORMATION:
8453 case SMB_SET_FILE_END_OF_FILE_INFO:
8456 * XP/Win7 both fail after the createfile with
8457 * SMB_SET_FILE_END_OF_FILE_INFO but not
8458 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8459 * The level is known here, so pass it down
8463 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8465 status = smb_set_file_end_of_file_info(conn, req,
8474 case SMB_FILE_DISPOSITION_INFORMATION:
8475 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8478 /* JRA - We used to just ignore this on a path ?
8479 * Shouldn't this be invalid level on a pathname
8482 if (tran_call != TRANSACT2_SETFILEINFO) {
8483 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8486 status = smb_set_file_disposition_info(conn,
8494 case SMB_FILE_POSITION_INFORMATION:
8496 status = smb_file_position_information(conn,
8503 case SMB_FILE_FULL_EA_INFORMATION:
8505 status = smb_set_file_full_ea_info(conn,
8512 /* From tridge Samba4 :
8513 * MODE_INFORMATION in setfileinfo (I have no
8514 * idea what "mode information" on a file is - it takes a value of 0,
8515 * 2, 4 or 6. What could it be?).
8518 case SMB_FILE_MODE_INFORMATION:
8520 status = smb_file_mode_information(conn,
8527 * CIFS UNIX extensions.
8530 case SMB_SET_FILE_UNIX_BASIC:
8532 status = smb_set_file_unix_basic(conn, req,
8540 case SMB_SET_FILE_UNIX_INFO2:
8542 status = smb_set_file_unix_info2(conn, req,
8550 case SMB_SET_FILE_UNIX_LINK:
8553 /* We must have a pathname for this. */
8554 return NT_STATUS_INVALID_LEVEL;
8556 status = smb_set_file_unix_link(conn, req, pdata,
8557 total_data, smb_fname);
8561 case SMB_SET_FILE_UNIX_HLINK:
8564 /* We must have a pathname for this. */
8565 return NT_STATUS_INVALID_LEVEL;
8567 status = smb_set_file_unix_hlink(conn, req,
8573 case SMB_FILE_RENAME_INFORMATION:
8575 status = smb_file_rename_information(conn, req,
8581 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8583 /* SMB2 rename information. */
8584 status = smb2_file_rename_information(conn, req,
8590 case SMB_FILE_LINK_INFORMATION:
8592 status = smb_file_link_information(conn, req,
8598 #if defined(HAVE_POSIX_ACLS)
8599 case SMB_SET_POSIX_ACL:
8601 status = smb_set_posix_acl(conn,
8610 case SMB_SET_POSIX_LOCK:
8613 return NT_STATUS_INVALID_LEVEL;
8615 status = smb_set_posix_lock(conn, req,
8616 pdata, total_data, fsp);
8620 case SMB_POSIX_PATH_OPEN:
8623 /* We must have a pathname for this. */
8624 return NT_STATUS_INVALID_LEVEL;
8627 status = smb_posix_open(conn, req,
8635 case SMB_POSIX_PATH_UNLINK:
8638 /* We must have a pathname for this. */
8639 return NT_STATUS_INVALID_LEVEL;
8642 status = smb_posix_unlink(conn, req,
8650 return NT_STATUS_INVALID_LEVEL;
8653 if (!NT_STATUS_IS_OK(status)) {
8657 *ret_data_size = data_return_size;
8658 return NT_STATUS_OK;
8661 /****************************************************************************
8662 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8663 ****************************************************************************/
8665 static void call_trans2setfilepathinfo(connection_struct *conn,
8666 struct smb_request *req,
8667 unsigned int tran_call,
8668 char **pparams, int total_params,
8669 char **ppdata, int total_data,
8670 unsigned int max_data_bytes)
8672 char *params = *pparams;
8673 char *pdata = *ppdata;
8674 uint16_t info_level;
8675 struct smb_filename *smb_fname = NULL;
8676 files_struct *fsp = NULL;
8677 NTSTATUS status = NT_STATUS_OK;
8678 int data_return_size = 0;
8681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8685 if (tran_call == TRANSACT2_SETFILEINFO) {
8686 if (total_params < 4) {
8687 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8691 fsp = file_fsp(req, SVAL(params,0));
8692 /* Basic check for non-null fsp. */
8693 if (!check_fsp_open(conn, req, fsp)) {
8696 info_level = SVAL(params,2);
8698 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8699 if (smb_fname == NULL) {
8700 reply_nterror(req, NT_STATUS_NO_MEMORY);
8704 if(fsp->fh->fd == -1) {
8706 * This is actually a SETFILEINFO on a directory
8707 * handle (returned from an NT SMB). NT5.0 seems
8708 * to do this call. JRA.
8710 if (INFO_LEVEL_IS_UNIX(info_level)) {
8711 /* Always do lstat for UNIX calls. */
8712 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8713 DEBUG(3,("call_trans2setfilepathinfo: "
8714 "SMB_VFS_LSTAT of %s failed "
8716 smb_fname_str_dbg(smb_fname),
8718 reply_nterror(req, map_nt_error_from_unix(errno));
8722 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8723 DEBUG(3,("call_trans2setfilepathinfo: "
8724 "fileinfo of %s failed (%s)\n",
8725 smb_fname_str_dbg(smb_fname),
8727 reply_nterror(req, map_nt_error_from_unix(errno));
8731 } else if (fsp->print_file) {
8733 * Doing a DELETE_ON_CLOSE should cancel a print job.
8735 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8736 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8738 DEBUG(3,("call_trans2setfilepathinfo: "
8739 "Cancelling print job (%s)\n",
8743 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8749 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8754 * Original code - this is an open file.
8756 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8757 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8758 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8760 reply_nterror(req, map_nt_error_from_unix(errno));
8766 uint32_t ucf_flags = (req->posix_pathnames ?
8767 UCF_POSIX_PATHNAMES : 0);
8770 if (total_params < 7) {
8771 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8775 info_level = SVAL(params,0);
8776 if (req->posix_pathnames) {
8777 srvstr_get_path_posix(req,
8786 srvstr_get_path(req,
8795 if (!NT_STATUS_IS_OK(status)) {
8796 reply_nterror(req, status);
8800 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8801 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8802 info_level == SMB_FILE_RENAME_INFORMATION ||
8803 info_level == SMB_POSIX_PATH_UNLINK) {
8804 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8807 status = filename_convert(req, conn,
8808 req->flags2 & FLAGS2_DFS_PATHNAMES,
8813 if (!NT_STATUS_IS_OK(status)) {
8814 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8815 reply_botherror(req,
8816 NT_STATUS_PATH_NOT_COVERED,
8817 ERRSRV, ERRbadpath);
8820 reply_nterror(req, status);
8824 if (INFO_LEVEL_IS_UNIX(info_level)) {
8826 * For CIFS UNIX extensions the target name may not exist.
8829 /* Always do lstat for UNIX calls. */
8830 SMB_VFS_LSTAT(conn, smb_fname);
8832 } else if (!VALID_STAT(smb_fname->st) &&
8833 SMB_VFS_STAT(conn, smb_fname)) {
8834 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8836 smb_fname_str_dbg(smb_fname),
8838 reply_nterror(req, map_nt_error_from_unix(errno));
8843 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8844 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8846 info_level,total_data));
8848 /* Realloc the parameter size */
8849 *pparams = (char *)SMB_REALLOC(*pparams,2);
8850 if (*pparams == NULL) {
8851 reply_nterror(req, NT_STATUS_NO_MEMORY);
8858 status = smbd_do_setfilepathinfo(conn, req, req,
8864 if (!NT_STATUS_IS_OK(status)) {
8865 if (open_was_deferred(req->xconn, req->mid)) {
8866 /* We have re-scheduled this call. */
8869 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8870 /* We have re-scheduled this call. */
8873 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8874 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8875 ERRSRV, ERRbadpath);
8878 if (info_level == SMB_POSIX_PATH_OPEN) {
8879 reply_openerror(req, status);
8884 * Invalid EA name needs to return 2 param bytes,
8885 * not a zero-length error packet.
8887 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8888 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8891 reply_nterror(req, status);
8896 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8902 /****************************************************************************
8903 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8904 ****************************************************************************/
8906 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8907 char **pparams, int total_params,
8908 char **ppdata, int total_data,
8909 unsigned int max_data_bytes)
8911 struct smb_filename *smb_dname = NULL;
8912 char *params = *pparams;
8913 char *pdata = *ppdata;
8914 char *directory = NULL;
8915 NTSTATUS status = NT_STATUS_OK;
8916 struct ea_list *ea_list = NULL;
8917 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
8918 TALLOC_CTX *ctx = talloc_tos();
8920 if (!CAN_WRITE(conn)) {
8921 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8925 if (total_params < 5) {
8926 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8930 if (req->posix_pathnames) {
8931 srvstr_get_path_posix(ctx,
8940 srvstr_get_path(ctx,
8949 if (!NT_STATUS_IS_OK(status)) {
8950 reply_nterror(req, status);
8954 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8956 status = filename_convert(ctx,
8958 req->flags2 & FLAGS2_DFS_PATHNAMES,
8964 if (!NT_STATUS_IS_OK(status)) {
8965 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8966 reply_botherror(req,
8967 NT_STATUS_PATH_NOT_COVERED,
8968 ERRSRV, ERRbadpath);
8971 reply_nterror(req, status);
8976 * OS/2 workplace shell seems to send SET_EA requests of "null"
8977 * length (4 bytes containing IVAL 4).
8978 * They seem to have no effect. Bug #3212. JRA.
8981 if (total_data && (total_data != 4)) {
8982 /* Any data in this call is an EA list. */
8983 if (total_data < 10) {
8984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8988 if (IVAL(pdata,0) > total_data) {
8989 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8990 IVAL(pdata,0), (unsigned int)total_data));
8991 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8995 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8998 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9002 if (!lp_ea_support(SNUM(conn))) {
9003 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9007 /* If total_data == 4 Windows doesn't care what values
9008 * are placed in that field, it just ignores them.
9009 * The System i QNTC IBM SMB client puts bad values here,
9010 * so ignore them. */
9012 status = create_directory(conn, req, smb_dname);
9014 if (!NT_STATUS_IS_OK(status)) {
9015 reply_nterror(req, status);
9019 /* Try and set any given EA. */
9021 status = set_ea(conn, NULL, smb_dname, ea_list);
9022 if (!NT_STATUS_IS_OK(status)) {
9023 reply_nterror(req, status);
9028 /* Realloc the parameter and data sizes */
9029 *pparams = (char *)SMB_REALLOC(*pparams,2);
9030 if(*pparams == NULL) {
9031 reply_nterror(req, NT_STATUS_NO_MEMORY);
9038 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9041 TALLOC_FREE(smb_dname);
9045 /****************************************************************************
9046 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9047 We don't actually do this - we just send a null response.
9048 ****************************************************************************/
9050 static void call_trans2findnotifyfirst(connection_struct *conn,
9051 struct smb_request *req,
9052 char **pparams, int total_params,
9053 char **ppdata, int total_data,
9054 unsigned int max_data_bytes)
9056 char *params = *pparams;
9057 uint16_t info_level;
9059 if (total_params < 6) {
9060 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9064 info_level = SVAL(params,4);
9065 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9067 switch (info_level) {
9072 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9076 /* Realloc the parameter and data sizes */
9077 *pparams = (char *)SMB_REALLOC(*pparams,6);
9078 if (*pparams == NULL) {
9079 reply_nterror(req, NT_STATUS_NO_MEMORY);
9084 SSVAL(params,0,fnf_handle);
9085 SSVAL(params,2,0); /* No changes */
9086 SSVAL(params,4,0); /* No EA errors */
9093 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9098 /****************************************************************************
9099 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9100 changes). Currently this does nothing.
9101 ****************************************************************************/
9103 static void call_trans2findnotifynext(connection_struct *conn,
9104 struct smb_request *req,
9105 char **pparams, int total_params,
9106 char **ppdata, int total_data,
9107 unsigned int max_data_bytes)
9109 char *params = *pparams;
9111 DEBUG(3,("call_trans2findnotifynext\n"));
9113 /* Realloc the parameter and data sizes */
9114 *pparams = (char *)SMB_REALLOC(*pparams,4);
9115 if (*pparams == NULL) {
9116 reply_nterror(req, NT_STATUS_NO_MEMORY);
9121 SSVAL(params,0,0); /* No changes */
9122 SSVAL(params,2,0); /* No EA errors */
9124 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9129 /****************************************************************************
9130 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9131 ****************************************************************************/
9133 static void call_trans2getdfsreferral(connection_struct *conn,
9134 struct smb_request *req,
9135 char **pparams, int total_params,
9136 char **ppdata, int total_data,
9137 unsigned int max_data_bytes)
9139 char *params = *pparams;
9140 char *pathname = NULL;
9142 int max_referral_level;
9143 NTSTATUS status = NT_STATUS_OK;
9144 TALLOC_CTX *ctx = talloc_tos();
9146 DEBUG(10,("call_trans2getdfsreferral\n"));
9148 if (total_params < 3) {
9149 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9153 max_referral_level = SVAL(params,0);
9155 if(!lp_host_msdfs()) {
9156 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9160 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9161 total_params - 2, STR_TERMINATE);
9163 reply_nterror(req, NT_STATUS_NOT_FOUND);
9166 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9167 ppdata,&status)) < 0) {
9168 reply_nterror(req, status);
9172 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9173 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9174 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9179 #define LMCAT_SPL 0x53
9180 #define LMFUNC_GETJOBID 0x60
9182 /****************************************************************************
9183 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9184 ****************************************************************************/
9186 static void call_trans2ioctl(connection_struct *conn,
9187 struct smb_request *req,
9188 char **pparams, int total_params,
9189 char **ppdata, int total_data,
9190 unsigned int max_data_bytes)
9192 char *pdata = *ppdata;
9193 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9197 /* check for an invalid fid before proceeding */
9200 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9204 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9205 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9206 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9207 if (*ppdata == NULL) {
9208 reply_nterror(req, NT_STATUS_NO_MEMORY);
9213 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9214 CAN ACCEPT THIS IN UNICODE. JRA. */
9217 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9219 status = srvstr_push(pdata, req->flags2, pdata + 2,
9220 lp_netbios_name(), 15,
9221 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9222 if (!NT_STATUS_IS_OK(status)) {
9223 reply_nterror(req, status);
9226 status = srvstr_push(pdata, req->flags2, pdata+18,
9227 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9228 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9229 if (!NT_STATUS_IS_OK(status)) {
9230 reply_nterror(req, status);
9233 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9238 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9239 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9242 /****************************************************************************
9243 Reply to a SMBfindclose (stop trans2 directory search).
9244 ****************************************************************************/
9246 void reply_findclose(struct smb_request *req)
9249 struct smbd_server_connection *sconn = req->sconn;
9251 START_PROFILE(SMBfindclose);
9254 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9255 END_PROFILE(SMBfindclose);
9259 dptr_num = SVALS(req->vwv+0, 0);
9261 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9263 dptr_close(sconn, &dptr_num);
9265 reply_outbuf(req, 0, 0);
9267 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9269 END_PROFILE(SMBfindclose);
9273 /****************************************************************************
9274 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9275 ****************************************************************************/
9277 void reply_findnclose(struct smb_request *req)
9281 START_PROFILE(SMBfindnclose);
9284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9285 END_PROFILE(SMBfindnclose);
9289 dptr_num = SVAL(req->vwv+0, 0);
9291 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9293 /* We never give out valid handles for a
9294 findnotifyfirst - so any dptr_num is ok here.
9297 reply_outbuf(req, 0, 0);
9299 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9301 END_PROFILE(SMBfindnclose);
9305 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9306 struct trans_state *state)
9308 if (get_Protocol() >= PROTOCOL_NT1) {
9309 req->flags2 |= 0x40; /* IS_LONG_NAME */
9310 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9313 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9314 if (state->call != TRANSACT2_QFSINFO &&
9315 state->call != TRANSACT2_SETFSINFO) {
9316 DEBUG(0,("handle_trans2: encryption required "
9318 (unsigned int)state->call));
9319 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9324 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9326 /* Now we must call the relevant TRANS2 function */
9327 switch(state->call) {
9328 case TRANSACT2_OPEN:
9330 START_PROFILE(Trans2_open);
9331 call_trans2open(conn, req,
9332 &state->param, state->total_param,
9333 &state->data, state->total_data,
9334 state->max_data_return);
9335 END_PROFILE(Trans2_open);
9339 case TRANSACT2_FINDFIRST:
9341 START_PROFILE(Trans2_findfirst);
9342 call_trans2findfirst(conn, req,
9343 &state->param, state->total_param,
9344 &state->data, state->total_data,
9345 state->max_data_return);
9346 END_PROFILE(Trans2_findfirst);
9350 case TRANSACT2_FINDNEXT:
9352 START_PROFILE(Trans2_findnext);
9353 call_trans2findnext(conn, req,
9354 &state->param, state->total_param,
9355 &state->data, state->total_data,
9356 state->max_data_return);
9357 END_PROFILE(Trans2_findnext);
9361 case TRANSACT2_QFSINFO:
9363 START_PROFILE(Trans2_qfsinfo);
9364 call_trans2qfsinfo(conn, req,
9365 &state->param, state->total_param,
9366 &state->data, state->total_data,
9367 state->max_data_return);
9368 END_PROFILE(Trans2_qfsinfo);
9372 case TRANSACT2_SETFSINFO:
9374 START_PROFILE(Trans2_setfsinfo);
9375 call_trans2setfsinfo(conn, req,
9376 &state->param, state->total_param,
9377 &state->data, state->total_data,
9378 state->max_data_return);
9379 END_PROFILE(Trans2_setfsinfo);
9383 case TRANSACT2_QPATHINFO:
9384 case TRANSACT2_QFILEINFO:
9386 START_PROFILE(Trans2_qpathinfo);
9387 call_trans2qfilepathinfo(conn, req, state->call,
9388 &state->param, state->total_param,
9389 &state->data, state->total_data,
9390 state->max_data_return);
9391 END_PROFILE(Trans2_qpathinfo);
9395 case TRANSACT2_SETPATHINFO:
9396 case TRANSACT2_SETFILEINFO:
9398 START_PROFILE(Trans2_setpathinfo);
9399 call_trans2setfilepathinfo(conn, req, state->call,
9400 &state->param, state->total_param,
9401 &state->data, state->total_data,
9402 state->max_data_return);
9403 END_PROFILE(Trans2_setpathinfo);
9407 case TRANSACT2_FINDNOTIFYFIRST:
9409 START_PROFILE(Trans2_findnotifyfirst);
9410 call_trans2findnotifyfirst(conn, req,
9411 &state->param, state->total_param,
9412 &state->data, state->total_data,
9413 state->max_data_return);
9414 END_PROFILE(Trans2_findnotifyfirst);
9418 case TRANSACT2_FINDNOTIFYNEXT:
9420 START_PROFILE(Trans2_findnotifynext);
9421 call_trans2findnotifynext(conn, req,
9422 &state->param, state->total_param,
9423 &state->data, state->total_data,
9424 state->max_data_return);
9425 END_PROFILE(Trans2_findnotifynext);
9429 case TRANSACT2_MKDIR:
9431 START_PROFILE(Trans2_mkdir);
9432 call_trans2mkdir(conn, req,
9433 &state->param, state->total_param,
9434 &state->data, state->total_data,
9435 state->max_data_return);
9436 END_PROFILE(Trans2_mkdir);
9440 case TRANSACT2_GET_DFS_REFERRAL:
9442 START_PROFILE(Trans2_get_dfs_referral);
9443 call_trans2getdfsreferral(conn, req,
9444 &state->param, state->total_param,
9445 &state->data, state->total_data,
9446 state->max_data_return);
9447 END_PROFILE(Trans2_get_dfs_referral);
9451 case TRANSACT2_IOCTL:
9453 START_PROFILE(Trans2_ioctl);
9454 call_trans2ioctl(conn, req,
9455 &state->param, state->total_param,
9456 &state->data, state->total_data,
9457 state->max_data_return);
9458 END_PROFILE(Trans2_ioctl);
9463 /* Error in request */
9464 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9465 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9469 /****************************************************************************
9470 Reply to a SMBtrans2.
9471 ****************************************************************************/
9473 void reply_trans2(struct smb_request *req)
9475 connection_struct *conn = req->conn;
9480 unsigned int tran_call;
9481 struct trans_state *state;
9484 START_PROFILE(SMBtrans2);
9486 if (req->wct < 14) {
9487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9488 END_PROFILE(SMBtrans2);
9492 dsoff = SVAL(req->vwv+12, 0);
9493 dscnt = SVAL(req->vwv+11, 0);
9494 psoff = SVAL(req->vwv+10, 0);
9495 pscnt = SVAL(req->vwv+9, 0);
9496 tran_call = SVAL(req->vwv+14, 0);
9498 result = allow_new_trans(conn->pending_trans, req->mid);
9499 if (!NT_STATUS_IS_OK(result)) {
9500 DEBUG(2, ("Got invalid trans2 request: %s\n",
9501 nt_errstr(result)));
9502 reply_nterror(req, result);
9503 END_PROFILE(SMBtrans2);
9508 switch (tran_call) {
9509 /* List the allowed trans2 calls on IPC$ */
9510 case TRANSACT2_OPEN:
9511 case TRANSACT2_GET_DFS_REFERRAL:
9512 case TRANSACT2_QFILEINFO:
9513 case TRANSACT2_QFSINFO:
9514 case TRANSACT2_SETFSINFO:
9517 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9518 END_PROFILE(SMBtrans2);
9523 if ((state = talloc(conn, struct trans_state)) == NULL) {
9524 DEBUG(0, ("talloc failed\n"));
9525 reply_nterror(req, NT_STATUS_NO_MEMORY);
9526 END_PROFILE(SMBtrans2);
9530 state->cmd = SMBtrans2;
9532 state->mid = req->mid;
9533 state->vuid = req->vuid;
9534 state->setup_count = SVAL(req->vwv+13, 0);
9535 state->setup = NULL;
9536 state->total_param = SVAL(req->vwv+0, 0);
9537 state->param = NULL;
9538 state->total_data = SVAL(req->vwv+1, 0);
9540 state->max_param_return = SVAL(req->vwv+2, 0);
9541 state->max_data_return = SVAL(req->vwv+3, 0);
9542 state->max_setup_return = SVAL(req->vwv+4, 0);
9543 state->close_on_completion = BITSETW(req->vwv+5, 0);
9544 state->one_way = BITSETW(req->vwv+5, 1);
9546 state->call = tran_call;
9548 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9549 is so as a sanity check */
9550 if (state->setup_count != 1) {
9552 * Need to have rc=0 for ioctl to get job id for OS/2.
9553 * Network printing will fail if function is not successful.
9554 * Similar function in reply.c will be used if protocol
9555 * is LANMAN1.0 instead of LM1.2X002.
9556 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9557 * outbuf doesn't have to be set(only job id is used).
9559 if ( (state->setup_count == 4)
9560 && (tran_call == TRANSACT2_IOCTL)
9561 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9562 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9563 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9565 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9566 DEBUG(2,("Transaction is %d\n",tran_call));
9568 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9569 END_PROFILE(SMBtrans2);
9574 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9577 if (state->total_data) {
9579 if (trans_oob(state->total_data, 0, dscnt)
9580 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9584 /* Can't use talloc here, the core routines do realloc on the
9585 * params and data. */
9586 state->data = (char *)SMB_MALLOC(state->total_data);
9587 if (state->data == NULL) {
9588 DEBUG(0,("reply_trans2: data malloc fail for %u "
9589 "bytes !\n", (unsigned int)state->total_data));
9591 reply_nterror(req, NT_STATUS_NO_MEMORY);
9592 END_PROFILE(SMBtrans2);
9596 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9599 if (state->total_param) {
9601 if (trans_oob(state->total_param, 0, pscnt)
9602 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9606 /* Can't use talloc here, the core routines do realloc on the
9607 * params and data. */
9608 state->param = (char *)SMB_MALLOC(state->total_param);
9609 if (state->param == NULL) {
9610 DEBUG(0,("reply_trans: param malloc fail for %u "
9611 "bytes !\n", (unsigned int)state->total_param));
9612 SAFE_FREE(state->data);
9614 reply_nterror(req, NT_STATUS_NO_MEMORY);
9615 END_PROFILE(SMBtrans2);
9619 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9622 state->received_data = dscnt;
9623 state->received_param = pscnt;
9625 if ((state->received_param == state->total_param) &&
9626 (state->received_data == state->total_data)) {
9628 handle_trans2(conn, req, state);
9630 SAFE_FREE(state->data);
9631 SAFE_FREE(state->param);
9633 END_PROFILE(SMBtrans2);
9637 DLIST_ADD(conn->pending_trans, state);
9639 /* We need to send an interim response then receive the rest
9640 of the parameter/data bytes */
9641 reply_outbuf(req, 0, 0);
9642 show_msg((char *)req->outbuf);
9643 END_PROFILE(SMBtrans2);
9648 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9649 SAFE_FREE(state->data);
9650 SAFE_FREE(state->param);
9652 END_PROFILE(SMBtrans2);
9653 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9657 /****************************************************************************
9658 Reply to a SMBtranss2
9659 ****************************************************************************/
9661 void reply_transs2(struct smb_request *req)
9663 connection_struct *conn = req->conn;
9664 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9665 struct trans_state *state;
9667 START_PROFILE(SMBtranss2);
9669 show_msg((const char *)req->inbuf);
9671 /* Windows clients expect all replies to
9672 a transact secondary (SMBtranss2 0x33)
9673 to have a command code of transact
9674 (SMBtrans2 0x32). See bug #8989
9675 and also [MS-CIFS] section 2.2.4.47.2
9678 req->cmd = SMBtrans2;
9681 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9682 END_PROFILE(SMBtranss2);
9686 for (state = conn->pending_trans; state != NULL;
9687 state = state->next) {
9688 if (state->mid == req->mid) {
9693 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9695 END_PROFILE(SMBtranss2);
9699 /* Revise state->total_param and state->total_data in case they have
9700 changed downwards */
9702 if (SVAL(req->vwv+0, 0) < state->total_param)
9703 state->total_param = SVAL(req->vwv+0, 0);
9704 if (SVAL(req->vwv+1, 0) < state->total_data)
9705 state->total_data = SVAL(req->vwv+1, 0);
9707 pcnt = SVAL(req->vwv+2, 0);
9708 poff = SVAL(req->vwv+3, 0);
9709 pdisp = SVAL(req->vwv+4, 0);
9711 dcnt = SVAL(req->vwv+5, 0);
9712 doff = SVAL(req->vwv+6, 0);
9713 ddisp = SVAL(req->vwv+7, 0);
9715 state->received_param += pcnt;
9716 state->received_data += dcnt;
9718 if ((state->received_data > state->total_data) ||
9719 (state->received_param > state->total_param))
9723 if (trans_oob(state->total_param, pdisp, pcnt)
9724 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9727 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9731 if (trans_oob(state->total_data, ddisp, dcnt)
9732 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9735 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9738 if ((state->received_param < state->total_param) ||
9739 (state->received_data < state->total_data)) {
9740 END_PROFILE(SMBtranss2);
9744 handle_trans2(conn, req, state);
9746 DLIST_REMOVE(conn->pending_trans, state);
9747 SAFE_FREE(state->data);
9748 SAFE_FREE(state->param);
9751 END_PROFILE(SMBtranss2);
9756 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9757 DLIST_REMOVE(conn->pending_trans, state);
9758 SAFE_FREE(state->data);
9759 SAFE_FREE(state->param);
9761 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9762 END_PROFILE(SMBtranss2);