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,
79 return map_nt_error_from_unix(errno);
84 if (S_ISLNK(pst->st_ex_mode)) {
85 return NT_STATUS_ACCESS_DENIED;
90 NTSTATUS check_access_fsp(const struct files_struct *fsp,
93 if (!(fsp->access_mask & access_mask)) {
94 return NT_STATUS_ACCESS_DENIED;
99 /********************************************************************
100 The canonical "check access" based on object handle or path function.
101 ********************************************************************/
103 NTSTATUS check_access(connection_struct *conn,
105 const struct smb_filename *smb_fname,
106 uint32_t access_mask)
111 status = check_access_fsp(fsp, access_mask);
113 status = smbd_check_access_rights(conn, smb_fname,
120 /********************************************************************
121 Roundup a value to the nearest allocation roundup size boundary.
122 Only do this for Windows clients.
123 ********************************************************************/
125 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
127 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
129 /* Only roundup for Windows clients. */
130 enum remote_arch_types ra_type = get_remote_arch();
131 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
132 val = SMB_ROUNDUP(val,rval);
137 /********************************************************************
138 Create a 64 bit FileIndex. If the file is on the same device as
139 the root of the share, just return the 64-bit inode. If it isn't,
140 mangle as we used to do.
141 ********************************************************************/
143 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
146 if (conn->base_share_dev == psbuf->st_ex_dev) {
147 return (uint64_t)psbuf->st_ex_ino;
149 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
150 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
154 /****************************************************************************
155 Utility functions for dealing with extended attributes.
156 ****************************************************************************/
158 /****************************************************************************
159 Refuse to allow clients to overwrite our private xattrs.
160 ****************************************************************************/
162 bool samba_private_attr_name(const char *unix_ea_name)
164 static const char * const prohibited_ea_names[] = {
165 SAMBA_POSIX_INHERITANCE_EA_NAME,
166 SAMBA_XATTR_DOS_ATTRIB,
174 for (i = 0; prohibited_ea_names[i]; i++) {
175 if (strequal( prohibited_ea_names[i], unix_ea_name))
178 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
179 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
185 /****************************************************************************
186 Get one EA value. Fill in a struct ea_struct.
187 ****************************************************************************/
189 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
190 files_struct *fsp, const char *fname,
191 const char *ea_name, struct ea_struct *pea)
193 /* Get the value of this xattr. Max size is 64k. */
194 size_t attr_size = 256;
200 val = talloc_realloc(mem_ctx, val, char, attr_size);
202 return NT_STATUS_NO_MEMORY;
205 if (fsp && fsp->fh->fd != -1) {
206 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
208 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
211 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
217 return map_nt_error_from_unix(errno);
220 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
221 dump_data(10, (uint8_t *)val, sizeret);
224 if (strnequal(ea_name, "user.", 5)) {
225 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
227 pea->name = talloc_strdup(mem_ctx, ea_name);
229 if (pea->name == NULL) {
231 return NT_STATUS_NO_MEMORY;
233 pea->value.data = (unsigned char *)val;
234 pea->value.length = (size_t)sizeret;
238 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
239 connection_struct *conn,
241 const struct smb_filename *smb_fname,
246 /* Get a list of all xattrs. Max namesize is 64k. */
247 size_t ea_namelist_size = 1024;
248 char *ea_namelist = smallbuf;
249 char *to_free = NULL;
254 ssize_t sizeret = -1;
262 if (!lp_ea_support(SNUM(conn))) {
266 status = refuse_symlink(conn, fsp, smb_fname);
267 if (!NT_STATUS_IS_OK(status)) {
269 * Just return no EA's on a symlink.
274 if (fsp && fsp->fh->fd != -1) {
275 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
278 sizeret = SMB_VFS_LISTXATTR(conn,
279 smb_fname->base_name,
284 if ((sizeret == -1) && (errno == ERANGE)) {
285 ea_namelist_size = 65536;
286 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
287 if (ea_namelist == NULL) {
288 return NT_STATUS_NO_MEMORY;
290 to_free = ea_namelist;
292 if (fsp && fsp->fh->fd != -1) {
293 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
296 sizeret = SMB_VFS_LISTXATTR(conn,
297 smb_fname->base_name,
304 status = map_nt_error_from_unix(errno);
305 TALLOC_FREE(to_free);
309 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
312 TALLOC_FREE(to_free);
317 * Ensure the result is 0-terminated
320 if (ea_namelist[sizeret-1] != '\0') {
321 TALLOC_FREE(to_free);
322 return NT_STATUS_INTERNAL_ERROR;
330 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
334 *pnum_names = num_names;
336 if (pnames == NULL) {
337 TALLOC_FREE(to_free);
341 names = talloc_array(mem_ctx, char *, num_names);
343 DEBUG(0, ("talloc failed\n"));
344 TALLOC_FREE(to_free);
345 return NT_STATUS_NO_MEMORY;
348 if (ea_namelist == smallbuf) {
349 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
350 if (ea_namelist == NULL) {
352 return NT_STATUS_NO_MEMORY;
355 talloc_steal(names, ea_namelist);
357 ea_namelist = talloc_realloc(names, ea_namelist, char,
359 if (ea_namelist == NULL) {
361 return NT_STATUS_NO_MEMORY;
367 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
368 names[num_names++] = p;
376 /****************************************************************************
377 Return a linked list of the total EA's. Plus the total size
378 ****************************************************************************/
380 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
381 connection_struct *conn,
383 const struct smb_filename *smb_fname,
384 size_t *pea_total_len,
385 struct ea_list **ea_list)
387 /* Get a list of all xattrs. Max namesize is 64k. */
390 struct ea_list *ea_list_head = NULL;
391 bool posix_pathnames = false;
399 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
401 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
404 status = get_ea_names_from_file(talloc_tos(),
411 if (!NT_STATUS_IS_OK(status)) {
415 if (num_names == 0) {
420 for (i=0; i<num_names; i++) {
421 struct ea_list *listp;
424 if (strnequal(names[i], "system.", 7)
425 || samba_private_attr_name(names[i]))
429 * Filter out any underlying POSIX EA names
430 * that a Windows client can't handle.
432 if (!posix_pathnames &&
433 is_invalid_windows_ea_name(names[i])) {
437 listp = talloc(mem_ctx, struct ea_list);
439 return NT_STATUS_NO_MEMORY;
442 status = get_ea_value(listp,
445 smb_fname->base_name,
449 if (!NT_STATUS_IS_OK(status)) {
454 if (listp->ea.value.length == 0) {
456 * We can never return a zero length EA.
457 * Windows reports the EA's as corrupted.
463 push_ascii_fstring(dos_ea_name, listp->ea.name);
466 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
468 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
469 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
470 (unsigned int)listp->ea.value.length));
472 DLIST_ADD_END(ea_list_head, listp);
476 /* Add on 4 for total length. */
477 if (*pea_total_len) {
481 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
482 (unsigned int)*pea_total_len));
484 *ea_list = ea_list_head;
488 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
489 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
494 if (!lp_ea_support(SNUM(conn))) {
498 if (is_ntfs_stream_smb_fname(smb_fname)) {
499 return NT_STATUS_INVALID_PARAMETER;
502 return get_ea_list_from_file_path(mem_ctx,
510 /****************************************************************************
511 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
513 ****************************************************************************/
515 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
516 connection_struct *conn, struct ea_list *ea_list)
518 unsigned int ret_data_size = 4;
521 SMB_ASSERT(total_data_size >= 4);
523 if (!lp_ea_support(SNUM(conn))) {
528 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
531 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
532 dos_namelen = strlen(dos_ea_name);
533 if (dos_namelen > 255 || dos_namelen == 0) {
536 if (ea_list->ea.value.length > 65535) {
539 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
543 /* We know we have room. */
544 SCVAL(p,0,ea_list->ea.flags);
545 SCVAL(p,1,dos_namelen);
546 SSVAL(p,2,ea_list->ea.value.length);
547 strlcpy(p+4, dos_ea_name, dos_namelen+1);
548 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
550 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
551 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
554 ret_data_size = PTR_DIFF(p, pdata);
555 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
556 SIVAL(pdata,0,ret_data_size);
557 return ret_data_size;
560 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
562 unsigned int total_data_size,
563 unsigned int *ret_data_size,
564 connection_struct *conn,
565 struct ea_list *ea_list)
567 uint8_t *p = (uint8_t *)pdata;
568 uint8_t *last_start = NULL;
569 bool do_store_data = (pdata != NULL);
573 if (!lp_ea_support(SNUM(conn))) {
574 return NT_STATUS_NO_EAS_ON_FILE;
577 for (; ea_list; ea_list = ea_list->next) {
583 if (last_start != NULL && do_store_data) {
584 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
588 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
589 dos_namelen = strlen(dos_ea_name);
590 if (dos_namelen > 255 || dos_namelen == 0) {
591 return NT_STATUS_INTERNAL_ERROR;
593 if (ea_list->ea.value.length > 65535) {
594 return NT_STATUS_INTERNAL_ERROR;
597 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
600 pad = (4 - (this_size % 4)) % 4;
605 if (this_size > total_data_size) {
606 return NT_STATUS_INFO_LENGTH_MISMATCH;
609 /* We know we have room. */
610 SIVAL(p, 0x00, 0); /* next offset */
611 SCVAL(p, 0x04, ea_list->ea.flags);
612 SCVAL(p, 0x05, dos_namelen);
613 SSVAL(p, 0x06, ea_list->ea.value.length);
614 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
615 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
617 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
621 total_data_size -= this_size;
627 *ret_data_size = PTR_DIFF(p, pdata);
628 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
632 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
634 size_t total_ea_len = 0;
636 struct ea_list *ea_list = NULL;
638 if (!lp_ea_support(SNUM(conn))) {
641 mem_ctx = talloc_stackframe();
643 /* If this is a stream fsp, then we need to instead find the
644 * estimated ea len from the main file, not the stream
645 * (streams cannot have EAs), but the estimate isn't just 0 in
647 if (is_ntfs_stream_smb_fname(smb_fname)) {
650 (void)get_ea_list_from_file_path(mem_ctx,
656 if(conn->sconn->using_smb2) {
658 unsigned int ret_data_size;
660 * We're going to be using fill_ea_chained_buffer() to
661 * marshall EA's - this size is significantly larger
662 * than the SMB1 buffer. Re-calculate the size without
665 status = fill_ea_chained_buffer(mem_ctx,
671 if (!NT_STATUS_IS_OK(status)) {
674 total_ea_len = ret_data_size;
676 TALLOC_FREE(mem_ctx);
680 /****************************************************************************
681 Ensure the EA name is case insensitive by matching any existing EA name.
682 ****************************************************************************/
684 static void canonicalize_ea_name(connection_struct *conn,
686 const struct smb_filename *smb_fname,
687 fstring unix_ea_name)
690 TALLOC_CTX *mem_ctx = talloc_tos();
691 struct ea_list *ea_list;
692 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
698 if (!NT_STATUS_IS_OK(status)) {
702 for (; ea_list; ea_list = ea_list->next) {
703 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
704 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
705 &unix_ea_name[5], ea_list->ea.name));
706 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
712 /****************************************************************************
713 Set or delete an extended attribute.
714 ****************************************************************************/
716 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
717 const struct smb_filename *smb_fname, struct ea_list *ea_list)
720 bool posix_pathnames = false;
722 if (!lp_ea_support(SNUM(conn))) {
723 return NT_STATUS_EAS_NOT_SUPPORTED;
728 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
730 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
733 status = refuse_symlink(conn, fsp, smb_fname);
734 if (!NT_STATUS_IS_OK(status)) {
738 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
739 if (!NT_STATUS_IS_OK(status)) {
743 /* Setting EAs on streams isn't supported. */
744 if (is_ntfs_stream_smb_fname(smb_fname)) {
745 return NT_STATUS_INVALID_PARAMETER;
749 * Filter out invalid Windows EA names - before
750 * we set *any* of them.
753 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
754 return STATUS_INVALID_EA_NAME;
757 for (;ea_list; ea_list = ea_list->next) {
759 fstring unix_ea_name;
761 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
762 fstrcat(unix_ea_name, ea_list->ea.name);
764 canonicalize_ea_name(conn,
769 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
771 if (samba_private_attr_name(unix_ea_name)) {
772 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
773 return NT_STATUS_ACCESS_DENIED;
776 if (ea_list->ea.value.length == 0) {
777 /* Remove the attribute. */
778 if (fsp && (fsp->fh->fd != -1)) {
779 DEBUG(10,("set_ea: deleting ea name %s on "
780 "file %s by file descriptor.\n",
781 unix_ea_name, fsp_str_dbg(fsp)));
782 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
784 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
785 unix_ea_name, smb_fname->base_name));
786 ret = SMB_VFS_REMOVEXATTR(conn,
787 smb_fname->base_name,
791 /* Removing a non existent attribute always succeeds. */
792 if (ret == -1 && errno == ENOATTR) {
793 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
799 if (fsp && (fsp->fh->fd != -1)) {
800 DEBUG(10,("set_ea: setting ea name %s on file "
801 "%s by file descriptor.\n",
802 unix_ea_name, fsp_str_dbg(fsp)));
803 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
804 ea_list->ea.value.data, ea_list->ea.value.length, 0);
806 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
807 unix_ea_name, smb_fname->base_name));
808 ret = SMB_VFS_SETXATTR(conn,
809 smb_fname->base_name,
811 ea_list->ea.value.data,
812 ea_list->ea.value.length,
819 if (errno == ENOTSUP) {
820 return NT_STATUS_EAS_NOT_SUPPORTED;
823 return map_nt_error_from_unix(errno);
829 /****************************************************************************
830 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
831 ****************************************************************************/
833 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
835 struct ea_list *ea_list_head = NULL;
836 size_t converted_size, offset = 0;
838 while (offset + 2 < data_size) {
839 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
840 unsigned int namelen = CVAL(pdata,offset);
842 offset++; /* Go past the namelen byte. */
844 /* integer wrap paranioa. */
845 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
846 (offset > data_size) || (namelen > data_size) ||
847 (offset + namelen >= data_size)) {
850 /* Ensure the name is null terminated. */
851 if (pdata[offset + namelen] != '\0') {
854 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
856 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
857 "failed: %s", strerror(errno)));
863 offset += (namelen + 1); /* Go past the name + terminating zero. */
864 DLIST_ADD_END(ea_list_head, eal);
865 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
871 /****************************************************************************
872 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
873 ****************************************************************************/
875 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
877 struct ea_list *ea_list_head = NULL;
879 size_t bytes_used = 0;
881 while (offset < data_size) {
882 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
888 DLIST_ADD_END(ea_list_head, eal);
889 offset += bytes_used;
895 /****************************************************************************
896 Count the total EA size needed.
897 ****************************************************************************/
899 static size_t ea_list_size(struct ea_list *ealist)
902 struct ea_list *listp;
905 for (listp = ealist; listp; listp = listp->next) {
906 push_ascii_fstring(dos_ea_name, listp->ea.name);
907 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
909 /* Add on 4 for total length. */
917 /****************************************************************************
918 Return a union of EA's from a file list and a list of names.
919 The TALLOC context for the two lists *MUST* be identical as we steal
920 memory from one list to add to another. JRA.
921 ****************************************************************************/
923 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
925 struct ea_list *nlistp, *flistp;
927 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
928 for (flistp = file_list; flistp; flistp = flistp->next) {
929 if (strequal(nlistp->ea.name, flistp->ea.name)) {
935 /* Copy the data from this entry. */
936 nlistp->ea.flags = flistp->ea.flags;
937 nlistp->ea.value = flistp->ea.value;
940 nlistp->ea.flags = 0;
941 ZERO_STRUCT(nlistp->ea.value);
945 *total_ea_len = ea_list_size(name_list);
949 /****************************************************************************
950 Send the required number of replies back.
951 We assume all fields other than the data fields are
952 set correctly for the type of call.
953 HACK ! Always assumes smb_setup field is zero.
954 ****************************************************************************/
956 void send_trans2_replies(connection_struct *conn,
957 struct smb_request *req,
965 /* As we are using a protocol > LANMAN1 then the max_send
966 variable must have been set in the sessetupX call.
967 This takes precedence over the max_xmit field in the
968 global struct. These different max_xmit variables should
969 be merged as this is now too confusing */
971 int data_to_send = datasize;
972 int params_to_send = paramsize;
974 const char *pp = params;
975 const char *pd = pdata;
976 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
977 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
978 int data_alignment_offset = 0;
979 bool overflow = False;
980 struct smbXsrv_connection *xconn = req->xconn;
981 int max_send = xconn->smb1.sessions.max_send;
983 /* Modify the data_to_send and datasize and set the error if
984 we're trying to send more than max_data_bytes. We still send
985 the part of the packet(s) that fit. Strange, but needed
988 if (max_data_bytes > 0 && datasize > max_data_bytes) {
989 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
990 max_data_bytes, datasize ));
991 datasize = data_to_send = max_data_bytes;
995 /* If there genuinely are no parameters or data to send just send the empty packet */
997 if(params_to_send == 0 && data_to_send == 0) {
998 reply_outbuf(req, 10, 0);
999 if (NT_STATUS_V(status)) {
1002 ntstatus_to_dos(status, &eclass, &ecode);
1003 error_packet_set((char *)req->outbuf,
1004 eclass, ecode, status,
1007 show_msg((char *)req->outbuf);
1008 if (!srv_send_smb(xconn,
1009 (char *)req->outbuf,
1010 true, req->seqnum+1,
1011 IS_CONN_ENCRYPTED(conn),
1013 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1015 TALLOC_FREE(req->outbuf);
1019 /* When sending params and data ensure that both are nicely aligned */
1020 /* Only do this alignment when there is also data to send - else
1021 can cause NT redirector problems. */
1023 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1024 data_alignment_offset = 4 - (params_to_send % 4);
1026 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1027 /* The alignment_offset is to align the param bytes on an even byte
1028 boundary. NT 4.0 Beta needs this to work correctly. */
1030 useable_space = max_send - (smb_size
1033 + data_alignment_offset);
1035 if (useable_space < 0) {
1036 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1037 "= %d!!!", useable_space));
1038 exit_server_cleanly("send_trans2_replies: Not enough space");
1041 while (params_to_send || data_to_send) {
1042 /* Calculate whether we will totally or partially fill this packet */
1044 total_sent_thistime = params_to_send + data_to_send;
1046 /* We can never send more than useable_space */
1048 * Note that 'useable_space' does not include the alignment offsets,
1049 * but we must include the alignment offsets in the calculation of
1050 * the length of the data we send over the wire, as the alignment offsets
1051 * are sent here. Fix from Marc_Jacobsen@hp.com.
1054 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1056 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1057 + data_alignment_offset);
1059 /* Set total params and data to be sent */
1060 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1061 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1063 /* Calculate how many parameters and data we can fit into
1064 * this packet. Parameters get precedence
1067 params_sent_thistime = MIN(params_to_send,useable_space);
1068 data_sent_thistime = useable_space - params_sent_thistime;
1069 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1071 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1073 /* smb_proff is the offset from the start of the SMB header to the
1074 parameter bytes, however the first 4 bytes of outbuf are
1075 the Netbios over TCP header. Thus use smb_base() to subtract
1076 them from the calculation */
1078 SSVAL(req->outbuf,smb_proff,
1079 ((smb_buf(req->outbuf)+alignment_offset)
1080 - smb_base(req->outbuf)));
1082 if(params_sent_thistime == 0)
1083 SSVAL(req->outbuf,smb_prdisp,0);
1085 /* Absolute displacement of param bytes sent in this packet */
1086 SSVAL(req->outbuf,smb_prdisp,pp - params);
1088 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1089 if(data_sent_thistime == 0) {
1090 SSVAL(req->outbuf,smb_droff,0);
1091 SSVAL(req->outbuf,smb_drdisp, 0);
1093 /* The offset of the data bytes is the offset of the
1094 parameter bytes plus the number of parameters being sent this time */
1095 SSVAL(req->outbuf, smb_droff,
1096 ((smb_buf(req->outbuf)+alignment_offset)
1097 - smb_base(req->outbuf))
1098 + params_sent_thistime + data_alignment_offset);
1099 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1102 /* Initialize the padding for alignment */
1104 if (alignment_offset != 0) {
1105 memset(smb_buf(req->outbuf), 0, alignment_offset);
1108 /* Copy the param bytes into the packet */
1110 if(params_sent_thistime) {
1111 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1112 params_sent_thistime);
1115 /* Copy in the data bytes */
1116 if(data_sent_thistime) {
1117 if (data_alignment_offset != 0) {
1118 memset((smb_buf(req->outbuf)+alignment_offset+
1119 params_sent_thistime), 0,
1120 data_alignment_offset);
1122 memcpy(smb_buf(req->outbuf)+alignment_offset
1123 +params_sent_thistime+data_alignment_offset,
1124 pd,data_sent_thistime);
1127 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1128 params_sent_thistime, data_sent_thistime, useable_space));
1129 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1130 params_to_send, data_to_send, paramsize, datasize));
1133 error_packet_set((char *)req->outbuf,
1134 ERRDOS,ERRbufferoverflow,
1135 STATUS_BUFFER_OVERFLOW,
1137 } else if (NT_STATUS_V(status)) {
1140 ntstatus_to_dos(status, &eclass, &ecode);
1141 error_packet_set((char *)req->outbuf,
1142 eclass, ecode, status,
1146 /* Send the packet */
1147 show_msg((char *)req->outbuf);
1148 if (!srv_send_smb(xconn,
1149 (char *)req->outbuf,
1150 true, req->seqnum+1,
1151 IS_CONN_ENCRYPTED(conn),
1153 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1155 TALLOC_FREE(req->outbuf);
1157 pp += params_sent_thistime;
1158 pd += data_sent_thistime;
1160 params_to_send -= params_sent_thistime;
1161 data_to_send -= data_sent_thistime;
1164 if(params_to_send < 0 || data_to_send < 0) {
1165 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1166 params_to_send, data_to_send));
1174 /****************************************************************************
1175 Reply to a TRANSACT2_OPEN.
1176 ****************************************************************************/
1178 static void call_trans2open(connection_struct *conn,
1179 struct smb_request *req,
1180 char **pparams, int total_params,
1181 char **ppdata, int total_data,
1182 unsigned int max_data_bytes)
1184 struct smb_filename *smb_fname = NULL;
1185 char *params = *pparams;
1186 char *pdata = *ppdata;
1189 bool oplock_request;
1191 bool return_additional_info;
1200 int fattr=0,mtime=0;
1201 SMB_INO_T inode = 0;
1204 struct ea_list *ea_list = NULL;
1207 uint32_t access_mask;
1208 uint32_t share_mode;
1209 uint32_t create_disposition;
1210 uint32_t create_options = 0;
1211 uint32_t private_flags = 0;
1212 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1213 TALLOC_CTX *ctx = talloc_tos();
1216 * Ensure we have enough parameters to perform the operation.
1219 if (total_params < 29) {
1220 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1224 flags = SVAL(params, 0);
1225 deny_mode = SVAL(params, 2);
1226 open_attr = SVAL(params,6);
1227 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1228 if (oplock_request) {
1229 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1233 return_additional_info = BITSETW(params,0);
1234 open_sattr = SVAL(params, 4);
1235 open_time = make_unix_date3(params+8);
1237 open_ofun = SVAL(params,12);
1238 open_size = IVAL(params,14);
1239 pname = ¶ms[28];
1242 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1246 if (req->posix_pathnames) {
1247 srvstr_get_path_posix(ctx,
1256 srvstr_get_path(ctx,
1265 if (!NT_STATUS_IS_OK(status)) {
1266 reply_nterror(req, status);
1270 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1271 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1272 (unsigned int)open_ofun, open_size));
1274 status = filename_convert(ctx,
1276 req->flags2 & FLAGS2_DFS_PATHNAMES,
1281 if (!NT_STATUS_IS_OK(status)) {
1282 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1283 reply_botherror(req,
1284 NT_STATUS_PATH_NOT_COVERED,
1285 ERRSRV, ERRbadpath);
1288 reply_nterror(req, status);
1292 if (open_ofun == 0) {
1293 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1297 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1299 &access_mask, &share_mode,
1300 &create_disposition,
1303 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1307 /* Any data in this call is an EA list. */
1308 if (total_data && (total_data != 4)) {
1309 if (total_data < 10) {
1310 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1314 if (IVAL(pdata,0) > total_data) {
1315 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1316 IVAL(pdata,0), (unsigned int)total_data));
1317 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1321 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1328 if (!lp_ea_support(SNUM(conn))) {
1329 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1333 if (!req->posix_pathnames &&
1334 ea_list_has_invalid_name(ea_list)) {
1336 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1337 if(*pparams == NULL ) {
1338 reply_nterror(req, NT_STATUS_NO_MEMORY);
1342 memset(params, '\0', param_len);
1343 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1344 params, param_len, NULL, 0, max_data_bytes);
1349 status = SMB_VFS_CREATE_FILE(
1352 0, /* root_dir_fid */
1353 smb_fname, /* fname */
1354 access_mask, /* access_mask */
1355 share_mode, /* share_access */
1356 create_disposition, /* create_disposition*/
1357 create_options, /* create_options */
1358 open_attr, /* file_attributes */
1359 oplock_request, /* oplock_request */
1361 open_size, /* allocation_size */
1364 ea_list, /* ea_list */
1366 &smb_action, /* psbuf */
1367 NULL, NULL); /* create context */
1369 if (!NT_STATUS_IS_OK(status)) {
1370 if (open_was_deferred(req->xconn, req->mid)) {
1371 /* We have re-scheduled this call. */
1374 reply_openerror(req, status);
1378 size = get_file_size_stat(&smb_fname->st);
1379 fattr = dos_mode(conn, smb_fname);
1380 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1381 inode = smb_fname->st.st_ex_ino;
1382 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1383 close_file(req, fsp, ERROR_CLOSE);
1384 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1388 /* Realloc the size of parameters and data we will return */
1389 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1390 if(*pparams == NULL ) {
1391 reply_nterror(req, NT_STATUS_NO_MEMORY);
1396 SSVAL(params,0,fsp->fnum);
1397 SSVAL(params,2,fattr);
1398 srv_put_dos_date2(params,4, mtime);
1399 SIVAL(params,8, (uint32_t)size);
1400 SSVAL(params,12,deny_mode);
1401 SSVAL(params,14,0); /* open_type - file or directory. */
1402 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1404 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1405 smb_action |= EXTENDED_OPLOCK_GRANTED;
1408 SSVAL(params,18,smb_action);
1411 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1413 SIVAL(params,20,inode);
1414 SSVAL(params,24,0); /* Padding. */
1416 uint32_t ea_size = estimate_ea_size(conn, fsp,
1418 SIVAL(params, 26, ea_size);
1420 SIVAL(params, 26, 0);
1423 /* Send the required number of replies */
1424 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1426 TALLOC_FREE(smb_fname);
1429 /*********************************************************
1430 Routine to check if a given string matches exactly.
1431 as a special case a mask of "." does NOT match. That
1432 is required for correct wildcard semantics
1433 Case can be significant or not.
1434 **********************************************************/
1436 static bool exact_match(bool has_wild,
1437 bool case_sensitive,
1441 if (mask[0] == '.' && mask[1] == 0) {
1449 if (case_sensitive) {
1450 return strcmp(str,mask)==0;
1452 return strcasecmp_m(str,mask) == 0;
1456 /****************************************************************************
1457 Return the filetype for UNIX extensions.
1458 ****************************************************************************/
1460 static uint32_t unix_filetype(mode_t mode)
1463 return UNIX_TYPE_FILE;
1464 else if(S_ISDIR(mode))
1465 return UNIX_TYPE_DIR;
1467 else if(S_ISLNK(mode))
1468 return UNIX_TYPE_SYMLINK;
1471 else if(S_ISCHR(mode))
1472 return UNIX_TYPE_CHARDEV;
1475 else if(S_ISBLK(mode))
1476 return UNIX_TYPE_BLKDEV;
1479 else if(S_ISFIFO(mode))
1480 return UNIX_TYPE_FIFO;
1483 else if(S_ISSOCK(mode))
1484 return UNIX_TYPE_SOCKET;
1487 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1488 return UNIX_TYPE_UNKNOWN;
1491 /****************************************************************************
1492 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1493 ****************************************************************************/
1495 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1497 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1498 const SMB_STRUCT_STAT *psbuf,
1500 enum perm_type ptype,
1505 if (perms == SMB_MODE_NO_CHANGE) {
1506 if (!VALID_STAT(*psbuf)) {
1507 return NT_STATUS_INVALID_PARAMETER;
1509 *ret_perms = psbuf->st_ex_mode;
1510 return NT_STATUS_OK;
1514 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1515 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1516 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1517 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1518 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1519 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1520 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1521 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1522 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1524 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1527 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1530 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1533 if (ptype == PERM_NEW_FILE) {
1535 * "create mask"/"force create mode" are
1536 * only applied to new files, not existing ones.
1538 ret &= lp_create_mask(SNUM(conn));
1539 /* Add in force bits */
1540 ret |= lp_force_create_mode(SNUM(conn));
1541 } else if (ptype == PERM_NEW_DIR) {
1543 * "directory mask"/"force directory mode" are
1544 * only applied to new directories, not existing ones.
1546 ret &= lp_directory_mask(SNUM(conn));
1547 /* Add in force bits */
1548 ret |= lp_force_directory_mode(SNUM(conn));
1552 return NT_STATUS_OK;
1555 /****************************************************************************
1556 Needed to show the msdfs symlinks as directories. Modifies psbuf
1557 to be a directory if it's a msdfs link.
1558 ****************************************************************************/
1560 static bool check_msdfs_link(connection_struct *conn,
1561 const char *pathname,
1562 SMB_STRUCT_STAT *psbuf)
1564 int saved_errno = errno;
1565 if(lp_host_msdfs() &&
1566 lp_msdfs_root(SNUM(conn)) &&
1567 is_msdfs_link(conn, pathname, psbuf)) {
1569 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1572 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1573 errno = saved_errno;
1576 errno = saved_errno;
1581 /****************************************************************************
1582 Get a level dependent lanman2 dir entry.
1583 ****************************************************************************/
1585 struct smbd_dirptr_lanman2_state {
1586 connection_struct *conn;
1587 uint32_t info_level;
1588 bool check_mangled_names;
1590 bool got_exact_match;
1593 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1599 struct smbd_dirptr_lanman2_state *state =
1600 (struct smbd_dirptr_lanman2_state *)private_data;
1602 char mangled_name[13]; /* mangled 8.3 name. */
1606 /* Mangle fname if it's an illegal name. */
1607 if (mangle_must_mangle(dname, state->conn->params)) {
1609 * Slow path - ensure we can push the original name as UCS2. If
1610 * not, then just don't return this name.
1614 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1615 uint8_t *tmp = talloc_array(talloc_tos(),
1619 status = srvstr_push(NULL,
1620 FLAGS2_UNICODE_STRINGS,
1629 if (!NT_STATUS_IS_OK(status)) {
1633 ok = name_to_8_3(dname, mangled_name,
1634 true, state->conn->params);
1638 fname = mangled_name;
1643 got_match = exact_match(state->has_wild,
1644 state->conn->case_sensitive,
1646 state->got_exact_match = got_match;
1648 got_match = mask_match(fname, mask,
1649 state->conn->case_sensitive);
1652 if(!got_match && state->check_mangled_names &&
1653 !mangle_is_8_3(fname, false, state->conn->params)) {
1655 * It turns out that NT matches wildcards against
1656 * both long *and* short names. This may explain some
1657 * of the wildcard wierdness from old DOS clients
1658 * that some people have been seeing.... JRA.
1660 /* Force the mangling into 8.3. */
1661 ok = name_to_8_3(fname, mangled_name,
1662 false, state->conn->params);
1667 got_match = exact_match(state->has_wild,
1668 state->conn->case_sensitive,
1669 mangled_name, mask);
1670 state->got_exact_match = got_match;
1672 got_match = mask_match(mangled_name, mask,
1673 state->conn->case_sensitive);
1681 *_fname = talloc_strdup(ctx, fname);
1682 if (*_fname == NULL) {
1689 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1691 struct smb_filename *smb_fname,
1694 struct smbd_dirptr_lanman2_state *state =
1695 (struct smbd_dirptr_lanman2_state *)private_data;
1696 bool ms_dfs_link = false;
1699 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1700 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1701 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1702 "Couldn't lstat [%s] (%s)\n",
1703 smb_fname_str_dbg(smb_fname),
1707 } else if (!VALID_STAT(smb_fname->st) &&
1708 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1709 /* Needed to show the msdfs symlinks as
1712 ms_dfs_link = check_msdfs_link(state->conn,
1713 smb_fname->base_name,
1716 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1717 "Couldn't stat [%s] (%s)\n",
1718 smb_fname_str_dbg(smb_fname),
1725 mode = dos_mode_msdfs(state->conn, smb_fname);
1727 mode = dos_mode(state->conn, smb_fname);
1734 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1735 connection_struct *conn,
1737 uint32_t info_level,
1738 struct ea_list *name_list,
1739 bool check_mangled_names,
1740 bool requires_resume_key,
1743 const struct smb_filename *smb_fname,
1744 int space_remaining,
1750 uint64_t *last_entry_off)
1752 char *p, *q, *pdata = *ppdata;
1754 uint64_t file_size = 0;
1755 uint64_t allocation_size = 0;
1756 uint64_t file_index = 0;
1758 struct timespec mdate_ts = {0};
1759 struct timespec adate_ts = {0};
1760 struct timespec cdate_ts = {0};
1761 struct timespec create_date_ts = {0};
1762 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1764 char *last_entry_ptr;
1769 struct readdir_attr_data *readdir_attr_data = NULL;
1771 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1772 file_size = get_file_size_stat(&smb_fname->st);
1774 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1776 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1777 if (!NT_STATUS_IS_OK(status)) {
1778 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1783 file_index = get_FileIndex(conn, &smb_fname->st);
1785 mdate_ts = smb_fname->st.st_ex_mtime;
1786 adate_ts = smb_fname->st.st_ex_atime;
1787 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1788 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1790 if (lp_dos_filetime_resolution(SNUM(conn))) {
1791 dos_filetime_timespec(&create_date_ts);
1792 dos_filetime_timespec(&mdate_ts);
1793 dos_filetime_timespec(&adate_ts);
1794 dos_filetime_timespec(&cdate_ts);
1797 create_date = convert_timespec_to_time_t(create_date_ts);
1798 mdate = convert_timespec_to_time_t(mdate_ts);
1799 adate = convert_timespec_to_time_t(adate_ts);
1801 /* align the record */
1802 SMB_ASSERT(align >= 1);
1804 off = (int)PTR_DIFF(pdata, base_data);
1805 pad = (off + (align-1)) & ~(align-1);
1808 if (pad && pad > space_remaining) {
1809 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1810 "for padding (wanted %u, had %d)\n",
1813 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1817 /* initialize padding to 0 */
1819 memset(pdata, 0, pad);
1821 space_remaining -= pad;
1823 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1833 switch (info_level) {
1834 case SMB_FIND_INFO_STANDARD:
1835 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1836 if(requires_resume_key) {
1840 srv_put_dos_date2(p,0,create_date);
1841 srv_put_dos_date2(p,4,adate);
1842 srv_put_dos_date2(p,8,mdate);
1843 SIVAL(p,12,(uint32_t)file_size);
1844 SIVAL(p,16,(uint32_t)allocation_size);
1848 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1849 p += ucs2_align(base_data, p, 0);
1851 status = srvstr_push(base_data, flags2, p,
1852 fname, PTR_DIFF(end_data, p),
1853 STR_TERMINATE, &len);
1854 if (!NT_STATUS_IS_OK(status)) {
1857 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1859 SCVAL(nameptr, -1, len - 2);
1861 SCVAL(nameptr, -1, 0);
1865 SCVAL(nameptr, -1, len - 1);
1867 SCVAL(nameptr, -1, 0);
1873 case SMB_FIND_EA_SIZE:
1874 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1875 if (requires_resume_key) {
1879 srv_put_dos_date2(p,0,create_date);
1880 srv_put_dos_date2(p,4,adate);
1881 srv_put_dos_date2(p,8,mdate);
1882 SIVAL(p,12,(uint32_t)file_size);
1883 SIVAL(p,16,(uint32_t)allocation_size);
1886 unsigned int ea_size = estimate_ea_size(conn, NULL,
1888 SIVAL(p,22,ea_size); /* Extended attributes */
1892 status = srvstr_push(base_data, flags2,
1893 p, fname, PTR_DIFF(end_data, p),
1894 STR_TERMINATE | STR_NOALIGN, &len);
1895 if (!NT_STATUS_IS_OK(status)) {
1898 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1911 SCVAL(nameptr,0,len);
1913 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1916 case SMB_FIND_EA_LIST:
1918 struct ea_list *file_list = NULL;
1921 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1923 return NT_STATUS_INVALID_PARAMETER;
1925 if (requires_resume_key) {
1929 srv_put_dos_date2(p,0,create_date);
1930 srv_put_dos_date2(p,4,adate);
1931 srv_put_dos_date2(p,8,mdate);
1932 SIVAL(p,12,(uint32_t)file_size);
1933 SIVAL(p,16,(uint32_t)allocation_size);
1935 p += 22; /* p now points to the EA area. */
1937 status = get_ea_list_from_file(ctx, conn, NULL,
1939 &ea_len, &file_list);
1940 if (!NT_STATUS_IS_OK(status)) {
1943 name_list = ea_list_union(name_list, file_list, &ea_len);
1945 /* We need to determine if this entry will fit in the space available. */
1946 /* Max string size is 255 bytes. */
1947 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1948 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1949 "(wanted %u, had %d)\n",
1950 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1952 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1955 /* Push the ea_data followed by the name. */
1956 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1958 status = srvstr_push(base_data, flags2,
1959 p + 1, fname, PTR_DIFF(end_data, p+1),
1960 STR_TERMINATE | STR_NOALIGN, &len);
1961 if (!NT_STATUS_IS_OK(status)) {
1964 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1977 SCVAL(nameptr,0,len);
1979 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1983 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1984 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1985 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1987 SIVAL(p,0,reskey); p += 4;
1988 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1989 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1990 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1991 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1992 SOFF_T(p,0,file_size); p += 8;
1993 SOFF_T(p,0,allocation_size); p += 8;
1994 SIVAL(p,0,mode); p += 4;
1995 q = p; p += 4; /* q is placeholder for name length. */
1996 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1997 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1999 unsigned int ea_size = estimate_ea_size(conn, NULL,
2001 SIVAL(p,0,ea_size); /* Extended attributes */
2004 /* Clear the short name buffer. This is
2005 * IMPORTANT as not doing so will trigger
2006 * a Win2k client bug. JRA.
2008 if (!was_8_3 && check_mangled_names) {
2009 char mangled_name[13]; /* mangled 8.3 name. */
2010 if (!name_to_8_3(fname,mangled_name,True,
2012 /* Error - mangle failed ! */
2013 memset(mangled_name,'\0',12);
2015 mangled_name[12] = 0;
2016 status = srvstr_push(base_data, flags2,
2017 p+2, mangled_name, 24,
2018 STR_UPPER|STR_UNICODE, &len);
2019 if (!NT_STATUS_IS_OK(status)) {
2023 memset(p + 2 + len,'\0',24 - len);
2030 status = srvstr_push(base_data, flags2, p,
2031 fname, PTR_DIFF(end_data, p),
2032 STR_TERMINATE_ASCII, &len);
2033 if (!NT_STATUS_IS_OK(status)) {
2039 len = PTR_DIFF(p, pdata);
2040 pad = (len + (align-1)) & ~(align-1);
2042 * offset to the next entry, the caller
2043 * will overwrite it for the last entry
2044 * that's why we always include the padding
2048 * set padding to zero
2051 memset(p, 0, pad - len);
2058 case SMB_FIND_FILE_DIRECTORY_INFO:
2059 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2061 SIVAL(p,0,reskey); p += 4;
2062 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2063 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2064 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2065 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2066 SOFF_T(p,0,file_size); p += 8;
2067 SOFF_T(p,0,allocation_size); p += 8;
2068 SIVAL(p,0,mode); p += 4;
2069 status = srvstr_push(base_data, flags2,
2070 p + 4, fname, PTR_DIFF(end_data, p+4),
2071 STR_TERMINATE_ASCII, &len);
2072 if (!NT_STATUS_IS_OK(status)) {
2078 len = PTR_DIFF(p, pdata);
2079 pad = (len + (align-1)) & ~(align-1);
2081 * offset to the next entry, the caller
2082 * will overwrite it for the last entry
2083 * that's why we always include the padding
2087 * set padding to zero
2090 memset(p, 0, pad - len);
2097 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2098 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2100 SIVAL(p,0,reskey); p += 4;
2101 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2102 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2103 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2104 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2105 SOFF_T(p,0,file_size); p += 8;
2106 SOFF_T(p,0,allocation_size); p += 8;
2107 SIVAL(p,0,mode); p += 4;
2108 q = p; p += 4; /* q is placeholder for name length. */
2110 unsigned int ea_size = estimate_ea_size(conn, NULL,
2112 SIVAL(p,0,ea_size); /* Extended attributes */
2115 status = srvstr_push(base_data, flags2, p,
2116 fname, PTR_DIFF(end_data, p),
2117 STR_TERMINATE_ASCII, &len);
2118 if (!NT_STATUS_IS_OK(status)) {
2124 len = PTR_DIFF(p, pdata);
2125 pad = (len + (align-1)) & ~(align-1);
2127 * offset to the next entry, the caller
2128 * will overwrite it for the last entry
2129 * that's why we always include the padding
2133 * set padding to zero
2136 memset(p, 0, pad - len);
2143 case SMB_FIND_FILE_NAMES_INFO:
2144 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2146 SIVAL(p,0,reskey); p += 4;
2148 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2149 acl on a dir (tridge) */
2150 status = srvstr_push(base_data, flags2, p,
2151 fname, PTR_DIFF(end_data, p),
2152 STR_TERMINATE_ASCII, &len);
2153 if (!NT_STATUS_IS_OK(status)) {
2159 len = PTR_DIFF(p, pdata);
2160 pad = (len + (align-1)) & ~(align-1);
2162 * offset to the next entry, the caller
2163 * will overwrite it for the last entry
2164 * that's why we always include the padding
2168 * set padding to zero
2171 memset(p, 0, pad - len);
2178 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2179 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2181 SIVAL(p,0,reskey); p += 4;
2182 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2183 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2184 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2185 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2186 SOFF_T(p,0,file_size); p += 8;
2187 SOFF_T(p,0,allocation_size); p += 8;
2188 SIVAL(p,0,mode); p += 4;
2189 q = p; p += 4; /* q is placeholder for name length. */
2190 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2191 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2193 unsigned int ea_size = estimate_ea_size(conn, NULL,
2195 SIVAL(p,0,ea_size); /* Extended attributes */
2198 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2199 SBVAL(p,0,file_index); p += 8;
2200 status = srvstr_push(base_data, flags2, p,
2201 fname, PTR_DIFF(end_data, p),
2202 STR_TERMINATE_ASCII, &len);
2203 if (!NT_STATUS_IS_OK(status)) {
2209 len = PTR_DIFF(p, pdata);
2210 pad = (len + (align-1)) & ~(align-1);
2212 * offset to the next entry, the caller
2213 * will overwrite it for the last entry
2214 * that's why we always include the padding
2218 * set padding to zero
2221 memset(p, 0, pad - len);
2228 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2229 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2230 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2232 SIVAL(p,0,reskey); p += 4;
2233 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2234 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2235 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2236 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2237 SOFF_T(p,0,file_size); p += 8;
2238 SOFF_T(p,0,allocation_size); p += 8;
2239 SIVAL(p,0,mode); p += 4;
2240 q = p; p += 4; /* q is placeholder for name length */
2241 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2242 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2243 } else if (readdir_attr_data &&
2244 readdir_attr_data->type == RDATTR_AAPL) {
2246 * OS X specific SMB2 extension negotiated via
2247 * AAPL create context: return max_access in
2250 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2252 unsigned int ea_size = estimate_ea_size(conn, NULL,
2254 SIVAL(p,0,ea_size); /* Extended attributes */
2258 if (readdir_attr_data &&
2259 readdir_attr_data->type == RDATTR_AAPL) {
2261 * OS X specific SMB2 extension negotiated via
2262 * AAPL create context: return resource fork
2263 * length and compressed FinderInfo in
2266 * According to documentation short_name_len
2267 * should be 0, but on the wire behaviour
2268 * shows its set to 24 by clients.
2272 /* Resourefork length */
2273 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2275 /* Compressed FinderInfo */
2276 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2277 } else if (!was_8_3 && check_mangled_names) {
2278 char mangled_name[13]; /* mangled 8.3 name. */
2279 if (!name_to_8_3(fname,mangled_name,True,
2281 /* Error - mangle failed ! */
2282 memset(mangled_name,'\0',12);
2284 mangled_name[12] = 0;
2285 status = srvstr_push(base_data, flags2,
2286 p+2, mangled_name, 24,
2287 STR_UPPER|STR_UNICODE, &len);
2288 if (!NT_STATUS_IS_OK(status)) {
2293 memset(p + 2 + len,'\0',24 - len);
2297 /* Clear the short name buffer. This is
2298 * IMPORTANT as not doing so will trigger
2299 * a Win2k client bug. JRA.
2306 if (readdir_attr_data &&
2307 readdir_attr_data->type == RDATTR_AAPL) {
2309 * OS X specific SMB2 extension negotiated via
2310 * AAPL create context: return UNIX mode in
2313 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2314 SSVAL(p, 0, aapl_mode);
2320 SBVAL(p,0,file_index); p += 8;
2321 status = srvstr_push(base_data, flags2, p,
2322 fname, PTR_DIFF(end_data, p),
2323 STR_TERMINATE_ASCII, &len);
2324 if (!NT_STATUS_IS_OK(status)) {
2330 len = PTR_DIFF(p, pdata);
2331 pad = (len + (align-1)) & ~(align-1);
2333 * offset to the next entry, the caller
2334 * will overwrite it for the last entry
2335 * that's why we always include the padding
2339 * set padding to zero
2342 memset(p, 0, pad - len);
2349 /* CIFS UNIX Extension. */
2351 case SMB_FIND_FILE_UNIX:
2352 case SMB_FIND_FILE_UNIX_INFO2:
2354 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2356 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2358 if (info_level == SMB_FIND_FILE_UNIX) {
2359 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2360 p = store_file_unix_basic(conn, p,
2361 NULL, &smb_fname->st);
2362 status = srvstr_push(base_data, flags2, p,
2363 fname, PTR_DIFF(end_data, p),
2364 STR_TERMINATE, &len);
2365 if (!NT_STATUS_IS_OK(status)) {
2369 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2370 p = store_file_unix_basic_info2(conn, p,
2371 NULL, &smb_fname->st);
2374 status = srvstr_push(base_data, flags2, p, fname,
2375 PTR_DIFF(end_data, p), 0, &len);
2376 if (!NT_STATUS_IS_OK(status)) {
2379 SIVAL(nameptr, 0, len);
2384 len = PTR_DIFF(p, pdata);
2385 pad = (len + (align-1)) & ~(align-1);
2387 * offset to the next entry, the caller
2388 * will overwrite it for the last entry
2389 * that's why we always include the padding
2393 * set padding to zero
2396 memset(p, 0, pad - len);
2401 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2406 return NT_STATUS_INVALID_LEVEL;
2409 if (PTR_DIFF(p,pdata) > space_remaining) {
2410 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2411 "(wanted %u, had %d)\n",
2412 (unsigned int)PTR_DIFF(p,pdata),
2414 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2417 /* Setup the last entry pointer, as an offset from base_data */
2418 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2419 /* Advance the data pointer to the next slot */
2422 return NT_STATUS_OK;
2425 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2426 connection_struct *conn,
2427 struct dptr_struct *dirptr,
2429 const char *path_mask,
2432 int requires_resume_key,
2440 int space_remaining,
2441 bool *got_exact_match,
2442 int *_last_entry_off,
2443 struct ea_list *name_list)
2446 const char *mask = NULL;
2447 long prev_dirpos = 0;
2450 struct smb_filename *smb_fname = NULL;
2451 struct smbd_dirptr_lanman2_state state;
2453 uint64_t last_entry_off = 0;
2455 enum mangled_names_options mangled_names;
2456 bool marshall_with_83_names;
2458 mangled_names = lp_mangled_names(conn->params);
2462 state.info_level = info_level;
2463 if (mangled_names != MANGLED_NAMES_NO) {
2464 state.check_mangled_names = true;
2466 state.has_wild = dptr_has_wild(dirptr);
2467 state.got_exact_match = false;
2469 *got_exact_match = false;
2471 p = strrchr_m(path_mask,'/');
2482 ok = smbd_dirptr_get_entry(ctx,
2488 smbd_dirptr_lanman2_match_fn,
2489 smbd_dirptr_lanman2_mode_fn,
2496 return NT_STATUS_END_OF_FILE;
2499 *got_exact_match = state.got_exact_match;
2501 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2503 status = smbd_marshall_dir_entry(ctx,
2508 marshall_with_83_names,
2509 requires_resume_key,
2520 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2521 DEBUG(1,("Conversion error: illegal character: %s\n",
2522 smb_fname_str_dbg(smb_fname)));
2525 TALLOC_FREE(smb_fname);
2526 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2527 dptr_SeekDir(dirptr, prev_dirpos);
2530 if (!NT_STATUS_IS_OK(status)) {
2534 *_last_entry_off = last_entry_off;
2535 return NT_STATUS_OK;
2538 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2539 connection_struct *conn,
2540 struct dptr_struct *dirptr,
2542 const char *path_mask,
2545 bool requires_resume_key,
2551 int space_remaining,
2552 bool *got_exact_match,
2553 int *last_entry_off,
2554 struct ea_list *name_list)
2557 const bool do_pad = true;
2559 if (info_level >= 1 && info_level <= 3) {
2560 /* No alignment on earlier info levels. */
2564 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2565 path_mask, dirtype, info_level,
2566 requires_resume_key, dont_descend, ask_sharemode,
2568 ppdata, base_data, end_data,
2571 last_entry_off, name_list);
2574 /****************************************************************************
2575 Reply to a TRANS2_FINDFIRST.
2576 ****************************************************************************/
2578 static void call_trans2findfirst(connection_struct *conn,
2579 struct smb_request *req,
2580 char **pparams, int total_params,
2581 char **ppdata, int total_data,
2582 unsigned int max_data_bytes)
2584 /* We must be careful here that we don't return more than the
2585 allowed number of data bytes. If this means returning fewer than
2586 maxentries then so be it. We assume that the redirector has
2587 enough room for the fixed number of parameter bytes it has
2589 struct smb_filename *smb_dname = NULL;
2590 char *params = *pparams;
2591 char *pdata = *ppdata;
2595 uint16_t findfirst_flags;
2596 bool close_after_first;
2598 bool requires_resume_key;
2600 char *directory = NULL;
2603 int last_entry_off=0;
2607 bool finished = False;
2608 bool dont_descend = False;
2609 bool out_of_space = False;
2610 int space_remaining;
2611 bool mask_contains_wcard = False;
2612 struct ea_list *ea_list = NULL;
2613 NTSTATUS ntstatus = NT_STATUS_OK;
2614 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2615 struct dptr_struct *dirptr = NULL;
2616 struct smbd_server_connection *sconn = req->sconn;
2617 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2618 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2619 bool backup_priv = false;
2620 bool as_root = false;
2622 if (total_params < 13) {
2623 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2627 dirtype = SVAL(params,0);
2628 maxentries = SVAL(params,2);
2629 findfirst_flags = SVAL(params,4);
2630 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2631 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2632 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2633 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2634 security_token_has_privilege(get_current_nttok(conn),
2637 info_level = SVAL(params,6);
2639 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2640 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2641 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2643 info_level, max_data_bytes));
2646 /* W2K3 seems to treat zero as 1. */
2650 switch (info_level) {
2651 case SMB_FIND_INFO_STANDARD:
2652 case SMB_FIND_EA_SIZE:
2653 case SMB_FIND_EA_LIST:
2654 case SMB_FIND_FILE_DIRECTORY_INFO:
2655 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2656 case SMB_FIND_FILE_NAMES_INFO:
2657 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2658 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2659 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2661 case SMB_FIND_FILE_UNIX:
2662 case SMB_FIND_FILE_UNIX_INFO2:
2663 /* Always use filesystem for UNIX mtime query. */
2664 ask_sharemode = false;
2665 if (!lp_unix_extensions()) {
2666 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2669 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2672 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2676 if (req->posix_pathnames) {
2677 srvstr_get_path_wcard_posix(talloc_tos(),
2685 &mask_contains_wcard);
2687 srvstr_get_path_wcard(talloc_tos(),
2695 &mask_contains_wcard);
2697 if (!NT_STATUS_IS_OK(ntstatus)) {
2698 reply_nterror(req, ntstatus);
2705 ntstatus = filename_convert_with_privilege(talloc_tos(),
2710 &mask_contains_wcard,
2713 ntstatus = filename_convert(talloc_tos(), conn,
2714 req->flags2 & FLAGS2_DFS_PATHNAMES,
2717 &mask_contains_wcard,
2721 if (!NT_STATUS_IS_OK(ntstatus)) {
2722 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2723 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2724 ERRSRV, ERRbadpath);
2727 reply_nterror(req, ntstatus);
2731 mask = smb_dname->original_lcomp;
2733 directory = smb_dname->base_name;
2735 p = strrchr_m(directory,'/');
2737 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2738 if((directory[0] == '.') && (directory[1] == '\0')) {
2739 mask = talloc_strdup(talloc_tos(),"*");
2741 reply_nterror(req, NT_STATUS_NO_MEMORY);
2744 mask_contains_wcard = True;
2750 if (p == NULL || p == directory) {
2751 /* Ensure we don't have a directory name of "". */
2752 directory = talloc_strdup(talloc_tos(), ".");
2754 reply_nterror(req, NT_STATUS_NO_MEMORY);
2757 /* Ensure smb_dname->base_name matches. */
2758 smb_dname->base_name = directory;
2761 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2763 if (info_level == SMB_FIND_EA_LIST) {
2766 if (total_data < 4) {
2767 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2771 ea_size = IVAL(pdata,0);
2772 if (ea_size != total_data) {
2773 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2774 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2775 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2779 if (!lp_ea_support(SNUM(conn))) {
2780 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2784 /* Pull out the list of names. */
2785 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2787 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2792 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2793 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2797 *ppdata = (char *)SMB_REALLOC(
2798 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2799 if(*ppdata == NULL ) {
2800 reply_nterror(req, NT_STATUS_NO_MEMORY);
2804 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2806 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2809 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2810 /* Realloc the params space */
2811 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2812 if (*pparams == NULL) {
2813 reply_nterror(req, NT_STATUS_NO_MEMORY);
2818 /* Save the wildcard match and attribs we are using on this directory -
2819 needed as lanman2 assumes these are being saved between calls */
2821 ntstatus = dptr_create(conn,
2829 mask_contains_wcard,
2833 if (!NT_STATUS_IS_OK(ntstatus)) {
2834 reply_nterror(req, ntstatus);
2839 /* Remember this in case we have
2840 to do a findnext. */
2841 dptr_set_priv(dirptr);
2844 dptr_num = dptr_dnum(dirptr);
2845 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2847 /* Initialize per TRANS2_FIND_FIRST operation data */
2848 dptr_init_search_op(dirptr);
2850 /* We don't need to check for VOL here as this is returned by
2851 a different TRANS2 call. */
2853 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2854 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2855 if (in_list(directory,
2856 lp_dont_descend(talloc_tos(), SNUM(conn)),
2857 conn->case_sensitive)) {
2858 dont_descend = True;
2862 space_remaining = max_data_bytes;
2863 out_of_space = False;
2865 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2866 bool got_exact_match = False;
2868 /* this is a heuristic to avoid seeking the dirptr except when
2869 absolutely necessary. It allows for a filename of about 40 chars */
2870 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2871 out_of_space = True;
2874 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2878 mask,dirtype,info_level,
2879 requires_resume_key,dont_descend,
2884 &last_entry_off, ea_list);
2885 if (NT_STATUS_EQUAL(ntstatus,
2886 NT_STATUS_ILLEGAL_CHARACTER)) {
2888 * Bad character conversion on name. Ignore this
2893 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2894 out_of_space = true;
2896 finished = !NT_STATUS_IS_OK(ntstatus);
2900 if (!finished && !out_of_space)
2904 * As an optimisation if we know we aren't looking
2905 * for a wildcard name (ie. the name matches the wildcard exactly)
2906 * then we can finish on any (first) match.
2907 * This speeds up large directory searches. JRA.
2913 /* Ensure space_remaining never goes -ve. */
2914 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2915 space_remaining = 0;
2916 out_of_space = true;
2918 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2922 /* Check if we can close the dirptr */
2923 if(close_after_first || (finished && close_if_end)) {
2924 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2925 dptr_close(sconn, &dptr_num);
2929 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2930 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2931 * the protocol level is less than NT1. Tested with smbclient. JRA.
2932 * This should fix the OS/2 client bug #2335.
2935 if(numentries == 0) {
2936 dptr_close(sconn, &dptr_num);
2937 if (get_Protocol() < PROTOCOL_NT1) {
2938 reply_force_doserror(req, ERRDOS, ERRnofiles);
2941 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2942 ERRDOS, ERRbadfile);
2947 /* At this point pdata points to numentries directory entries. */
2949 /* Set up the return parameter block */
2950 SSVAL(params,0,dptr_num);
2951 SSVAL(params,2,numentries);
2952 SSVAL(params,4,finished);
2953 SSVAL(params,6,0); /* Never an EA error */
2954 SSVAL(params,8,last_entry_off);
2956 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2959 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2960 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2962 reply_nterror(req, NT_STATUS_NO_MEMORY);
2966 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2967 smb_fn_name(req->cmd),
2968 mask, directory, dirtype, numentries ) );
2971 * Force a name mangle here to ensure that the
2972 * mask as an 8.3 name is top of the mangled cache.
2973 * The reasons for this are subtle. Don't remove
2974 * this code unless you know what you are doing
2975 * (see PR#13758). JRA.
2978 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2979 char mangled_name[13];
2980 name_to_8_3(mask, mangled_name, True, conn->params);
2988 TALLOC_FREE(smb_dname);
2992 /****************************************************************************
2993 Reply to a TRANS2_FINDNEXT.
2994 ****************************************************************************/
2996 static void call_trans2findnext(connection_struct *conn,
2997 struct smb_request *req,
2998 char **pparams, int total_params,
2999 char **ppdata, int total_data,
3000 unsigned int max_data_bytes)
3002 /* We must be careful here that we don't return more than the
3003 allowed number of data bytes. If this means returning fewer than
3004 maxentries then so be it. We assume that the redirector has
3005 enough room for the fixed number of parameter bytes it has
3007 char *params = *pparams;
3008 char *pdata = *ppdata;
3012 uint16_t info_level;
3013 uint32_t resume_key;
3014 uint16_t findnext_flags;
3015 bool close_after_request;
3017 bool requires_resume_key;
3019 bool mask_contains_wcard = False;
3020 char *resume_name = NULL;
3021 const char *mask = NULL;
3022 const char *directory = NULL;
3026 int i, last_entry_off=0;
3027 bool finished = False;
3028 bool dont_descend = False;
3029 bool out_of_space = False;
3030 int space_remaining;
3031 struct ea_list *ea_list = NULL;
3032 NTSTATUS ntstatus = NT_STATUS_OK;
3033 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3034 TALLOC_CTX *ctx = talloc_tos();
3035 struct dptr_struct *dirptr;
3036 struct smbd_server_connection *sconn = req->sconn;
3037 bool backup_priv = false;
3038 bool as_root = false;
3040 if (total_params < 13) {
3041 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3045 dptr_num = SVAL(params,0);
3046 maxentries = SVAL(params,2);
3047 info_level = SVAL(params,4);
3048 resume_key = IVAL(params,6);
3049 findnext_flags = SVAL(params,10);
3050 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3051 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3052 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3053 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3055 if (!continue_bit) {
3056 /* We only need resume_name if continue_bit is zero. */
3057 if (req->posix_pathnames) {
3058 srvstr_get_path_wcard_posix(ctx,
3066 &mask_contains_wcard);
3068 srvstr_get_path_wcard(ctx,
3076 &mask_contains_wcard);
3078 if (!NT_STATUS_IS_OK(ntstatus)) {
3079 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3080 complain (it thinks we're asking for the directory above the shared
3081 path or an invalid name). Catch this as the resume name is only compared, never used in
3082 a file access. JRA. */
3083 srvstr_pull_talloc(ctx, params, req->flags2,
3084 &resume_name, params+12,
3088 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3089 reply_nterror(req, ntstatus);
3095 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3096 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3097 resume_key = %d resume name = %s continue=%d level = %d\n",
3098 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3099 requires_resume_key, resume_key,
3100 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3103 /* W2K3 seems to treat zero as 1. */
3107 switch (info_level) {
3108 case SMB_FIND_INFO_STANDARD:
3109 case SMB_FIND_EA_SIZE:
3110 case SMB_FIND_EA_LIST:
3111 case SMB_FIND_FILE_DIRECTORY_INFO:
3112 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3113 case SMB_FIND_FILE_NAMES_INFO:
3114 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3115 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3116 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3118 case SMB_FIND_FILE_UNIX:
3119 case SMB_FIND_FILE_UNIX_INFO2:
3120 /* Always use filesystem for UNIX mtime query. */
3121 ask_sharemode = false;
3122 if (!lp_unix_extensions()) {
3123 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3128 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3132 if (info_level == SMB_FIND_EA_LIST) {
3135 if (total_data < 4) {
3136 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3140 ea_size = IVAL(pdata,0);
3141 if (ea_size != total_data) {
3142 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3143 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3144 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3148 if (!lp_ea_support(SNUM(conn))) {
3149 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3153 /* Pull out the list of names. */
3154 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3161 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3166 *ppdata = (char *)SMB_REALLOC(
3167 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3168 if(*ppdata == NULL) {
3169 reply_nterror(req, NT_STATUS_NO_MEMORY);
3174 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3177 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3180 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3181 /* Realloc the params space */
3182 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3183 if(*pparams == NULL ) {
3184 reply_nterror(req, NT_STATUS_NO_MEMORY);
3190 /* Check that the dptr is valid */
3191 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3192 reply_nterror(req, STATUS_NO_MORE_FILES);
3196 directory = dptr_path(sconn, dptr_num);
3198 /* Get the wildcard mask from the dptr */
3199 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3200 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3201 reply_nterror(req, STATUS_NO_MORE_FILES);
3205 /* Get the attr mask from the dptr */
3206 dirtype = dptr_attr(sconn, dptr_num);
3208 backup_priv = dptr_get_priv(dirptr);
3210 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3211 "backup_priv = %d\n",
3212 dptr_num, mask, dirtype,
3214 dptr_TellDir(dirptr),
3217 /* Initialize per TRANS2_FIND_NEXT operation data */
3218 dptr_init_search_op(dirptr);
3220 /* We don't need to check for VOL here as this is returned by
3221 a different TRANS2 call. */
3223 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3224 directory,lp_dont_descend(ctx, SNUM(conn))));
3225 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3226 dont_descend = True;
3229 space_remaining = max_data_bytes;
3230 out_of_space = False;
3238 * Seek to the correct position. We no longer use the resume key but
3239 * depend on the last file name instead.
3242 if(!continue_bit && resume_name && *resume_name) {
3245 long current_pos = 0;
3247 * Remember, name_to_8_3 is called by
3248 * get_lanman2_dir_entry(), so the resume name
3249 * could be mangled. Ensure we check the unmangled name.
3252 if (mangle_is_mangled(resume_name, conn->params)) {
3253 char *new_resume_name = NULL;
3254 mangle_lookup_name_from_8_3(ctx,
3258 if (new_resume_name) {
3259 resume_name = new_resume_name;
3264 * Fix for NT redirector problem triggered by resume key indexes
3265 * changing between directory scans. We now return a resume key of 0
3266 * and instead look for the filename to continue from (also given
3267 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3268 * findfirst/findnext (as is usual) then the directory pointer
3269 * should already be at the correct place.
3272 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3273 } /* end if resume_name && !continue_bit */
3275 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3276 bool got_exact_match = False;
3278 /* this is a heuristic to avoid seeking the dirptr except when
3279 absolutely necessary. It allows for a filename of about 40 chars */
3280 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3281 out_of_space = True;
3284 ntstatus = get_lanman2_dir_entry(ctx,
3288 mask,dirtype,info_level,
3289 requires_resume_key,dont_descend,
3294 &last_entry_off, ea_list);
3295 if (NT_STATUS_EQUAL(ntstatus,
3296 NT_STATUS_ILLEGAL_CHARACTER)) {
3298 * Bad character conversion on name. Ignore this
3303 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3304 out_of_space = true;
3306 finished = !NT_STATUS_IS_OK(ntstatus);
3310 if (!finished && !out_of_space)
3314 * As an optimisation if we know we aren't looking
3315 * for a wildcard name (ie. the name matches the wildcard exactly)
3316 * then we can finish on any (first) match.
3317 * This speeds up large directory searches. JRA.
3323 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3326 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3327 smb_fn_name(req->cmd),
3328 mask, directory, dirtype, numentries ) );
3330 /* Check if we can close the dirptr */
3331 if(close_after_request || (finished && close_if_end)) {
3332 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3333 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3340 /* Set up the return parameter block */
3341 SSVAL(params,0,numentries);
3342 SSVAL(params,2,finished);
3343 SSVAL(params,4,0); /* Never an EA error */
3344 SSVAL(params,6,last_entry_off);
3346 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3352 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3354 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3358 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3360 SMB_ASSERT(extended_info != NULL);
3362 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3363 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3364 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3365 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3366 #ifdef SAMBA_VERSION_REVISION
3367 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3369 extended_info->samba_subversion = 0;
3370 #ifdef SAMBA_VERSION_RC_RELEASE
3371 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3373 #ifdef SAMBA_VERSION_PRE_RELEASE
3374 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3377 #ifdef SAMBA_VERSION_VENDOR_PATCH
3378 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3380 extended_info->samba_gitcommitdate = 0;
3381 #ifdef SAMBA_VERSION_COMMIT_TIME
3382 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3385 memset(extended_info->samba_version_string, 0,
3386 sizeof(extended_info->samba_version_string));
3388 snprintf (extended_info->samba_version_string,
3389 sizeof(extended_info->samba_version_string),
3390 "%s", samba_version_string());
3393 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3394 connection_struct *conn,
3395 TALLOC_CTX *mem_ctx,
3396 uint16_t info_level,
3398 unsigned int max_data_bytes,
3399 size_t *fixed_portion,
3400 struct smb_filename *fname,
3404 char *pdata, *end_data;
3407 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3408 int snum = SNUM(conn);
3409 const char *fstype = lp_fstype(SNUM(conn));
3410 const char *filename = NULL;
3411 const uint64_t bytes_per_sector = 512;
3412 uint32_t additional_flags = 0;
3413 struct smb_filename smb_fname;
3415 NTSTATUS status = NT_STATUS_OK;
3418 if (fname == NULL || fname->base_name == NULL) {
3421 filename = fname->base_name;
3425 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3426 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3427 "info level (0x%x) on IPC$.\n",
3428 (unsigned int)info_level));
3429 return NT_STATUS_ACCESS_DENIED;
3433 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3435 ZERO_STRUCT(smb_fname);
3436 smb_fname.base_name = discard_const_p(char, filename);
3438 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3439 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3440 return map_nt_error_from_unix(errno);
3445 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3446 return NT_STATUS_INVALID_PARAMETER;
3449 *ppdata = (char *)SMB_REALLOC(
3450 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3451 if (*ppdata == NULL) {
3452 return NT_STATUS_NO_MEMORY;
3456 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3457 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3461 switch (info_level) {
3462 case SMB_INFO_ALLOCATION:
3464 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3466 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3468 if (df_ret == (uint64_t)-1) {
3469 return map_nt_error_from_unix(errno);
3472 block_size = lp_block_size(snum);
3473 if (bsize < block_size) {
3474 uint64_t factor = block_size/bsize;
3479 if (bsize > block_size) {
3480 uint64_t factor = bsize/block_size;
3485 sectors_per_unit = bsize/bytes_per_sector;
3487 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3488 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3489 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3491 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3492 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3493 SIVAL(pdata,l1_cUnit,dsize);
3494 SIVAL(pdata,l1_cUnitAvail,dfree);
3495 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3499 case SMB_INFO_VOLUME:
3500 /* Return volume name */
3502 * Add volume serial number - hash of a combination of
3503 * the called hostname and the service name.
3505 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3507 * Win2k3 and previous mess this up by sending a name length
3508 * one byte short. I believe only older clients (OS/2 Win9x) use
3509 * this call so try fixing this by adding a terminating null to
3510 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3512 status = srvstr_push(
3514 pdata+l2_vol_szVolLabel, vname,
3515 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3516 STR_NOALIGN|STR_TERMINATE, &len);
3517 if (!NT_STATUS_IS_OK(status)) {
3520 SCVAL(pdata,l2_vol_cch,len);
3521 data_len = l2_vol_szVolLabel + len;
3522 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3523 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3524 (unsigned)len, vname));
3527 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3528 case SMB_FS_ATTRIBUTE_INFORMATION:
3530 additional_flags = 0;
3531 #if defined(HAVE_SYS_QUOTAS)
3532 additional_flags |= FILE_VOLUME_QUOTAS;
3535 if(lp_nt_acl_support(SNUM(conn))) {
3536 additional_flags |= FILE_PERSISTENT_ACLS;
3539 /* Capabilities are filled in at connection time through STATVFS call */
3540 additional_flags |= conn->fs_capabilities;
3541 additional_flags |= lp_parm_int(conn->params->service,
3542 "share", "fake_fscaps",
3545 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3546 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3547 additional_flags); /* FS ATTRIBUTES */
3549 SIVAL(pdata,4,255); /* Max filename component length */
3550 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3551 and will think we can't do long filenames */
3552 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3553 PTR_DIFF(end_data, pdata+12),
3555 if (!NT_STATUS_IS_OK(status)) {
3559 data_len = 12 + len;
3560 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3561 /* the client only requested a portion of the
3563 data_len = max_data_bytes;
3564 status = STATUS_BUFFER_OVERFLOW;
3566 *fixed_portion = 16;
3569 case SMB_QUERY_FS_LABEL_INFO:
3570 case SMB_FS_LABEL_INFORMATION:
3571 status = srvstr_push(pdata, flags2, pdata+4, vname,
3572 PTR_DIFF(end_data, pdata+4), 0, &len);
3573 if (!NT_STATUS_IS_OK(status)) {
3580 case SMB_QUERY_FS_VOLUME_INFO:
3581 case SMB_FS_VOLUME_INFORMATION:
3584 * Add volume serial number - hash of a combination of
3585 * the called hostname and the service name.
3587 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3588 (str_checksum(get_local_machine_name())<<16));
3590 /* Max label len is 32 characters. */
3591 status = srvstr_push(pdata, flags2, pdata+18, vname,
3592 PTR_DIFF(end_data, pdata+18),
3594 if (!NT_STATUS_IS_OK(status)) {
3597 SIVAL(pdata,12,len);
3600 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3601 (int)strlen(vname),vname,
3602 lp_servicename(talloc_tos(), snum)));
3603 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3604 /* the client only requested a portion of the
3606 data_len = max_data_bytes;
3607 status = STATUS_BUFFER_OVERFLOW;
3609 *fixed_portion = 24;
3612 case SMB_QUERY_FS_SIZE_INFO:
3613 case SMB_FS_SIZE_INFORMATION:
3615 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3617 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3619 if (df_ret == (uint64_t)-1) {
3620 return map_nt_error_from_unix(errno);
3622 block_size = lp_block_size(snum);
3623 if (bsize < block_size) {
3624 uint64_t factor = block_size/bsize;
3629 if (bsize > block_size) {
3630 uint64_t factor = bsize/block_size;
3635 sectors_per_unit = bsize/bytes_per_sector;
3636 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3637 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3638 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3639 SBIG_UINT(pdata,0,dsize);
3640 SBIG_UINT(pdata,8,dfree);
3641 SIVAL(pdata,16,sectors_per_unit);
3642 SIVAL(pdata,20,bytes_per_sector);
3643 *fixed_portion = 24;
3647 case SMB_FS_FULL_SIZE_INFORMATION:
3649 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3651 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3653 if (df_ret == (uint64_t)-1) {
3654 return map_nt_error_from_unix(errno);
3656 block_size = lp_block_size(snum);
3657 if (bsize < block_size) {
3658 uint64_t factor = block_size/bsize;
3663 if (bsize > block_size) {
3664 uint64_t factor = bsize/block_size;
3669 sectors_per_unit = bsize/bytes_per_sector;
3670 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3671 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3672 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3673 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3674 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3675 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3676 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3677 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3678 *fixed_portion = 32;
3682 case SMB_QUERY_FS_DEVICE_INFO:
3683 case SMB_FS_DEVICE_INFORMATION:
3685 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3687 if (!CAN_WRITE(conn)) {
3688 characteristics |= FILE_READ_ONLY_DEVICE;
3691 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3692 SIVAL(pdata,4,characteristics);
3697 #ifdef HAVE_SYS_QUOTAS
3698 case SMB_FS_QUOTA_INFORMATION:
3700 * what we have to send --metze:
3702 * Unknown1: 24 NULL bytes
3703 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3704 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3705 * Quota Flags: 2 byte :
3706 * Unknown3: 6 NULL bytes
3710 * details for Quota Flags:
3712 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3713 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3714 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3715 * 0x0001 Enable Quotas: enable quota for this fs
3719 /* we need to fake up a fsp here,
3720 * because its not send in this call
3723 SMB_NTQUOTA_STRUCT quotas;
3726 ZERO_STRUCT(quotas);
3729 fsp.fnum = FNUM_FIELD_INVALID;
3732 if (get_current_uid(conn) != 0) {
3733 DEBUG(0,("get_user_quota: access_denied "
3734 "service [%s] user [%s]\n",
3735 lp_servicename(talloc_tos(), SNUM(conn)),
3736 conn->session_info->unix_info->unix_name));
3737 return NT_STATUS_ACCESS_DENIED;
3740 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3742 if (!NT_STATUS_IS_OK(status)) {
3743 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3749 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3750 lp_servicename(talloc_tos(), SNUM(conn))));
3752 /* Unknown1 24 NULL bytes*/
3753 SBIG_UINT(pdata,0,(uint64_t)0);
3754 SBIG_UINT(pdata,8,(uint64_t)0);
3755 SBIG_UINT(pdata,16,(uint64_t)0);
3757 /* Default Soft Quota 8 bytes */
3758 SBIG_UINT(pdata,24,quotas.softlim);
3760 /* Default Hard Quota 8 bytes */
3761 SBIG_UINT(pdata,32,quotas.hardlim);
3763 /* Quota flag 2 bytes */
3764 SSVAL(pdata,40,quotas.qflags);
3766 /* Unknown3 6 NULL bytes */
3772 #endif /* HAVE_SYS_QUOTAS */
3773 case SMB_FS_OBJECTID_INFORMATION:
3775 unsigned char objid[16];
3776 struct smb_extended_info extended_info;
3777 memcpy(pdata,create_volume_objectid(conn, objid),16);
3778 samba_extended_info_version (&extended_info);
3779 SIVAL(pdata,16,extended_info.samba_magic);
3780 SIVAL(pdata,20,extended_info.samba_version);
3781 SIVAL(pdata,24,extended_info.samba_subversion);
3782 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3783 memcpy(pdata+36,extended_info.samba_version_string,28);
3788 case SMB_FS_SECTOR_SIZE_INFORMATION:
3792 * These values match a physical Windows Server 2012
3793 * share backed by NTFS atop spinning rust.
3795 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3796 /* logical_bytes_per_sector */
3797 SIVAL(pdata, 0, bytes_per_sector);
3798 /* phys_bytes_per_sector_atomic */
3799 SIVAL(pdata, 4, bytes_per_sector);
3800 /* phys_bytes_per_sector_perf */
3801 SIVAL(pdata, 8, bytes_per_sector);
3802 /* fs_effective_phys_bytes_per_sector_atomic */
3803 SIVAL(pdata, 12, bytes_per_sector);
3805 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3806 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3807 /* byte_off_sector_align */
3808 SIVAL(pdata, 20, 0);
3809 /* byte_off_partition_align */
3810 SIVAL(pdata, 24, 0);
3811 *fixed_portion = 28;
3817 * Query the version and capabilities of the CIFS UNIX extensions
3821 case SMB_QUERY_CIFS_UNIX_INFO:
3823 bool large_write = lp_min_receive_file_size() &&
3824 !srv_is_signing_active(xconn);
3825 bool large_read = !srv_is_signing_active(xconn);
3826 int encrypt_caps = 0;
3828 if (!lp_unix_extensions()) {
3829 return NT_STATUS_INVALID_LEVEL;
3832 switch (conn->encrypt_level) {
3833 case SMB_SIGNING_OFF:
3836 case SMB_SIGNING_DESIRED:
3837 case SMB_SIGNING_IF_REQUIRED:
3838 case SMB_SIGNING_DEFAULT:
3839 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3841 case SMB_SIGNING_REQUIRED:
3842 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3843 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3844 large_write = false;
3850 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3851 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3853 /* We have POSIX ACLs, pathname, encryption,
3854 * large read/write, and locking capability. */
3856 SBIG_UINT(pdata,4,((uint64_t)(
3857 CIFS_UNIX_POSIX_ACLS_CAP|
3858 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3859 CIFS_UNIX_FCNTL_LOCKS_CAP|
3860 CIFS_UNIX_EXTATTR_CAP|
3861 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3863 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3865 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3869 case SMB_QUERY_POSIX_FS_INFO:
3872 vfs_statvfs_struct svfs;
3874 if (!lp_unix_extensions()) {
3875 return NT_STATUS_INVALID_LEVEL;
3878 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3882 SIVAL(pdata,0,svfs.OptimalTransferSize);
3883 SIVAL(pdata,4,svfs.BlockSize);
3884 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3885 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3886 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3887 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3888 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3889 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3890 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3892 } else if (rc == EOPNOTSUPP) {
3893 return NT_STATUS_INVALID_LEVEL;
3894 #endif /* EOPNOTSUPP */
3896 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3897 return NT_STATUS_DOS(ERRSRV, ERRerror);
3902 case SMB_QUERY_POSIX_WHOAMI:
3908 if (!lp_unix_extensions()) {
3909 return NT_STATUS_INVALID_LEVEL;
3912 if (max_data_bytes < 40) {
3913 return NT_STATUS_BUFFER_TOO_SMALL;
3916 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3917 flags |= SMB_WHOAMI_GUEST;
3920 /* NOTE: 8 bytes for UID/GID, irrespective of native
3921 * platform size. This matches
3922 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3924 data_len = 4 /* flags */
3931 + 4 /* pad/reserved */
3932 + (conn->session_info->unix_token->ngroups * 8)
3934 + (conn->session_info->security_token->num_sids *
3938 SIVAL(pdata, 0, flags);
3939 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3941 (uint64_t)conn->session_info->unix_token->uid);
3942 SBIG_UINT(pdata, 16,
3943 (uint64_t)conn->session_info->unix_token->gid);
3946 if (data_len >= max_data_bytes) {
3947 /* Potential overflow, skip the GIDs and SIDs. */
3949 SIVAL(pdata, 24, 0); /* num_groups */
3950 SIVAL(pdata, 28, 0); /* num_sids */
3951 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3952 SIVAL(pdata, 36, 0); /* reserved */
3958 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3959 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3961 /* We walk the SID list twice, but this call is fairly
3962 * infrequent, and I don't expect that it's performance
3963 * sensitive -- jpeach
3965 for (i = 0, sid_bytes = 0;
3966 i < conn->session_info->security_token->num_sids; ++i) {
3967 sid_bytes += ndr_size_dom_sid(
3968 &conn->session_info->security_token->sids[i],
3972 /* SID list byte count */
3973 SIVAL(pdata, 32, sid_bytes);
3975 /* 4 bytes pad/reserved - must be zero */
3976 SIVAL(pdata, 36, 0);
3980 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3981 SBIG_UINT(pdata, data_len,
3982 (uint64_t)conn->session_info->unix_token->groups[i]);
3988 i < conn->session_info->security_token->num_sids; ++i) {
3989 int sid_len = ndr_size_dom_sid(
3990 &conn->session_info->security_token->sids[i],
3993 sid_linearize((uint8_t *)(pdata + data_len),
3995 &conn->session_info->security_token->sids[i]);
3996 data_len += sid_len;
4002 case SMB_MAC_QUERY_FS_INFO:
4004 * Thursby MAC extension... ONLY on NTFS filesystems
4005 * once we do streams then we don't need this
4007 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4009 SIVAL(pdata,84,0x100); /* Don't support mac... */
4014 return NT_STATUS_INVALID_LEVEL;
4017 *ret_data_len = data_len;
4021 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4022 struct smb_request *req,
4024 const DATA_BLOB *qdata)
4027 SMB_NTQUOTA_STRUCT quotas;
4029 ZERO_STRUCT(quotas);
4032 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4033 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4034 lp_servicename(talloc_tos(), SNUM(conn)),
4035 conn->session_info->unix_info->unix_name));
4036 return NT_STATUS_ACCESS_DENIED;
4039 if (!check_fsp_ntquota_handle(conn, req,
4041 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4042 return NT_STATUS_INVALID_HANDLE;
4045 /* note: normally there're 48 bytes,
4046 * but we didn't use the last 6 bytes for now
4049 if (qdata->length < 42) {
4050 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4051 (unsigned int)qdata->length));
4052 return NT_STATUS_INVALID_PARAMETER;
4055 /* unknown_1 24 NULL bytes in pdata*/
4057 /* the soft quotas 8 bytes (uint64_t)*/
4058 quotas.softlim = BVAL(qdata->data,24);
4060 /* the hard quotas 8 bytes (uint64_t)*/
4061 quotas.hardlim = BVAL(qdata->data,32);
4063 /* quota_flags 2 bytes **/
4064 quotas.qflags = SVAL(qdata->data,40);
4066 /* unknown_2 6 NULL bytes follow*/
4068 /* now set the quotas */
4069 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4070 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4071 lp_servicename(talloc_tos(), SNUM(conn))));
4072 status = map_nt_error_from_unix(errno);
4074 status = NT_STATUS_OK;
4079 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4080 struct smb_request *req,
4081 TALLOC_CTX *mem_ctx,
4082 uint16_t info_level,
4084 const DATA_BLOB *pdata)
4086 switch (info_level) {
4087 case SMB_FS_QUOTA_INFORMATION:
4089 return smb_set_fsquota(conn,
4098 return NT_STATUS_INVALID_LEVEL;
4101 /****************************************************************************
4102 Reply to a TRANS2_QFSINFO (query filesystem info).
4103 ****************************************************************************/
4105 static void call_trans2qfsinfo(connection_struct *conn,
4106 struct smb_request *req,
4107 char **pparams, int total_params,
4108 char **ppdata, int total_data,
4109 unsigned int max_data_bytes)
4111 char *params = *pparams;
4112 uint16_t info_level;
4114 size_t fixed_portion;
4117 if (total_params < 2) {
4118 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4122 info_level = SVAL(params,0);
4124 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4125 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4126 DEBUG(0,("call_trans2qfsinfo: encryption required "
4127 "and info level 0x%x sent.\n",
4128 (unsigned int)info_level));
4129 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4134 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4136 status = smbd_do_qfsinfo(req->xconn, conn, req,
4143 if (!NT_STATUS_IS_OK(status)) {
4144 reply_nterror(req, status);
4148 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4151 DEBUG( 4, ( "%s info_level = %d\n",
4152 smb_fn_name(req->cmd), info_level) );
4157 /****************************************************************************
4158 Reply to a TRANS2_SETFSINFO (set filesystem info).
4159 ****************************************************************************/
4161 static void call_trans2setfsinfo(connection_struct *conn,
4162 struct smb_request *req,
4163 char **pparams, int total_params,
4164 char **ppdata, int total_data,
4165 unsigned int max_data_bytes)
4167 struct smbXsrv_connection *xconn = req->xconn;
4168 char *pdata = *ppdata;
4169 char *params = *pparams;
4170 uint16_t info_level;
4172 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4173 lp_servicename(talloc_tos(), SNUM(conn))));
4176 if (total_params < 4) {
4177 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4183 info_level = SVAL(params,2);
4186 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4187 info_level != SMB_SET_CIFS_UNIX_INFO) {
4188 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4189 "info level (0x%x) on IPC$.\n",
4190 (unsigned int)info_level));
4191 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4196 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4197 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4198 DEBUG(0,("call_trans2setfsinfo: encryption required "
4199 "and info level 0x%x sent.\n",
4200 (unsigned int)info_level));
4201 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4206 switch(info_level) {
4207 case SMB_SET_CIFS_UNIX_INFO:
4208 if (!lp_unix_extensions()) {
4209 DEBUG(2,("call_trans2setfsinfo: "
4210 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4211 "unix extensions off\n"));
4213 NT_STATUS_INVALID_LEVEL);
4217 /* There should be 12 bytes of capabilities set. */
4218 if (total_data < 12) {
4221 NT_STATUS_INVALID_PARAMETER);
4224 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4225 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4226 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4227 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4228 /* Just print these values for now. */
4229 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4230 "major = %u, minor = %u cap_low = 0x%x, "
4232 (unsigned int)xconn->
4233 smb1.unix_info.client_major,
4234 (unsigned int)xconn->
4235 smb1.unix_info.client_minor,
4236 (unsigned int)xconn->
4237 smb1.unix_info.client_cap_low,
4238 (unsigned int)xconn->
4239 smb1.unix_info.client_cap_high));
4241 /* Here is where we must switch to posix pathname processing... */
4242 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4243 lp_set_posix_pathnames();
4244 mangle_change_to_posix();
4247 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4248 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4249 /* Client that knows how to do posix locks,
4250 * but not posix open/mkdir operations. Set a
4251 * default type for read/write checks. */
4253 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4258 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4261 size_t param_len = 0;
4262 size_t data_len = total_data;
4264 if (!lp_unix_extensions()) {
4267 NT_STATUS_INVALID_LEVEL);
4271 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4274 NT_STATUS_NOT_SUPPORTED);
4278 if (xconn->smb1.echo_handler.trusted_fde) {
4279 DEBUG( 2,("call_trans2setfsinfo: "
4280 "request transport encryption disabled"
4281 "with 'fork echo handler = yes'\n"));
4284 NT_STATUS_NOT_SUPPORTED);
4288 DEBUG( 4,("call_trans2setfsinfo: "
4289 "request transport encryption.\n"));
4291 status = srv_request_encryption_setup(conn,
4292 (unsigned char **)ppdata,
4294 (unsigned char **)pparams,
4297 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4298 !NT_STATUS_IS_OK(status)) {
4299 reply_nterror(req, status);
4303 send_trans2_replies(conn, req,
4311 if (NT_STATUS_IS_OK(status)) {
4312 /* Server-side transport
4313 * encryption is now *on*. */
4314 status = srv_encryption_start(conn);
4315 if (!NT_STATUS_IS_OK(status)) {
4316 char *reason = talloc_asprintf(talloc_tos(),
4317 "Failure in setting "
4318 "up encrypted transport: %s",
4320 exit_server_cleanly(reason);
4326 case SMB_FS_QUOTA_INFORMATION:
4330 .data = (uint8_t *)pdata,
4331 .length = total_data
4333 files_struct *fsp = NULL;
4334 fsp = file_fsp(req, SVAL(params,0));
4336 status = smb_set_fsquota(conn,
4340 if (!NT_STATUS_IS_OK(status)) {
4341 reply_nterror(req, status);
4347 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4349 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4355 * sending this reply works fine,
4356 * but I'm not sure it's the same
4357 * like windows do...
4360 reply_outbuf(req, 10, 0);
4363 #if defined(HAVE_POSIX_ACLS)
4364 /****************************************************************************
4365 Utility function to count the number of entries in a POSIX acl.
4366 ****************************************************************************/
4368 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4370 unsigned int ace_count = 0;
4371 int entry_id = SMB_ACL_FIRST_ENTRY;
4372 SMB_ACL_ENTRY_T entry;
4374 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4376 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4377 entry_id = SMB_ACL_NEXT_ENTRY;
4384 /****************************************************************************
4385 Utility function to marshall a POSIX acl into wire format.
4386 ****************************************************************************/
4388 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4390 int entry_id = SMB_ACL_FIRST_ENTRY;
4391 SMB_ACL_ENTRY_T entry;
4393 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4394 SMB_ACL_TAG_T tagtype;
4395 SMB_ACL_PERMSET_T permset;
4396 unsigned char perms = 0;
4397 unsigned int own_grp;
4400 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4401 entry_id = SMB_ACL_NEXT_ENTRY;
4404 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4405 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4409 if (sys_acl_get_permset(entry, &permset) == -1) {
4410 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4414 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4415 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4416 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4418 SCVAL(pdata,1,perms);
4421 case SMB_ACL_USER_OBJ:
4422 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4423 own_grp = (unsigned int)pst->st_ex_uid;
4424 SIVAL(pdata,2,own_grp);
4429 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4431 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4434 own_grp = (unsigned int)*puid;
4435 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4436 SIVAL(pdata,2,own_grp);
4440 case SMB_ACL_GROUP_OBJ:
4441 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4442 own_grp = (unsigned int)pst->st_ex_gid;
4443 SIVAL(pdata,2,own_grp);
4448 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4450 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4453 own_grp = (unsigned int)*pgid;
4454 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4455 SIVAL(pdata,2,own_grp);
4460 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4461 SIVAL(pdata,2,0xFFFFFFFF);
4462 SIVAL(pdata,6,0xFFFFFFFF);
4465 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4466 SIVAL(pdata,2,0xFFFFFFFF);
4467 SIVAL(pdata,6,0xFFFFFFFF);
4470 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4473 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4480 /****************************************************************************
4481 Store the FILE_UNIX_BASIC info.
4482 ****************************************************************************/
4484 static char *store_file_unix_basic(connection_struct *conn,
4487 const SMB_STRUCT_STAT *psbuf)
4489 uint64_t file_index = get_FileIndex(conn, psbuf);
4492 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4493 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4495 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4498 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4501 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4502 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4503 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4506 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4510 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4514 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4517 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4518 devno = psbuf->st_ex_rdev;
4520 devno = psbuf->st_ex_dev;
4523 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4527 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4531 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4534 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4538 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4545 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4546 * the chflags(2) (or equivalent) flags.
4548 * XXX: this really should be behind the VFS interface. To do this, we would
4549 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4550 * Each VFS module could then implement its own mapping as appropriate for the
4551 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4553 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4557 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4561 { UF_IMMUTABLE, EXT_IMMUTABLE },
4565 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4569 { UF_HIDDEN, EXT_HIDDEN },
4572 /* Do not remove. We need to guarantee that this array has at least one
4573 * entry to build on HP-UX.
4579 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4580 uint32_t *smb_fflags, uint32_t *smb_fmask)
4584 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4585 *smb_fmask |= info2_flags_map[i].smb_fflag;
4586 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4587 *smb_fflags |= info2_flags_map[i].smb_fflag;
4592 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4593 const uint32_t smb_fflags,
4594 const uint32_t smb_fmask,
4597 uint32_t max_fmask = 0;
4600 *stat_fflags = psbuf->st_ex_flags;
4602 /* For each flags requested in smb_fmask, check the state of the
4603 * corresponding flag in smb_fflags and set or clear the matching
4607 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4608 max_fmask |= info2_flags_map[i].smb_fflag;
4609 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4610 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4611 *stat_fflags |= info2_flags_map[i].stat_fflag;
4613 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4618 /* If smb_fmask is asking to set any bits that are not supported by
4619 * our flag mappings, we should fail.
4621 if ((smb_fmask & max_fmask) != smb_fmask) {
4629 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4630 * of file flags and birth (create) time.
4632 static char *store_file_unix_basic_info2(connection_struct *conn,
4635 const SMB_STRUCT_STAT *psbuf)
4637 uint32_t file_flags = 0;
4638 uint32_t flags_mask = 0;
4640 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4642 /* Create (birth) time 64 bit */
4643 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4646 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4647 SIVAL(pdata, 0, file_flags); /* flags */
4648 SIVAL(pdata, 4, flags_mask); /* mask */
4654 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4655 const struct stream_struct *streams,
4657 unsigned int max_data_bytes,
4658 unsigned int *data_size)
4661 unsigned int ofs = 0;
4663 if (max_data_bytes < 32) {
4664 return NT_STATUS_INFO_LENGTH_MISMATCH;
4667 for (i = 0; i < num_streams; i++) {
4668 unsigned int next_offset;
4670 smb_ucs2_t *namebuf;
4672 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4673 streams[i].name, &namelen) ||
4676 return NT_STATUS_INVALID_PARAMETER;
4680 * name_buf is now null-terminated, we need to marshall as not
4687 * We cannot overflow ...
4689 if ((ofs + 24 + namelen) > max_data_bytes) {
4690 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4692 TALLOC_FREE(namebuf);
4693 return STATUS_BUFFER_OVERFLOW;
4696 SIVAL(data, ofs+4, namelen);
4697 SOFF_T(data, ofs+8, streams[i].size);
4698 SOFF_T(data, ofs+16, streams[i].alloc_size);
4699 memcpy(data+ofs+24, namebuf, namelen);
4700 TALLOC_FREE(namebuf);
4702 next_offset = ofs + 24 + namelen;
4704 if (i == num_streams-1) {
4705 SIVAL(data, ofs, 0);
4708 unsigned int align = ndr_align_size(next_offset, 8);
4710 if ((next_offset + align) > max_data_bytes) {
4711 DEBUG(10, ("refusing to overflow align "
4712 "reply at stream %u\n",
4714 TALLOC_FREE(namebuf);
4715 return STATUS_BUFFER_OVERFLOW;
4718 memset(data+next_offset, 0, align);
4719 next_offset += align;
4721 SIVAL(data, ofs, next_offset - ofs);
4728 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4732 return NT_STATUS_OK;
4735 /****************************************************************************
4736 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4737 ****************************************************************************/
4739 static void call_trans2qpipeinfo(connection_struct *conn,
4740 struct smb_request *req,
4741 unsigned int tran_call,
4742 char **pparams, int total_params,
4743 char **ppdata, int total_data,
4744 unsigned int max_data_bytes)
4746 char *params = *pparams;
4747 char *pdata = *ppdata;
4748 unsigned int data_size = 0;
4749 unsigned int param_size = 2;
4750 uint16_t info_level;
4754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4758 if (total_params < 4) {
4759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4763 fsp = file_fsp(req, SVAL(params,0));
4764 if (!fsp_is_np(fsp)) {
4765 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4769 info_level = SVAL(params,2);
4771 *pparams = (char *)SMB_REALLOC(*pparams,2);
4772 if (*pparams == NULL) {
4773 reply_nterror(req, NT_STATUS_NO_MEMORY);
4778 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4779 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4782 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4783 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4784 if (*ppdata == NULL ) {
4785 reply_nterror(req, NT_STATUS_NO_MEMORY);
4790 switch (info_level) {
4791 case SMB_FILE_STANDARD_INFORMATION:
4793 SOFF_T(pdata,0,4096LL);
4800 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4804 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4810 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4811 TALLOC_CTX *mem_ctx,
4812 uint16_t info_level,
4814 struct smb_filename *smb_fname,
4815 bool delete_pending,
4816 struct timespec write_time_ts,
4817 struct ea_list *ea_list,
4818 int lock_data_count,
4821 unsigned int max_data_bytes,
4822 size_t *fixed_portion,
4824 unsigned int *pdata_size)
4826 char *pdata = *ppdata;
4827 char *dstart, *dend;
4828 unsigned int data_size;
4829 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4830 time_t create_time, mtime, atime, c_time;
4831 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4838 uint64_t file_size = 0;
4840 uint64_t allocation_size = 0;
4841 uint64_t file_index = 0;
4842 uint32_t access_mask = 0;
4845 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4846 return NT_STATUS_INVALID_LEVEL;
4849 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4850 smb_fname_str_dbg(smb_fname),
4852 info_level, max_data_bytes));
4854 mode = dos_mode(conn, smb_fname);
4855 nlink = psbuf->st_ex_nlink;
4857 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4861 if ((nlink > 0) && delete_pending) {
4865 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4866 return NT_STATUS_INVALID_PARAMETER;
4869 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4870 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4871 if (*ppdata == NULL) {
4872 return NT_STATUS_NO_MEMORY;
4876 dend = dstart + data_size - 1;
4878 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4879 update_stat_ex_mtime(psbuf, write_time_ts);
4882 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4883 mtime_ts = psbuf->st_ex_mtime;
4884 atime_ts = psbuf->st_ex_atime;
4885 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4887 if (lp_dos_filetime_resolution(SNUM(conn))) {
4888 dos_filetime_timespec(&create_time_ts);
4889 dos_filetime_timespec(&mtime_ts);
4890 dos_filetime_timespec(&atime_ts);
4891 dos_filetime_timespec(&ctime_ts);
4894 create_time = convert_timespec_to_time_t(create_time_ts);
4895 mtime = convert_timespec_to_time_t(mtime_ts);
4896 atime = convert_timespec_to_time_t(atime_ts);
4897 c_time = convert_timespec_to_time_t(ctime_ts);
4899 p = strrchr_m(smb_fname->base_name,'/');
4901 base_name = smb_fname->base_name;
4905 /* NT expects the name to be in an exact form of the *full*
4906 filename. See the trans2 torture test */
4907 if (ISDOT(base_name)) {
4908 dos_fname = talloc_strdup(mem_ctx, "\\");
4910 return NT_STATUS_NO_MEMORY;
4913 dos_fname = talloc_asprintf(mem_ctx,
4915 smb_fname->base_name);
4917 return NT_STATUS_NO_MEMORY;
4919 if (is_ntfs_stream_smb_fname(smb_fname)) {
4920 dos_fname = talloc_asprintf(dos_fname, "%s",
4921 smb_fname->stream_name);
4923 return NT_STATUS_NO_MEMORY;
4927 string_replace(dos_fname, '/', '\\');
4930 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4933 /* Do we have this path open ? */
4935 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4936 fsp1 = file_find_di_first(conn->sconn, fileid);
4937 if (fsp1 && fsp1->initial_allocation_size) {
4938 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4942 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4943 file_size = get_file_size_stat(psbuf);
4947 pos = fsp->fh->position_information;
4951 access_mask = fsp->access_mask;
4953 /* GENERIC_EXECUTE mapping from Windows */
4954 access_mask = 0x12019F;
4957 /* This should be an index number - looks like
4960 I think this causes us to fail the IFSKIT
4961 BasicFileInformationTest. -tpot */
4962 file_index = get_FileIndex(conn, psbuf);
4966 switch (info_level) {
4967 case SMB_INFO_STANDARD:
4968 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4970 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4971 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4972 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4973 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4974 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4975 SSVAL(pdata,l1_attrFile,mode);
4978 case SMB_INFO_QUERY_EA_SIZE:
4980 unsigned int ea_size =
4981 estimate_ea_size(conn, fsp,
4983 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4985 srv_put_dos_date2(pdata,0,create_time);
4986 srv_put_dos_date2(pdata,4,atime);
4987 srv_put_dos_date2(pdata,8,mtime); /* write time */
4988 SIVAL(pdata,12,(uint32_t)file_size);
4989 SIVAL(pdata,16,(uint32_t)allocation_size);
4990 SSVAL(pdata,20,mode);
4991 SIVAL(pdata,22,ea_size);
4995 case SMB_INFO_IS_NAME_VALID:
4996 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4998 /* os/2 needs this ? really ?*/
4999 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5001 /* This is only reached for qpathinfo */
5005 case SMB_INFO_QUERY_EAS_FROM_LIST:
5007 size_t total_ea_len = 0;
5008 struct ea_list *ea_file_list = NULL;
5009 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5012 get_ea_list_from_file(mem_ctx, conn, fsp,
5014 &total_ea_len, &ea_file_list);
5015 if (!NT_STATUS_IS_OK(status)) {
5019 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5021 if (!ea_list || (total_ea_len > data_size)) {
5023 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5027 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5031 case SMB_INFO_QUERY_ALL_EAS:
5033 /* We have data_size bytes to put EA's into. */
5034 size_t total_ea_len = 0;
5035 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5037 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5039 &total_ea_len, &ea_list);
5040 if (!NT_STATUS_IS_OK(status)) {
5044 if (!ea_list || (total_ea_len > data_size)) {
5046 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5050 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5054 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5056 /* This is FileFullEaInformation - 0xF which maps to
5057 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5059 /* We have data_size bytes to put EA's into. */
5060 size_t total_ea_len = 0;
5061 struct ea_list *ea_file_list = NULL;
5063 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5065 /*TODO: add filtering and index handling */
5068 get_ea_list_from_file(mem_ctx, conn, fsp,
5070 &total_ea_len, &ea_file_list);
5071 if (!NT_STATUS_IS_OK(status)) {
5074 if (!ea_file_list) {
5075 return NT_STATUS_NO_EAS_ON_FILE;
5078 status = fill_ea_chained_buffer(mem_ctx,
5082 conn, ea_file_list);
5083 if (!NT_STATUS_IS_OK(status)) {
5089 case SMB_FILE_BASIC_INFORMATION:
5090 case SMB_QUERY_FILE_BASIC_INFO:
5092 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5093 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5094 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5096 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5100 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5101 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5102 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5103 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5104 SIVAL(pdata,32,mode);
5106 DEBUG(5,("SMB_QFBI - "));
5107 DEBUG(5,("create: %s ", ctime(&create_time)));
5108 DEBUG(5,("access: %s ", ctime(&atime)));
5109 DEBUG(5,("write: %s ", ctime(&mtime)));
5110 DEBUG(5,("change: %s ", ctime(&c_time)));
5111 DEBUG(5,("mode: %x\n", mode));
5112 *fixed_portion = data_size;
5115 case SMB_FILE_STANDARD_INFORMATION:
5116 case SMB_QUERY_FILE_STANDARD_INFO:
5118 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5120 SOFF_T(pdata,0,allocation_size);
5121 SOFF_T(pdata,8,file_size);
5122 SIVAL(pdata,16,nlink);
5123 SCVAL(pdata,20,delete_pending?1:0);
5124 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5125 SSVAL(pdata,22,0); /* Padding. */
5126 *fixed_portion = 24;
5129 case SMB_FILE_EA_INFORMATION:
5130 case SMB_QUERY_FILE_EA_INFO:
5132 unsigned int ea_size =
5133 estimate_ea_size(conn, fsp, smb_fname);
5134 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5137 SIVAL(pdata,0,ea_size);
5141 /* Get the 8.3 name - used if NT SMB was negotiated. */
5142 case SMB_QUERY_FILE_ALT_NAME_INFO:
5143 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5145 char mangled_name[13];
5146 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5147 if (!name_to_8_3(base_name,mangled_name,
5148 True,conn->params)) {
5149 return NT_STATUS_NO_MEMORY;
5151 status = srvstr_push(dstart, flags2,
5152 pdata+4, mangled_name,
5153 PTR_DIFF(dend, pdata+4),
5155 if (!NT_STATUS_IS_OK(status)) {
5158 data_size = 4 + len;
5164 case SMB_QUERY_FILE_NAME_INFO:
5167 this must be *exactly* right for ACLs on mapped drives to work
5169 status = srvstr_push(dstart, flags2,
5171 PTR_DIFF(dend, pdata+4),
5173 if (!NT_STATUS_IS_OK(status)) {
5176 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5177 data_size = 4 + len;
5182 case SMB_FILE_ALLOCATION_INFORMATION:
5183 case SMB_QUERY_FILE_ALLOCATION_INFO:
5184 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5186 SOFF_T(pdata,0,allocation_size);
5189 case SMB_FILE_END_OF_FILE_INFORMATION:
5190 case SMB_QUERY_FILE_END_OF_FILEINFO:
5191 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5193 SOFF_T(pdata,0,file_size);
5196 case SMB_QUERY_FILE_ALL_INFO:
5197 case SMB_FILE_ALL_INFORMATION:
5199 unsigned int ea_size =
5200 estimate_ea_size(conn, fsp, smb_fname);
5201 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5202 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5203 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5204 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5205 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5206 SIVAL(pdata,32,mode);
5207 SIVAL(pdata,36,0); /* padding. */
5209 SOFF_T(pdata,0,allocation_size);
5210 SOFF_T(pdata,8,file_size);
5211 SIVAL(pdata,16,nlink);
5212 SCVAL(pdata,20,delete_pending);
5213 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5216 SIVAL(pdata,0,ea_size);
5217 pdata += 4; /* EA info */
5218 status = srvstr_push(dstart, flags2,
5220 PTR_DIFF(dend, pdata+4),
5222 if (!NT_STATUS_IS_OK(status)) {
5227 data_size = PTR_DIFF(pdata,(*ppdata));
5228 *fixed_portion = 10;
5232 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5234 unsigned int ea_size =
5235 estimate_ea_size(conn, fsp, smb_fname);
5236 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5237 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5238 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5239 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5240 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5241 SIVAL(pdata, 0x20, mode);
5242 SIVAL(pdata, 0x24, 0); /* padding. */
5243 SBVAL(pdata, 0x28, allocation_size);
5244 SBVAL(pdata, 0x30, file_size);
5245 SIVAL(pdata, 0x38, nlink);
5246 SCVAL(pdata, 0x3C, delete_pending);
5247 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5248 SSVAL(pdata, 0x3E, 0); /* padding */
5249 SBVAL(pdata, 0x40, file_index);
5250 SIVAL(pdata, 0x48, ea_size);
5251 SIVAL(pdata, 0x4C, access_mask);
5252 SBVAL(pdata, 0x50, pos);
5253 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5254 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5258 status = srvstr_push(dstart, flags2,
5260 PTR_DIFF(dend, pdata+4),
5262 if (!NT_STATUS_IS_OK(status)) {
5267 data_size = PTR_DIFF(pdata,(*ppdata));
5268 *fixed_portion = 104;
5271 case SMB_FILE_INTERNAL_INFORMATION:
5273 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5274 SBVAL(pdata, 0, file_index);
5279 case SMB_FILE_ACCESS_INFORMATION:
5280 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5281 SIVAL(pdata, 0, access_mask);
5286 case SMB_FILE_NAME_INFORMATION:
5287 /* Pathname with leading '\'. */
5290 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5291 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5292 SIVAL(pdata,0,byte_len);
5293 data_size = 4 + byte_len;
5297 case SMB_FILE_DISPOSITION_INFORMATION:
5298 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5300 SCVAL(pdata,0,delete_pending);
5304 case SMB_FILE_POSITION_INFORMATION:
5305 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5307 SOFF_T(pdata,0,pos);
5311 case SMB_FILE_MODE_INFORMATION:
5312 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5313 SIVAL(pdata,0,mode);
5318 case SMB_FILE_ALIGNMENT_INFORMATION:
5319 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5320 SIVAL(pdata,0,0); /* No alignment needed. */
5326 * NT4 server just returns "invalid query" to this - if we try
5327 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5330 /* The first statement above is false - verified using Thursby
5331 * client against NT4 -- gcolley.
5333 case SMB_QUERY_FILE_STREAM_INFO:
5334 case SMB_FILE_STREAM_INFORMATION: {
5335 unsigned int num_streams = 0;
5336 struct stream_struct *streams = NULL;
5338 DEBUG(10,("smbd_do_qfilepathinfo: "
5339 "SMB_FILE_STREAM_INFORMATION\n"));
5341 if (is_ntfs_stream_smb_fname(smb_fname)) {
5342 return NT_STATUS_INVALID_PARAMETER;
5345 status = vfs_streaminfo(conn,
5352 if (!NT_STATUS_IS_OK(status)) {
5353 DEBUG(10, ("could not get stream info: %s\n",
5354 nt_errstr(status)));
5358 status = marshall_stream_info(num_streams, streams,
5359 pdata, max_data_bytes,
5362 if (!NT_STATUS_IS_OK(status)) {
5363 DEBUG(10, ("marshall_stream_info failed: %s\n",
5364 nt_errstr(status)));
5365 TALLOC_FREE(streams);
5369 TALLOC_FREE(streams);
5371 *fixed_portion = 32;
5375 case SMB_QUERY_COMPRESSION_INFO:
5376 case SMB_FILE_COMPRESSION_INFORMATION:
5377 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5378 SOFF_T(pdata,0,file_size);
5379 SIVAL(pdata,8,0); /* ??? */
5380 SIVAL(pdata,12,0); /* ??? */
5382 *fixed_portion = 16;
5385 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5386 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5387 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5388 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5389 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5390 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5391 SOFF_T(pdata,32,allocation_size);
5392 SOFF_T(pdata,40,file_size);
5393 SIVAL(pdata,48,mode);
5394 SIVAL(pdata,52,0); /* ??? */
5396 *fixed_portion = 56;
5399 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5400 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5401 SIVAL(pdata,0,mode);
5408 * CIFS UNIX Extensions.
5411 case SMB_QUERY_FILE_UNIX_BASIC:
5413 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5414 data_size = PTR_DIFF(pdata,(*ppdata));
5416 DEBUG(4,("smbd_do_qfilepathinfo: "
5417 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5418 dump_data(4, (uint8_t *)(*ppdata), data_size);
5422 case SMB_QUERY_FILE_UNIX_INFO2:
5424 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5425 data_size = PTR_DIFF(pdata,(*ppdata));
5429 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5431 for (i=0; i<100; i++)
5432 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5438 case SMB_QUERY_FILE_UNIX_LINK:
5441 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5444 return NT_STATUS_NO_MEMORY;
5447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5449 if(!S_ISLNK(psbuf->st_ex_mode)) {
5450 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5453 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5455 link_len = SMB_VFS_READLINK(conn,
5456 smb_fname->base_name,
5458 if (link_len == -1) {
5459 return map_nt_error_from_unix(errno);
5461 buffer[link_len] = 0;
5462 status = srvstr_push(dstart, flags2,
5464 PTR_DIFF(dend, pdata),
5465 STR_TERMINATE, &len);
5466 if (!NT_STATUS_IS_OK(status)) {
5470 data_size = PTR_DIFF(pdata,(*ppdata));
5475 #if defined(HAVE_POSIX_ACLS)
5476 case SMB_QUERY_POSIX_ACL:
5478 SMB_ACL_T file_acl = NULL;
5479 SMB_ACL_T def_acl = NULL;
5480 uint16_t num_file_acls = 0;
5481 uint16_t num_def_acls = 0;
5483 status = refuse_symlink(conn,
5486 if (!NT_STATUS_IS_OK(status)) {
5490 if (fsp && fsp->fh->fd != -1) {
5491 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5495 SMB_VFS_SYS_ACL_GET_FILE(conn,
5496 smb_fname->base_name,
5497 SMB_ACL_TYPE_ACCESS,
5501 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5502 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5503 "not implemented on "
5504 "filesystem containing %s\n",
5505 smb_fname->base_name));
5506 return NT_STATUS_NOT_IMPLEMENTED;
5509 if (S_ISDIR(psbuf->st_ex_mode)) {
5510 if (fsp && fsp->is_directory) {
5512 SMB_VFS_SYS_ACL_GET_FILE(
5514 fsp->fsp_name->base_name,
5515 SMB_ACL_TYPE_DEFAULT,
5519 SMB_VFS_SYS_ACL_GET_FILE(
5521 smb_fname->base_name,
5522 SMB_ACL_TYPE_DEFAULT,
5525 def_acl = free_empty_sys_acl(conn, def_acl);
5528 num_file_acls = count_acl_entries(conn, file_acl);
5529 num_def_acls = count_acl_entries(conn, def_acl);
5531 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5532 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5534 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5535 SMB_POSIX_ACL_HEADER_SIZE) ));
5537 TALLOC_FREE(file_acl);
5540 TALLOC_FREE(def_acl);
5542 return NT_STATUS_BUFFER_TOO_SMALL;
5545 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5546 SSVAL(pdata,2,num_file_acls);
5547 SSVAL(pdata,4,num_def_acls);
5548 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5550 TALLOC_FREE(file_acl);
5553 TALLOC_FREE(def_acl);
5555 return NT_STATUS_INTERNAL_ERROR;
5557 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5559 TALLOC_FREE(file_acl);
5562 TALLOC_FREE(def_acl);
5564 return NT_STATUS_INTERNAL_ERROR;
5568 TALLOC_FREE(file_acl);
5571 TALLOC_FREE(def_acl);
5573 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5579 case SMB_QUERY_POSIX_LOCK:
5584 enum brl_type lock_type;
5586 /* We need an open file with a real fd for this. */
5587 if (!fsp || fsp->fh->fd == -1) {
5588 return NT_STATUS_INVALID_LEVEL;
5591 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5592 return NT_STATUS_INVALID_PARAMETER;
5595 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5596 case POSIX_LOCK_TYPE_READ:
5597 lock_type = READ_LOCK;
5599 case POSIX_LOCK_TYPE_WRITE:
5600 lock_type = WRITE_LOCK;
5602 case POSIX_LOCK_TYPE_UNLOCK:
5604 /* There's no point in asking for an unlock... */
5605 return NT_STATUS_INVALID_PARAMETER;
5608 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5609 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5610 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5612 status = query_lock(fsp,
5619 if (ERROR_WAS_LOCK_DENIED(status)) {
5620 /* Here we need to report who has it locked... */
5621 data_size = POSIX_LOCK_DATA_SIZE;
5623 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5624 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5625 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5626 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5627 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5629 } else if (NT_STATUS_IS_OK(status)) {
5630 /* For success we just return a copy of what we sent
5631 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5632 data_size = POSIX_LOCK_DATA_SIZE;
5633 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5634 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5642 return NT_STATUS_INVALID_LEVEL;
5645 *pdata_size = data_size;
5646 return NT_STATUS_OK;
5649 /****************************************************************************
5650 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5651 file name or file id).
5652 ****************************************************************************/
5654 static void call_trans2qfilepathinfo(connection_struct *conn,
5655 struct smb_request *req,
5656 unsigned int tran_call,
5657 char **pparams, int total_params,
5658 char **ppdata, int total_data,
5659 unsigned int max_data_bytes)
5661 char *params = *pparams;
5662 char *pdata = *ppdata;
5663 uint16_t info_level;
5664 unsigned int data_size = 0;
5665 unsigned int param_size = 2;
5666 struct smb_filename *smb_fname = NULL;
5667 bool delete_pending = False;
5668 struct timespec write_time_ts;
5669 files_struct *fsp = NULL;
5670 struct file_id fileid;
5671 struct ea_list *ea_list = NULL;
5672 int lock_data_count = 0;
5673 char *lock_data = NULL;
5674 size_t fixed_portion;
5675 NTSTATUS status = NT_STATUS_OK;
5678 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5682 ZERO_STRUCT(write_time_ts);
5684 if (tran_call == TRANSACT2_QFILEINFO) {
5685 if (total_params < 4) {
5686 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5691 call_trans2qpipeinfo(conn, req, tran_call,
5692 pparams, total_params,
5698 fsp = file_fsp(req, SVAL(params,0));
5699 info_level = SVAL(params,2);
5701 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5703 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5704 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5708 /* Initial check for valid fsp ptr. */
5709 if (!check_fsp_open(conn, req, fsp)) {
5713 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5714 if (smb_fname == NULL) {
5715 reply_nterror(req, NT_STATUS_NO_MEMORY);
5719 if(fsp->fake_file_handle) {
5721 * This is actually for the QUOTA_FAKE_FILE --metze
5724 /* We know this name is ok, it's already passed the checks. */
5726 } else if(fsp->fh->fd == -1) {
5728 * This is actually a QFILEINFO on a directory
5729 * handle (returned from an NT SMB). NT5.0 seems
5730 * to do this call. JRA.
5733 if (INFO_LEVEL_IS_UNIX(info_level)) {
5734 /* Always do lstat for UNIX calls. */
5735 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5736 DEBUG(3,("call_trans2qfilepathinfo: "
5737 "SMB_VFS_LSTAT of %s failed "
5739 smb_fname_str_dbg(smb_fname),
5742 map_nt_error_from_unix(errno));
5745 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5746 DEBUG(3,("call_trans2qfilepathinfo: "
5747 "SMB_VFS_STAT of %s failed (%s)\n",
5748 smb_fname_str_dbg(smb_fname),
5751 map_nt_error_from_unix(errno));
5755 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5756 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5759 * Original code - this is an open file.
5761 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5762 DEBUG(3, ("fstat of %s failed (%s)\n",
5763 fsp_fnum_dbg(fsp), strerror(errno)));
5765 map_nt_error_from_unix(errno));
5768 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5769 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5775 uint32_t ucf_flags = (req->posix_pathnames ?
5776 UCF_POSIX_PATHNAMES : 0);
5779 if (total_params < 7) {
5780 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5784 info_level = SVAL(params,0);
5786 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5788 if (INFO_LEVEL_IS_UNIX(info_level)) {
5789 if (!lp_unix_extensions()) {
5790 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5793 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5794 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5795 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5796 req->posix_pathnames) {
5797 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5801 if (req->posix_pathnames) {
5802 srvstr_get_path_posix(req,
5811 srvstr_get_path(req,
5820 if (!NT_STATUS_IS_OK(status)) {
5821 reply_nterror(req, status);
5825 status = filename_convert(req,
5827 req->flags2 & FLAGS2_DFS_PATHNAMES,
5832 if (!NT_STATUS_IS_OK(status)) {
5833 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5834 reply_botherror(req,
5835 NT_STATUS_PATH_NOT_COVERED,
5836 ERRSRV, ERRbadpath);
5839 reply_nterror(req, status);
5843 /* If this is a stream, check if there is a delete_pending. */
5844 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5845 && is_ntfs_stream_smb_fname(smb_fname)) {
5846 struct smb_filename *smb_fname_base;
5848 /* Create an smb_filename with stream_name == NULL. */
5849 smb_fname_base = synthetic_smb_fname(
5851 smb_fname->base_name,
5855 if (smb_fname_base == NULL) {
5856 reply_nterror(req, NT_STATUS_NO_MEMORY);
5860 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5861 /* Always do lstat for UNIX calls. */
5862 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5863 DEBUG(3,("call_trans2qfilepathinfo: "
5864 "SMB_VFS_LSTAT of %s failed "
5866 smb_fname_str_dbg(smb_fname_base),
5868 TALLOC_FREE(smb_fname_base);
5870 map_nt_error_from_unix(errno));
5874 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5875 DEBUG(3,("call_trans2qfilepathinfo: "
5876 "fileinfo of %s failed "
5878 smb_fname_str_dbg(smb_fname_base),
5880 TALLOC_FREE(smb_fname_base);
5882 map_nt_error_from_unix(errno));
5887 status = file_name_hash(conn,
5888 smb_fname_str_dbg(smb_fname_base),
5890 if (!NT_STATUS_IS_OK(status)) {
5891 TALLOC_FREE(smb_fname_base);
5892 reply_nterror(req, status);
5896 fileid = vfs_file_id_from_sbuf(conn,
5897 &smb_fname_base->st);
5898 TALLOC_FREE(smb_fname_base);
5899 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5900 if (delete_pending) {
5901 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5906 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5907 /* Always do lstat for UNIX calls. */
5908 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5909 DEBUG(3,("call_trans2qfilepathinfo: "
5910 "SMB_VFS_LSTAT of %s failed (%s)\n",
5911 smb_fname_str_dbg(smb_fname),
5914 map_nt_error_from_unix(errno));
5919 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5920 DEBUG(3,("call_trans2qfilepathinfo: "
5921 "SMB_VFS_STAT of %s failed (%s)\n",
5922 smb_fname_str_dbg(smb_fname),
5925 map_nt_error_from_unix(errno));
5930 status = file_name_hash(conn,
5931 smb_fname_str_dbg(smb_fname),
5933 if (!NT_STATUS_IS_OK(status)) {
5934 reply_nterror(req, status);
5938 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5939 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5940 if (delete_pending) {
5941 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5946 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5947 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5949 info_level,tran_call,total_data));
5951 /* Pull out any data sent here before we realloc. */
5952 switch (info_level) {
5953 case SMB_INFO_QUERY_EAS_FROM_LIST:
5955 /* Pull any EA list from the data portion. */
5958 if (total_data < 4) {
5960 req, NT_STATUS_INVALID_PARAMETER);
5963 ea_size = IVAL(pdata,0);
5965 if (total_data > 0 && ea_size != total_data) {
5966 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5967 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5969 req, NT_STATUS_INVALID_PARAMETER);
5973 if (!lp_ea_support(SNUM(conn))) {
5974 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5978 /* Pull out the list of names. */
5979 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5982 req, NT_STATUS_INVALID_PARAMETER);
5988 case SMB_QUERY_POSIX_LOCK:
5990 if (fsp == NULL || fsp->fh->fd == -1) {
5991 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5995 if (total_data != POSIX_LOCK_DATA_SIZE) {
5997 req, NT_STATUS_INVALID_PARAMETER);
6001 /* Copy the lock range data. */
6002 lock_data = (char *)talloc_memdup(
6003 req, pdata, total_data);
6005 reply_nterror(req, NT_STATUS_NO_MEMORY);
6008 lock_data_count = total_data;
6014 *pparams = (char *)SMB_REALLOC(*pparams,2);
6015 if (*pparams == NULL) {
6016 reply_nterror(req, NT_STATUS_NO_MEMORY);
6023 * draft-leach-cifs-v1-spec-02.txt
6024 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6027 * The requested information is placed in the Data portion of the
6028 * transaction response. For the information levels greater than 0x100,
6029 * the transaction response has 1 parameter word which should be
6030 * ignored by the client.
6032 * However Windows only follows this rule for the IS_NAME_VALID call.
6034 switch (info_level) {
6035 case SMB_INFO_IS_NAME_VALID:
6040 if ((info_level & 0xFF00) == 0xFF00) {
6042 * We use levels that start with 0xFF00
6043 * internally to represent SMB2 specific levels
6045 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6049 status = smbd_do_qfilepathinfo(conn, req, info_level,
6051 delete_pending, write_time_ts,
6053 lock_data_count, lock_data,
6054 req->flags2, max_data_bytes,
6056 ppdata, &data_size);
6057 if (!NT_STATUS_IS_OK(status)) {
6058 reply_nterror(req, status);
6061 if (fixed_portion > max_data_bytes) {
6062 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6066 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6072 /****************************************************************************
6073 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6075 ****************************************************************************/
6077 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6078 connection_struct *conn,
6079 struct smb_request *req,
6080 bool overwrite_if_exists,
6081 const struct smb_filename *smb_fname_old,
6082 struct smb_filename *smb_fname_new)
6084 NTSTATUS status = NT_STATUS_OK;
6086 /* source must already exist. */
6087 if (!VALID_STAT(smb_fname_old->st)) {
6088 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6091 if (VALID_STAT(smb_fname_new->st)) {
6092 if (overwrite_if_exists) {
6093 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6094 return NT_STATUS_FILE_IS_A_DIRECTORY;
6096 status = unlink_internals(conn,
6098 FILE_ATTRIBUTE_NORMAL,
6101 if (!NT_STATUS_IS_OK(status)) {
6105 /* Disallow if newname already exists. */
6106 return NT_STATUS_OBJECT_NAME_COLLISION;
6110 /* No links from a directory. */
6111 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6112 return NT_STATUS_FILE_IS_A_DIRECTORY;
6115 /* Setting a hardlink to/from a stream isn't currently supported. */
6116 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6117 is_ntfs_stream_smb_fname(smb_fname_new)) {
6118 return NT_STATUS_INVALID_PARAMETER;
6121 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6122 smb_fname_old->base_name, smb_fname_new->base_name));
6124 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
6125 smb_fname_new->base_name) != 0) {
6126 status = map_nt_error_from_unix(errno);
6127 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6128 nt_errstr(status), smb_fname_old->base_name,
6129 smb_fname_new->base_name));
6134 /****************************************************************************
6135 Deal with setting the time from any of the setfilepathinfo functions.
6136 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6137 calling this function.
6138 ****************************************************************************/
6140 NTSTATUS smb_set_file_time(connection_struct *conn,
6142 const struct smb_filename *smb_fname,
6143 struct smb_file_time *ft,
6144 bool setting_write_time)
6146 struct smb_filename smb_fname_base;
6148 FILE_NOTIFY_CHANGE_LAST_ACCESS
6149 |FILE_NOTIFY_CHANGE_LAST_WRITE
6150 |FILE_NOTIFY_CHANGE_CREATION;
6152 if (!VALID_STAT(smb_fname->st)) {
6153 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6156 /* get some defaults (no modifications) if any info is zero or -1. */
6157 if (null_timespec(ft->create_time)) {
6158 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6161 if (null_timespec(ft->atime)) {
6162 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6165 if (null_timespec(ft->mtime)) {
6166 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6169 if (!setting_write_time) {
6170 /* ft->mtime comes from change time, not write time. */
6171 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6174 /* Ensure the resolution is the correct for
6175 * what we can store on this filesystem. */
6177 round_timespec(conn->ts_res, &ft->create_time);
6178 round_timespec(conn->ts_res, &ft->ctime);
6179 round_timespec(conn->ts_res, &ft->atime);
6180 round_timespec(conn->ts_res, &ft->mtime);
6182 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6183 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6184 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6185 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6186 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6187 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6188 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6189 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6191 if (setting_write_time) {
6193 * This was a Windows setfileinfo on an open file.
6194 * NT does this a lot. We also need to
6195 * set the time here, as it can be read by
6196 * FindFirst/FindNext and with the patch for bug #2045
6197 * in smbd/fileio.c it ensures that this timestamp is
6198 * kept sticky even after a write. We save the request
6199 * away and will set it on file close and after a write. JRA.
6202 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6203 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6206 if (fsp->base_fsp) {
6207 set_sticky_write_time_fsp(fsp->base_fsp,
6210 set_sticky_write_time_fsp(fsp, ft->mtime);
6213 set_sticky_write_time_path(
6214 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6219 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6221 /* Always call ntimes on the base, even if a stream was passed in. */
6222 smb_fname_base = *smb_fname;
6223 smb_fname_base.stream_name = NULL;
6225 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6226 return map_nt_error_from_unix(errno);
6229 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6230 smb_fname->base_name);
6231 return NT_STATUS_OK;
6234 /****************************************************************************
6235 Deal with setting the dosmode from any of the setfilepathinfo functions.
6236 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6237 done before calling this function.
6238 ****************************************************************************/
6240 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6241 const struct smb_filename *smb_fname,
6244 struct smb_filename *smb_fname_base;
6247 if (!VALID_STAT(smb_fname->st)) {
6248 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6251 /* Always operate on the base_name, even if a stream was passed in. */
6252 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6253 smb_fname->base_name,
6257 if (smb_fname_base == NULL) {
6258 return NT_STATUS_NO_MEMORY;
6262 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6263 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6265 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6269 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6271 /* check the mode isn't different, before changing it */
6272 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6273 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6274 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6275 (unsigned int)dosmode));
6277 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6279 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6281 smb_fname_str_dbg(smb_fname_base),
6283 status = map_nt_error_from_unix(errno);
6287 status = NT_STATUS_OK;
6289 TALLOC_FREE(smb_fname_base);
6293 /****************************************************************************
6294 Deal with setting the size from any of the setfilepathinfo functions.
6295 ****************************************************************************/
6297 static NTSTATUS smb_set_file_size(connection_struct *conn,
6298 struct smb_request *req,
6300 const struct smb_filename *smb_fname,
6301 const SMB_STRUCT_STAT *psbuf,
6303 bool fail_after_createfile)
6305 NTSTATUS status = NT_STATUS_OK;
6306 struct smb_filename *smb_fname_tmp = NULL;
6307 files_struct *new_fsp = NULL;
6309 if (!VALID_STAT(*psbuf)) {
6310 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6313 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6315 if (size == get_file_size_stat(psbuf)) {
6316 return NT_STATUS_OK;
6319 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6320 smb_fname_str_dbg(smb_fname), (double)size));
6322 if (fsp && fsp->fh->fd != -1) {
6323 /* Handle based call. */
6324 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6325 return NT_STATUS_ACCESS_DENIED;
6328 if (vfs_set_filelen(fsp, size) == -1) {
6329 return map_nt_error_from_unix(errno);
6331 trigger_write_time_update_immediate(fsp);
6332 return NT_STATUS_OK;
6335 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6336 if (smb_fname_tmp == NULL) {
6337 return NT_STATUS_NO_MEMORY;
6340 smb_fname_tmp->st = *psbuf;
6342 status = SMB_VFS_CREATE_FILE(
6345 0, /* root_dir_fid */
6346 smb_fname_tmp, /* fname */
6347 FILE_WRITE_DATA, /* access_mask */
6348 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6350 FILE_OPEN, /* create_disposition*/
6351 0, /* create_options */
6352 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6353 0, /* oplock_request */
6355 0, /* allocation_size */
6356 0, /* private_flags */
6359 &new_fsp, /* result */
6361 NULL, NULL); /* create context */
6363 TALLOC_FREE(smb_fname_tmp);
6365 if (!NT_STATUS_IS_OK(status)) {
6366 /* NB. We check for open_was_deferred in the caller. */
6370 /* See RAW-SFILEINFO-END-OF-FILE */
6371 if (fail_after_createfile) {
6372 close_file(req, new_fsp,NORMAL_CLOSE);
6373 return NT_STATUS_INVALID_LEVEL;
6376 if (vfs_set_filelen(new_fsp, size) == -1) {
6377 status = map_nt_error_from_unix(errno);
6378 close_file(req, new_fsp,NORMAL_CLOSE);
6382 trigger_write_time_update_immediate(new_fsp);
6383 close_file(req, new_fsp,NORMAL_CLOSE);
6384 return NT_STATUS_OK;
6387 /****************************************************************************
6388 Deal with SMB_INFO_SET_EA.
6389 ****************************************************************************/
6391 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6395 const struct smb_filename *smb_fname)
6397 struct ea_list *ea_list = NULL;
6398 TALLOC_CTX *ctx = NULL;
6399 NTSTATUS status = NT_STATUS_OK;
6401 if (total_data < 10) {
6403 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6404 length. They seem to have no effect. Bug #3212. JRA */
6406 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6407 /* We're done. We only get EA info in this call. */
6408 return NT_STATUS_OK;
6411 return NT_STATUS_INVALID_PARAMETER;
6414 if (IVAL(pdata,0) > total_data) {
6415 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6416 IVAL(pdata,0), (unsigned int)total_data));
6417 return NT_STATUS_INVALID_PARAMETER;
6421 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6423 return NT_STATUS_INVALID_PARAMETER;
6426 status = set_ea(conn, fsp, smb_fname, ea_list);
6431 /****************************************************************************
6432 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6433 ****************************************************************************/
6435 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6440 struct ea_list *ea_list = NULL;
6444 return NT_STATUS_INVALID_HANDLE;
6447 if (!lp_ea_support(SNUM(conn))) {
6448 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6449 "EA's not supported.\n",
6450 (unsigned int)total_data));
6451 return NT_STATUS_EAS_NOT_SUPPORTED;
6454 if (total_data < 10) {
6455 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6457 (unsigned int)total_data));
6458 return NT_STATUS_INVALID_PARAMETER;
6461 ea_list = read_nttrans_ea_list(talloc_tos(),
6466 return NT_STATUS_INVALID_PARAMETER;
6469 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6471 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6472 smb_fname_str_dbg(fsp->fsp_name),
6473 nt_errstr(status) ));
6479 /****************************************************************************
6480 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6481 ****************************************************************************/
6483 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6487 struct smb_filename *smb_fname)
6489 NTSTATUS status = NT_STATUS_OK;
6490 bool delete_on_close;
6491 uint32_t dosmode = 0;
6493 if (total_data < 1) {
6494 return NT_STATUS_INVALID_PARAMETER;
6498 return NT_STATUS_INVALID_HANDLE;
6501 delete_on_close = (CVAL(pdata,0) ? True : False);
6502 dosmode = dos_mode(conn, smb_fname);
6504 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6505 "delete_on_close = %u\n",
6506 smb_fname_str_dbg(smb_fname),
6507 (unsigned int)dosmode,
6508 (unsigned int)delete_on_close ));
6510 if (delete_on_close) {
6511 status = can_set_delete_on_close(fsp, dosmode);
6512 if (!NT_STATUS_IS_OK(status)) {
6517 /* The set is across all open files on this dev/inode pair. */
6518 if (!set_delete_on_close(fsp, delete_on_close,
6519 conn->session_info->security_token,
6520 conn->session_info->unix_token)) {
6521 return NT_STATUS_ACCESS_DENIED;
6523 return NT_STATUS_OK;
6526 /****************************************************************************
6527 Deal with SMB_FILE_POSITION_INFORMATION.
6528 ****************************************************************************/
6530 static NTSTATUS smb_file_position_information(connection_struct *conn,
6535 uint64_t position_information;
6537 if (total_data < 8) {
6538 return NT_STATUS_INVALID_PARAMETER;
6542 /* Ignore on pathname based set. */
6543 return NT_STATUS_OK;
6546 position_information = (uint64_t)IVAL(pdata,0);
6547 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6549 DEBUG(10,("smb_file_position_information: Set file position "
6550 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6551 (double)position_information));
6552 fsp->fh->position_information = position_information;
6553 return NT_STATUS_OK;
6556 /****************************************************************************
6557 Deal with SMB_FILE_MODE_INFORMATION.
6558 ****************************************************************************/
6560 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6566 if (total_data < 4) {
6567 return NT_STATUS_INVALID_PARAMETER;
6569 mode = IVAL(pdata,0);
6570 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6571 return NT_STATUS_INVALID_PARAMETER;
6573 return NT_STATUS_OK;
6576 /****************************************************************************
6577 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6578 ****************************************************************************/
6580 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6581 struct smb_request *req,
6584 const struct smb_filename *smb_fname)
6586 char *link_target = NULL;
6587 const char *newname = smb_fname->base_name;
6588 TALLOC_CTX *ctx = talloc_tos();
6590 /* Set a symbolic link. */
6591 /* Don't allow this if follow links is false. */
6593 if (total_data == 0) {
6594 return NT_STATUS_INVALID_PARAMETER;
6597 if (!lp_follow_symlinks(SNUM(conn))) {
6598 return NT_STATUS_ACCESS_DENIED;
6601 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6602 total_data, STR_TERMINATE);
6605 return NT_STATUS_INVALID_PARAMETER;
6608 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6609 newname, link_target ));
6611 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6612 return map_nt_error_from_unix(errno);
6615 return NT_STATUS_OK;
6618 /****************************************************************************
6619 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6620 ****************************************************************************/
6622 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6623 struct smb_request *req,
6624 const char *pdata, int total_data,
6625 struct smb_filename *smb_fname_new)
6627 char *oldname = NULL;
6628 struct smb_filename *smb_fname_old = NULL;
6629 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6630 TALLOC_CTX *ctx = talloc_tos();
6631 NTSTATUS status = NT_STATUS_OK;
6633 /* Set a hard link. */
6634 if (total_data == 0) {
6635 return NT_STATUS_INVALID_PARAMETER;
6638 if (req->posix_pathnames) {
6639 srvstr_get_path_posix(ctx,
6648 srvstr_get_path(ctx,
6657 if (!NT_STATUS_IS_OK(status)) {
6661 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6662 smb_fname_str_dbg(smb_fname_new), oldname));
6664 status = filename_convert(ctx,
6666 req->flags2 & FLAGS2_DFS_PATHNAMES,
6671 if (!NT_STATUS_IS_OK(status)) {
6675 return hardlink_internals(ctx, conn, req, false,
6676 smb_fname_old, smb_fname_new);
6679 /****************************************************************************
6680 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6681 ****************************************************************************/
6683 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6684 struct smb_request *req,
6688 struct smb_filename *smb_fname_src)
6692 char *newname = NULL;
6693 struct smb_filename *smb_fname_dst = NULL;
6694 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6695 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6696 NTSTATUS status = NT_STATUS_OK;
6697 TALLOC_CTX *ctx = talloc_tos();
6700 return NT_STATUS_INVALID_HANDLE;
6703 if (total_data < 20) {
6704 return NT_STATUS_INVALID_PARAMETER;
6707 overwrite = (CVAL(pdata,0) ? True : False);
6708 len = IVAL(pdata,16);
6710 if (len > (total_data - 20) || (len == 0)) {
6711 return NT_STATUS_INVALID_PARAMETER;
6714 if (req->posix_pathnames) {
6715 srvstr_get_path_posix(ctx,
6724 srvstr_get_path(ctx,
6733 if (!NT_STATUS_IS_OK(status)) {
6737 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6740 status = filename_convert(ctx,
6742 req->flags2 & FLAGS2_DFS_PATHNAMES,
6747 if (!NT_STATUS_IS_OK(status)) {
6751 if (fsp->base_fsp) {
6752 /* newname must be a stream name. */
6753 if (newname[0] != ':') {
6754 return NT_STATUS_NOT_SUPPORTED;
6757 /* Create an smb_fname to call rename_internals_fsp() with. */
6758 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6759 fsp->base_fsp->fsp_name->base_name,
6762 fsp->base_fsp->fsp_name->flags);
6763 if (smb_fname_dst == NULL) {
6764 status = NT_STATUS_NO_MEMORY;
6769 * Set the original last component, since
6770 * rename_internals_fsp() requires it.
6772 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6774 if (smb_fname_dst->original_lcomp == NULL) {
6775 status = NT_STATUS_NO_MEMORY;
6781 DEBUG(10,("smb2_file_rename_information: "
6782 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6783 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6784 smb_fname_str_dbg(smb_fname_dst)));
6785 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6786 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6790 TALLOC_FREE(smb_fname_dst);
6794 static NTSTATUS smb_file_link_information(connection_struct *conn,
6795 struct smb_request *req,
6799 struct smb_filename *smb_fname_src)
6803 char *newname = NULL;
6804 struct smb_filename *smb_fname_dst = NULL;
6805 NTSTATUS status = NT_STATUS_OK;
6806 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6807 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6808 TALLOC_CTX *ctx = talloc_tos();
6811 return NT_STATUS_INVALID_HANDLE;
6814 if (total_data < 20) {
6815 return NT_STATUS_INVALID_PARAMETER;
6818 overwrite = (CVAL(pdata,0) ? true : false);
6819 len = IVAL(pdata,16);
6821 if (len > (total_data - 20) || (len == 0)) {
6822 return NT_STATUS_INVALID_PARAMETER;
6825 if (req->posix_pathnames) {
6826 srvstr_get_path_posix(ctx,
6835 srvstr_get_path(ctx,
6844 if (!NT_STATUS_IS_OK(status)) {
6848 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6851 status = filename_convert(ctx,
6853 req->flags2 & FLAGS2_DFS_PATHNAMES,
6858 if (!NT_STATUS_IS_OK(status)) {
6862 if (fsp->base_fsp) {
6863 /* No stream names. */
6864 return NT_STATUS_NOT_SUPPORTED;
6867 DEBUG(10,("smb_file_link_information: "
6868 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6869 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6870 smb_fname_str_dbg(smb_fname_dst)));
6871 status = hardlink_internals(ctx,
6878 TALLOC_FREE(smb_fname_dst);
6882 /****************************************************************************
6883 Deal with SMB_FILE_RENAME_INFORMATION.
6884 ****************************************************************************/
6886 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6887 struct smb_request *req,
6891 struct smb_filename *smb_fname_src)
6896 char *newname = NULL;
6897 struct smb_filename *smb_fname_dst = NULL;
6898 bool dest_has_wcard = False;
6899 NTSTATUS status = NT_STATUS_OK;
6901 TALLOC_CTX *ctx = talloc_tos();
6903 if (total_data < 13) {
6904 return NT_STATUS_INVALID_PARAMETER;
6907 overwrite = (CVAL(pdata,0) ? True : False);
6908 root_fid = IVAL(pdata,4);
6909 len = IVAL(pdata,8);
6911 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6912 return NT_STATUS_INVALID_PARAMETER;
6915 if (req->posix_pathnames) {
6916 srvstr_get_path_wcard_posix(ctx,
6926 srvstr_get_path_wcard(ctx,
6936 if (!NT_STATUS_IS_OK(status)) {
6940 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6943 status = resolve_dfspath_wcard(ctx, conn,
6944 req->flags2 & FLAGS2_DFS_PATHNAMES,
6946 UCF_COND_ALLOW_WCARD_LCOMP,
6947 !conn->sconn->using_smb2,
6950 if (!NT_STATUS_IS_OK(status)) {
6954 /* Check the new name has no '/' characters. */
6955 if (strchr_m(newname, '/')) {
6956 return NT_STATUS_NOT_SUPPORTED;
6959 if (fsp && fsp->base_fsp) {
6960 /* newname must be a stream name. */
6961 if (newname[0] != ':') {
6962 return NT_STATUS_NOT_SUPPORTED;
6965 /* Create an smb_fname to call rename_internals_fsp() with. */
6966 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6967 fsp->base_fsp->fsp_name->base_name,
6970 fsp->base_fsp->fsp_name->flags);
6971 if (smb_fname_dst == NULL) {
6972 status = NT_STATUS_NO_MEMORY;
6977 * Set the original last component, since
6978 * rename_internals_fsp() requires it.
6980 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6982 if (smb_fname_dst->original_lcomp == NULL) {
6983 status = NT_STATUS_NO_MEMORY;
6989 * Build up an smb_fname_dst based on the filename passed in.
6990 * We basically just strip off the last component, and put on
6991 * the newname instead.
6993 char *base_name = NULL;
6995 /* newname must *not* be a stream name. */
6996 if (newname[0] == ':') {
6997 return NT_STATUS_NOT_SUPPORTED;
7001 * Strip off the last component (filename) of the path passed
7004 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7006 return NT_STATUS_NO_MEMORY;
7008 p = strrchr_m(base_name, '/');
7012 base_name = talloc_strdup(ctx, "");
7014 return NT_STATUS_NO_MEMORY;
7017 /* Append the new name. */
7018 base_name = talloc_asprintf_append(base_name,
7022 return NT_STATUS_NO_MEMORY;
7025 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7028 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
7031 /* If an error we expect this to be
7032 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7034 if (!NT_STATUS_IS_OK(status)) {
7035 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7039 /* Create an smb_fname to call rename_internals_fsp() */
7040 smb_fname_dst = synthetic_smb_fname(ctx,
7044 smb_fname_src->flags);
7045 if (smb_fname_dst == NULL) {
7046 status = NT_STATUS_NO_MEMORY;
7053 DEBUG(10,("smb_file_rename_information: "
7054 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7055 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7056 smb_fname_str_dbg(smb_fname_dst)));
7057 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7060 DEBUG(10,("smb_file_rename_information: "
7061 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7062 smb_fname_str_dbg(smb_fname_src),
7063 smb_fname_str_dbg(smb_fname_dst)));
7064 status = rename_internals(ctx, conn, req, smb_fname_src,
7065 smb_fname_dst, 0, overwrite, false,
7067 FILE_WRITE_ATTRIBUTES);
7070 TALLOC_FREE(smb_fname_dst);
7074 /****************************************************************************
7075 Deal with SMB_SET_POSIX_ACL.
7076 ****************************************************************************/
7078 #if defined(HAVE_POSIX_ACLS)
7079 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7083 const struct smb_filename *smb_fname)
7085 uint16_t posix_acl_version;
7086 uint16_t num_file_acls;
7087 uint16_t num_def_acls;
7088 bool valid_file_acls = True;
7089 bool valid_def_acls = True;
7092 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7093 return NT_STATUS_INVALID_PARAMETER;
7095 posix_acl_version = SVAL(pdata,0);
7096 num_file_acls = SVAL(pdata,2);
7097 num_def_acls = SVAL(pdata,4);
7099 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7100 valid_file_acls = False;
7104 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7105 valid_def_acls = False;
7109 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7110 return NT_STATUS_INVALID_PARAMETER;
7113 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7114 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7115 return NT_STATUS_INVALID_PARAMETER;
7118 status = refuse_symlink(conn, fsp, smb_fname);
7119 if (!NT_STATUS_IS_OK(status)) {
7123 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7124 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7125 (unsigned int)num_file_acls,
7126 (unsigned int)num_def_acls));
7128 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7129 smb_fname->base_name, num_file_acls,
7130 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7131 return map_nt_error_from_unix(errno);
7134 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7135 smb_fname->base_name, &smb_fname->st, num_def_acls,
7136 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7137 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7138 return map_nt_error_from_unix(errno);
7140 return NT_STATUS_OK;
7144 /****************************************************************************
7145 Deal with SMB_SET_POSIX_LOCK.
7146 ****************************************************************************/
7148 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7149 struct smb_request *req,
7157 bool blocking_lock = False;
7158 enum brl_type lock_type;
7160 NTSTATUS status = NT_STATUS_OK;
7162 if (fsp == NULL || fsp->fh->fd == -1) {
7163 return NT_STATUS_INVALID_HANDLE;
7166 if (total_data != POSIX_LOCK_DATA_SIZE) {
7167 return NT_STATUS_INVALID_PARAMETER;
7170 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7171 case POSIX_LOCK_TYPE_READ:
7172 lock_type = READ_LOCK;
7174 case POSIX_LOCK_TYPE_WRITE:
7175 /* Return the right POSIX-mappable error code for files opened read-only. */
7176 if (!fsp->can_write) {
7177 return NT_STATUS_INVALID_HANDLE;
7179 lock_type = WRITE_LOCK;
7181 case POSIX_LOCK_TYPE_UNLOCK:
7182 lock_type = UNLOCK_LOCK;
7185 return NT_STATUS_INVALID_PARAMETER;
7188 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7189 blocking_lock = False;
7190 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7191 blocking_lock = True;
7193 return NT_STATUS_INVALID_PARAMETER;
7196 if (!lp_blocking_locks(SNUM(conn))) {
7197 blocking_lock = False;
7200 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7201 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7202 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7203 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7204 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7206 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7207 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7209 (unsigned int)lock_type,
7210 (unsigned long long)smblctx,
7214 if (lock_type == UNLOCK_LOCK) {
7215 status = do_unlock(req->sconn->msg_ctx,
7222 uint64_t block_smblctx;
7224 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7235 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7237 * A blocking lock was requested. Package up
7238 * this smb into a queued request and push it
7239 * onto the blocking lock queue.
7241 if(push_blocking_lock_request(br_lck,
7244 -1, /* infinite timeout. */
7252 TALLOC_FREE(br_lck);
7256 TALLOC_FREE(br_lck);
7262 /****************************************************************************
7263 Deal with SMB_SET_FILE_BASIC_INFO.
7264 ****************************************************************************/
7266 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7270 const struct smb_filename *smb_fname)
7272 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7273 struct smb_file_time ft;
7274 uint32_t dosmode = 0;
7275 NTSTATUS status = NT_STATUS_OK;
7279 if (total_data < 36) {
7280 return NT_STATUS_INVALID_PARAMETER;
7283 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7284 if (!NT_STATUS_IS_OK(status)) {
7288 /* Set the attributes */
7289 dosmode = IVAL(pdata,32);
7290 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7291 if (!NT_STATUS_IS_OK(status)) {
7296 ft.create_time = interpret_long_date(pdata);
7299 ft.atime = interpret_long_date(pdata+8);
7302 ft.mtime = interpret_long_date(pdata+16);
7305 ft.ctime = interpret_long_date(pdata+24);
7307 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7308 smb_fname_str_dbg(smb_fname)));
7310 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7314 /****************************************************************************
7315 Deal with SMB_INFO_STANDARD.
7316 ****************************************************************************/
7318 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7322 const struct smb_filename *smb_fname)
7325 struct smb_file_time ft;
7329 if (total_data < 12) {
7330 return NT_STATUS_INVALID_PARAMETER;
7334 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7336 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7338 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7340 DEBUG(10,("smb_set_info_standard: file %s\n",
7341 smb_fname_str_dbg(smb_fname)));
7343 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7344 if (!NT_STATUS_IS_OK(status)) {
7348 return smb_set_file_time(conn,
7355 /****************************************************************************
7356 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7357 ****************************************************************************/
7359 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7360 struct smb_request *req,
7364 struct smb_filename *smb_fname)
7366 uint64_t allocation_size = 0;
7367 NTSTATUS status = NT_STATUS_OK;
7368 files_struct *new_fsp = NULL;
7370 if (!VALID_STAT(smb_fname->st)) {
7371 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7374 if (total_data < 8) {
7375 return NT_STATUS_INVALID_PARAMETER;
7378 allocation_size = (uint64_t)IVAL(pdata,0);
7379 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7380 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7381 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7382 (double)allocation_size));
7384 if (allocation_size) {
7385 allocation_size = smb_roundup(conn, allocation_size);
7388 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7389 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7390 (double)allocation_size));
7392 if (fsp && fsp->fh->fd != -1) {
7393 /* Open file handle. */
7394 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7395 return NT_STATUS_ACCESS_DENIED;
7398 /* Only change if needed. */
7399 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7400 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7401 return map_nt_error_from_unix(errno);
7404 /* But always update the time. */
7406 * This is equivalent to a write. Ensure it's seen immediately
7407 * if there are no pending writes.
7409 trigger_write_time_update_immediate(fsp);
7410 return NT_STATUS_OK;
7413 /* Pathname or stat or directory file. */
7414 status = SMB_VFS_CREATE_FILE(
7417 0, /* root_dir_fid */
7418 smb_fname, /* fname */
7419 FILE_WRITE_DATA, /* access_mask */
7420 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7422 FILE_OPEN, /* create_disposition*/
7423 0, /* create_options */
7424 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7425 0, /* oplock_request */
7427 0, /* allocation_size */
7428 0, /* private_flags */
7431 &new_fsp, /* result */
7433 NULL, NULL); /* create context */
7435 if (!NT_STATUS_IS_OK(status)) {
7436 /* NB. We check for open_was_deferred in the caller. */
7440 /* Only change if needed. */
7441 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7442 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7443 status = map_nt_error_from_unix(errno);
7444 close_file(req, new_fsp, NORMAL_CLOSE);
7449 /* Changing the allocation size should set the last mod time. */
7451 * This is equivalent to a write. Ensure it's seen immediately
7452 * if there are no pending writes.
7454 trigger_write_time_update_immediate(new_fsp);
7455 close_file(req, new_fsp, NORMAL_CLOSE);
7456 return NT_STATUS_OK;
7459 /****************************************************************************
7460 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7461 ****************************************************************************/
7463 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7464 struct smb_request *req,
7468 const struct smb_filename *smb_fname,
7469 bool fail_after_createfile)
7473 if (total_data < 8) {
7474 return NT_STATUS_INVALID_PARAMETER;
7477 size = IVAL(pdata,0);
7478 size |= (((off_t)IVAL(pdata,4)) << 32);
7479 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7480 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7483 return smb_set_file_size(conn, req,
7488 fail_after_createfile);
7491 /****************************************************************************
7492 Allow a UNIX info mknod.
7493 ****************************************************************************/
7495 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7498 const struct smb_filename *smb_fname)
7500 uint32_t file_type = IVAL(pdata,56);
7501 #if defined(HAVE_MAKEDEV)
7502 uint32_t dev_major = IVAL(pdata,60);
7503 uint32_t dev_minor = IVAL(pdata,68);
7505 SMB_DEV_T dev = (SMB_DEV_T)0;
7506 uint32_t raw_unixmode = IVAL(pdata,84);
7510 if (total_data < 100) {
7511 return NT_STATUS_INVALID_PARAMETER;
7514 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7515 PERM_NEW_FILE, &unixmode);
7516 if (!NT_STATUS_IS_OK(status)) {
7520 #if defined(HAVE_MAKEDEV)
7521 dev = makedev(dev_major, dev_minor);
7524 switch (file_type) {
7525 #if defined(S_IFIFO)
7526 case UNIX_TYPE_FIFO:
7527 unixmode |= S_IFIFO;
7530 #if defined(S_IFSOCK)
7531 case UNIX_TYPE_SOCKET:
7532 unixmode |= S_IFSOCK;
7535 #if defined(S_IFCHR)
7536 case UNIX_TYPE_CHARDEV:
7537 unixmode |= S_IFCHR;
7540 #if defined(S_IFBLK)
7541 case UNIX_TYPE_BLKDEV:
7542 unixmode |= S_IFBLK;
7546 return NT_STATUS_INVALID_PARAMETER;
7549 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7550 "%.0f mode 0%o for file %s\n", (double)dev,
7551 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7553 /* Ok - do the mknod. */
7554 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7555 return map_nt_error_from_unix(errno);
7558 /* If any of the other "set" calls fail we
7559 * don't want to end up with a half-constructed mknod.
7562 if (lp_inherit_permissions(SNUM(conn))) {
7564 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7566 return NT_STATUS_NO_MEMORY;
7568 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7570 TALLOC_FREE(parent);
7573 return NT_STATUS_OK;
7576 /****************************************************************************
7577 Deal with SMB_SET_FILE_UNIX_BASIC.
7578 ****************************************************************************/
7580 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7581 struct smb_request *req,
7585 const struct smb_filename *smb_fname)
7587 struct smb_file_time ft;
7588 uint32_t raw_unixmode;
7591 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7592 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7593 NTSTATUS status = NT_STATUS_OK;
7594 bool delete_on_fail = False;
7595 enum perm_type ptype;
7596 files_struct *all_fsps = NULL;
7597 bool modify_mtime = true;
7599 struct smb_filename *smb_fname_tmp = NULL;
7600 SMB_STRUCT_STAT sbuf;
7604 if (total_data < 100) {
7605 return NT_STATUS_INVALID_PARAMETER;
7608 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7609 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7610 size=IVAL(pdata,0); /* first 8 Bytes are size */
7611 size |= (((off_t)IVAL(pdata,4)) << 32);
7614 ft.atime = interpret_long_date(pdata+24); /* access_time */
7615 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7616 set_owner = (uid_t)IVAL(pdata,40);
7617 set_grp = (gid_t)IVAL(pdata,48);
7618 raw_unixmode = IVAL(pdata,84);
7620 if (VALID_STAT(smb_fname->st)) {
7621 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7622 ptype = PERM_EXISTING_DIR;
7624 ptype = PERM_EXISTING_FILE;
7627 ptype = PERM_NEW_FILE;
7630 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7632 if (!NT_STATUS_IS_OK(status)) {
7636 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7637 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7638 smb_fname_str_dbg(smb_fname), (double)size,
7639 (unsigned int)set_owner, (unsigned int)set_grp,
7640 (int)raw_unixmode));
7642 sbuf = smb_fname->st;
7644 if (!VALID_STAT(sbuf)) {
7646 * The only valid use of this is to create character and block
7647 * devices, and named pipes. This is deprecated (IMHO) and
7648 * a new info level should be used for mknod. JRA.
7651 status = smb_unix_mknod(conn,
7655 if (!NT_STATUS_IS_OK(status)) {
7659 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7660 if (smb_fname_tmp == NULL) {
7661 return NT_STATUS_NO_MEMORY;
7664 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7665 status = map_nt_error_from_unix(errno);
7666 TALLOC_FREE(smb_fname_tmp);
7667 SMB_VFS_UNLINK(conn, smb_fname);
7671 sbuf = smb_fname_tmp->st;
7672 smb_fname = smb_fname_tmp;
7674 /* Ensure we don't try and change anything else. */
7675 raw_unixmode = SMB_MODE_NO_CHANGE;
7676 size = get_file_size_stat(&sbuf);
7677 ft.atime = sbuf.st_ex_atime;
7678 ft.mtime = sbuf.st_ex_mtime;
7680 * We continue here as we might want to change the
7683 delete_on_fail = True;
7687 /* Horrible backwards compatibility hack as an old server bug
7688 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7692 size = get_file_size_stat(&sbuf);
7697 * Deal with the UNIX specific mode set.
7700 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7703 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7704 "setting mode 0%o for file %s\n",
7705 (unsigned int)unixmode,
7706 smb_fname_str_dbg(smb_fname)));
7707 if (fsp && fsp->fh->fd != -1) {
7708 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7710 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7713 return map_nt_error_from_unix(errno);
7718 * Deal with the UNIX specific uid set.
7721 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7722 (sbuf.st_ex_uid != set_owner)) {
7725 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7726 "changing owner %u for path %s\n",
7727 (unsigned int)set_owner,
7728 smb_fname_str_dbg(smb_fname)));
7730 if (fsp && fsp->fh->fd != -1) {
7731 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7734 * UNIX extensions calls must always operate
7737 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7738 set_owner, (gid_t)-1);
7742 status = map_nt_error_from_unix(errno);
7743 if (delete_on_fail) {
7744 SMB_VFS_UNLINK(conn, smb_fname);
7751 * Deal with the UNIX specific gid set.
7754 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7755 (sbuf.st_ex_gid != set_grp)) {
7758 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7759 "changing group %u for file %s\n",
7760 (unsigned int)set_owner,
7761 smb_fname_str_dbg(smb_fname)));
7762 if (fsp && fsp->fh->fd != -1) {
7763 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7766 * UNIX extensions calls must always operate
7769 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7773 status = map_nt_error_from_unix(errno);
7774 if (delete_on_fail) {
7775 SMB_VFS_UNLINK(conn, smb_fname);
7781 /* Deal with any size changes. */
7783 status = smb_set_file_size(conn, req,
7789 if (!NT_STATUS_IS_OK(status)) {
7793 /* Deal with any time changes. */
7794 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7795 /* No change, don't cancel anything. */
7799 id = vfs_file_id_from_sbuf(conn, &sbuf);
7800 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7801 all_fsps = file_find_di_next(all_fsps)) {
7803 * We're setting the time explicitly for UNIX.
7804 * Cancel any pending changes over all handles.
7806 all_fsps->update_write_time_on_close = false;
7807 TALLOC_FREE(all_fsps->update_write_time_event);
7811 * Override the "setting_write_time"
7812 * parameter here as it almost does what
7813 * we need. Just remember if we modified
7814 * mtime and send the notify ourselves.
7816 if (null_timespec(ft.mtime)) {
7817 modify_mtime = false;
7820 status = smb_set_file_time(conn,
7826 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7827 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7832 /****************************************************************************
7833 Deal with SMB_SET_FILE_UNIX_INFO2.
7834 ****************************************************************************/
7836 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7837 struct smb_request *req,
7841 const struct smb_filename *smb_fname)
7844 uint32_t smb_fflags;
7847 if (total_data < 116) {
7848 return NT_STATUS_INVALID_PARAMETER;
7851 /* Start by setting all the fields that are common between UNIX_BASIC
7854 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7856 if (!NT_STATUS_IS_OK(status)) {
7860 smb_fflags = IVAL(pdata, 108);
7861 smb_fmask = IVAL(pdata, 112);
7863 /* NB: We should only attempt to alter the file flags if the client
7864 * sends a non-zero mask.
7866 if (smb_fmask != 0) {
7867 int stat_fflags = 0;
7869 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7870 smb_fmask, &stat_fflags)) {
7871 /* Client asked to alter a flag we don't understand. */
7872 return NT_STATUS_INVALID_PARAMETER;
7875 if (fsp && fsp->fh->fd != -1) {
7876 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7877 return NT_STATUS_NOT_SUPPORTED;
7879 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7880 stat_fflags) != 0) {
7881 return map_nt_error_from_unix(errno);
7886 /* XXX: need to add support for changing the create_time here. You
7887 * can do this for paths on Darwin with setattrlist(2). The right way
7888 * to hook this up is probably by extending the VFS utimes interface.
7891 return NT_STATUS_OK;
7894 /****************************************************************************
7895 Create a directory with POSIX semantics.
7896 ****************************************************************************/
7898 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7899 struct smb_request *req,
7902 struct smb_filename *smb_fname,
7903 int *pdata_return_size)
7905 NTSTATUS status = NT_STATUS_OK;
7906 uint32_t raw_unixmode = 0;
7907 uint32_t mod_unixmode = 0;
7908 mode_t unixmode = (mode_t)0;
7909 files_struct *fsp = NULL;
7910 uint16_t info_level_return = 0;
7912 char *pdata = *ppdata;
7914 if (total_data < 18) {
7915 return NT_STATUS_INVALID_PARAMETER;
7918 raw_unixmode = IVAL(pdata,8);
7919 /* Next 4 bytes are not yet defined. */
7921 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7922 PERM_NEW_DIR, &unixmode);
7923 if (!NT_STATUS_IS_OK(status)) {
7927 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7929 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7930 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7932 status = SMB_VFS_CREATE_FILE(
7935 0, /* root_dir_fid */
7936 smb_fname, /* fname */
7937 FILE_READ_ATTRIBUTES, /* access_mask */
7938 FILE_SHARE_NONE, /* share_access */
7939 FILE_CREATE, /* create_disposition*/
7940 FILE_DIRECTORY_FILE, /* create_options */
7941 mod_unixmode, /* file_attributes */
7942 0, /* oplock_request */
7944 0, /* allocation_size */
7945 0, /* private_flags */
7950 NULL, NULL); /* create context */
7952 if (NT_STATUS_IS_OK(status)) {
7953 close_file(req, fsp, NORMAL_CLOSE);
7956 info_level_return = SVAL(pdata,16);
7958 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7959 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7960 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7961 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7963 *pdata_return_size = 12;
7966 /* Realloc the data size */
7967 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7968 if (*ppdata == NULL) {
7969 *pdata_return_size = 0;
7970 return NT_STATUS_NO_MEMORY;
7974 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7975 SSVAL(pdata,2,0); /* No fnum. */
7976 SIVAL(pdata,4,info); /* Was directory created. */
7978 switch (info_level_return) {
7979 case SMB_QUERY_FILE_UNIX_BASIC:
7980 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7981 SSVAL(pdata,10,0); /* Padding. */
7982 store_file_unix_basic(conn, pdata + 12, fsp,
7985 case SMB_QUERY_FILE_UNIX_INFO2:
7986 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7987 SSVAL(pdata,10,0); /* Padding. */
7988 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7992 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7993 SSVAL(pdata,10,0); /* Padding. */
8000 /****************************************************************************
8001 Open/Create a file with POSIX semantics.
8002 ****************************************************************************/
8004 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8005 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8007 static NTSTATUS smb_posix_open(connection_struct *conn,
8008 struct smb_request *req,
8011 struct smb_filename *smb_fname,
8012 int *pdata_return_size)
8014 bool extended_oplock_granted = False;
8015 char *pdata = *ppdata;
8017 uint32_t wire_open_mode = 0;
8018 uint32_t raw_unixmode = 0;
8019 uint32_t mod_unixmode = 0;
8020 uint32_t create_disp = 0;
8021 uint32_t access_mask = 0;
8022 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8023 NTSTATUS status = NT_STATUS_OK;
8024 mode_t unixmode = (mode_t)0;
8025 files_struct *fsp = NULL;
8026 int oplock_request = 0;
8028 uint16_t info_level_return = 0;
8030 if (total_data < 18) {
8031 return NT_STATUS_INVALID_PARAMETER;
8034 flags = IVAL(pdata,0);
8035 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8036 if (oplock_request) {
8037 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8040 wire_open_mode = IVAL(pdata,4);
8042 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8043 return smb_posix_mkdir(conn, req,
8050 switch (wire_open_mode & SMB_ACCMODE) {
8052 access_mask = SMB_O_RDONLY_MAPPING;
8055 access_mask = SMB_O_WRONLY_MAPPING;
8058 access_mask = (SMB_O_RDONLY_MAPPING|
8059 SMB_O_WRONLY_MAPPING);
8062 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8063 (unsigned int)wire_open_mode ));
8064 return NT_STATUS_INVALID_PARAMETER;
8067 wire_open_mode &= ~SMB_ACCMODE;
8069 /* First take care of O_CREAT|O_EXCL interactions. */
8070 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8071 case (SMB_O_CREAT | SMB_O_EXCL):
8072 /* File exists fail. File not exist create. */
8073 create_disp = FILE_CREATE;
8076 /* File exists open. File not exist create. */
8077 create_disp = FILE_OPEN_IF;
8080 /* O_EXCL on its own without O_CREAT is undefined.
8081 We deliberately ignore it as some versions of
8082 Linux CIFSFS can send a bare O_EXCL on the
8083 wire which other filesystems in the kernel
8084 ignore. See bug 9519 for details. */
8089 /* File exists open. File not exist fail. */
8090 create_disp = FILE_OPEN;
8093 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8094 (unsigned int)wire_open_mode ));
8095 return NT_STATUS_INVALID_PARAMETER;
8098 /* Next factor in the effects of O_TRUNC. */
8099 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8101 if (wire_open_mode & SMB_O_TRUNC) {
8102 switch (create_disp) {
8104 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8105 /* Leave create_disp alone as
8106 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8108 /* File exists fail. File not exist create. */
8111 /* SMB_O_CREAT | SMB_O_TRUNC */
8112 /* File exists overwrite. File not exist create. */
8113 create_disp = FILE_OVERWRITE_IF;
8117 /* File exists overwrite. File not exist fail. */
8118 create_disp = FILE_OVERWRITE;
8121 /* Cannot get here. */
8122 smb_panic("smb_posix_open: logic error");
8123 return NT_STATUS_INVALID_PARAMETER;
8127 raw_unixmode = IVAL(pdata,8);
8128 /* Next 4 bytes are not yet defined. */
8130 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8131 (VALID_STAT(smb_fname->st) ?
8132 PERM_EXISTING_FILE : PERM_NEW_FILE),
8135 if (!NT_STATUS_IS_OK(status)) {
8139 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8141 if (wire_open_mode & SMB_O_SYNC) {
8142 create_options |= FILE_WRITE_THROUGH;
8144 if (wire_open_mode & SMB_O_APPEND) {
8145 access_mask |= FILE_APPEND_DATA;
8147 if (wire_open_mode & SMB_O_DIRECT) {
8148 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8151 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8152 VALID_STAT_OF_DIR(smb_fname->st)) {
8153 if (access_mask != SMB_O_RDONLY_MAPPING) {
8154 return NT_STATUS_FILE_IS_A_DIRECTORY;
8156 create_options &= ~FILE_NON_DIRECTORY_FILE;
8157 create_options |= FILE_DIRECTORY_FILE;
8160 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8161 smb_fname_str_dbg(smb_fname),
8162 (unsigned int)wire_open_mode,
8163 (unsigned int)unixmode ));
8165 status = SMB_VFS_CREATE_FILE(
8168 0, /* root_dir_fid */
8169 smb_fname, /* fname */
8170 access_mask, /* access_mask */
8171 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8173 create_disp, /* create_disposition*/
8174 create_options, /* create_options */
8175 mod_unixmode, /* file_attributes */
8176 oplock_request, /* oplock_request */
8178 0, /* allocation_size */
8179 0, /* private_flags */
8184 NULL, NULL); /* create context */
8186 if (!NT_STATUS_IS_OK(status)) {
8190 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8191 extended_oplock_granted = True;
8194 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8195 extended_oplock_granted = True;
8198 info_level_return = SVAL(pdata,16);
8200 /* Allocate the correct return size. */
8202 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8203 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8204 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8205 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8207 *pdata_return_size = 12;
8210 /* Realloc the data size */
8211 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8212 if (*ppdata == NULL) {
8213 close_file(req, fsp, ERROR_CLOSE);
8214 *pdata_return_size = 0;
8215 return NT_STATUS_NO_MEMORY;
8219 if (extended_oplock_granted) {
8220 if (flags & REQUEST_BATCH_OPLOCK) {
8221 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8223 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8225 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8226 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8228 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8231 SSVAL(pdata,2,fsp->fnum);
8232 SIVAL(pdata,4,info); /* Was file created etc. */
8234 switch (info_level_return) {
8235 case SMB_QUERY_FILE_UNIX_BASIC:
8236 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8237 SSVAL(pdata,10,0); /* padding. */
8238 store_file_unix_basic(conn, pdata + 12, fsp,
8241 case SMB_QUERY_FILE_UNIX_INFO2:
8242 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8243 SSVAL(pdata,10,0); /* padding. */
8244 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8248 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8249 SSVAL(pdata,10,0); /* padding. */
8252 return NT_STATUS_OK;
8255 /****************************************************************************
8256 Delete a file with POSIX semantics.
8257 ****************************************************************************/
8259 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8260 struct smb_request *req,
8263 struct smb_filename *smb_fname)
8265 NTSTATUS status = NT_STATUS_OK;
8266 files_struct *fsp = NULL;
8270 int create_options = 0;
8272 struct share_mode_lock *lck = NULL;
8274 if (total_data < 2) {
8275 return NT_STATUS_INVALID_PARAMETER;
8278 flags = SVAL(pdata,0);
8280 if (!VALID_STAT(smb_fname->st)) {
8281 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8284 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8285 !VALID_STAT_OF_DIR(smb_fname->st)) {
8286 return NT_STATUS_NOT_A_DIRECTORY;
8289 DEBUG(10,("smb_posix_unlink: %s %s\n",
8290 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8291 smb_fname_str_dbg(smb_fname)));
8293 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8294 create_options |= FILE_DIRECTORY_FILE;
8297 status = SMB_VFS_CREATE_FILE(
8300 0, /* root_dir_fid */
8301 smb_fname, /* fname */
8302 DELETE_ACCESS, /* access_mask */
8303 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8305 FILE_OPEN, /* create_disposition*/
8306 create_options, /* create_options */
8307 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8308 0, /* oplock_request */
8310 0, /* allocation_size */
8311 0, /* private_flags */
8316 NULL, NULL); /* create context */
8318 if (!NT_STATUS_IS_OK(status)) {
8323 * Don't lie to client. If we can't really delete due to
8324 * non-POSIX opens return SHARING_VIOLATION.
8327 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8329 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8330 "lock for file %s\n", fsp_str_dbg(fsp)));
8331 close_file(req, fsp, NORMAL_CLOSE);
8332 return NT_STATUS_INVALID_PARAMETER;
8336 * See if others still have the file open. If this is the case, then
8337 * don't delete. If all opens are POSIX delete we can set the delete
8338 * on close disposition.
8340 for (i=0; i<lck->data->num_share_modes; i++) {
8341 struct share_mode_entry *e = &lck->data->share_modes[i];
8342 if (is_valid_share_mode_entry(e)) {
8343 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8346 if (share_mode_stale_pid(lck->data, i)) {
8349 /* Fail with sharing violation. */
8351 close_file(req, fsp, NORMAL_CLOSE);
8352 return NT_STATUS_SHARING_VIOLATION;
8357 * Set the delete on close.
8359 status = smb_set_file_disposition_info(conn,
8367 if (!NT_STATUS_IS_OK(status)) {
8368 close_file(req, fsp, NORMAL_CLOSE);
8371 return close_file(req, fsp, NORMAL_CLOSE);
8374 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8375 struct smb_request *req,
8376 TALLOC_CTX *mem_ctx,
8377 uint16_t info_level,
8379 struct smb_filename *smb_fname,
8380 char **ppdata, int total_data,
8383 char *pdata = *ppdata;
8384 NTSTATUS status = NT_STATUS_OK;
8385 int data_return_size = 0;
8389 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8390 return NT_STATUS_INVALID_LEVEL;
8393 if (!CAN_WRITE(conn)) {
8394 /* Allow POSIX opens. The open path will deny
8395 * any non-readonly opens. */
8396 if (info_level != SMB_POSIX_PATH_OPEN) {
8397 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8401 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8402 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8404 info_level, total_data));
8406 switch (info_level) {
8408 case SMB_INFO_STANDARD:
8410 status = smb_set_info_standard(conn,
8418 case SMB_INFO_SET_EA:
8420 status = smb_info_set_ea(conn,
8428 case SMB_SET_FILE_BASIC_INFO:
8429 case SMB_FILE_BASIC_INFORMATION:
8431 status = smb_set_file_basic_info(conn,
8439 case SMB_FILE_ALLOCATION_INFORMATION:
8440 case SMB_SET_FILE_ALLOCATION_INFO:
8442 status = smb_set_file_allocation_info(conn, req,
8450 case SMB_FILE_END_OF_FILE_INFORMATION:
8451 case SMB_SET_FILE_END_OF_FILE_INFO:
8454 * XP/Win7 both fail after the createfile with
8455 * SMB_SET_FILE_END_OF_FILE_INFO but not
8456 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8457 * The level is known here, so pass it down
8461 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8463 status = smb_set_file_end_of_file_info(conn, req,
8472 case SMB_FILE_DISPOSITION_INFORMATION:
8473 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8476 /* JRA - We used to just ignore this on a path ?
8477 * Shouldn't this be invalid level on a pathname
8480 if (tran_call != TRANSACT2_SETFILEINFO) {
8481 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8484 status = smb_set_file_disposition_info(conn,
8492 case SMB_FILE_POSITION_INFORMATION:
8494 status = smb_file_position_information(conn,
8501 case SMB_FILE_FULL_EA_INFORMATION:
8503 status = smb_set_file_full_ea_info(conn,
8510 /* From tridge Samba4 :
8511 * MODE_INFORMATION in setfileinfo (I have no
8512 * idea what "mode information" on a file is - it takes a value of 0,
8513 * 2, 4 or 6. What could it be?).
8516 case SMB_FILE_MODE_INFORMATION:
8518 status = smb_file_mode_information(conn,
8525 * CIFS UNIX extensions.
8528 case SMB_SET_FILE_UNIX_BASIC:
8530 status = smb_set_file_unix_basic(conn, req,
8538 case SMB_SET_FILE_UNIX_INFO2:
8540 status = smb_set_file_unix_info2(conn, req,
8548 case SMB_SET_FILE_UNIX_LINK:
8551 /* We must have a pathname for this. */
8552 return NT_STATUS_INVALID_LEVEL;
8554 status = smb_set_file_unix_link(conn, req, pdata,
8555 total_data, smb_fname);
8559 case SMB_SET_FILE_UNIX_HLINK:
8562 /* We must have a pathname for this. */
8563 return NT_STATUS_INVALID_LEVEL;
8565 status = smb_set_file_unix_hlink(conn, req,
8571 case SMB_FILE_RENAME_INFORMATION:
8573 status = smb_file_rename_information(conn, req,
8579 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8581 /* SMB2 rename information. */
8582 status = smb2_file_rename_information(conn, req,
8588 case SMB_FILE_LINK_INFORMATION:
8590 status = smb_file_link_information(conn, req,
8596 #if defined(HAVE_POSIX_ACLS)
8597 case SMB_SET_POSIX_ACL:
8599 status = smb_set_posix_acl(conn,
8608 case SMB_SET_POSIX_LOCK:
8611 return NT_STATUS_INVALID_LEVEL;
8613 status = smb_set_posix_lock(conn, req,
8614 pdata, total_data, fsp);
8618 case SMB_POSIX_PATH_OPEN:
8621 /* We must have a pathname for this. */
8622 return NT_STATUS_INVALID_LEVEL;
8625 status = smb_posix_open(conn, req,
8633 case SMB_POSIX_PATH_UNLINK:
8636 /* We must have a pathname for this. */
8637 return NT_STATUS_INVALID_LEVEL;
8640 status = smb_posix_unlink(conn, req,
8648 return NT_STATUS_INVALID_LEVEL;
8651 if (!NT_STATUS_IS_OK(status)) {
8655 *ret_data_size = data_return_size;
8656 return NT_STATUS_OK;
8659 /****************************************************************************
8660 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8661 ****************************************************************************/
8663 static void call_trans2setfilepathinfo(connection_struct *conn,
8664 struct smb_request *req,
8665 unsigned int tran_call,
8666 char **pparams, int total_params,
8667 char **ppdata, int total_data,
8668 unsigned int max_data_bytes)
8670 char *params = *pparams;
8671 char *pdata = *ppdata;
8672 uint16_t info_level;
8673 struct smb_filename *smb_fname = NULL;
8674 files_struct *fsp = NULL;
8675 NTSTATUS status = NT_STATUS_OK;
8676 int data_return_size = 0;
8679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8683 if (tran_call == TRANSACT2_SETFILEINFO) {
8684 if (total_params < 4) {
8685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8689 fsp = file_fsp(req, SVAL(params,0));
8690 /* Basic check for non-null fsp. */
8691 if (!check_fsp_open(conn, req, fsp)) {
8694 info_level = SVAL(params,2);
8696 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8697 if (smb_fname == NULL) {
8698 reply_nterror(req, NT_STATUS_NO_MEMORY);
8702 if(fsp->fh->fd == -1) {
8704 * This is actually a SETFILEINFO on a directory
8705 * handle (returned from an NT SMB). NT5.0 seems
8706 * to do this call. JRA.
8708 if (INFO_LEVEL_IS_UNIX(info_level)) {
8709 /* Always do lstat for UNIX calls. */
8710 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8711 DEBUG(3,("call_trans2setfilepathinfo: "
8712 "SMB_VFS_LSTAT of %s failed "
8714 smb_fname_str_dbg(smb_fname),
8716 reply_nterror(req, map_nt_error_from_unix(errno));
8720 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8721 DEBUG(3,("call_trans2setfilepathinfo: "
8722 "fileinfo of %s failed (%s)\n",
8723 smb_fname_str_dbg(smb_fname),
8725 reply_nterror(req, map_nt_error_from_unix(errno));
8729 } else if (fsp->print_file) {
8731 * Doing a DELETE_ON_CLOSE should cancel a print job.
8733 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8734 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8736 DEBUG(3,("call_trans2setfilepathinfo: "
8737 "Cancelling print job (%s)\n",
8741 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8747 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8752 * Original code - this is an open file.
8754 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8755 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8756 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8758 reply_nterror(req, map_nt_error_from_unix(errno));
8764 uint32_t ucf_flags = (req->posix_pathnames ?
8765 UCF_POSIX_PATHNAMES : 0);
8768 if (total_params < 7) {
8769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8773 info_level = SVAL(params,0);
8774 if (req->posix_pathnames) {
8775 srvstr_get_path_posix(req,
8784 srvstr_get_path(req,
8793 if (!NT_STATUS_IS_OK(status)) {
8794 reply_nterror(req, status);
8798 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8799 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8800 info_level == SMB_FILE_RENAME_INFORMATION ||
8801 info_level == SMB_POSIX_PATH_UNLINK) {
8802 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8805 status = filename_convert(req, conn,
8806 req->flags2 & FLAGS2_DFS_PATHNAMES,
8811 if (!NT_STATUS_IS_OK(status)) {
8812 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8813 reply_botherror(req,
8814 NT_STATUS_PATH_NOT_COVERED,
8815 ERRSRV, ERRbadpath);
8818 reply_nterror(req, status);
8822 if (INFO_LEVEL_IS_UNIX(info_level)) {
8824 * For CIFS UNIX extensions the target name may not exist.
8827 /* Always do lstat for UNIX calls. */
8828 SMB_VFS_LSTAT(conn, smb_fname);
8830 } else if (!VALID_STAT(smb_fname->st) &&
8831 SMB_VFS_STAT(conn, smb_fname)) {
8832 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8834 smb_fname_str_dbg(smb_fname),
8836 reply_nterror(req, map_nt_error_from_unix(errno));
8841 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8842 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8844 info_level,total_data));
8846 /* Realloc the parameter size */
8847 *pparams = (char *)SMB_REALLOC(*pparams,2);
8848 if (*pparams == NULL) {
8849 reply_nterror(req, NT_STATUS_NO_MEMORY);
8856 status = smbd_do_setfilepathinfo(conn, req, req,
8862 if (!NT_STATUS_IS_OK(status)) {
8863 if (open_was_deferred(req->xconn, req->mid)) {
8864 /* We have re-scheduled this call. */
8867 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8868 /* We have re-scheduled this call. */
8871 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8872 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8873 ERRSRV, ERRbadpath);
8876 if (info_level == SMB_POSIX_PATH_OPEN) {
8877 reply_openerror(req, status);
8882 * Invalid EA name needs to return 2 param bytes,
8883 * not a zero-length error packet.
8885 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8886 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8889 reply_nterror(req, status);
8894 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8900 /****************************************************************************
8901 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8902 ****************************************************************************/
8904 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8905 char **pparams, int total_params,
8906 char **ppdata, int total_data,
8907 unsigned int max_data_bytes)
8909 struct smb_filename *smb_dname = NULL;
8910 char *params = *pparams;
8911 char *pdata = *ppdata;
8912 char *directory = NULL;
8913 NTSTATUS status = NT_STATUS_OK;
8914 struct ea_list *ea_list = NULL;
8915 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
8916 TALLOC_CTX *ctx = talloc_tos();
8918 if (!CAN_WRITE(conn)) {
8919 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8923 if (total_params < 5) {
8924 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8928 if (req->posix_pathnames) {
8929 srvstr_get_path_posix(ctx,
8938 srvstr_get_path(ctx,
8947 if (!NT_STATUS_IS_OK(status)) {
8948 reply_nterror(req, status);
8952 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8954 status = filename_convert(ctx,
8956 req->flags2 & FLAGS2_DFS_PATHNAMES,
8962 if (!NT_STATUS_IS_OK(status)) {
8963 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8964 reply_botherror(req,
8965 NT_STATUS_PATH_NOT_COVERED,
8966 ERRSRV, ERRbadpath);
8969 reply_nterror(req, status);
8974 * OS/2 workplace shell seems to send SET_EA requests of "null"
8975 * length (4 bytes containing IVAL 4).
8976 * They seem to have no effect. Bug #3212. JRA.
8979 if (total_data && (total_data != 4)) {
8980 /* Any data in this call is an EA list. */
8981 if (total_data < 10) {
8982 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8986 if (IVAL(pdata,0) > total_data) {
8987 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8988 IVAL(pdata,0), (unsigned int)total_data));
8989 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8993 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8996 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9000 if (!lp_ea_support(SNUM(conn))) {
9001 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9005 /* If total_data == 4 Windows doesn't care what values
9006 * are placed in that field, it just ignores them.
9007 * The System i QNTC IBM SMB client puts bad values here,
9008 * so ignore them. */
9010 status = create_directory(conn, req, smb_dname);
9012 if (!NT_STATUS_IS_OK(status)) {
9013 reply_nterror(req, status);
9017 /* Try and set any given EA. */
9019 status = set_ea(conn, NULL, smb_dname, ea_list);
9020 if (!NT_STATUS_IS_OK(status)) {
9021 reply_nterror(req, status);
9026 /* Realloc the parameter and data sizes */
9027 *pparams = (char *)SMB_REALLOC(*pparams,2);
9028 if(*pparams == NULL) {
9029 reply_nterror(req, NT_STATUS_NO_MEMORY);
9036 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9039 TALLOC_FREE(smb_dname);
9043 /****************************************************************************
9044 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9045 We don't actually do this - we just send a null response.
9046 ****************************************************************************/
9048 static void call_trans2findnotifyfirst(connection_struct *conn,
9049 struct smb_request *req,
9050 char **pparams, int total_params,
9051 char **ppdata, int total_data,
9052 unsigned int max_data_bytes)
9054 char *params = *pparams;
9055 uint16_t info_level;
9057 if (total_params < 6) {
9058 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9062 info_level = SVAL(params,4);
9063 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9065 switch (info_level) {
9070 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9074 /* Realloc the parameter and data sizes */
9075 *pparams = (char *)SMB_REALLOC(*pparams,6);
9076 if (*pparams == NULL) {
9077 reply_nterror(req, NT_STATUS_NO_MEMORY);
9082 SSVAL(params,0,fnf_handle);
9083 SSVAL(params,2,0); /* No changes */
9084 SSVAL(params,4,0); /* No EA errors */
9091 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9096 /****************************************************************************
9097 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9098 changes). Currently this does nothing.
9099 ****************************************************************************/
9101 static void call_trans2findnotifynext(connection_struct *conn,
9102 struct smb_request *req,
9103 char **pparams, int total_params,
9104 char **ppdata, int total_data,
9105 unsigned int max_data_bytes)
9107 char *params = *pparams;
9109 DEBUG(3,("call_trans2findnotifynext\n"));
9111 /* Realloc the parameter and data sizes */
9112 *pparams = (char *)SMB_REALLOC(*pparams,4);
9113 if (*pparams == NULL) {
9114 reply_nterror(req, NT_STATUS_NO_MEMORY);
9119 SSVAL(params,0,0); /* No changes */
9120 SSVAL(params,2,0); /* No EA errors */
9122 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9127 /****************************************************************************
9128 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9129 ****************************************************************************/
9131 static void call_trans2getdfsreferral(connection_struct *conn,
9132 struct smb_request *req,
9133 char **pparams, int total_params,
9134 char **ppdata, int total_data,
9135 unsigned int max_data_bytes)
9137 char *params = *pparams;
9138 char *pathname = NULL;
9140 int max_referral_level;
9141 NTSTATUS status = NT_STATUS_OK;
9142 TALLOC_CTX *ctx = talloc_tos();
9144 DEBUG(10,("call_trans2getdfsreferral\n"));
9146 if (total_params < 3) {
9147 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9151 max_referral_level = SVAL(params,0);
9153 if(!lp_host_msdfs()) {
9154 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9158 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9159 total_params - 2, STR_TERMINATE);
9161 reply_nterror(req, NT_STATUS_NOT_FOUND);
9164 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9165 ppdata,&status)) < 0) {
9166 reply_nterror(req, status);
9170 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9171 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9172 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9177 #define LMCAT_SPL 0x53
9178 #define LMFUNC_GETJOBID 0x60
9180 /****************************************************************************
9181 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9182 ****************************************************************************/
9184 static void call_trans2ioctl(connection_struct *conn,
9185 struct smb_request *req,
9186 char **pparams, int total_params,
9187 char **ppdata, int total_data,
9188 unsigned int max_data_bytes)
9190 char *pdata = *ppdata;
9191 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9195 /* check for an invalid fid before proceeding */
9198 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9202 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9203 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9204 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9205 if (*ppdata == NULL) {
9206 reply_nterror(req, NT_STATUS_NO_MEMORY);
9211 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9212 CAN ACCEPT THIS IN UNICODE. JRA. */
9215 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9217 status = srvstr_push(pdata, req->flags2, pdata + 2,
9218 lp_netbios_name(), 15,
9219 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9220 if (!NT_STATUS_IS_OK(status)) {
9221 reply_nterror(req, status);
9224 status = srvstr_push(pdata, req->flags2, pdata+18,
9225 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9226 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9227 if (!NT_STATUS_IS_OK(status)) {
9228 reply_nterror(req, status);
9231 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9236 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9237 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9240 /****************************************************************************
9241 Reply to a SMBfindclose (stop trans2 directory search).
9242 ****************************************************************************/
9244 void reply_findclose(struct smb_request *req)
9247 struct smbd_server_connection *sconn = req->sconn;
9249 START_PROFILE(SMBfindclose);
9252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9253 END_PROFILE(SMBfindclose);
9257 dptr_num = SVALS(req->vwv+0, 0);
9259 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9261 dptr_close(sconn, &dptr_num);
9263 reply_outbuf(req, 0, 0);
9265 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9267 END_PROFILE(SMBfindclose);
9271 /****************************************************************************
9272 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9273 ****************************************************************************/
9275 void reply_findnclose(struct smb_request *req)
9279 START_PROFILE(SMBfindnclose);
9282 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9283 END_PROFILE(SMBfindnclose);
9287 dptr_num = SVAL(req->vwv+0, 0);
9289 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9291 /* We never give out valid handles for a
9292 findnotifyfirst - so any dptr_num is ok here.
9295 reply_outbuf(req, 0, 0);
9297 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9299 END_PROFILE(SMBfindnclose);
9303 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9304 struct trans_state *state)
9306 if (get_Protocol() >= PROTOCOL_NT1) {
9307 req->flags2 |= 0x40; /* IS_LONG_NAME */
9308 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9311 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9312 if (state->call != TRANSACT2_QFSINFO &&
9313 state->call != TRANSACT2_SETFSINFO) {
9314 DEBUG(0,("handle_trans2: encryption required "
9316 (unsigned int)state->call));
9317 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9322 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9324 /* Now we must call the relevant TRANS2 function */
9325 switch(state->call) {
9326 case TRANSACT2_OPEN:
9328 START_PROFILE(Trans2_open);
9329 call_trans2open(conn, req,
9330 &state->param, state->total_param,
9331 &state->data, state->total_data,
9332 state->max_data_return);
9333 END_PROFILE(Trans2_open);
9337 case TRANSACT2_FINDFIRST:
9339 START_PROFILE(Trans2_findfirst);
9340 call_trans2findfirst(conn, req,
9341 &state->param, state->total_param,
9342 &state->data, state->total_data,
9343 state->max_data_return);
9344 END_PROFILE(Trans2_findfirst);
9348 case TRANSACT2_FINDNEXT:
9350 START_PROFILE(Trans2_findnext);
9351 call_trans2findnext(conn, req,
9352 &state->param, state->total_param,
9353 &state->data, state->total_data,
9354 state->max_data_return);
9355 END_PROFILE(Trans2_findnext);
9359 case TRANSACT2_QFSINFO:
9361 START_PROFILE(Trans2_qfsinfo);
9362 call_trans2qfsinfo(conn, req,
9363 &state->param, state->total_param,
9364 &state->data, state->total_data,
9365 state->max_data_return);
9366 END_PROFILE(Trans2_qfsinfo);
9370 case TRANSACT2_SETFSINFO:
9372 START_PROFILE(Trans2_setfsinfo);
9373 call_trans2setfsinfo(conn, req,
9374 &state->param, state->total_param,
9375 &state->data, state->total_data,
9376 state->max_data_return);
9377 END_PROFILE(Trans2_setfsinfo);
9381 case TRANSACT2_QPATHINFO:
9382 case TRANSACT2_QFILEINFO:
9384 START_PROFILE(Trans2_qpathinfo);
9385 call_trans2qfilepathinfo(conn, req, state->call,
9386 &state->param, state->total_param,
9387 &state->data, state->total_data,
9388 state->max_data_return);
9389 END_PROFILE(Trans2_qpathinfo);
9393 case TRANSACT2_SETPATHINFO:
9394 case TRANSACT2_SETFILEINFO:
9396 START_PROFILE(Trans2_setpathinfo);
9397 call_trans2setfilepathinfo(conn, req, state->call,
9398 &state->param, state->total_param,
9399 &state->data, state->total_data,
9400 state->max_data_return);
9401 END_PROFILE(Trans2_setpathinfo);
9405 case TRANSACT2_FINDNOTIFYFIRST:
9407 START_PROFILE(Trans2_findnotifyfirst);
9408 call_trans2findnotifyfirst(conn, req,
9409 &state->param, state->total_param,
9410 &state->data, state->total_data,
9411 state->max_data_return);
9412 END_PROFILE(Trans2_findnotifyfirst);
9416 case TRANSACT2_FINDNOTIFYNEXT:
9418 START_PROFILE(Trans2_findnotifynext);
9419 call_trans2findnotifynext(conn, req,
9420 &state->param, state->total_param,
9421 &state->data, state->total_data,
9422 state->max_data_return);
9423 END_PROFILE(Trans2_findnotifynext);
9427 case TRANSACT2_MKDIR:
9429 START_PROFILE(Trans2_mkdir);
9430 call_trans2mkdir(conn, req,
9431 &state->param, state->total_param,
9432 &state->data, state->total_data,
9433 state->max_data_return);
9434 END_PROFILE(Trans2_mkdir);
9438 case TRANSACT2_GET_DFS_REFERRAL:
9440 START_PROFILE(Trans2_get_dfs_referral);
9441 call_trans2getdfsreferral(conn, req,
9442 &state->param, state->total_param,
9443 &state->data, state->total_data,
9444 state->max_data_return);
9445 END_PROFILE(Trans2_get_dfs_referral);
9449 case TRANSACT2_IOCTL:
9451 START_PROFILE(Trans2_ioctl);
9452 call_trans2ioctl(conn, req,
9453 &state->param, state->total_param,
9454 &state->data, state->total_data,
9455 state->max_data_return);
9456 END_PROFILE(Trans2_ioctl);
9461 /* Error in request */
9462 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9463 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9467 /****************************************************************************
9468 Reply to a SMBtrans2.
9469 ****************************************************************************/
9471 void reply_trans2(struct smb_request *req)
9473 connection_struct *conn = req->conn;
9478 unsigned int tran_call;
9479 struct trans_state *state;
9482 START_PROFILE(SMBtrans2);
9484 if (req->wct < 14) {
9485 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9486 END_PROFILE(SMBtrans2);
9490 dsoff = SVAL(req->vwv+12, 0);
9491 dscnt = SVAL(req->vwv+11, 0);
9492 psoff = SVAL(req->vwv+10, 0);
9493 pscnt = SVAL(req->vwv+9, 0);
9494 tran_call = SVAL(req->vwv+14, 0);
9496 result = allow_new_trans(conn->pending_trans, req->mid);
9497 if (!NT_STATUS_IS_OK(result)) {
9498 DEBUG(2, ("Got invalid trans2 request: %s\n",
9499 nt_errstr(result)));
9500 reply_nterror(req, result);
9501 END_PROFILE(SMBtrans2);
9506 switch (tran_call) {
9507 /* List the allowed trans2 calls on IPC$ */
9508 case TRANSACT2_OPEN:
9509 case TRANSACT2_GET_DFS_REFERRAL:
9510 case TRANSACT2_QFILEINFO:
9511 case TRANSACT2_QFSINFO:
9512 case TRANSACT2_SETFSINFO:
9515 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9516 END_PROFILE(SMBtrans2);
9521 if ((state = talloc(conn, struct trans_state)) == NULL) {
9522 DEBUG(0, ("talloc failed\n"));
9523 reply_nterror(req, NT_STATUS_NO_MEMORY);
9524 END_PROFILE(SMBtrans2);
9528 state->cmd = SMBtrans2;
9530 state->mid = req->mid;
9531 state->vuid = req->vuid;
9532 state->setup_count = SVAL(req->vwv+13, 0);
9533 state->setup = NULL;
9534 state->total_param = SVAL(req->vwv+0, 0);
9535 state->param = NULL;
9536 state->total_data = SVAL(req->vwv+1, 0);
9538 state->max_param_return = SVAL(req->vwv+2, 0);
9539 state->max_data_return = SVAL(req->vwv+3, 0);
9540 state->max_setup_return = SVAL(req->vwv+4, 0);
9541 state->close_on_completion = BITSETW(req->vwv+5, 0);
9542 state->one_way = BITSETW(req->vwv+5, 1);
9544 state->call = tran_call;
9546 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9547 is so as a sanity check */
9548 if (state->setup_count != 1) {
9550 * Need to have rc=0 for ioctl to get job id for OS/2.
9551 * Network printing will fail if function is not successful.
9552 * Similar function in reply.c will be used if protocol
9553 * is LANMAN1.0 instead of LM1.2X002.
9554 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9555 * outbuf doesn't have to be set(only job id is used).
9557 if ( (state->setup_count == 4)
9558 && (tran_call == TRANSACT2_IOCTL)
9559 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9560 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9561 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9563 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9564 DEBUG(2,("Transaction is %d\n",tran_call));
9566 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9567 END_PROFILE(SMBtrans2);
9572 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9575 if (state->total_data) {
9577 if (trans_oob(state->total_data, 0, dscnt)
9578 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9582 /* Can't use talloc here, the core routines do realloc on the
9583 * params and data. */
9584 state->data = (char *)SMB_MALLOC(state->total_data);
9585 if (state->data == NULL) {
9586 DEBUG(0,("reply_trans2: data malloc fail for %u "
9587 "bytes !\n", (unsigned int)state->total_data));
9589 reply_nterror(req, NT_STATUS_NO_MEMORY);
9590 END_PROFILE(SMBtrans2);
9594 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9597 if (state->total_param) {
9599 if (trans_oob(state->total_param, 0, pscnt)
9600 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9604 /* Can't use talloc here, the core routines do realloc on the
9605 * params and data. */
9606 state->param = (char *)SMB_MALLOC(state->total_param);
9607 if (state->param == NULL) {
9608 DEBUG(0,("reply_trans: param malloc fail for %u "
9609 "bytes !\n", (unsigned int)state->total_param));
9610 SAFE_FREE(state->data);
9612 reply_nterror(req, NT_STATUS_NO_MEMORY);
9613 END_PROFILE(SMBtrans2);
9617 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9620 state->received_data = dscnt;
9621 state->received_param = pscnt;
9623 if ((state->received_param == state->total_param) &&
9624 (state->received_data == state->total_data)) {
9626 handle_trans2(conn, req, state);
9628 SAFE_FREE(state->data);
9629 SAFE_FREE(state->param);
9631 END_PROFILE(SMBtrans2);
9635 DLIST_ADD(conn->pending_trans, state);
9637 /* We need to send an interim response then receive the rest
9638 of the parameter/data bytes */
9639 reply_outbuf(req, 0, 0);
9640 show_msg((char *)req->outbuf);
9641 END_PROFILE(SMBtrans2);
9646 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9647 SAFE_FREE(state->data);
9648 SAFE_FREE(state->param);
9650 END_PROFILE(SMBtrans2);
9651 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9655 /****************************************************************************
9656 Reply to a SMBtranss2
9657 ****************************************************************************/
9659 void reply_transs2(struct smb_request *req)
9661 connection_struct *conn = req->conn;
9662 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9663 struct trans_state *state;
9665 START_PROFILE(SMBtranss2);
9667 show_msg((const char *)req->inbuf);
9669 /* Windows clients expect all replies to
9670 a transact secondary (SMBtranss2 0x33)
9671 to have a command code of transact
9672 (SMBtrans2 0x32). See bug #8989
9673 and also [MS-CIFS] section 2.2.4.47.2
9676 req->cmd = SMBtrans2;
9679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9680 END_PROFILE(SMBtranss2);
9684 for (state = conn->pending_trans; state != NULL;
9685 state = state->next) {
9686 if (state->mid == req->mid) {
9691 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9692 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9693 END_PROFILE(SMBtranss2);
9697 /* Revise state->total_param and state->total_data in case they have
9698 changed downwards */
9700 if (SVAL(req->vwv+0, 0) < state->total_param)
9701 state->total_param = SVAL(req->vwv+0, 0);
9702 if (SVAL(req->vwv+1, 0) < state->total_data)
9703 state->total_data = SVAL(req->vwv+1, 0);
9705 pcnt = SVAL(req->vwv+2, 0);
9706 poff = SVAL(req->vwv+3, 0);
9707 pdisp = SVAL(req->vwv+4, 0);
9709 dcnt = SVAL(req->vwv+5, 0);
9710 doff = SVAL(req->vwv+6, 0);
9711 ddisp = SVAL(req->vwv+7, 0);
9713 state->received_param += pcnt;
9714 state->received_data += dcnt;
9716 if ((state->received_data > state->total_data) ||
9717 (state->received_param > state->total_param))
9721 if (trans_oob(state->total_param, pdisp, pcnt)
9722 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9725 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9729 if (trans_oob(state->total_data, ddisp, dcnt)
9730 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9733 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9736 if ((state->received_param < state->total_param) ||
9737 (state->received_data < state->total_data)) {
9738 END_PROFILE(SMBtranss2);
9742 handle_trans2(conn, req, state);
9744 DLIST_REMOVE(conn->pending_trans, state);
9745 SAFE_FREE(state->data);
9746 SAFE_FREE(state->param);
9749 END_PROFILE(SMBtranss2);
9754 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9755 DLIST_REMOVE(conn->pending_trans, state);
9756 SAFE_FREE(state->data);
9757 SAFE_FREE(state->param);
9759 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9760 END_PROFILE(SMBtranss2);