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/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS check_access(connection_struct *conn,
60 const struct smb_filename *smb_fname,
64 if (!(fsp->access_mask & access_mask)) {
65 return NT_STATUS_ACCESS_DENIED;
68 NTSTATUS status = smbd_check_access_rights(conn,
72 if (!NT_STATUS_IS_OK(status)) {
79 /********************************************************************
80 Roundup a value to the nearest allocation roundup size boundary.
81 Only do this for Windows clients.
82 ********************************************************************/
84 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
86 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
88 /* Only roundup for Windows clients. */
89 enum remote_arch_types ra_type = get_remote_arch();
90 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
91 val = SMB_ROUNDUP(val,rval);
96 /********************************************************************
97 Create a 64 bit FileIndex. If the file is on the same device as
98 the root of the share, just return the 64-bit inode. If it isn't,
99 mangle as we used to do.
100 ********************************************************************/
102 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
105 if (conn->base_share_dev == psbuf->st_ex_dev) {
106 return (uint64_t)psbuf->st_ex_ino;
108 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
109 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
113 /****************************************************************************
114 Utility functions for dealing with extended attributes.
115 ****************************************************************************/
117 /****************************************************************************
118 Refuse to allow clients to overwrite our private xattrs.
119 ****************************************************************************/
121 static bool samba_private_attr_name(const char *unix_ea_name)
123 static const char * const prohibited_ea_names[] = {
124 SAMBA_POSIX_INHERITANCE_EA_NAME,
125 SAMBA_XATTR_DOS_ATTRIB,
133 for (i = 0; prohibited_ea_names[i]; i++) {
134 if (strequal( prohibited_ea_names[i], unix_ea_name))
137 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
138 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
144 /****************************************************************************
145 Get one EA value. Fill in a struct ea_struct.
146 ****************************************************************************/
148 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
149 files_struct *fsp, const char *fname,
150 const char *ea_name, struct ea_struct *pea)
152 /* Get the value of this xattr. Max size is 64k. */
153 size_t attr_size = 256;
159 val = talloc_realloc(mem_ctx, val, char, attr_size);
161 return NT_STATUS_NO_MEMORY;
164 if (fsp && fsp->fh->fd != -1) {
165 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
167 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
170 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
176 return map_nt_error_from_unix(errno);
179 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
180 dump_data(10, (uint8 *)val, sizeret);
183 if (strnequal(ea_name, "user.", 5)) {
184 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
186 pea->name = talloc_strdup(mem_ctx, ea_name);
188 if (pea->name == NULL) {
190 return NT_STATUS_NO_MEMORY;
192 pea->value.data = (unsigned char *)val;
193 pea->value.length = (size_t)sizeret;
197 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
198 files_struct *fsp, const char *fname,
199 char ***pnames, size_t *pnum_names)
201 /* Get a list of all xattrs. Max namesize is 64k. */
202 size_t ea_namelist_size = 1024;
203 char *ea_namelist = NULL;
208 ssize_t sizeret = -1;
210 if (!lp_ea_support(SNUM(conn))) {
219 * TALLOC the result early to get the talloc hierarchy right.
222 names = talloc_array(mem_ctx, char *, 1);
224 DEBUG(0, ("talloc failed\n"));
225 return NT_STATUS_NO_MEMORY;
228 while (ea_namelist_size <= 65536) {
230 ea_namelist = talloc_realloc(
231 names, ea_namelist, char, ea_namelist_size);
232 if (ea_namelist == NULL) {
233 DEBUG(0, ("talloc failed\n"));
235 return NT_STATUS_NO_MEMORY;
238 if (fsp && fsp->fh->fd != -1) {
239 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
242 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
246 if ((sizeret == -1) && (errno == ERANGE)) {
247 ea_namelist_size *= 2;
256 return map_nt_error_from_unix(errno);
259 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
260 (unsigned int)sizeret));
272 * Ensure the result is 0-terminated
275 if (ea_namelist[sizeret-1] != '\0') {
277 return NT_STATUS_INTERNAL_ERROR;
285 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
289 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
291 DEBUG(0, ("talloc failed\n"));
293 return NT_STATUS_NO_MEMORY;
299 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
300 names[num_names++] = p;
308 *pnum_names = num_names;
312 /****************************************************************************
313 Return a linked list of the total EA's. Plus the total size
314 ****************************************************************************/
316 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
317 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
319 /* Get a list of all xattrs. Max namesize is 64k. */
322 struct ea_list *ea_list_head = NULL;
328 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
331 if (!NT_STATUS_IS_OK(status)) {
335 if (num_names == 0) {
340 for (i=0; i<num_names; i++) {
341 struct ea_list *listp;
344 if (strnequal(names[i], "system.", 7)
345 || samba_private_attr_name(names[i]))
349 * Filter out any underlying POSIX EA names
350 * that a Windows client can't handle.
352 if (!lp_posix_pathnames() &&
353 is_invalid_windows_ea_name(names[i])) {
357 listp = talloc(mem_ctx, struct ea_list);
359 return NT_STATUS_NO_MEMORY;
362 status = get_ea_value(listp, conn, fsp,
366 if (!NT_STATUS_IS_OK(status)) {
371 if (listp->ea.value.length == 0) {
373 * We can never return a zero length EA.
374 * Windows reports the EA's as corrupted.
380 push_ascii_fstring(dos_ea_name, listp->ea.name);
383 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
385 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
386 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
387 (unsigned int)listp->ea.value.length));
389 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
393 /* Add on 4 for total length. */
394 if (*pea_total_len) {
398 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
399 (unsigned int)*pea_total_len));
401 *ea_list = ea_list_head;
405 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
406 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
411 if (!lp_ea_support(SNUM(conn))) {
415 if (is_ntfs_stream_smb_fname(smb_fname)) {
416 return NT_STATUS_INVALID_PARAMETER;
419 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
422 /****************************************************************************
423 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
425 ****************************************************************************/
427 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
428 connection_struct *conn, struct ea_list *ea_list)
430 unsigned int ret_data_size = 4;
433 SMB_ASSERT(total_data_size >= 4);
435 if (!lp_ea_support(SNUM(conn))) {
440 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
443 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
444 dos_namelen = strlen(dos_ea_name);
445 if (dos_namelen > 255 || dos_namelen == 0) {
448 if (ea_list->ea.value.length > 65535) {
451 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
455 /* We know we have room. */
456 SCVAL(p,0,ea_list->ea.flags);
457 SCVAL(p,1,dos_namelen);
458 SSVAL(p,2,ea_list->ea.value.length);
459 strlcpy(p+4, dos_ea_name, dos_namelen+1);
460 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
462 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
463 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
466 ret_data_size = PTR_DIFF(p, pdata);
467 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
468 SIVAL(pdata,0,ret_data_size);
469 return ret_data_size;
472 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
474 unsigned int total_data_size,
475 unsigned int *ret_data_size,
476 connection_struct *conn,
477 struct ea_list *ea_list)
479 uint8_t *p = (uint8_t *)pdata;
480 uint8_t *last_start = NULL;
481 bool do_store_data = (pdata != NULL);
485 if (!lp_ea_support(SNUM(conn))) {
486 return NT_STATUS_NO_EAS_ON_FILE;
489 for (; ea_list; ea_list = ea_list->next) {
495 if (last_start != NULL && do_store_data) {
496 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
500 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
501 dos_namelen = strlen(dos_ea_name);
502 if (dos_namelen > 255 || dos_namelen == 0) {
503 return NT_STATUS_INTERNAL_ERROR;
505 if (ea_list->ea.value.length > 65535) {
506 return NT_STATUS_INTERNAL_ERROR;
509 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
512 pad = (4 - (this_size % 4)) % 4;
517 if (this_size > total_data_size) {
518 return NT_STATUS_INFO_LENGTH_MISMATCH;
521 /* We know we have room. */
522 SIVAL(p, 0x00, 0); /* next offset */
523 SCVAL(p, 0x04, ea_list->ea.flags);
524 SCVAL(p, 0x05, dos_namelen);
525 SSVAL(p, 0x06, ea_list->ea.value.length);
526 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
527 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
529 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
533 total_data_size -= this_size;
539 *ret_data_size = PTR_DIFF(p, pdata);
540 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
544 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
546 size_t total_ea_len = 0;
548 struct ea_list *ea_list = NULL;
550 if (!lp_ea_support(SNUM(conn))) {
553 mem_ctx = talloc_stackframe();
555 /* If this is a stream fsp, then we need to instead find the
556 * estimated ea len from the main file, not the stream
557 * (streams cannot have EAs), but the estimate isn't just 0 in
559 if (is_ntfs_stream_smb_fname(smb_fname)) {
562 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
563 if(conn->sconn->using_smb2) {
565 unsigned int ret_data_size;
567 * We're going to be using fill_ea_chained_buffer() to
568 * marshall EA's - this size is significantly larger
569 * than the SMB1 buffer. Re-calculate the size without
572 status = fill_ea_chained_buffer(mem_ctx,
578 if (!NT_STATUS_IS_OK(status)) {
581 total_ea_len = ret_data_size;
583 TALLOC_FREE(mem_ctx);
587 /****************************************************************************
588 Ensure the EA name is case insensitive by matching any existing EA name.
589 ****************************************************************************/
591 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
594 TALLOC_CTX *mem_ctx = talloc_tos();
595 struct ea_list *ea_list;
596 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
597 if (!NT_STATUS_IS_OK(status)) {
601 for (; ea_list; ea_list = ea_list->next) {
602 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
603 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
604 &unix_ea_name[5], ea_list->ea.name));
605 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
611 /****************************************************************************
612 Set or delete an extended attribute.
613 ****************************************************************************/
615 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
616 const struct smb_filename *smb_fname, struct ea_list *ea_list)
621 if (!lp_ea_support(SNUM(conn))) {
622 return NT_STATUS_EAS_NOT_SUPPORTED;
625 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
626 if (!NT_STATUS_IS_OK(status)) {
630 /* Setting EAs on streams isn't supported. */
631 if (is_ntfs_stream_smb_fname(smb_fname)) {
632 return NT_STATUS_INVALID_PARAMETER;
636 * Filter out invalid Windows EA names - before
637 * we set *any* of them.
640 if (ea_list_has_invalid_name(ea_list)) {
641 return STATUS_INVALID_EA_NAME;
644 fname = smb_fname->base_name;
646 for (;ea_list; ea_list = ea_list->next) {
648 fstring unix_ea_name;
650 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
651 fstrcat(unix_ea_name, ea_list->ea.name);
653 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
655 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
657 if (samba_private_attr_name(unix_ea_name)) {
658 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
659 return NT_STATUS_ACCESS_DENIED;
662 if (ea_list->ea.value.length == 0) {
663 /* Remove the attribute. */
664 if (fsp && (fsp->fh->fd != -1)) {
665 DEBUG(10,("set_ea: deleting ea name %s on "
666 "file %s by file descriptor.\n",
667 unix_ea_name, fsp_str_dbg(fsp)));
668 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
670 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
671 unix_ea_name, fname));
672 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
675 /* Removing a non existent attribute always succeeds. */
676 if (ret == -1 && errno == ENOATTR) {
677 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
683 if (fsp && (fsp->fh->fd != -1)) {
684 DEBUG(10,("set_ea: setting ea name %s on file "
685 "%s by file descriptor.\n",
686 unix_ea_name, fsp_str_dbg(fsp)));
687 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
688 ea_list->ea.value.data, ea_list->ea.value.length, 0);
690 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
691 unix_ea_name, fname));
692 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
693 ea_list->ea.value.data, ea_list->ea.value.length, 0);
699 if (errno == ENOTSUP) {
700 return NT_STATUS_EAS_NOT_SUPPORTED;
703 return map_nt_error_from_unix(errno);
709 /****************************************************************************
710 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
711 ****************************************************************************/
713 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
715 struct ea_list *ea_list_head = NULL;
716 size_t converted_size, offset = 0;
718 while (offset + 2 < data_size) {
719 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
720 unsigned int namelen = CVAL(pdata,offset);
722 offset++; /* Go past the namelen byte. */
724 /* integer wrap paranioa. */
725 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
726 (offset > data_size) || (namelen > data_size) ||
727 (offset + namelen >= data_size)) {
730 /* Ensure the name is null terminated. */
731 if (pdata[offset + namelen] != '\0') {
734 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
736 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
737 "failed: %s", strerror(errno)));
743 offset += (namelen + 1); /* Go past the name + terminating zero. */
744 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
745 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
751 /****************************************************************************
752 Read one EA list entry from the buffer.
753 ****************************************************************************/
755 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
757 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
759 unsigned int namelen;
760 size_t converted_size;
770 eal->ea.flags = CVAL(pdata,0);
771 namelen = CVAL(pdata,1);
772 val_len = SVAL(pdata,2);
774 if (4 + namelen + 1 + val_len > data_size) {
778 /* Ensure the name is null terminated. */
779 if (pdata[namelen + 4] != '\0') {
782 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
783 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
790 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
791 if (!eal->ea.value.data) {
795 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
797 /* Ensure we're null terminated just in case we print the value. */
798 eal->ea.value.data[val_len] = '\0';
799 /* But don't count the null. */
800 eal->ea.value.length--;
803 *pbytes_used = 4 + namelen + 1 + val_len;
806 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
807 dump_data(10, eal->ea.value.data, eal->ea.value.length);
812 /****************************************************************************
813 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
814 ****************************************************************************/
816 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
818 struct ea_list *ea_list_head = NULL;
820 size_t bytes_used = 0;
822 while (offset < data_size) {
823 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
829 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
830 offset += bytes_used;
836 /****************************************************************************
837 Count the total EA size needed.
838 ****************************************************************************/
840 static size_t ea_list_size(struct ea_list *ealist)
843 struct ea_list *listp;
846 for (listp = ealist; listp; listp = listp->next) {
847 push_ascii_fstring(dos_ea_name, listp->ea.name);
848 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
850 /* Add on 4 for total length. */
858 /****************************************************************************
859 Return a union of EA's from a file list and a list of names.
860 The TALLOC context for the two lists *MUST* be identical as we steal
861 memory from one list to add to another. JRA.
862 ****************************************************************************/
864 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
866 struct ea_list *nlistp, *flistp;
868 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
869 for (flistp = file_list; flistp; flistp = flistp->next) {
870 if (strequal(nlistp->ea.name, flistp->ea.name)) {
876 /* Copy the data from this entry. */
877 nlistp->ea.flags = flistp->ea.flags;
878 nlistp->ea.value = flistp->ea.value;
881 nlistp->ea.flags = 0;
882 ZERO_STRUCT(nlistp->ea.value);
886 *total_ea_len = ea_list_size(name_list);
890 /****************************************************************************
891 Send the required number of replies back.
892 We assume all fields other than the data fields are
893 set correctly for the type of call.
894 HACK ! Always assumes smb_setup field is zero.
895 ****************************************************************************/
897 void send_trans2_replies(connection_struct *conn,
898 struct smb_request *req,
906 /* As we are using a protocol > LANMAN1 then the max_send
907 variable must have been set in the sessetupX call.
908 This takes precedence over the max_xmit field in the
909 global struct. These different max_xmit variables should
910 be merged as this is now too confusing */
912 int data_to_send = datasize;
913 int params_to_send = paramsize;
915 const char *pp = params;
916 const char *pd = pdata;
917 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
918 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
919 int data_alignment_offset = 0;
920 bool overflow = False;
921 struct smbd_server_connection *sconn = req->sconn;
922 int max_send = sconn->smb1.sessions.max_send;
924 /* Modify the data_to_send and datasize and set the error if
925 we're trying to send more than max_data_bytes. We still send
926 the part of the packet(s) that fit. Strange, but needed
929 if (max_data_bytes > 0 && datasize > max_data_bytes) {
930 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
931 max_data_bytes, datasize ));
932 datasize = data_to_send = max_data_bytes;
936 /* If there genuinely are no parameters or data to send just send the empty packet */
938 if(params_to_send == 0 && data_to_send == 0) {
939 reply_outbuf(req, 10, 0);
940 if (NT_STATUS_V(status)) {
943 ntstatus_to_dos(status, &eclass, &ecode);
944 error_packet_set((char *)req->outbuf,
945 eclass, ecode, status,
948 show_msg((char *)req->outbuf);
949 if (!srv_send_smb(sconn,
952 IS_CONN_ENCRYPTED(conn),
954 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
956 TALLOC_FREE(req->outbuf);
960 /* When sending params and data ensure that both are nicely aligned */
961 /* Only do this alignment when there is also data to send - else
962 can cause NT redirector problems. */
964 if (((params_to_send % 4) != 0) && (data_to_send != 0))
965 data_alignment_offset = 4 - (params_to_send % 4);
967 /* Space is bufsize minus Netbios over TCP header minus SMB header */
968 /* The alignment_offset is to align the param bytes on an even byte
969 boundary. NT 4.0 Beta needs this to work correctly. */
971 useable_space = max_send - (smb_size
974 + data_alignment_offset);
976 if (useable_space < 0) {
977 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
978 "= %d!!!", useable_space));
979 exit_server_cleanly("send_trans2_replies: Not enough space");
982 while (params_to_send || data_to_send) {
983 /* Calculate whether we will totally or partially fill this packet */
985 total_sent_thistime = params_to_send + data_to_send;
987 /* We can never send more than useable_space */
989 * Note that 'useable_space' does not include the alignment offsets,
990 * but we must include the alignment offsets in the calculation of
991 * the length of the data we send over the wire, as the alignment offsets
992 * are sent here. Fix from Marc_Jacobsen@hp.com.
995 total_sent_thistime = MIN(total_sent_thistime, useable_space);
997 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
998 + data_alignment_offset);
1000 /* Set total params and data to be sent */
1001 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1002 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1004 /* Calculate how many parameters and data we can fit into
1005 * this packet. Parameters get precedence
1008 params_sent_thistime = MIN(params_to_send,useable_space);
1009 data_sent_thistime = useable_space - params_sent_thistime;
1010 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1012 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1014 /* smb_proff is the offset from the start of the SMB header to the
1015 parameter bytes, however the first 4 bytes of outbuf are
1016 the Netbios over TCP header. Thus use smb_base() to subtract
1017 them from the calculation */
1019 SSVAL(req->outbuf,smb_proff,
1020 ((smb_buf(req->outbuf)+alignment_offset)
1021 - smb_base(req->outbuf)));
1023 if(params_sent_thistime == 0)
1024 SSVAL(req->outbuf,smb_prdisp,0);
1026 /* Absolute displacement of param bytes sent in this packet */
1027 SSVAL(req->outbuf,smb_prdisp,pp - params);
1029 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1030 if(data_sent_thistime == 0) {
1031 SSVAL(req->outbuf,smb_droff,0);
1032 SSVAL(req->outbuf,smb_drdisp, 0);
1034 /* The offset of the data bytes is the offset of the
1035 parameter bytes plus the number of parameters being sent this time */
1036 SSVAL(req->outbuf, smb_droff,
1037 ((smb_buf(req->outbuf)+alignment_offset)
1038 - smb_base(req->outbuf))
1039 + params_sent_thistime + data_alignment_offset);
1040 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1043 /* Initialize the padding for alignment */
1045 if (alignment_offset != 0) {
1046 memset(smb_buf(req->outbuf), 0, alignment_offset);
1049 /* Copy the param bytes into the packet */
1051 if(params_sent_thistime) {
1052 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1053 params_sent_thistime);
1056 /* Copy in the data bytes */
1057 if(data_sent_thistime) {
1058 if (data_alignment_offset != 0) {
1059 memset((smb_buf(req->outbuf)+alignment_offset+
1060 params_sent_thistime), 0,
1061 data_alignment_offset);
1063 memcpy(smb_buf(req->outbuf)+alignment_offset
1064 +params_sent_thistime+data_alignment_offset,
1065 pd,data_sent_thistime);
1068 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1069 params_sent_thistime, data_sent_thistime, useable_space));
1070 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1071 params_to_send, data_to_send, paramsize, datasize));
1074 error_packet_set((char *)req->outbuf,
1075 ERRDOS,ERRbufferoverflow,
1076 STATUS_BUFFER_OVERFLOW,
1078 } else if (NT_STATUS_V(status)) {
1081 ntstatus_to_dos(status, &eclass, &ecode);
1082 error_packet_set((char *)req->outbuf,
1083 eclass, ecode, status,
1087 /* Send the packet */
1088 show_msg((char *)req->outbuf);
1089 if (!srv_send_smb(sconn,
1090 (char *)req->outbuf,
1091 true, req->seqnum+1,
1092 IS_CONN_ENCRYPTED(conn),
1094 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1096 TALLOC_FREE(req->outbuf);
1098 pp += params_sent_thistime;
1099 pd += data_sent_thistime;
1101 params_to_send -= params_sent_thistime;
1102 data_to_send -= data_sent_thistime;
1105 if(params_to_send < 0 || data_to_send < 0) {
1106 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1107 params_to_send, data_to_send));
1115 /****************************************************************************
1116 Reply to a TRANSACT2_OPEN.
1117 ****************************************************************************/
1119 static void call_trans2open(connection_struct *conn,
1120 struct smb_request *req,
1121 char **pparams, int total_params,
1122 char **ppdata, int total_data,
1123 unsigned int max_data_bytes)
1125 struct smb_filename *smb_fname = NULL;
1126 char *params = *pparams;
1127 char *pdata = *ppdata;
1130 bool oplock_request;
1132 bool return_additional_info;
1141 int fattr=0,mtime=0;
1142 SMB_INO_T inode = 0;
1145 struct ea_list *ea_list = NULL;
1150 uint32 create_disposition;
1151 uint32 create_options = 0;
1152 uint32_t private_flags = 0;
1153 TALLOC_CTX *ctx = talloc_tos();
1156 * Ensure we have enough parameters to perform the operation.
1159 if (total_params < 29) {
1160 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1164 flags = SVAL(params, 0);
1165 deny_mode = SVAL(params, 2);
1166 open_attr = SVAL(params,6);
1167 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1168 if (oplock_request) {
1169 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1173 return_additional_info = BITSETW(params,0);
1174 open_sattr = SVAL(params, 4);
1175 open_time = make_unix_date3(params+8);
1177 open_ofun = SVAL(params,12);
1178 open_size = IVAL(params,14);
1179 pname = ¶ms[28];
1182 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1186 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1187 total_params - 28, STR_TERMINATE,
1189 if (!NT_STATUS_IS_OK(status)) {
1190 reply_nterror(req, status);
1194 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1195 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1196 (unsigned int)open_ofun, open_size));
1198 status = filename_convert(ctx,
1200 req->flags2 & FLAGS2_DFS_PATHNAMES,
1205 if (!NT_STATUS_IS_OK(status)) {
1206 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1207 reply_botherror(req,
1208 NT_STATUS_PATH_NOT_COVERED,
1209 ERRSRV, ERRbadpath);
1212 reply_nterror(req, status);
1216 if (open_ofun == 0) {
1217 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1221 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1223 &access_mask, &share_mode,
1224 &create_disposition,
1227 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1231 /* Any data in this call is an EA list. */
1232 if (total_data && (total_data != 4)) {
1233 if (total_data < 10) {
1234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1238 if (IVAL(pdata,0) > total_data) {
1239 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1240 IVAL(pdata,0), (unsigned int)total_data));
1241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1245 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1248 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1252 if (!lp_ea_support(SNUM(conn))) {
1253 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1257 if (ea_list_has_invalid_name(ea_list)) {
1259 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1260 if(*pparams == NULL ) {
1261 reply_nterror(req, NT_STATUS_NO_MEMORY);
1265 memset(params, '\0', param_len);
1266 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1267 params, param_len, NULL, 0, max_data_bytes);
1272 status = SMB_VFS_CREATE_FILE(
1275 0, /* root_dir_fid */
1276 smb_fname, /* fname */
1277 access_mask, /* access_mask */
1278 share_mode, /* share_access */
1279 create_disposition, /* create_disposition*/
1280 create_options, /* create_options */
1281 open_attr, /* file_attributes */
1282 oplock_request, /* oplock_request */
1283 open_size, /* allocation_size */
1286 ea_list, /* ea_list */
1288 &smb_action); /* psbuf */
1290 if (!NT_STATUS_IS_OK(status)) {
1291 if (open_was_deferred(req->sconn, req->mid)) {
1292 /* We have re-scheduled this call. */
1295 reply_openerror(req, status);
1299 size = get_file_size_stat(&smb_fname->st);
1300 fattr = dos_mode(conn, smb_fname);
1301 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1302 inode = smb_fname->st.st_ex_ino;
1303 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1304 close_file(req, fsp, ERROR_CLOSE);
1305 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1309 /* Realloc the size of parameters and data we will return */
1310 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1311 if(*pparams == NULL ) {
1312 reply_nterror(req, NT_STATUS_NO_MEMORY);
1317 SSVAL(params,0,fsp->fnum);
1318 SSVAL(params,2,fattr);
1319 srv_put_dos_date2(params,4, mtime);
1320 SIVAL(params,8, (uint32)size);
1321 SSVAL(params,12,deny_mode);
1322 SSVAL(params,14,0); /* open_type - file or directory. */
1323 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1325 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1326 smb_action |= EXTENDED_OPLOCK_GRANTED;
1329 SSVAL(params,18,smb_action);
1332 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1334 SIVAL(params,20,inode);
1335 SSVAL(params,24,0); /* Padding. */
1337 uint32 ea_size = estimate_ea_size(conn, fsp,
1339 SIVAL(params, 26, ea_size);
1341 SIVAL(params, 26, 0);
1344 /* Send the required number of replies */
1345 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1347 TALLOC_FREE(smb_fname);
1350 /*********************************************************
1351 Routine to check if a given string matches exactly.
1352 as a special case a mask of "." does NOT match. That
1353 is required for correct wildcard semantics
1354 Case can be significant or not.
1355 **********************************************************/
1357 static bool exact_match(bool has_wild,
1358 bool case_sensitive,
1362 if (mask[0] == '.' && mask[1] == 0) {
1370 if (case_sensitive) {
1371 return strcmp(str,mask)==0;
1373 return strcasecmp_m(str,mask) == 0;
1377 /****************************************************************************
1378 Return the filetype for UNIX extensions.
1379 ****************************************************************************/
1381 static uint32 unix_filetype(mode_t mode)
1384 return UNIX_TYPE_FILE;
1385 else if(S_ISDIR(mode))
1386 return UNIX_TYPE_DIR;
1388 else if(S_ISLNK(mode))
1389 return UNIX_TYPE_SYMLINK;
1392 else if(S_ISCHR(mode))
1393 return UNIX_TYPE_CHARDEV;
1396 else if(S_ISBLK(mode))
1397 return UNIX_TYPE_BLKDEV;
1400 else if(S_ISFIFO(mode))
1401 return UNIX_TYPE_FIFO;
1404 else if(S_ISSOCK(mode))
1405 return UNIX_TYPE_SOCKET;
1408 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1409 return UNIX_TYPE_UNKNOWN;
1412 /****************************************************************************
1413 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1414 ****************************************************************************/
1416 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1418 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1419 const SMB_STRUCT_STAT *psbuf,
1421 enum perm_type ptype,
1426 if (perms == SMB_MODE_NO_CHANGE) {
1427 if (!VALID_STAT(*psbuf)) {
1428 return NT_STATUS_INVALID_PARAMETER;
1430 *ret_perms = psbuf->st_ex_mode;
1431 return NT_STATUS_OK;
1435 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1436 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1437 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1438 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1439 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1440 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1441 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1442 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1443 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1445 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1448 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1451 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1456 case PERM_EXISTING_FILE:
1457 /* Apply mode mask */
1458 ret &= lp_create_mask(SNUM(conn));
1459 /* Add in force bits */
1460 ret |= lp_force_create_mode(SNUM(conn));
1463 case PERM_EXISTING_DIR:
1464 ret &= lp_dir_mask(SNUM(conn));
1465 /* Add in force bits */
1466 ret |= lp_force_dir_mode(SNUM(conn));
1471 return NT_STATUS_OK;
1474 /****************************************************************************
1475 Needed to show the msdfs symlinks as directories. Modifies psbuf
1476 to be a directory if it's a msdfs link.
1477 ****************************************************************************/
1479 static bool check_msdfs_link(connection_struct *conn,
1480 const char *pathname,
1481 SMB_STRUCT_STAT *psbuf)
1483 int saved_errno = errno;
1484 if(lp_host_msdfs() &&
1485 lp_msdfs_root(SNUM(conn)) &&
1486 is_msdfs_link(conn, pathname, psbuf)) {
1488 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1491 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1492 errno = saved_errno;
1495 errno = saved_errno;
1500 /****************************************************************************
1501 Get a level dependent lanman2 dir entry.
1502 ****************************************************************************/
1504 struct smbd_dirptr_lanman2_state {
1505 connection_struct *conn;
1506 uint32_t info_level;
1507 bool check_mangled_names;
1509 bool got_exact_match;
1512 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1518 struct smbd_dirptr_lanman2_state *state =
1519 (struct smbd_dirptr_lanman2_state *)private_data;
1521 char mangled_name[13]; /* mangled 8.3 name. */
1525 /* Mangle fname if it's an illegal name. */
1526 if (mangle_must_mangle(dname, state->conn->params)) {
1527 ok = name_to_8_3(dname, mangled_name,
1528 true, state->conn->params);
1532 fname = mangled_name;
1537 got_match = exact_match(state->has_wild,
1538 state->conn->case_sensitive,
1540 state->got_exact_match = got_match;
1542 got_match = mask_match(fname, mask,
1543 state->conn->case_sensitive);
1546 if(!got_match && state->check_mangled_names &&
1547 !mangle_is_8_3(fname, false, state->conn->params)) {
1549 * It turns out that NT matches wildcards against
1550 * both long *and* short names. This may explain some
1551 * of the wildcard wierdness from old DOS clients
1552 * that some people have been seeing.... JRA.
1554 /* Force the mangling into 8.3. */
1555 ok = name_to_8_3(fname, mangled_name,
1556 false, state->conn->params);
1561 got_match = exact_match(state->has_wild,
1562 state->conn->case_sensitive,
1563 mangled_name, mask);
1564 state->got_exact_match = got_match;
1566 got_match = mask_match(mangled_name, mask,
1567 state->conn->case_sensitive);
1575 *_fname = talloc_strdup(ctx, fname);
1576 if (*_fname == NULL) {
1583 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1585 struct smb_filename *smb_fname,
1588 struct smbd_dirptr_lanman2_state *state =
1589 (struct smbd_dirptr_lanman2_state *)private_data;
1590 bool ms_dfs_link = false;
1593 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1594 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1595 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1596 "Couldn't lstat [%s] (%s)\n",
1597 smb_fname_str_dbg(smb_fname),
1601 } else if (!VALID_STAT(smb_fname->st) &&
1602 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1603 /* Needed to show the msdfs symlinks as
1606 ms_dfs_link = check_msdfs_link(state->conn,
1607 smb_fname->base_name,
1610 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1611 "Couldn't stat [%s] (%s)\n",
1612 smb_fname_str_dbg(smb_fname),
1619 mode = dos_mode_msdfs(state->conn, smb_fname);
1621 mode = dos_mode(state->conn, smb_fname);
1628 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1629 connection_struct *conn,
1631 uint32_t info_level,
1632 struct ea_list *name_list,
1633 bool check_mangled_names,
1634 bool requires_resume_key,
1637 const struct smb_filename *smb_fname,
1638 int space_remaining,
1645 uint64_t *last_entry_off)
1647 char *p, *q, *pdata = *ppdata;
1649 uint64_t file_size = 0;
1650 uint64_t allocation_size = 0;
1651 uint64_t file_index = 0;
1653 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1654 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1656 char *last_entry_ptr;
1661 *out_of_space = false;
1663 ZERO_STRUCT(mdate_ts);
1664 ZERO_STRUCT(adate_ts);
1665 ZERO_STRUCT(create_date_ts);
1666 ZERO_STRUCT(cdate_ts);
1668 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1669 file_size = get_file_size_stat(&smb_fname->st);
1671 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1673 file_index = get_FileIndex(conn, &smb_fname->st);
1675 mdate_ts = smb_fname->st.st_ex_mtime;
1676 adate_ts = smb_fname->st.st_ex_atime;
1677 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1678 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1680 if (lp_dos_filetime_resolution(SNUM(conn))) {
1681 dos_filetime_timespec(&create_date_ts);
1682 dos_filetime_timespec(&mdate_ts);
1683 dos_filetime_timespec(&adate_ts);
1684 dos_filetime_timespec(&cdate_ts);
1687 create_date = convert_timespec_to_time_t(create_date_ts);
1688 mdate = convert_timespec_to_time_t(mdate_ts);
1689 adate = convert_timespec_to_time_t(adate_ts);
1691 /* align the record */
1692 SMB_ASSERT(align >= 1);
1694 off = (int)PTR_DIFF(pdata, base_data);
1695 pad = (off + (align-1)) & ~(align-1);
1698 if (pad && pad > space_remaining) {
1699 *out_of_space = true;
1700 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1701 "for padding (wanted %u, had %d)\n",
1704 return false; /* Not finished - just out of space */
1708 /* initialize padding to 0 */
1710 memset(pdata, 0, pad);
1712 space_remaining -= pad;
1714 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1724 switch (info_level) {
1725 case SMB_FIND_INFO_STANDARD:
1726 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1727 if(requires_resume_key) {
1731 srv_put_dos_date2(p,0,create_date);
1732 srv_put_dos_date2(p,4,adate);
1733 srv_put_dos_date2(p,8,mdate);
1734 SIVAL(p,12,(uint32)file_size);
1735 SIVAL(p,16,(uint32)allocation_size);
1739 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1740 p += ucs2_align(base_data, p, 0);
1742 len = srvstr_push(base_data, flags2, p,
1743 fname, PTR_DIFF(end_data, p),
1745 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1747 SCVAL(nameptr, -1, len - 2);
1749 SCVAL(nameptr, -1, 0);
1753 SCVAL(nameptr, -1, len - 1);
1755 SCVAL(nameptr, -1, 0);
1761 case SMB_FIND_EA_SIZE:
1762 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1763 if (requires_resume_key) {
1767 srv_put_dos_date2(p,0,create_date);
1768 srv_put_dos_date2(p,4,adate);
1769 srv_put_dos_date2(p,8,mdate);
1770 SIVAL(p,12,(uint32)file_size);
1771 SIVAL(p,16,(uint32)allocation_size);
1774 unsigned int ea_size = estimate_ea_size(conn, NULL,
1776 SIVAL(p,22,ea_size); /* Extended attributes */
1780 len = srvstr_push(base_data, flags2,
1781 p, fname, PTR_DIFF(end_data, p),
1782 STR_TERMINATE | STR_NOALIGN);
1783 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1796 SCVAL(nameptr,0,len);
1798 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1801 case SMB_FIND_EA_LIST:
1803 struct ea_list *file_list = NULL;
1807 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1811 if (requires_resume_key) {
1815 srv_put_dos_date2(p,0,create_date);
1816 srv_put_dos_date2(p,4,adate);
1817 srv_put_dos_date2(p,8,mdate);
1818 SIVAL(p,12,(uint32)file_size);
1819 SIVAL(p,16,(uint32)allocation_size);
1821 p += 22; /* p now points to the EA area. */
1823 status = get_ea_list_from_file(ctx, conn, NULL,
1825 &ea_len, &file_list);
1826 if (!NT_STATUS_IS_OK(status)) {
1829 name_list = ea_list_union(name_list, file_list, &ea_len);
1831 /* We need to determine if this entry will fit in the space available. */
1832 /* Max string size is 255 bytes. */
1833 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1834 *out_of_space = true;
1835 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1836 "(wanted %u, had %d)\n",
1837 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1839 return False; /* Not finished - just out of space */
1842 /* Push the ea_data followed by the name. */
1843 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1845 len = srvstr_push(base_data, flags2,
1846 p + 1, fname, PTR_DIFF(end_data, p+1),
1847 STR_TERMINATE | STR_NOALIGN);
1848 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1861 SCVAL(nameptr,0,len);
1863 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1867 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1868 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1869 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1871 SIVAL(p,0,reskey); p += 4;
1872 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1873 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1874 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1875 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1876 SOFF_T(p,0,file_size); p += 8;
1877 SOFF_T(p,0,allocation_size); p += 8;
1878 SIVAL(p,0,mode); p += 4;
1879 q = p; p += 4; /* q is placeholder for name length. */
1881 unsigned int ea_size = estimate_ea_size(conn, NULL,
1883 SIVAL(p,0,ea_size); /* Extended attributes */
1886 /* Clear the short name buffer. This is
1887 * IMPORTANT as not doing so will trigger
1888 * a Win2k client bug. JRA.
1890 if (!was_8_3 && check_mangled_names) {
1891 char mangled_name[13]; /* mangled 8.3 name. */
1892 if (!name_to_8_3(fname,mangled_name,True,
1894 /* Error - mangle failed ! */
1895 memset(mangled_name,'\0',12);
1897 mangled_name[12] = 0;
1898 len = srvstr_push(base_data, flags2,
1899 p+2, mangled_name, 24,
1900 STR_UPPER|STR_UNICODE);
1902 memset(p + 2 + len,'\0',24 - len);
1909 len = srvstr_push(base_data, flags2, p,
1910 fname, PTR_DIFF(end_data, p),
1911 STR_TERMINATE_ASCII);
1915 len = PTR_DIFF(p, pdata);
1916 pad = (len + (align-1)) & ~(align-1);
1918 * offset to the next entry, the caller
1919 * will overwrite it for the last entry
1920 * that's why we always include the padding
1924 * set padding to zero
1927 memset(p, 0, pad - len);
1934 case SMB_FIND_FILE_DIRECTORY_INFO:
1935 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1937 SIVAL(p,0,reskey); p += 4;
1938 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1939 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1940 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1941 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1942 SOFF_T(p,0,file_size); p += 8;
1943 SOFF_T(p,0,allocation_size); p += 8;
1944 SIVAL(p,0,mode); p += 4;
1945 len = srvstr_push(base_data, flags2,
1946 p + 4, fname, PTR_DIFF(end_data, p+4),
1947 STR_TERMINATE_ASCII);
1951 len = PTR_DIFF(p, pdata);
1952 pad = (len + (align-1)) & ~(align-1);
1954 * offset to the next entry, the caller
1955 * will overwrite it for the last entry
1956 * that's why we always include the padding
1960 * set padding to zero
1963 memset(p, 0, pad - len);
1970 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1971 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1973 SIVAL(p,0,reskey); p += 4;
1974 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1975 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1976 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1977 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1978 SOFF_T(p,0,file_size); p += 8;
1979 SOFF_T(p,0,allocation_size); p += 8;
1980 SIVAL(p,0,mode); p += 4;
1981 q = p; p += 4; /* q is placeholder for name length. */
1983 unsigned int ea_size = estimate_ea_size(conn, NULL,
1985 SIVAL(p,0,ea_size); /* Extended attributes */
1988 len = srvstr_push(base_data, flags2, p,
1989 fname, PTR_DIFF(end_data, p),
1990 STR_TERMINATE_ASCII);
1994 len = PTR_DIFF(p, pdata);
1995 pad = (len + (align-1)) & ~(align-1);
1997 * offset to the next entry, the caller
1998 * will overwrite it for the last entry
1999 * that's why we always include the padding
2003 * set padding to zero
2006 memset(p, 0, pad - len);
2013 case SMB_FIND_FILE_NAMES_INFO:
2014 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2016 SIVAL(p,0,reskey); p += 4;
2018 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2019 acl on a dir (tridge) */
2020 len = srvstr_push(base_data, flags2, p,
2021 fname, PTR_DIFF(end_data, p),
2022 STR_TERMINATE_ASCII);
2026 len = PTR_DIFF(p, pdata);
2027 pad = (len + (align-1)) & ~(align-1);
2029 * offset to the next entry, the caller
2030 * will overwrite it for the last entry
2031 * that's why we always include the padding
2035 * set padding to zero
2038 memset(p, 0, pad - len);
2045 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2046 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2048 SIVAL(p,0,reskey); p += 4;
2049 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2050 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2051 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2052 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2053 SOFF_T(p,0,file_size); p += 8;
2054 SOFF_T(p,0,allocation_size); p += 8;
2055 SIVAL(p,0,mode); p += 4;
2056 q = p; p += 4; /* q is placeholder for name length. */
2058 unsigned int ea_size = estimate_ea_size(conn, NULL,
2060 SIVAL(p,0,ea_size); /* Extended attributes */
2063 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2064 SBVAL(p,0,file_index); p += 8;
2065 len = srvstr_push(base_data, flags2, p,
2066 fname, PTR_DIFF(end_data, p),
2067 STR_TERMINATE_ASCII);
2071 len = PTR_DIFF(p, pdata);
2072 pad = (len + (align-1)) & ~(align-1);
2074 * offset to the next entry, the caller
2075 * will overwrite it for the last entry
2076 * that's why we always include the padding
2080 * set padding to zero
2083 memset(p, 0, pad - len);
2090 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2091 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2092 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2094 SIVAL(p,0,reskey); p += 4;
2095 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2096 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2097 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2098 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2099 SOFF_T(p,0,file_size); p += 8;
2100 SOFF_T(p,0,allocation_size); p += 8;
2101 SIVAL(p,0,mode); p += 4;
2102 q = p; p += 4; /* q is placeholder for name length */
2104 unsigned int ea_size = estimate_ea_size(conn, NULL,
2106 SIVAL(p,0,ea_size); /* Extended attributes */
2109 /* Clear the short name buffer. This is
2110 * IMPORTANT as not doing so will trigger
2111 * a Win2k client bug. JRA.
2113 if (!was_8_3 && check_mangled_names) {
2114 char mangled_name[13]; /* mangled 8.3 name. */
2115 if (!name_to_8_3(fname,mangled_name,True,
2117 /* Error - mangle failed ! */
2118 memset(mangled_name,'\0',12);
2120 mangled_name[12] = 0;
2121 len = srvstr_push(base_data, flags2,
2122 p+2, mangled_name, 24,
2123 STR_UPPER|STR_UNICODE);
2126 memset(p + 2 + len,'\0',24 - len);
2133 SSVAL(p,0,0); p += 2; /* Reserved ? */
2134 SBVAL(p,0,file_index); p += 8;
2135 len = srvstr_push(base_data, flags2, p,
2136 fname, PTR_DIFF(end_data, p),
2137 STR_TERMINATE_ASCII);
2141 len = PTR_DIFF(p, pdata);
2142 pad = (len + (align-1)) & ~(align-1);
2144 * offset to the next entry, the caller
2145 * will overwrite it for the last entry
2146 * that's why we always include the padding
2150 * set padding to zero
2153 memset(p, 0, pad - len);
2160 /* CIFS UNIX Extension. */
2162 case SMB_FIND_FILE_UNIX:
2163 case SMB_FIND_FILE_UNIX_INFO2:
2165 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2167 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2169 if (info_level == SMB_FIND_FILE_UNIX) {
2170 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2171 p = store_file_unix_basic(conn, p,
2172 NULL, &smb_fname->st);
2173 len = srvstr_push(base_data, flags2, p,
2174 fname, PTR_DIFF(end_data, p),
2177 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2178 p = store_file_unix_basic_info2(conn, p,
2179 NULL, &smb_fname->st);
2182 len = srvstr_push(base_data, flags2, p, fname,
2183 PTR_DIFF(end_data, p), 0);
2184 SIVAL(nameptr, 0, len);
2189 len = PTR_DIFF(p, pdata);
2190 pad = (len + (align-1)) & ~(align-1);
2192 * offset to the next entry, the caller
2193 * will overwrite it for the last entry
2194 * that's why we always include the padding
2198 * set padding to zero
2201 memset(p, 0, pad - len);
2206 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2214 if (PTR_DIFF(p,pdata) > space_remaining) {
2215 *out_of_space = true;
2216 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2217 "(wanted %u, had %d)\n",
2218 (unsigned int)PTR_DIFF(p,pdata),
2220 return false; /* Not finished - just out of space */
2223 /* Setup the last entry pointer, as an offset from base_data */
2224 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2225 /* Advance the data pointer to the next slot */
2231 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2232 connection_struct *conn,
2233 struct dptr_struct *dirptr,
2235 const char *path_mask,
2238 int requires_resume_key,
2246 int space_remaining,
2248 bool *got_exact_match,
2249 int *_last_entry_off,
2250 struct ea_list *name_list)
2253 const char *mask = NULL;
2254 long prev_dirpos = 0;
2257 struct smb_filename *smb_fname = NULL;
2258 struct smbd_dirptr_lanman2_state state;
2260 uint64_t last_entry_off = 0;
2264 state.info_level = info_level;
2265 state.check_mangled_names = lp_manglednames(conn->params);
2266 state.has_wild = dptr_has_wild(dirptr);
2267 state.got_exact_match = false;
2269 *out_of_space = false;
2270 *got_exact_match = false;
2272 p = strrchr_m(path_mask,'/');
2283 ok = smbd_dirptr_get_entry(ctx,
2289 smbd_dirptr_lanman2_match_fn,
2290 smbd_dirptr_lanman2_mode_fn,
2300 *got_exact_match = state.got_exact_match;
2302 ok = smbd_marshall_dir_entry(ctx,
2307 state.check_mangled_names,
2308 requires_resume_key,
2321 TALLOC_FREE(smb_fname);
2322 if (*out_of_space) {
2323 dptr_SeekDir(dirptr, prev_dirpos);
2330 *_last_entry_off = last_entry_off;
2334 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2335 connection_struct *conn,
2336 struct dptr_struct *dirptr,
2338 const char *path_mask,
2341 bool requires_resume_key,
2347 int space_remaining,
2349 bool *got_exact_match,
2350 int *last_entry_off,
2351 struct ea_list *name_list)
2354 const bool do_pad = true;
2356 if (info_level >= 1 && info_level <= 3) {
2357 /* No alignment on earlier info levels. */
2361 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2362 path_mask, dirtype, info_level,
2363 requires_resume_key, dont_descend, ask_sharemode,
2365 ppdata, base_data, end_data,
2367 out_of_space, got_exact_match,
2368 last_entry_off, name_list);
2371 /****************************************************************************
2372 Reply to a TRANS2_FINDFIRST.
2373 ****************************************************************************/
2375 static void call_trans2findfirst(connection_struct *conn,
2376 struct smb_request *req,
2377 char **pparams, int total_params,
2378 char **ppdata, int total_data,
2379 unsigned int max_data_bytes)
2381 /* We must be careful here that we don't return more than the
2382 allowed number of data bytes. If this means returning fewer than
2383 maxentries then so be it. We assume that the redirector has
2384 enough room for the fixed number of parameter bytes it has
2386 struct smb_filename *smb_dname = NULL;
2387 char *params = *pparams;
2388 char *pdata = *ppdata;
2392 uint16 findfirst_flags;
2393 bool close_after_first;
2395 bool requires_resume_key;
2397 char *directory = NULL;
2400 int last_entry_off=0;
2404 bool finished = False;
2405 bool dont_descend = False;
2406 bool out_of_space = False;
2407 int space_remaining;
2408 bool mask_contains_wcard = False;
2409 struct ea_list *ea_list = NULL;
2410 NTSTATUS ntstatus = NT_STATUS_OK;
2411 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2412 TALLOC_CTX *ctx = talloc_tos();
2413 struct dptr_struct *dirptr = NULL;
2414 struct smbd_server_connection *sconn = req->sconn;
2415 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2416 bool backup_priv = false;
2418 if (total_params < 13) {
2419 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2423 dirtype = SVAL(params,0);
2424 maxentries = SVAL(params,2);
2425 findfirst_flags = SVAL(params,4);
2426 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2427 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2428 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2429 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2430 security_token_has_privilege(get_current_nttok(conn),
2433 info_level = SVAL(params,6);
2435 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2436 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2437 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2439 info_level, max_data_bytes));
2442 /* W2K3 seems to treat zero as 1. */
2446 switch (info_level) {
2447 case SMB_FIND_INFO_STANDARD:
2448 case SMB_FIND_EA_SIZE:
2449 case SMB_FIND_EA_LIST:
2450 case SMB_FIND_FILE_DIRECTORY_INFO:
2451 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2452 case SMB_FIND_FILE_NAMES_INFO:
2453 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2454 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2455 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2457 case SMB_FIND_FILE_UNIX:
2458 case SMB_FIND_FILE_UNIX_INFO2:
2459 /* Always use filesystem for UNIX mtime query. */
2460 ask_sharemode = false;
2461 if (!lp_unix_extensions()) {
2462 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2465 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2468 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2472 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2473 params+12, total_params - 12,
2474 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2475 if (!NT_STATUS_IS_OK(ntstatus)) {
2476 reply_nterror(req, ntstatus);
2482 ntstatus = filename_convert_with_privilege(ctx,
2487 &mask_contains_wcard,
2490 ntstatus = filename_convert(ctx, conn,
2491 req->flags2 & FLAGS2_DFS_PATHNAMES,
2494 &mask_contains_wcard,
2498 if (!NT_STATUS_IS_OK(ntstatus)) {
2499 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2500 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2501 ERRSRV, ERRbadpath);
2504 reply_nterror(req, ntstatus);
2508 mask = smb_dname->original_lcomp;
2510 directory = smb_dname->base_name;
2512 p = strrchr_m(directory,'/');
2514 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2515 if((directory[0] == '.') && (directory[1] == '\0')) {
2516 mask = talloc_strdup(ctx,"*");
2518 reply_nterror(req, NT_STATUS_NO_MEMORY);
2521 mask_contains_wcard = True;
2527 if (p == NULL || p == directory) {
2528 /* Ensure we don't have a directory name of "". */
2529 directory = talloc_strdup(talloc_tos(), ".");
2531 reply_nterror(req, NT_STATUS_NO_MEMORY);
2536 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2538 if (info_level == SMB_FIND_EA_LIST) {
2541 if (total_data < 4) {
2542 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2546 ea_size = IVAL(pdata,0);
2547 if (ea_size != total_data) {
2548 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2549 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2550 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2554 if (!lp_ea_support(SNUM(conn))) {
2555 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2559 /* Pull out the list of names. */
2560 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2567 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2568 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2572 *ppdata = (char *)SMB_REALLOC(
2573 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2574 if(*ppdata == NULL ) {
2575 reply_nterror(req, NT_STATUS_NO_MEMORY);
2579 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2581 /* Realloc the params space */
2582 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2583 if (*pparams == NULL) {
2584 reply_nterror(req, NT_STATUS_NO_MEMORY);
2589 /* Save the wildcard match and attribs we are using on this directory -
2590 needed as lanman2 assumes these are being saved between calls */
2592 ntstatus = dptr_create(conn,
2600 mask_contains_wcard,
2604 if (!NT_STATUS_IS_OK(ntstatus)) {
2605 reply_nterror(req, ntstatus);
2610 /* Remember this in case we have
2611 to do a findnext. */
2612 dptr_set_priv(dirptr);
2615 dptr_num = dptr_dnum(dirptr);
2616 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2618 /* Initialize per TRANS2_FIND_FIRST operation data */
2619 dptr_init_search_op(dirptr);
2621 /* We don't need to check for VOL here as this is returned by
2622 a different TRANS2 call. */
2624 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2625 directory,lp_dontdescend(ctx, SNUM(conn))));
2626 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2627 dont_descend = True;
2630 space_remaining = max_data_bytes;
2631 out_of_space = False;
2633 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2634 bool got_exact_match = False;
2636 /* this is a heuristic to avoid seeking the dirptr except when
2637 absolutely necessary. It allows for a filename of about 40 chars */
2638 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2639 out_of_space = True;
2642 finished = !get_lanman2_dir_entry(ctx,
2646 mask,dirtype,info_level,
2647 requires_resume_key,dont_descend,
2650 space_remaining, &out_of_space,
2652 &last_entry_off, ea_list);
2655 if (finished && out_of_space)
2658 if (!finished && !out_of_space)
2662 * As an optimisation if we know we aren't looking
2663 * for a wildcard name (ie. the name matches the wildcard exactly)
2664 * then we can finish on any (first) match.
2665 * This speeds up large directory searches. JRA.
2671 /* Ensure space_remaining never goes -ve. */
2672 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2673 space_remaining = 0;
2674 out_of_space = true;
2676 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2680 /* Check if we can close the dirptr */
2681 if(close_after_first || (finished && close_if_end)) {
2682 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2683 dptr_close(sconn, &dptr_num);
2687 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2688 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2689 * the protocol level is less than NT1. Tested with smbclient. JRA.
2690 * This should fix the OS/2 client bug #2335.
2693 if(numentries == 0) {
2694 dptr_close(sconn, &dptr_num);
2695 if (get_Protocol() < PROTOCOL_NT1) {
2696 reply_force_doserror(req, ERRDOS, ERRnofiles);
2699 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2700 ERRDOS, ERRbadfile);
2705 /* At this point pdata points to numentries directory entries. */
2707 /* Set up the return parameter block */
2708 SSVAL(params,0,dptr_num);
2709 SSVAL(params,2,numentries);
2710 SSVAL(params,4,finished);
2711 SSVAL(params,6,0); /* Never an EA error */
2712 SSVAL(params,8,last_entry_off);
2714 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2717 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2718 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2720 reply_nterror(req, NT_STATUS_NO_MEMORY);
2724 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2725 smb_fn_name(req->cmd),
2726 mask, directory, dirtype, numentries ) );
2729 * Force a name mangle here to ensure that the
2730 * mask as an 8.3 name is top of the mangled cache.
2731 * The reasons for this are subtle. Don't remove
2732 * this code unless you know what you are doing
2733 * (see PR#13758). JRA.
2736 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2737 char mangled_name[13];
2738 name_to_8_3(mask, mangled_name, True, conn->params);
2746 TALLOC_FREE(smb_dname);
2750 /****************************************************************************
2751 Reply to a TRANS2_FINDNEXT.
2752 ****************************************************************************/
2754 static void call_trans2findnext(connection_struct *conn,
2755 struct smb_request *req,
2756 char **pparams, int total_params,
2757 char **ppdata, int total_data,
2758 unsigned int max_data_bytes)
2760 /* We must be careful here that we don't return more than the
2761 allowed number of data bytes. If this means returning fewer than
2762 maxentries then so be it. We assume that the redirector has
2763 enough room for the fixed number of parameter bytes it has
2765 char *params = *pparams;
2766 char *pdata = *ppdata;
2772 uint16 findnext_flags;
2773 bool close_after_request;
2775 bool requires_resume_key;
2777 bool mask_contains_wcard = False;
2778 char *resume_name = NULL;
2779 const char *mask = NULL;
2780 const char *directory = NULL;
2784 int i, last_entry_off=0;
2785 bool finished = False;
2786 bool dont_descend = False;
2787 bool out_of_space = False;
2788 int space_remaining;
2789 struct ea_list *ea_list = NULL;
2790 NTSTATUS ntstatus = NT_STATUS_OK;
2791 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2792 TALLOC_CTX *ctx = talloc_tos();
2793 struct dptr_struct *dirptr;
2794 struct smbd_server_connection *sconn = req->sconn;
2795 bool backup_priv = false;
2797 if (total_params < 13) {
2798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2802 dptr_num = SVAL(params,0);
2803 maxentries = SVAL(params,2);
2804 info_level = SVAL(params,4);
2805 resume_key = IVAL(params,6);
2806 findnext_flags = SVAL(params,10);
2807 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2808 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2809 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2810 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2812 if (!continue_bit) {
2813 /* We only need resume_name if continue_bit is zero. */
2814 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2816 total_params - 12, STR_TERMINATE, &ntstatus,
2817 &mask_contains_wcard);
2818 if (!NT_STATUS_IS_OK(ntstatus)) {
2819 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2820 complain (it thinks we're asking for the directory above the shared
2821 path or an invalid name). Catch this as the resume name is only compared, never used in
2822 a file access. JRA. */
2823 srvstr_pull_talloc(ctx, params, req->flags2,
2824 &resume_name, params+12,
2828 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2829 reply_nterror(req, ntstatus);
2835 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2836 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2837 resume_key = %d resume name = %s continue=%d level = %d\n",
2838 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2839 requires_resume_key, resume_key,
2840 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2843 /* W2K3 seems to treat zero as 1. */
2847 switch (info_level) {
2848 case SMB_FIND_INFO_STANDARD:
2849 case SMB_FIND_EA_SIZE:
2850 case SMB_FIND_EA_LIST:
2851 case SMB_FIND_FILE_DIRECTORY_INFO:
2852 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2853 case SMB_FIND_FILE_NAMES_INFO:
2854 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2855 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2856 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2858 case SMB_FIND_FILE_UNIX:
2859 case SMB_FIND_FILE_UNIX_INFO2:
2860 /* Always use filesystem for UNIX mtime query. */
2861 ask_sharemode = false;
2862 if (!lp_unix_extensions()) {
2863 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2868 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2872 if (info_level == SMB_FIND_EA_LIST) {
2875 if (total_data < 4) {
2876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2880 ea_size = IVAL(pdata,0);
2881 if (ea_size != total_data) {
2882 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2883 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2884 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2888 if (!lp_ea_support(SNUM(conn))) {
2889 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2893 /* Pull out the list of names. */
2894 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2901 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2902 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2906 *ppdata = (char *)SMB_REALLOC(
2907 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2908 if(*ppdata == NULL) {
2909 reply_nterror(req, NT_STATUS_NO_MEMORY);
2914 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2916 /* Realloc the params space */
2917 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2918 if(*pparams == NULL ) {
2919 reply_nterror(req, NT_STATUS_NO_MEMORY);
2925 /* Check that the dptr is valid */
2926 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2927 reply_nterror(req, STATUS_NO_MORE_FILES);
2931 directory = dptr_path(sconn, dptr_num);
2933 /* Get the wildcard mask from the dptr */
2934 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2935 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2936 reply_nterror(req, STATUS_NO_MORE_FILES);
2940 /* Get the attr mask from the dptr */
2941 dirtype = dptr_attr(sconn, dptr_num);
2943 backup_priv = dptr_get_priv(dirptr);
2945 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2946 "backup_priv = %d\n",
2947 dptr_num, mask, dirtype,
2949 dptr_TellDir(dirptr),
2952 /* Initialize per TRANS2_FIND_NEXT operation data */
2953 dptr_init_search_op(dirptr);
2955 /* We don't need to check for VOL here as this is returned by
2956 a different TRANS2 call. */
2958 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2959 directory,lp_dontdescend(ctx, SNUM(conn))));
2960 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2961 dont_descend = True;
2964 space_remaining = max_data_bytes;
2965 out_of_space = False;
2972 * Seek to the correct position. We no longer use the resume key but
2973 * depend on the last file name instead.
2976 if(!continue_bit && resume_name && *resume_name) {
2979 long current_pos = 0;
2981 * Remember, name_to_8_3 is called by
2982 * get_lanman2_dir_entry(), so the resume name
2983 * could be mangled. Ensure we check the unmangled name.
2986 if (mangle_is_mangled(resume_name, conn->params)) {
2987 char *new_resume_name = NULL;
2988 mangle_lookup_name_from_8_3(ctx,
2992 if (new_resume_name) {
2993 resume_name = new_resume_name;
2998 * Fix for NT redirector problem triggered by resume key indexes
2999 * changing between directory scans. We now return a resume key of 0
3000 * and instead look for the filename to continue from (also given
3001 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3002 * findfirst/findnext (as is usual) then the directory pointer
3003 * should already be at the correct place.
3006 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3007 } /* end if resume_name && !continue_bit */
3009 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3010 bool got_exact_match = False;
3012 /* this is a heuristic to avoid seeking the dirptr except when
3013 absolutely necessary. It allows for a filename of about 40 chars */
3014 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3015 out_of_space = True;
3018 finished = !get_lanman2_dir_entry(ctx,
3022 mask,dirtype,info_level,
3023 requires_resume_key,dont_descend,
3026 space_remaining, &out_of_space,
3028 &last_entry_off, ea_list);
3031 if (finished && out_of_space)
3034 if (!finished && !out_of_space)
3038 * As an optimisation if we know we aren't looking
3039 * for a wildcard name (ie. the name matches the wildcard exactly)
3040 * then we can finish on any (first) match.
3041 * This speeds up large directory searches. JRA.
3047 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3050 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3051 smb_fn_name(req->cmd),
3052 mask, directory, dirtype, numentries ) );
3054 /* Check if we can close the dirptr */
3055 if(close_after_request || (finished && close_if_end)) {
3056 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3057 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3064 /* Set up the return parameter block */
3065 SSVAL(params,0,numentries);
3066 SSVAL(params,2,finished);
3067 SSVAL(params,4,0); /* Never an EA error */
3068 SSVAL(params,6,last_entry_off);
3070 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3076 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3078 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3082 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3084 SMB_ASSERT(extended_info != NULL);
3086 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3087 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3088 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3089 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3090 #ifdef SAMBA_VERSION_REVISION
3091 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3093 extended_info->samba_subversion = 0;
3094 #ifdef SAMBA_VERSION_RC_RELEASE
3095 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3097 #ifdef SAMBA_VERSION_PRE_RELEASE
3098 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3101 #ifdef SAMBA_VERSION_VENDOR_PATCH
3102 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3104 extended_info->samba_gitcommitdate = 0;
3105 #ifdef SAMBA_VERSION_COMMIT_TIME
3106 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3109 memset(extended_info->samba_version_string, 0,
3110 sizeof(extended_info->samba_version_string));
3112 snprintf (extended_info->samba_version_string,
3113 sizeof(extended_info->samba_version_string),
3114 "%s", samba_version_string());
3117 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3118 TALLOC_CTX *mem_ctx,
3119 uint16_t info_level,
3121 unsigned int max_data_bytes,
3122 struct smb_filename *fname,
3126 char *pdata, *end_data;
3127 int data_len = 0, len;
3128 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3129 int snum = SNUM(conn);
3130 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3131 char *filename = NULL;
3132 uint32 additional_flags = 0;
3133 struct smb_filename smb_fname;
3135 NTSTATUS status = NT_STATUS_OK;
3137 if (fname == NULL || fname->base_name == NULL) {
3140 filename = fname->base_name;
3144 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3145 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3146 "info level (0x%x) on IPC$.\n",
3147 (unsigned int)info_level));
3148 return NT_STATUS_ACCESS_DENIED;
3152 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3154 ZERO_STRUCT(smb_fname);
3155 smb_fname.base_name = discard_const_p(char, filename);
3157 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3158 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3159 return map_nt_error_from_unix(errno);
3164 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3165 return NT_STATUS_INVALID_PARAMETER;
3168 *ppdata = (char *)SMB_REALLOC(
3169 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3170 if (*ppdata == NULL) {
3171 return NT_STATUS_NO_MEMORY;
3175 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3176 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3178 switch (info_level) {
3179 case SMB_INFO_ALLOCATION:
3181 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3183 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3184 return map_nt_error_from_unix(errno);
3187 block_size = lp_block_size(snum);
3188 if (bsize < block_size) {
3189 uint64_t factor = block_size/bsize;
3194 if (bsize > block_size) {
3195 uint64_t factor = bsize/block_size;
3200 bytes_per_sector = 512;
3201 sectors_per_unit = bsize/bytes_per_sector;
3203 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3204 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3205 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3207 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3208 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3209 SIVAL(pdata,l1_cUnit,dsize);
3210 SIVAL(pdata,l1_cUnitAvail,dfree);
3211 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3215 case SMB_INFO_VOLUME:
3216 /* Return volume name */
3218 * Add volume serial number - hash of a combination of
3219 * the called hostname and the service name.
3221 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3223 * Win2k3 and previous mess this up by sending a name length
3224 * one byte short. I believe only older clients (OS/2 Win9x) use
3225 * this call so try fixing this by adding a terminating null to
3226 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3230 pdata+l2_vol_szVolLabel, vname,
3231 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3232 STR_NOALIGN|STR_TERMINATE);
3233 SCVAL(pdata,l2_vol_cch,len);
3234 data_len = l2_vol_szVolLabel + len;
3235 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3236 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3240 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3241 case SMB_FS_ATTRIBUTE_INFORMATION:
3243 additional_flags = 0;
3244 #if defined(HAVE_SYS_QUOTAS)
3245 additional_flags |= FILE_VOLUME_QUOTAS;
3248 if(lp_nt_acl_support(SNUM(conn))) {
3249 additional_flags |= FILE_PERSISTENT_ACLS;
3252 /* Capabilities are filled in at connection time through STATVFS call */
3253 additional_flags |= conn->fs_capabilities;
3254 additional_flags |= lp_parm_int(conn->params->service,
3255 "share", "fake_fscaps",
3258 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3259 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3260 additional_flags); /* FS ATTRIBUTES */
3262 SIVAL(pdata,4,255); /* Max filename component length */
3263 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3264 and will think we can't do long filenames */
3265 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3266 PTR_DIFF(end_data, pdata+12),
3269 data_len = 12 + len;
3272 case SMB_QUERY_FS_LABEL_INFO:
3273 case SMB_FS_LABEL_INFORMATION:
3274 len = srvstr_push(pdata, flags2, pdata+4, vname,
3275 PTR_DIFF(end_data, pdata+4), 0);
3280 case SMB_QUERY_FS_VOLUME_INFO:
3281 case SMB_FS_VOLUME_INFORMATION:
3284 * Add volume serial number - hash of a combination of
3285 * the called hostname and the service name.
3287 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3288 (str_checksum(get_local_machine_name())<<16));
3290 /* Max label len is 32 characters. */
3291 len = srvstr_push(pdata, flags2, pdata+18, vname,
3292 PTR_DIFF(end_data, pdata+18),
3294 SIVAL(pdata,12,len);
3297 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3298 (int)strlen(vname),vname,
3299 lp_servicename(talloc_tos(), snum)));
3300 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3301 /* the client only requested a portion of the
3303 data_len = max_data_bytes;
3304 status = STATUS_BUFFER_OVERFLOW;
3308 case SMB_QUERY_FS_SIZE_INFO:
3309 case SMB_FS_SIZE_INFORMATION:
3311 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3313 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3314 return map_nt_error_from_unix(errno);
3316 block_size = lp_block_size(snum);
3317 if (bsize < block_size) {
3318 uint64_t factor = block_size/bsize;
3323 if (bsize > block_size) {
3324 uint64_t factor = bsize/block_size;
3329 bytes_per_sector = 512;
3330 sectors_per_unit = bsize/bytes_per_sector;
3331 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3332 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3333 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3334 SBIG_UINT(pdata,0,dsize);
3335 SBIG_UINT(pdata,8,dfree);
3336 SIVAL(pdata,16,sectors_per_unit);
3337 SIVAL(pdata,20,bytes_per_sector);
3341 case SMB_FS_FULL_SIZE_INFORMATION:
3343 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3345 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3346 return map_nt_error_from_unix(errno);
3348 block_size = lp_block_size(snum);
3349 if (bsize < block_size) {
3350 uint64_t factor = block_size/bsize;
3355 if (bsize > block_size) {
3356 uint64_t factor = bsize/block_size;
3361 bytes_per_sector = 512;
3362 sectors_per_unit = bsize/bytes_per_sector;
3363 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3364 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3365 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3366 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3367 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3368 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3369 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3370 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3374 case SMB_QUERY_FS_DEVICE_INFO:
3375 case SMB_FS_DEVICE_INFORMATION:
3377 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3379 if (!CAN_WRITE(conn)) {
3380 characteristics |= FILE_READ_ONLY_DEVICE;
3383 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3384 SIVAL(pdata,4,characteristics);
3388 #ifdef HAVE_SYS_QUOTAS
3389 case SMB_FS_QUOTA_INFORMATION:
3391 * what we have to send --metze:
3393 * Unknown1: 24 NULL bytes
3394 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3395 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3396 * Quota Flags: 2 byte :
3397 * Unknown3: 6 NULL bytes
3401 * details for Quota Flags:
3403 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3404 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3405 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3406 * 0x0001 Enable Quotas: enable quota for this fs
3410 /* we need to fake up a fsp here,
3411 * because its not send in this call
3414 SMB_NTQUOTA_STRUCT quotas;
3417 ZERO_STRUCT(quotas);
3420 fsp.fnum = FNUM_FIELD_INVALID;
3423 if (get_current_uid(conn) != 0) {
3424 DEBUG(0,("set_user_quota: access_denied "
3425 "service [%s] user [%s]\n",
3426 lp_servicename(talloc_tos(), SNUM(conn)),
3427 conn->session_info->unix_info->unix_name));
3428 return NT_STATUS_ACCESS_DENIED;
3431 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3432 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3433 return map_nt_error_from_unix(errno);
3438 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3439 lp_servicename(talloc_tos(), SNUM(conn))));
3441 /* Unknown1 24 NULL bytes*/
3442 SBIG_UINT(pdata,0,(uint64_t)0);
3443 SBIG_UINT(pdata,8,(uint64_t)0);
3444 SBIG_UINT(pdata,16,(uint64_t)0);
3446 /* Default Soft Quota 8 bytes */
3447 SBIG_UINT(pdata,24,quotas.softlim);
3449 /* Default Hard Quota 8 bytes */
3450 SBIG_UINT(pdata,32,quotas.hardlim);
3452 /* Quota flag 2 bytes */
3453 SSVAL(pdata,40,quotas.qflags);
3455 /* Unknown3 6 NULL bytes */
3461 #endif /* HAVE_SYS_QUOTAS */
3462 case SMB_FS_OBJECTID_INFORMATION:
3464 unsigned char objid[16];
3465 struct smb_extended_info extended_info;
3466 memcpy(pdata,create_volume_objectid(conn, objid),16);
3467 samba_extended_info_version (&extended_info);
3468 SIVAL(pdata,16,extended_info.samba_magic);
3469 SIVAL(pdata,20,extended_info.samba_version);
3470 SIVAL(pdata,24,extended_info.samba_subversion);
3471 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3472 memcpy(pdata+36,extended_info.samba_version_string,28);
3478 * Query the version and capabilities of the CIFS UNIX extensions
3482 case SMB_QUERY_CIFS_UNIX_INFO:
3484 bool large_write = lp_min_receive_file_size() &&
3485 !srv_is_signing_active(conn->sconn);
3486 bool large_read = !srv_is_signing_active(conn->sconn);
3487 int encrypt_caps = 0;
3489 if (!lp_unix_extensions()) {
3490 return NT_STATUS_INVALID_LEVEL;
3493 switch (conn->encrypt_level) {
3494 case SMB_SIGNING_OFF:
3497 case SMB_SIGNING_IF_REQUIRED:
3498 case SMB_SIGNING_DEFAULT:
3499 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3501 case SMB_SIGNING_REQUIRED:
3502 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3503 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3504 large_write = false;
3510 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3511 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3513 /* We have POSIX ACLs, pathname, encryption,
3514 * large read/write, and locking capability. */
3516 SBIG_UINT(pdata,4,((uint64_t)(
3517 CIFS_UNIX_POSIX_ACLS_CAP|
3518 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3519 CIFS_UNIX_FCNTL_LOCKS_CAP|
3520 CIFS_UNIX_EXTATTR_CAP|
3521 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3523 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3525 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3529 case SMB_QUERY_POSIX_FS_INFO:
3532 vfs_statvfs_struct svfs;
3534 if (!lp_unix_extensions()) {
3535 return NT_STATUS_INVALID_LEVEL;
3538 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3542 SIVAL(pdata,0,svfs.OptimalTransferSize);
3543 SIVAL(pdata,4,svfs.BlockSize);
3544 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3545 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3546 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3547 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3548 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3549 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3550 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3552 } else if (rc == EOPNOTSUPP) {
3553 return NT_STATUS_INVALID_LEVEL;
3554 #endif /* EOPNOTSUPP */
3556 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3557 return NT_STATUS_DOS(ERRSRV, ERRerror);
3562 case SMB_QUERY_POSIX_WHOAMI:
3568 if (!lp_unix_extensions()) {
3569 return NT_STATUS_INVALID_LEVEL;
3572 if (max_data_bytes < 40) {
3573 return NT_STATUS_BUFFER_TOO_SMALL;
3576 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3577 flags |= SMB_WHOAMI_GUEST;
3580 /* NOTE: 8 bytes for UID/GID, irrespective of native
3581 * platform size. This matches
3582 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3584 data_len = 4 /* flags */
3591 + 4 /* pad/reserved */
3592 + (conn->session_info->unix_token->ngroups * 8)
3594 + (conn->session_info->security_token->num_sids *
3598 SIVAL(pdata, 0, flags);
3599 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3601 (uint64_t)conn->session_info->unix_token->uid);
3602 SBIG_UINT(pdata, 16,
3603 (uint64_t)conn->session_info->unix_token->gid);
3606 if (data_len >= max_data_bytes) {
3607 /* Potential overflow, skip the GIDs and SIDs. */
3609 SIVAL(pdata, 24, 0); /* num_groups */
3610 SIVAL(pdata, 28, 0); /* num_sids */
3611 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3612 SIVAL(pdata, 36, 0); /* reserved */
3618 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3619 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3621 /* We walk the SID list twice, but this call is fairly
3622 * infrequent, and I don't expect that it's performance
3623 * sensitive -- jpeach
3625 for (i = 0, sid_bytes = 0;
3626 i < conn->session_info->security_token->num_sids; ++i) {
3627 sid_bytes += ndr_size_dom_sid(
3628 &conn->session_info->security_token->sids[i],
3632 /* SID list byte count */
3633 SIVAL(pdata, 32, sid_bytes);
3635 /* 4 bytes pad/reserved - must be zero */
3636 SIVAL(pdata, 36, 0);
3640 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3641 SBIG_UINT(pdata, data_len,
3642 (uint64_t)conn->session_info->unix_token->groups[i]);
3648 i < conn->session_info->security_token->num_sids; ++i) {
3649 int sid_len = ndr_size_dom_sid(
3650 &conn->session_info->security_token->sids[i],
3653 sid_linearize(pdata + data_len, sid_len,
3654 &conn->session_info->security_token->sids[i]);
3655 data_len += sid_len;
3661 case SMB_MAC_QUERY_FS_INFO:
3663 * Thursby MAC extension... ONLY on NTFS filesystems
3664 * once we do streams then we don't need this
3666 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3668 SIVAL(pdata,84,0x100); /* Don't support mac... */
3673 return NT_STATUS_INVALID_LEVEL;
3676 *ret_data_len = data_len;
3680 /****************************************************************************
3681 Reply to a TRANS2_QFSINFO (query filesystem info).
3682 ****************************************************************************/
3684 static void call_trans2qfsinfo(connection_struct *conn,
3685 struct smb_request *req,
3686 char **pparams, int total_params,
3687 char **ppdata, int total_data,
3688 unsigned int max_data_bytes)
3690 char *params = *pparams;
3691 uint16_t info_level;
3695 if (total_params < 2) {
3696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3700 info_level = SVAL(params,0);
3702 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3703 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3704 DEBUG(0,("call_trans2qfsinfo: encryption required "
3705 "and info level 0x%x sent.\n",
3706 (unsigned int)info_level));
3707 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3712 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3714 status = smbd_do_qfsinfo(conn, req,
3720 if (!NT_STATUS_IS_OK(status)) {
3721 reply_nterror(req, status);
3725 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3728 DEBUG( 4, ( "%s info_level = %d\n",
3729 smb_fn_name(req->cmd), info_level) );
3734 /****************************************************************************
3735 Reply to a TRANS2_SETFSINFO (set filesystem info).
3736 ****************************************************************************/
3738 static void call_trans2setfsinfo(connection_struct *conn,
3739 struct smb_request *req,
3740 char **pparams, int total_params,
3741 char **ppdata, int total_data,
3742 unsigned int max_data_bytes)
3744 struct smbd_server_connection *sconn = req->sconn;
3745 char *pdata = *ppdata;
3746 char *params = *pparams;
3749 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3750 lp_servicename(talloc_tos(), SNUM(conn))));
3753 if (total_params < 4) {
3754 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3756 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3760 info_level = SVAL(params,2);
3763 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3764 info_level != SMB_SET_CIFS_UNIX_INFO) {
3765 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3766 "info level (0x%x) on IPC$.\n",
3767 (unsigned int)info_level));
3768 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3773 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3774 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3775 DEBUG(0,("call_trans2setfsinfo: encryption required "
3776 "and info level 0x%x sent.\n",
3777 (unsigned int)info_level));
3778 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3783 switch(info_level) {
3784 case SMB_SET_CIFS_UNIX_INFO:
3785 if (!lp_unix_extensions()) {
3786 DEBUG(2,("call_trans2setfsinfo: "
3787 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3788 "unix extensions off\n"));
3790 NT_STATUS_INVALID_LEVEL);
3794 /* There should be 12 bytes of capabilities set. */
3795 if (total_data < 12) {
3798 NT_STATUS_INVALID_PARAMETER);
3801 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3802 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3803 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3804 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3805 /* Just print these values for now. */
3806 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3807 "major = %u, minor = %u cap_low = 0x%x, "
3809 (unsigned int)sconn->
3810 smb1.unix_info.client_major,
3811 (unsigned int)sconn->
3812 smb1.unix_info.client_minor,
3813 (unsigned int)sconn->
3814 smb1.unix_info.client_cap_low,
3815 (unsigned int)sconn->
3816 smb1.unix_info.client_cap_high));
3818 /* Here is where we must switch to posix pathname processing... */
3819 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3820 lp_set_posix_pathnames();
3821 mangle_change_to_posix();
3824 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3825 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3826 /* Client that knows how to do posix locks,
3827 * but not posix open/mkdir operations. Set a
3828 * default type for read/write checks. */
3830 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3835 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3838 size_t param_len = 0;
3839 size_t data_len = total_data;
3841 if (!lp_unix_extensions()) {
3844 NT_STATUS_INVALID_LEVEL);
3848 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3851 NT_STATUS_NOT_SUPPORTED);
3855 if (req->sconn->smb1.echo_handler.trusted_fde) {
3856 DEBUG( 2,("call_trans2setfsinfo: "
3857 "request transport encryption disabled"
3858 "with 'fork echo handler = yes'\n"));
3861 NT_STATUS_NOT_SUPPORTED);
3865 DEBUG( 4,("call_trans2setfsinfo: "
3866 "request transport encryption.\n"));
3868 status = srv_request_encryption_setup(conn,
3869 (unsigned char **)ppdata,
3871 (unsigned char **)pparams,
3874 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3875 !NT_STATUS_IS_OK(status)) {
3876 reply_nterror(req, status);
3880 send_trans2_replies(conn, req,
3888 if (NT_STATUS_IS_OK(status)) {
3889 /* Server-side transport
3890 * encryption is now *on*. */
3891 status = srv_encryption_start(conn);
3892 if (!NT_STATUS_IS_OK(status)) {
3893 char *reason = talloc_asprintf(talloc_tos(),
3894 "Failure in setting "
3895 "up encrypted transport: %s",
3897 exit_server_cleanly(reason);
3903 case SMB_FS_QUOTA_INFORMATION:
3905 files_struct *fsp = NULL;
3906 SMB_NTQUOTA_STRUCT quotas;
3908 ZERO_STRUCT(quotas);
3911 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3912 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3913 lp_servicename(talloc_tos(), SNUM(conn)),
3914 conn->session_info->unix_info->unix_name));
3915 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3919 /* note: normaly there're 48 bytes,
3920 * but we didn't use the last 6 bytes for now
3923 fsp = file_fsp(req, SVAL(params,0));
3925 if (!check_fsp_ntquota_handle(conn, req,
3927 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3929 req, NT_STATUS_INVALID_HANDLE);
3933 if (total_data < 42) {
3934 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3938 NT_STATUS_INVALID_PARAMETER);
3942 /* unknown_1 24 NULL bytes in pdata*/
3944 /* the soft quotas 8 bytes (uint64_t)*/
3945 quotas.softlim = BVAL(pdata,24);
3947 /* the hard quotas 8 bytes (uint64_t)*/
3948 quotas.hardlim = BVAL(pdata,32);
3950 /* quota_flags 2 bytes **/
3951 quotas.qflags = SVAL(pdata,40);
3953 /* unknown_2 6 NULL bytes follow*/
3955 /* now set the quotas */
3956 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3957 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3958 reply_nterror(req, map_nt_error_from_unix(errno));
3965 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3967 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3973 * sending this reply works fine,
3974 * but I'm not sure it's the same
3975 * like windows do...
3978 reply_outbuf(req, 10, 0);
3981 #if defined(HAVE_POSIX_ACLS)
3982 /****************************************************************************
3983 Utility function to count the number of entries in a POSIX acl.
3984 ****************************************************************************/
3986 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3988 unsigned int ace_count = 0;
3989 int entry_id = SMB_ACL_FIRST_ENTRY;
3990 SMB_ACL_ENTRY_T entry;
3992 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3994 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3995 entry_id = SMB_ACL_NEXT_ENTRY;
4002 /****************************************************************************
4003 Utility function to marshall a POSIX acl into wire format.
4004 ****************************************************************************/
4006 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4008 int entry_id = SMB_ACL_FIRST_ENTRY;
4009 SMB_ACL_ENTRY_T entry;
4011 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4012 SMB_ACL_TAG_T tagtype;
4013 SMB_ACL_PERMSET_T permset;
4014 unsigned char perms = 0;
4015 unsigned int own_grp;
4018 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4019 entry_id = SMB_ACL_NEXT_ENTRY;
4022 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4023 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4027 if (sys_acl_get_permset(entry, &permset) == -1) {
4028 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4032 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4033 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4034 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4036 SCVAL(pdata,1,perms);
4039 case SMB_ACL_USER_OBJ:
4040 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4041 own_grp = (unsigned int)pst->st_ex_uid;
4042 SIVAL(pdata,2,own_grp);
4047 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4049 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4052 own_grp = (unsigned int)*puid;
4053 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4054 SIVAL(pdata,2,own_grp);
4058 case SMB_ACL_GROUP_OBJ:
4059 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4060 own_grp = (unsigned int)pst->st_ex_gid;
4061 SIVAL(pdata,2,own_grp);
4066 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4068 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4071 own_grp = (unsigned int)*pgid;
4072 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4073 SIVAL(pdata,2,own_grp);
4078 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4079 SIVAL(pdata,2,0xFFFFFFFF);
4080 SIVAL(pdata,6,0xFFFFFFFF);
4083 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4084 SIVAL(pdata,2,0xFFFFFFFF);
4085 SIVAL(pdata,6,0xFFFFFFFF);
4088 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4091 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4098 /****************************************************************************
4099 Store the FILE_UNIX_BASIC info.
4100 ****************************************************************************/
4102 static char *store_file_unix_basic(connection_struct *conn,
4105 const SMB_STRUCT_STAT *psbuf)
4107 uint64_t file_index = get_FileIndex(conn, psbuf);
4110 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4111 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4113 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4116 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4119 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4120 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4121 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4124 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4128 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4132 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4135 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4136 devno = psbuf->st_ex_rdev;
4138 devno = psbuf->st_ex_dev;
4141 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4145 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4149 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4152 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4156 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4163 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4164 * the chflags(2) (or equivalent) flags.
4166 * XXX: this really should be behind the VFS interface. To do this, we would
4167 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4168 * Each VFS module could then implement its own mapping as appropriate for the
4169 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4171 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4175 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4179 { UF_IMMUTABLE, EXT_IMMUTABLE },
4183 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4187 { UF_HIDDEN, EXT_HIDDEN },
4190 /* Do not remove. We need to guarantee that this array has at least one
4191 * entry to build on HP-UX.
4197 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4198 uint32 *smb_fflags, uint32 *smb_fmask)
4202 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4203 *smb_fmask |= info2_flags_map[i].smb_fflag;
4204 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4205 *smb_fflags |= info2_flags_map[i].smb_fflag;
4210 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4211 const uint32 smb_fflags,
4212 const uint32 smb_fmask,
4215 uint32 max_fmask = 0;
4218 *stat_fflags = psbuf->st_ex_flags;
4220 /* For each flags requested in smb_fmask, check the state of the
4221 * corresponding flag in smb_fflags and set or clear the matching
4225 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4226 max_fmask |= info2_flags_map[i].smb_fflag;
4227 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4228 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4229 *stat_fflags |= info2_flags_map[i].stat_fflag;
4231 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4236 /* If smb_fmask is asking to set any bits that are not supported by
4237 * our flag mappings, we should fail.
4239 if ((smb_fmask & max_fmask) != smb_fmask) {
4247 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4248 * of file flags and birth (create) time.
4250 static char *store_file_unix_basic_info2(connection_struct *conn,
4253 const SMB_STRUCT_STAT *psbuf)
4255 uint32 file_flags = 0;
4256 uint32 flags_mask = 0;
4258 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4260 /* Create (birth) time 64 bit */
4261 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4264 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4265 SIVAL(pdata, 0, file_flags); /* flags */
4266 SIVAL(pdata, 4, flags_mask); /* mask */
4272 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4273 const struct stream_struct *streams,
4275 unsigned int max_data_bytes,
4276 unsigned int *data_size)
4279 unsigned int ofs = 0;
4281 for (i = 0; i < num_streams; i++) {
4282 unsigned int next_offset;
4284 smb_ucs2_t *namebuf;
4286 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4287 streams[i].name, &namelen) ||
4290 return NT_STATUS_INVALID_PARAMETER;
4294 * name_buf is now null-terminated, we need to marshall as not
4301 * We cannot overflow ...
4303 if ((ofs + 24 + namelen) > max_data_bytes) {
4304 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4306 TALLOC_FREE(namebuf);
4307 return STATUS_BUFFER_OVERFLOW;
4310 SIVAL(data, ofs+4, namelen);
4311 SOFF_T(data, ofs+8, streams[i].size);
4312 SOFF_T(data, ofs+16, streams[i].alloc_size);
4313 memcpy(data+ofs+24, namebuf, namelen);
4314 TALLOC_FREE(namebuf);
4316 next_offset = ofs + 24 + namelen;
4318 if (i == num_streams-1) {
4319 SIVAL(data, ofs, 0);
4322 unsigned int align = ndr_align_size(next_offset, 8);
4324 if ((next_offset + align) > max_data_bytes) {
4325 DEBUG(10, ("refusing to overflow align "
4326 "reply at stream %u\n",
4328 TALLOC_FREE(namebuf);
4329 return STATUS_BUFFER_OVERFLOW;
4332 memset(data+next_offset, 0, align);
4333 next_offset += align;
4335 SIVAL(data, ofs, next_offset - ofs);
4342 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4346 return NT_STATUS_OK;
4349 /****************************************************************************
4350 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4351 ****************************************************************************/
4353 static void call_trans2qpipeinfo(connection_struct *conn,
4354 struct smb_request *req,
4355 unsigned int tran_call,
4356 char **pparams, int total_params,
4357 char **ppdata, int total_data,
4358 unsigned int max_data_bytes)
4360 char *params = *pparams;
4361 char *pdata = *ppdata;
4362 unsigned int data_size = 0;
4363 unsigned int param_size = 2;
4368 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4372 if (total_params < 4) {
4373 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4377 fsp = file_fsp(req, SVAL(params,0));
4378 if (!fsp_is_np(fsp)) {
4379 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4383 info_level = SVAL(params,2);
4385 *pparams = (char *)SMB_REALLOC(*pparams,2);
4386 if (*pparams == NULL) {
4387 reply_nterror(req, NT_STATUS_NO_MEMORY);
4392 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4393 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4396 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4397 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4398 if (*ppdata == NULL ) {
4399 reply_nterror(req, NT_STATUS_NO_MEMORY);
4404 switch (info_level) {
4405 case SMB_FILE_STANDARD_INFORMATION:
4407 SOFF_T(pdata,0,4096LL);
4414 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4418 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4424 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4425 TALLOC_CTX *mem_ctx,
4426 uint16_t info_level,
4428 struct smb_filename *smb_fname,
4429 bool delete_pending,
4430 struct timespec write_time_ts,
4431 struct ea_list *ea_list,
4432 int lock_data_count,
4435 unsigned int max_data_bytes,
4437 unsigned int *pdata_size)
4439 char *pdata = *ppdata;
4440 char *dstart, *dend;
4441 unsigned int data_size;
4442 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4443 time_t create_time, mtime, atime, c_time;
4444 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4451 uint64_t file_size = 0;
4453 uint64_t allocation_size = 0;
4454 uint64_t file_index = 0;
4455 uint32_t access_mask = 0;
4457 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4458 return NT_STATUS_INVALID_LEVEL;
4461 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4462 smb_fname_str_dbg(smb_fname),
4464 info_level, max_data_bytes));
4466 mode = dos_mode(conn, smb_fname);
4467 nlink = psbuf->st_ex_nlink;
4469 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4473 if ((nlink > 0) && delete_pending) {
4477 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4478 return NT_STATUS_INVALID_PARAMETER;
4481 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4482 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4483 if (*ppdata == NULL) {
4484 return NT_STATUS_NO_MEMORY;
4488 dend = dstart + data_size - 1;
4490 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4491 update_stat_ex_mtime(psbuf, write_time_ts);
4494 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4495 mtime_ts = psbuf->st_ex_mtime;
4496 atime_ts = psbuf->st_ex_atime;
4497 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4499 if (lp_dos_filetime_resolution(SNUM(conn))) {
4500 dos_filetime_timespec(&create_time_ts);
4501 dos_filetime_timespec(&mtime_ts);
4502 dos_filetime_timespec(&atime_ts);
4503 dos_filetime_timespec(&ctime_ts);
4506 create_time = convert_timespec_to_time_t(create_time_ts);
4507 mtime = convert_timespec_to_time_t(mtime_ts);
4508 atime = convert_timespec_to_time_t(atime_ts);
4509 c_time = convert_timespec_to_time_t(ctime_ts);
4511 p = strrchr_m(smb_fname->base_name,'/');
4513 base_name = smb_fname->base_name;
4517 /* NT expects the name to be in an exact form of the *full*
4518 filename. See the trans2 torture test */
4519 if (ISDOT(base_name)) {
4520 dos_fname = talloc_strdup(mem_ctx, "\\");
4522 return NT_STATUS_NO_MEMORY;
4525 dos_fname = talloc_asprintf(mem_ctx,
4527 smb_fname->base_name);
4529 return NT_STATUS_NO_MEMORY;
4531 if (is_ntfs_stream_smb_fname(smb_fname)) {
4532 dos_fname = talloc_asprintf(dos_fname, "%s",
4533 smb_fname->stream_name);
4535 return NT_STATUS_NO_MEMORY;
4539 string_replace(dos_fname, '/', '\\');
4542 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4545 /* Do we have this path open ? */
4547 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4548 fsp1 = file_find_di_first(conn->sconn, fileid);
4549 if (fsp1 && fsp1->initial_allocation_size) {
4550 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4554 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4555 file_size = get_file_size_stat(psbuf);
4559 pos = fsp->fh->position_information;
4563 access_mask = fsp->access_mask;
4565 /* GENERIC_EXECUTE mapping from Windows */
4566 access_mask = 0x12019F;
4569 /* This should be an index number - looks like
4572 I think this causes us to fail the IFSKIT
4573 BasicFileInformationTest. -tpot */
4574 file_index = get_FileIndex(conn, psbuf);
4576 switch (info_level) {
4577 case SMB_INFO_STANDARD:
4578 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4580 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4581 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4582 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4583 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4584 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4585 SSVAL(pdata,l1_attrFile,mode);
4588 case SMB_INFO_QUERY_EA_SIZE:
4590 unsigned int ea_size =
4591 estimate_ea_size(conn, fsp,
4593 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4595 srv_put_dos_date2(pdata,0,create_time);
4596 srv_put_dos_date2(pdata,4,atime);
4597 srv_put_dos_date2(pdata,8,mtime); /* write time */
4598 SIVAL(pdata,12,(uint32)file_size);
4599 SIVAL(pdata,16,(uint32)allocation_size);
4600 SSVAL(pdata,20,mode);
4601 SIVAL(pdata,22,ea_size);
4605 case SMB_INFO_IS_NAME_VALID:
4606 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4608 /* os/2 needs this ? really ?*/
4609 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4611 /* This is only reached for qpathinfo */
4615 case SMB_INFO_QUERY_EAS_FROM_LIST:
4617 size_t total_ea_len = 0;
4618 struct ea_list *ea_file_list = NULL;
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4622 get_ea_list_from_file(mem_ctx, conn, fsp,
4624 &total_ea_len, &ea_file_list);
4625 if (!NT_STATUS_IS_OK(status)) {
4629 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4631 if (!ea_list || (total_ea_len > data_size)) {
4633 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4637 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4641 case SMB_INFO_QUERY_ALL_EAS:
4643 /* We have data_size bytes to put EA's into. */
4644 size_t total_ea_len = 0;
4645 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4647 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4649 &total_ea_len, &ea_list);
4650 if (!NT_STATUS_IS_OK(status)) {
4654 if (!ea_list || (total_ea_len > data_size)) {
4656 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4660 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4664 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4666 /* This is FileFullEaInformation - 0xF which maps to
4667 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4669 /* We have data_size bytes to put EA's into. */
4670 size_t total_ea_len = 0;
4671 struct ea_list *ea_file_list = NULL;
4673 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4675 /*TODO: add filtering and index handling */
4678 get_ea_list_from_file(mem_ctx, conn, fsp,
4680 &total_ea_len, &ea_file_list);
4681 if (!NT_STATUS_IS_OK(status)) {
4684 if (!ea_file_list) {
4685 return NT_STATUS_NO_EAS_ON_FILE;
4688 status = fill_ea_chained_buffer(mem_ctx,
4692 conn, ea_file_list);
4693 if (!NT_STATUS_IS_OK(status)) {
4699 case SMB_FILE_BASIC_INFORMATION:
4700 case SMB_QUERY_FILE_BASIC_INFO:
4702 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4703 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4704 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4706 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4710 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4711 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4712 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4713 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4714 SIVAL(pdata,32,mode);
4716 DEBUG(5,("SMB_QFBI - "));
4717 DEBUG(5,("create: %s ", ctime(&create_time)));
4718 DEBUG(5,("access: %s ", ctime(&atime)));
4719 DEBUG(5,("write: %s ", ctime(&mtime)));
4720 DEBUG(5,("change: %s ", ctime(&c_time)));
4721 DEBUG(5,("mode: %x\n", mode));
4724 case SMB_FILE_STANDARD_INFORMATION:
4725 case SMB_QUERY_FILE_STANDARD_INFO:
4727 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4729 SOFF_T(pdata,0,allocation_size);
4730 SOFF_T(pdata,8,file_size);
4731 SIVAL(pdata,16,nlink);
4732 SCVAL(pdata,20,delete_pending?1:0);
4733 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4734 SSVAL(pdata,22,0); /* Padding. */
4737 case SMB_FILE_EA_INFORMATION:
4738 case SMB_QUERY_FILE_EA_INFO:
4740 unsigned int ea_size =
4741 estimate_ea_size(conn, fsp, smb_fname);
4742 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4744 SIVAL(pdata,0,ea_size);
4748 /* Get the 8.3 name - used if NT SMB was negotiated. */
4749 case SMB_QUERY_FILE_ALT_NAME_INFO:
4750 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4753 char mangled_name[13];
4754 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4755 if (!name_to_8_3(base_name,mangled_name,
4756 True,conn->params)) {
4757 return NT_STATUS_NO_MEMORY;
4759 len = srvstr_push(dstart, flags2,
4760 pdata+4, mangled_name,
4761 PTR_DIFF(dend, pdata+4),
4763 data_size = 4 + len;
4768 case SMB_QUERY_FILE_NAME_INFO:
4772 this must be *exactly* right for ACLs on mapped drives to work
4774 len = srvstr_push(dstart, flags2,
4776 PTR_DIFF(dend, pdata+4),
4778 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4779 data_size = 4 + len;
4784 case SMB_FILE_ALLOCATION_INFORMATION:
4785 case SMB_QUERY_FILE_ALLOCATION_INFO:
4786 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4788 SOFF_T(pdata,0,allocation_size);
4791 case SMB_FILE_END_OF_FILE_INFORMATION:
4792 case SMB_QUERY_FILE_END_OF_FILEINFO:
4793 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4795 SOFF_T(pdata,0,file_size);
4798 case SMB_QUERY_FILE_ALL_INFO:
4799 case SMB_FILE_ALL_INFORMATION:
4802 unsigned int ea_size =
4803 estimate_ea_size(conn, fsp, smb_fname);
4804 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4805 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4806 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4807 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4808 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4809 SIVAL(pdata,32,mode);
4810 SIVAL(pdata,36,0); /* padding. */
4812 SOFF_T(pdata,0,allocation_size);
4813 SOFF_T(pdata,8,file_size);
4814 SIVAL(pdata,16,nlink);
4815 SCVAL(pdata,20,delete_pending);
4816 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4819 SIVAL(pdata,0,ea_size);
4820 pdata += 4; /* EA info */
4821 len = srvstr_push(dstart, flags2,
4823 PTR_DIFF(dend, pdata+4),
4827 data_size = PTR_DIFF(pdata,(*ppdata));
4831 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4834 unsigned int ea_size =
4835 estimate_ea_size(conn, fsp, smb_fname);
4836 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4837 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4838 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4839 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4840 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4841 SIVAL(pdata, 0x20, mode);
4842 SIVAL(pdata, 0x24, 0); /* padding. */
4843 SBVAL(pdata, 0x28, allocation_size);
4844 SBVAL(pdata, 0x30, file_size);
4845 SIVAL(pdata, 0x38, nlink);
4846 SCVAL(pdata, 0x3C, delete_pending);
4847 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4848 SSVAL(pdata, 0x3E, 0); /* padding */
4849 SBVAL(pdata, 0x40, file_index);
4850 SIVAL(pdata, 0x48, ea_size);
4851 SIVAL(pdata, 0x4C, access_mask);
4852 SBVAL(pdata, 0x50, pos);
4853 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4854 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4858 len = srvstr_push(dstart, flags2,
4860 PTR_DIFF(dend, pdata+4),
4864 data_size = PTR_DIFF(pdata,(*ppdata));
4867 case SMB_FILE_INTERNAL_INFORMATION:
4869 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4870 SBVAL(pdata, 0, file_index);
4874 case SMB_FILE_ACCESS_INFORMATION:
4875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4876 SIVAL(pdata, 0, access_mask);
4880 case SMB_FILE_NAME_INFORMATION:
4881 /* Pathname with leading '\'. */
4884 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4885 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4886 SIVAL(pdata,0,byte_len);
4887 data_size = 4 + byte_len;
4891 case SMB_FILE_DISPOSITION_INFORMATION:
4892 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4894 SCVAL(pdata,0,delete_pending);
4897 case SMB_FILE_POSITION_INFORMATION:
4898 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4900 SOFF_T(pdata,0,pos);
4903 case SMB_FILE_MODE_INFORMATION:
4904 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4905 SIVAL(pdata,0,mode);
4909 case SMB_FILE_ALIGNMENT_INFORMATION:
4910 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4911 SIVAL(pdata,0,0); /* No alignment needed. */
4916 * NT4 server just returns "invalid query" to this - if we try
4917 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4920 /* The first statement above is false - verified using Thursby
4921 * client against NT4 -- gcolley.
4923 case SMB_QUERY_FILE_STREAM_INFO:
4924 case SMB_FILE_STREAM_INFORMATION: {
4925 unsigned int num_streams = 0;
4926 struct stream_struct *streams = NULL;
4928 DEBUG(10,("smbd_do_qfilepathinfo: "
4929 "SMB_FILE_STREAM_INFORMATION\n"));
4931 if (is_ntfs_stream_smb_fname(smb_fname)) {
4932 return NT_STATUS_INVALID_PARAMETER;
4935 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4936 talloc_tos(), &num_streams, &streams);
4938 if (!NT_STATUS_IS_OK(status)) {
4939 DEBUG(10, ("could not get stream info: %s\n",
4940 nt_errstr(status)));
4944 status = marshall_stream_info(num_streams, streams,
4945 pdata, max_data_bytes,
4948 if (!NT_STATUS_IS_OK(status)) {
4949 DEBUG(10, ("marshall_stream_info failed: %s\n",
4950 nt_errstr(status)));
4951 TALLOC_FREE(streams);
4955 TALLOC_FREE(streams);
4959 case SMB_QUERY_COMPRESSION_INFO:
4960 case SMB_FILE_COMPRESSION_INFORMATION:
4961 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4962 SOFF_T(pdata,0,file_size);
4963 SIVAL(pdata,8,0); /* ??? */
4964 SIVAL(pdata,12,0); /* ??? */
4968 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4969 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4970 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4971 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4972 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4973 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4974 SOFF_T(pdata,32,allocation_size);
4975 SOFF_T(pdata,40,file_size);
4976 SIVAL(pdata,48,mode);
4977 SIVAL(pdata,52,0); /* ??? */
4981 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4982 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4983 SIVAL(pdata,0,mode);
4989 * CIFS UNIX Extensions.
4992 case SMB_QUERY_FILE_UNIX_BASIC:
4994 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4995 data_size = PTR_DIFF(pdata,(*ppdata));
4997 DEBUG(4,("smbd_do_qfilepathinfo: "
4998 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4999 dump_data(4, (uint8_t *)(*ppdata), data_size);
5003 case SMB_QUERY_FILE_UNIX_INFO2:
5005 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5006 data_size = PTR_DIFF(pdata,(*ppdata));
5010 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5012 for (i=0; i<100; i++)
5013 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5019 case SMB_QUERY_FILE_UNIX_LINK:
5022 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5025 return NT_STATUS_NO_MEMORY;
5028 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5030 if(!S_ISLNK(psbuf->st_ex_mode)) {
5031 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5034 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5036 len = SMB_VFS_READLINK(conn,
5037 smb_fname->base_name,
5040 return map_nt_error_from_unix(errno);
5043 len = srvstr_push(dstart, flags2,
5045 PTR_DIFF(dend, pdata),
5048 data_size = PTR_DIFF(pdata,(*ppdata));
5053 #if defined(HAVE_POSIX_ACLS)
5054 case SMB_QUERY_POSIX_ACL:
5056 SMB_ACL_T file_acl = NULL;
5057 SMB_ACL_T def_acl = NULL;
5058 uint16 num_file_acls = 0;
5059 uint16 num_def_acls = 0;
5061 if (fsp && fsp->fh->fd != -1) {
5062 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5066 SMB_VFS_SYS_ACL_GET_FILE(conn,
5067 smb_fname->base_name,
5068 SMB_ACL_TYPE_ACCESS,
5072 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5073 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5074 "not implemented on "
5075 "filesystem containing %s\n",
5076 smb_fname->base_name));
5077 return NT_STATUS_NOT_IMPLEMENTED;
5080 if (S_ISDIR(psbuf->st_ex_mode)) {
5081 if (fsp && fsp->is_directory) {
5083 SMB_VFS_SYS_ACL_GET_FILE(
5085 fsp->fsp_name->base_name,
5086 SMB_ACL_TYPE_DEFAULT,
5090 SMB_VFS_SYS_ACL_GET_FILE(
5092 smb_fname->base_name,
5093 SMB_ACL_TYPE_DEFAULT,
5096 def_acl = free_empty_sys_acl(conn, def_acl);
5099 num_file_acls = count_acl_entries(conn, file_acl);
5100 num_def_acls = count_acl_entries(conn, def_acl);
5102 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5103 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5105 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5106 SMB_POSIX_ACL_HEADER_SIZE) ));
5108 TALLOC_FREE(file_acl);
5111 TALLOC_FREE(def_acl);
5113 return NT_STATUS_BUFFER_TOO_SMALL;
5116 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5117 SSVAL(pdata,2,num_file_acls);
5118 SSVAL(pdata,4,num_def_acls);
5119 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5121 TALLOC_FREE(file_acl);
5124 TALLOC_FREE(def_acl);
5126 return NT_STATUS_INTERNAL_ERROR;
5128 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5130 TALLOC_FREE(file_acl);
5133 TALLOC_FREE(def_acl);
5135 return NT_STATUS_INTERNAL_ERROR;
5139 TALLOC_FREE(file_acl);
5142 TALLOC_FREE(def_acl);
5144 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5150 case SMB_QUERY_POSIX_LOCK:
5155 enum brl_type lock_type;
5157 /* We need an open file with a real fd for this. */
5158 if (!fsp || fsp->fh->fd == -1) {
5159 return NT_STATUS_INVALID_LEVEL;
5162 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5163 return NT_STATUS_INVALID_PARAMETER;
5166 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5167 case POSIX_LOCK_TYPE_READ:
5168 lock_type = READ_LOCK;
5170 case POSIX_LOCK_TYPE_WRITE:
5171 lock_type = WRITE_LOCK;
5173 case POSIX_LOCK_TYPE_UNLOCK:
5175 /* There's no point in asking for an unlock... */
5176 return NT_STATUS_INVALID_PARAMETER;
5179 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5180 #if defined(HAVE_LONGLONG)
5181 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5182 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5183 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5184 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5185 #else /* HAVE_LONGLONG */
5186 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5187 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5188 #endif /* HAVE_LONGLONG */
5190 status = query_lock(fsp,
5197 if (ERROR_WAS_LOCK_DENIED(status)) {
5198 /* Here we need to report who has it locked... */
5199 data_size = POSIX_LOCK_DATA_SIZE;
5201 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5202 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5203 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5204 #if defined(HAVE_LONGLONG)
5205 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5206 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5207 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5208 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5209 #else /* HAVE_LONGLONG */
5210 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5211 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5212 #endif /* HAVE_LONGLONG */
5214 } else if (NT_STATUS_IS_OK(status)) {
5215 /* For success we just return a copy of what we sent
5216 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5217 data_size = POSIX_LOCK_DATA_SIZE;
5218 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5219 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5227 return NT_STATUS_INVALID_LEVEL;
5230 *pdata_size = data_size;
5231 return NT_STATUS_OK;
5234 /****************************************************************************
5235 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5236 file name or file id).
5237 ****************************************************************************/
5239 static void call_trans2qfilepathinfo(connection_struct *conn,
5240 struct smb_request *req,
5241 unsigned int tran_call,
5242 char **pparams, int total_params,
5243 char **ppdata, int total_data,
5244 unsigned int max_data_bytes)
5246 char *params = *pparams;
5247 char *pdata = *ppdata;
5249 unsigned int data_size = 0;
5250 unsigned int param_size = 2;
5251 struct smb_filename *smb_fname = NULL;
5252 bool delete_pending = False;
5253 struct timespec write_time_ts;
5254 files_struct *fsp = NULL;
5255 struct file_id fileid;
5256 struct ea_list *ea_list = NULL;
5257 int lock_data_count = 0;
5258 char *lock_data = NULL;
5259 NTSTATUS status = NT_STATUS_OK;
5262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5266 ZERO_STRUCT(write_time_ts);
5268 if (tran_call == TRANSACT2_QFILEINFO) {
5269 if (total_params < 4) {
5270 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5275 call_trans2qpipeinfo(conn, req, tran_call,
5276 pparams, total_params,
5282 fsp = file_fsp(req, SVAL(params,0));
5283 info_level = SVAL(params,2);
5285 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5287 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5288 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5292 /* Initial check for valid fsp ptr. */
5293 if (!check_fsp_open(conn, req, fsp)) {
5297 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5298 if (smb_fname == NULL) {
5299 reply_nterror(req, NT_STATUS_NO_MEMORY);
5303 if(fsp->fake_file_handle) {
5305 * This is actually for the QUOTA_FAKE_FILE --metze
5308 /* We know this name is ok, it's already passed the checks. */
5310 } else if(fsp->fh->fd == -1) {
5312 * This is actually a QFILEINFO on a directory
5313 * handle (returned from an NT SMB). NT5.0 seems
5314 * to do this call. JRA.
5317 if (INFO_LEVEL_IS_UNIX(info_level)) {
5318 /* Always do lstat for UNIX calls. */
5319 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5320 DEBUG(3,("call_trans2qfilepathinfo: "
5321 "SMB_VFS_LSTAT of %s failed "
5323 smb_fname_str_dbg(smb_fname),
5326 map_nt_error_from_unix(errno));
5329 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5330 DEBUG(3,("call_trans2qfilepathinfo: "
5331 "SMB_VFS_STAT of %s failed (%s)\n",
5332 smb_fname_str_dbg(smb_fname),
5335 map_nt_error_from_unix(errno));
5339 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5340 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5343 * Original code - this is an open file.
5345 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5346 DEBUG(3, ("fstat of %s failed (%s)\n",
5347 fsp_fnum_dbg(fsp), strerror(errno)));
5349 map_nt_error_from_unix(errno));
5352 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5353 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5359 uint32_t ucf_flags = 0;
5362 if (total_params < 7) {
5363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5367 info_level = SVAL(params,0);
5369 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5371 if (INFO_LEVEL_IS_UNIX(info_level)) {
5372 if (!lp_unix_extensions()) {
5373 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5376 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5377 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5378 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5379 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5383 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5385 STR_TERMINATE, &status);
5386 if (!NT_STATUS_IS_OK(status)) {
5387 reply_nterror(req, status);
5391 status = filename_convert(req,
5393 req->flags2 & FLAGS2_DFS_PATHNAMES,
5398 if (!NT_STATUS_IS_OK(status)) {
5399 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5400 reply_botherror(req,
5401 NT_STATUS_PATH_NOT_COVERED,
5402 ERRSRV, ERRbadpath);
5405 reply_nterror(req, status);
5409 /* If this is a stream, check if there is a delete_pending. */
5410 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5411 && is_ntfs_stream_smb_fname(smb_fname)) {
5412 struct smb_filename *smb_fname_base;
5414 /* Create an smb_filename with stream_name == NULL. */
5415 smb_fname_base = synthetic_smb_fname(
5416 talloc_tos(), smb_fname->base_name,
5418 if (smb_fname_base == NULL) {
5419 reply_nterror(req, NT_STATUS_NO_MEMORY);
5423 if (INFO_LEVEL_IS_UNIX(info_level)) {
5424 /* Always do lstat for UNIX calls. */
5425 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5426 DEBUG(3,("call_trans2qfilepathinfo: "
5427 "SMB_VFS_LSTAT of %s failed "
5429 smb_fname_str_dbg(smb_fname_base),
5431 TALLOC_FREE(smb_fname_base);
5433 map_nt_error_from_unix(errno));
5437 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5438 DEBUG(3,("call_trans2qfilepathinfo: "
5439 "fileinfo of %s failed "
5441 smb_fname_str_dbg(smb_fname_base),
5443 TALLOC_FREE(smb_fname_base);
5445 map_nt_error_from_unix(errno));
5450 status = file_name_hash(conn,
5451 smb_fname_str_dbg(smb_fname_base),
5453 if (!NT_STATUS_IS_OK(status)) {
5454 TALLOC_FREE(smb_fname_base);
5455 reply_nterror(req, status);
5459 fileid = vfs_file_id_from_sbuf(conn,
5460 &smb_fname_base->st);
5461 TALLOC_FREE(smb_fname_base);
5462 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5463 if (delete_pending) {
5464 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5469 if (INFO_LEVEL_IS_UNIX(info_level)) {
5470 /* Always do lstat for UNIX calls. */
5471 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5472 DEBUG(3,("call_trans2qfilepathinfo: "
5473 "SMB_VFS_LSTAT of %s failed (%s)\n",
5474 smb_fname_str_dbg(smb_fname),
5477 map_nt_error_from_unix(errno));
5482 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5483 DEBUG(3,("call_trans2qfilepathinfo: "
5484 "SMB_VFS_STAT of %s failed (%s)\n",
5485 smb_fname_str_dbg(smb_fname),
5488 map_nt_error_from_unix(errno));
5493 status = file_name_hash(conn,
5494 smb_fname_str_dbg(smb_fname),
5496 if (!NT_STATUS_IS_OK(status)) {
5497 reply_nterror(req, status);
5501 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5502 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5503 if (delete_pending) {
5504 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5509 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5510 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5512 info_level,tran_call,total_data));
5514 /* Pull out any data sent here before we realloc. */
5515 switch (info_level) {
5516 case SMB_INFO_QUERY_EAS_FROM_LIST:
5518 /* Pull any EA list from the data portion. */
5521 if (total_data < 4) {
5523 req, NT_STATUS_INVALID_PARAMETER);
5526 ea_size = IVAL(pdata,0);
5528 if (total_data > 0 && ea_size != total_data) {
5529 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5530 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5532 req, NT_STATUS_INVALID_PARAMETER);
5536 if (!lp_ea_support(SNUM(conn))) {
5537 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5541 /* Pull out the list of names. */
5542 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5545 req, NT_STATUS_INVALID_PARAMETER);
5551 case SMB_QUERY_POSIX_LOCK:
5553 if (fsp == NULL || fsp->fh->fd == -1) {
5554 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5558 if (total_data != POSIX_LOCK_DATA_SIZE) {
5560 req, NT_STATUS_INVALID_PARAMETER);
5564 /* Copy the lock range data. */
5565 lock_data = (char *)talloc_memdup(
5566 req, pdata, total_data);
5568 reply_nterror(req, NT_STATUS_NO_MEMORY);
5571 lock_data_count = total_data;
5577 *pparams = (char *)SMB_REALLOC(*pparams,2);
5578 if (*pparams == NULL) {
5579 reply_nterror(req, NT_STATUS_NO_MEMORY);
5586 * draft-leach-cifs-v1-spec-02.txt
5587 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5590 * The requested information is placed in the Data portion of the
5591 * transaction response. For the information levels greater than 0x100,
5592 * the transaction response has 1 parameter word which should be
5593 * ignored by the client.
5595 * However Windows only follows this rule for the IS_NAME_VALID call.
5597 switch (info_level) {
5598 case SMB_INFO_IS_NAME_VALID:
5603 if ((info_level & 0xFF00) == 0xFF00) {
5605 * We use levels that start with 0xFF00
5606 * internally to represent SMB2 specific levels
5608 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5612 status = smbd_do_qfilepathinfo(conn, req, info_level,
5614 delete_pending, write_time_ts,
5616 lock_data_count, lock_data,
5617 req->flags2, max_data_bytes,
5618 ppdata, &data_size);
5619 if (!NT_STATUS_IS_OK(status)) {
5620 reply_nterror(req, status);
5624 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5630 /****************************************************************************
5631 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5633 ****************************************************************************/
5635 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5636 connection_struct *conn,
5637 struct smb_request *req,
5638 bool overwrite_if_exists,
5639 const struct smb_filename *smb_fname_old,
5640 struct smb_filename *smb_fname_new)
5642 NTSTATUS status = NT_STATUS_OK;
5644 /* source must already exist. */
5645 if (!VALID_STAT(smb_fname_old->st)) {
5646 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5649 if (VALID_STAT(smb_fname_new->st)) {
5650 if (overwrite_if_exists) {
5651 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5652 return NT_STATUS_FILE_IS_A_DIRECTORY;
5654 status = unlink_internals(conn,
5656 FILE_ATTRIBUTE_NORMAL,
5659 if (!NT_STATUS_IS_OK(status)) {
5663 /* Disallow if newname already exists. */
5664 return NT_STATUS_OBJECT_NAME_COLLISION;
5668 /* No links from a directory. */
5669 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5670 return NT_STATUS_FILE_IS_A_DIRECTORY;
5673 /* Setting a hardlink to/from a stream isn't currently supported. */
5674 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5675 is_ntfs_stream_smb_fname(smb_fname_new)) {
5676 return NT_STATUS_INVALID_PARAMETER;
5679 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5680 smb_fname_old->base_name, smb_fname_new->base_name));
5682 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5683 smb_fname_new->base_name) != 0) {
5684 status = map_nt_error_from_unix(errno);
5685 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5686 nt_errstr(status), smb_fname_old->base_name,
5687 smb_fname_new->base_name));
5692 /****************************************************************************
5693 Deal with setting the time from any of the setfilepathinfo functions.
5694 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5695 calling this function.
5696 ****************************************************************************/
5698 NTSTATUS smb_set_file_time(connection_struct *conn,
5700 const struct smb_filename *smb_fname,
5701 struct smb_file_time *ft,
5702 bool setting_write_time)
5704 struct smb_filename smb_fname_base;
5706 FILE_NOTIFY_CHANGE_LAST_ACCESS
5707 |FILE_NOTIFY_CHANGE_LAST_WRITE
5708 |FILE_NOTIFY_CHANGE_CREATION;
5710 if (!VALID_STAT(smb_fname->st)) {
5711 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5714 /* get some defaults (no modifications) if any info is zero or -1. */
5715 if (null_timespec(ft->create_time)) {
5716 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5719 if (null_timespec(ft->atime)) {
5720 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5723 if (null_timespec(ft->mtime)) {
5724 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5727 if (!setting_write_time) {
5728 /* ft->mtime comes from change time, not write time. */
5729 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5732 /* Ensure the resolution is the correct for
5733 * what we can store on this filesystem. */
5735 round_timespec(conn->ts_res, &ft->create_time);
5736 round_timespec(conn->ts_res, &ft->ctime);
5737 round_timespec(conn->ts_res, &ft->atime);
5738 round_timespec(conn->ts_res, &ft->mtime);
5740 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5741 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5742 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5743 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5744 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5745 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5746 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5747 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5749 if (setting_write_time) {
5751 * This was a Windows setfileinfo on an open file.
5752 * NT does this a lot. We also need to
5753 * set the time here, as it can be read by
5754 * FindFirst/FindNext and with the patch for bug #2045
5755 * in smbd/fileio.c it ensures that this timestamp is
5756 * kept sticky even after a write. We save the request
5757 * away and will set it on file close and after a write. JRA.
5760 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5761 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5764 if (fsp->base_fsp) {
5765 set_sticky_write_time_fsp(fsp->base_fsp,
5768 set_sticky_write_time_fsp(fsp, ft->mtime);
5771 set_sticky_write_time_path(
5772 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5777 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5779 /* Always call ntimes on the base, even if a stream was passed in. */
5780 smb_fname_base = *smb_fname;
5781 smb_fname_base.stream_name = NULL;
5783 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5784 return map_nt_error_from_unix(errno);
5787 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5788 smb_fname->base_name);
5789 return NT_STATUS_OK;
5792 /****************************************************************************
5793 Deal with setting the dosmode from any of the setfilepathinfo functions.
5794 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5795 done before calling this function.
5796 ****************************************************************************/
5798 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5799 const struct smb_filename *smb_fname,
5802 struct smb_filename *smb_fname_base;
5805 if (!VALID_STAT(smb_fname->st)) {
5806 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5809 /* Always operate on the base_name, even if a stream was passed in. */
5810 smb_fname_base = synthetic_smb_fname(
5811 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5812 if (smb_fname_base == NULL) {
5813 return NT_STATUS_NO_MEMORY;
5817 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5818 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5820 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5824 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5826 /* check the mode isn't different, before changing it */
5827 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5828 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5829 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5830 (unsigned int)dosmode));
5832 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5834 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5836 smb_fname_str_dbg(smb_fname_base),
5838 status = map_nt_error_from_unix(errno);
5842 status = NT_STATUS_OK;
5844 TALLOC_FREE(smb_fname_base);
5848 /****************************************************************************
5849 Deal with setting the size from any of the setfilepathinfo functions.
5850 ****************************************************************************/
5852 static NTSTATUS smb_set_file_size(connection_struct *conn,
5853 struct smb_request *req,
5855 const struct smb_filename *smb_fname,
5856 const SMB_STRUCT_STAT *psbuf,
5858 bool fail_after_createfile)
5860 NTSTATUS status = NT_STATUS_OK;
5861 struct smb_filename *smb_fname_tmp = NULL;
5862 files_struct *new_fsp = NULL;
5864 if (!VALID_STAT(*psbuf)) {
5865 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5868 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5870 if (size == get_file_size_stat(psbuf)) {
5871 return NT_STATUS_OK;
5874 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5875 smb_fname_str_dbg(smb_fname), (double)size));
5877 if (fsp && fsp->fh->fd != -1) {
5878 /* Handle based call. */
5879 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5880 return NT_STATUS_ACCESS_DENIED;
5883 if (vfs_set_filelen(fsp, size) == -1) {
5884 return map_nt_error_from_unix(errno);
5886 trigger_write_time_update_immediate(fsp);
5887 return NT_STATUS_OK;
5890 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5891 if (smb_fname_tmp == NULL) {
5892 return NT_STATUS_NO_MEMORY;
5895 smb_fname_tmp->st = *psbuf;
5897 status = SMB_VFS_CREATE_FILE(
5900 0, /* root_dir_fid */
5901 smb_fname_tmp, /* fname */
5902 FILE_WRITE_DATA, /* access_mask */
5903 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5905 FILE_OPEN, /* create_disposition*/
5906 0, /* create_options */
5907 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5908 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5909 0, /* allocation_size */
5910 0, /* private_flags */
5913 &new_fsp, /* result */
5916 TALLOC_FREE(smb_fname_tmp);
5918 if (!NT_STATUS_IS_OK(status)) {
5919 /* NB. We check for open_was_deferred in the caller. */
5923 /* See RAW-SFILEINFO-END-OF-FILE */
5924 if (fail_after_createfile) {
5925 close_file(req, new_fsp,NORMAL_CLOSE);
5926 return NT_STATUS_INVALID_LEVEL;
5929 if (vfs_set_filelen(new_fsp, size) == -1) {
5930 status = map_nt_error_from_unix(errno);
5931 close_file(req, new_fsp,NORMAL_CLOSE);
5935 trigger_write_time_update_immediate(new_fsp);
5936 close_file(req, new_fsp,NORMAL_CLOSE);
5937 return NT_STATUS_OK;
5940 /****************************************************************************
5941 Deal with SMB_INFO_SET_EA.
5942 ****************************************************************************/
5944 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5948 const struct smb_filename *smb_fname)
5950 struct ea_list *ea_list = NULL;
5951 TALLOC_CTX *ctx = NULL;
5952 NTSTATUS status = NT_STATUS_OK;
5954 if (total_data < 10) {
5956 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5957 length. They seem to have no effect. Bug #3212. JRA */
5959 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5960 /* We're done. We only get EA info in this call. */
5961 return NT_STATUS_OK;
5964 return NT_STATUS_INVALID_PARAMETER;
5967 if (IVAL(pdata,0) > total_data) {
5968 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5969 IVAL(pdata,0), (unsigned int)total_data));
5970 return NT_STATUS_INVALID_PARAMETER;
5974 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5976 return NT_STATUS_INVALID_PARAMETER;
5979 status = set_ea(conn, fsp, smb_fname, ea_list);
5984 /****************************************************************************
5985 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5986 ****************************************************************************/
5988 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5993 struct ea_list *ea_list = NULL;
5997 return NT_STATUS_INVALID_HANDLE;
6000 if (!lp_ea_support(SNUM(conn))) {
6001 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6002 "EA's not supported.\n",
6003 (unsigned int)total_data));
6004 return NT_STATUS_EAS_NOT_SUPPORTED;
6007 if (total_data < 10) {
6008 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6010 (unsigned int)total_data));
6011 return NT_STATUS_INVALID_PARAMETER;
6014 ea_list = read_nttrans_ea_list(talloc_tos(),
6019 return NT_STATUS_INVALID_PARAMETER;
6022 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6024 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6025 smb_fname_str_dbg(fsp->fsp_name),
6026 nt_errstr(status) ));
6032 /****************************************************************************
6033 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6034 ****************************************************************************/
6036 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6040 struct smb_filename *smb_fname)
6042 NTSTATUS status = NT_STATUS_OK;
6043 bool delete_on_close;
6046 if (total_data < 1) {
6047 return NT_STATUS_INVALID_PARAMETER;
6051 return NT_STATUS_INVALID_HANDLE;
6054 delete_on_close = (CVAL(pdata,0) ? True : False);
6055 dosmode = dos_mode(conn, smb_fname);
6057 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6058 "delete_on_close = %u\n",
6059 smb_fname_str_dbg(smb_fname),
6060 (unsigned int)dosmode,
6061 (unsigned int)delete_on_close ));
6063 if (delete_on_close) {
6064 status = can_set_delete_on_close(fsp, dosmode);
6065 if (!NT_STATUS_IS_OK(status)) {
6070 /* The set is across all open files on this dev/inode pair. */
6071 if (!set_delete_on_close(fsp, delete_on_close,
6072 conn->session_info->security_token,
6073 conn->session_info->unix_token)) {
6074 return NT_STATUS_ACCESS_DENIED;
6076 return NT_STATUS_OK;
6079 /****************************************************************************
6080 Deal with SMB_FILE_POSITION_INFORMATION.
6081 ****************************************************************************/
6083 static NTSTATUS smb_file_position_information(connection_struct *conn,
6088 uint64_t position_information;
6090 if (total_data < 8) {
6091 return NT_STATUS_INVALID_PARAMETER;
6095 /* Ignore on pathname based set. */
6096 return NT_STATUS_OK;
6099 position_information = (uint64_t)IVAL(pdata,0);
6100 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6102 DEBUG(10,("smb_file_position_information: Set file position "
6103 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6104 (double)position_information));
6105 fsp->fh->position_information = position_information;
6106 return NT_STATUS_OK;
6109 /****************************************************************************
6110 Deal with SMB_FILE_MODE_INFORMATION.
6111 ****************************************************************************/
6113 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6119 if (total_data < 4) {
6120 return NT_STATUS_INVALID_PARAMETER;
6122 mode = IVAL(pdata,0);
6123 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6124 return NT_STATUS_INVALID_PARAMETER;
6126 return NT_STATUS_OK;
6129 /****************************************************************************
6130 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6131 ****************************************************************************/
6133 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6134 struct smb_request *req,
6137 const struct smb_filename *smb_fname)
6139 char *link_target = NULL;
6140 const char *newname = smb_fname->base_name;
6141 TALLOC_CTX *ctx = talloc_tos();
6143 /* Set a symbolic link. */
6144 /* Don't allow this if follow links is false. */
6146 if (total_data == 0) {
6147 return NT_STATUS_INVALID_PARAMETER;
6150 if (!lp_symlinks(SNUM(conn))) {
6151 return NT_STATUS_ACCESS_DENIED;
6154 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6155 total_data, STR_TERMINATE);
6158 return NT_STATUS_INVALID_PARAMETER;
6161 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6162 newname, link_target ));
6164 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6165 return map_nt_error_from_unix(errno);
6168 return NT_STATUS_OK;
6171 /****************************************************************************
6172 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6173 ****************************************************************************/
6175 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6176 struct smb_request *req,
6177 const char *pdata, int total_data,
6178 struct smb_filename *smb_fname_new)
6180 char *oldname = NULL;
6181 struct smb_filename *smb_fname_old = NULL;
6182 TALLOC_CTX *ctx = talloc_tos();
6183 NTSTATUS status = NT_STATUS_OK;
6185 /* Set a hard link. */
6186 if (total_data == 0) {
6187 return NT_STATUS_INVALID_PARAMETER;
6190 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6191 total_data, STR_TERMINATE, &status);
6192 if (!NT_STATUS_IS_OK(status)) {
6196 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6197 smb_fname_str_dbg(smb_fname_new), oldname));
6199 status = filename_convert(ctx,
6201 req->flags2 & FLAGS2_DFS_PATHNAMES,
6206 if (!NT_STATUS_IS_OK(status)) {
6210 return hardlink_internals(ctx, conn, req, false,
6211 smb_fname_old, smb_fname_new);
6214 /****************************************************************************
6215 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6216 ****************************************************************************/
6218 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6219 struct smb_request *req,
6223 struct smb_filename *smb_fname_src)
6227 char *newname = NULL;
6228 struct smb_filename *smb_fname_dst = NULL;
6229 NTSTATUS status = NT_STATUS_OK;
6230 TALLOC_CTX *ctx = talloc_tos();
6233 return NT_STATUS_INVALID_HANDLE;
6236 if (total_data < 20) {
6237 return NT_STATUS_INVALID_PARAMETER;
6240 overwrite = (CVAL(pdata,0) ? True : False);
6241 len = IVAL(pdata,16);
6243 if (len > (total_data - 20) || (len == 0)) {
6244 return NT_STATUS_INVALID_PARAMETER;
6247 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6248 &pdata[20], len, STR_TERMINATE,
6250 if (!NT_STATUS_IS_OK(status)) {
6254 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6257 status = filename_convert(ctx,
6259 req->flags2 & FLAGS2_DFS_PATHNAMES,
6264 if (!NT_STATUS_IS_OK(status)) {
6268 if (fsp->base_fsp) {
6269 /* newname must be a stream name. */
6270 if (newname[0] != ':') {
6271 return NT_STATUS_NOT_SUPPORTED;
6274 /* Create an smb_fname to call rename_internals_fsp() with. */
6275 smb_fname_dst = synthetic_smb_fname(
6276 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6278 if (smb_fname_dst == NULL) {
6279 status = NT_STATUS_NO_MEMORY;
6284 * Set the original last component, since
6285 * rename_internals_fsp() requires it.
6287 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6289 if (smb_fname_dst->original_lcomp == NULL) {
6290 status = NT_STATUS_NO_MEMORY;
6296 DEBUG(10,("smb2_file_rename_information: "
6297 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6298 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6299 smb_fname_str_dbg(smb_fname_dst)));
6300 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6301 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6305 TALLOC_FREE(smb_fname_dst);
6309 static NTSTATUS smb_file_link_information(connection_struct *conn,
6310 struct smb_request *req,
6314 struct smb_filename *smb_fname_src)
6318 char *newname = NULL;
6319 struct smb_filename *smb_fname_dst = NULL;
6320 NTSTATUS status = NT_STATUS_OK;
6321 TALLOC_CTX *ctx = talloc_tos();
6324 return NT_STATUS_INVALID_HANDLE;
6327 if (total_data < 20) {
6328 return NT_STATUS_INVALID_PARAMETER;
6331 overwrite = (CVAL(pdata,0) ? true : false);
6332 len = IVAL(pdata,16);
6334 if (len > (total_data - 20) || (len == 0)) {
6335 return NT_STATUS_INVALID_PARAMETER;
6338 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6339 &pdata[20], len, STR_TERMINATE,
6341 if (!NT_STATUS_IS_OK(status)) {
6345 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6348 status = filename_convert(ctx,
6350 req->flags2 & FLAGS2_DFS_PATHNAMES,
6355 if (!NT_STATUS_IS_OK(status)) {
6359 if (fsp->base_fsp) {
6360 /* No stream names. */
6361 return NT_STATUS_NOT_SUPPORTED;
6364 DEBUG(10,("smb_file_link_information: "
6365 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6366 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6367 smb_fname_str_dbg(smb_fname_dst)));
6368 status = hardlink_internals(ctx,
6375 TALLOC_FREE(smb_fname_dst);
6379 /****************************************************************************
6380 Deal with SMB_FILE_RENAME_INFORMATION.
6381 ****************************************************************************/
6383 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6384 struct smb_request *req,
6388 struct smb_filename *smb_fname_src)
6393 char *newname = NULL;
6394 struct smb_filename *smb_fname_dst = NULL;
6395 bool dest_has_wcard = False;
6396 NTSTATUS status = NT_STATUS_OK;
6398 TALLOC_CTX *ctx = talloc_tos();
6400 if (total_data < 13) {
6401 return NT_STATUS_INVALID_PARAMETER;
6404 overwrite = (CVAL(pdata,0) ? True : False);
6405 root_fid = IVAL(pdata,4);
6406 len = IVAL(pdata,8);
6408 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6409 return NT_STATUS_INVALID_PARAMETER;
6412 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6415 if (!NT_STATUS_IS_OK(status)) {
6419 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6422 status = resolve_dfspath_wcard(ctx, conn,
6423 req->flags2 & FLAGS2_DFS_PATHNAMES,
6426 !conn->sconn->using_smb2,
6429 if (!NT_STATUS_IS_OK(status)) {
6433 /* Check the new name has no '/' characters. */
6434 if (strchr_m(newname, '/')) {
6435 return NT_STATUS_NOT_SUPPORTED;
6438 if (fsp && fsp->base_fsp) {
6439 /* newname must be a stream name. */
6440 if (newname[0] != ':') {
6441 return NT_STATUS_NOT_SUPPORTED;
6444 /* Create an smb_fname to call rename_internals_fsp() with. */
6445 smb_fname_dst = synthetic_smb_fname(
6446 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6448 if (smb_fname_dst == NULL) {
6449 status = NT_STATUS_NO_MEMORY;
6454 * Set the original last component, since
6455 * rename_internals_fsp() requires it.
6457 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6459 if (smb_fname_dst->original_lcomp == NULL) {
6460 status = NT_STATUS_NO_MEMORY;
6466 * Build up an smb_fname_dst based on the filename passed in.
6467 * We basically just strip off the last component, and put on
6468 * the newname instead.
6470 char *base_name = NULL;
6472 /* newname must *not* be a stream name. */
6473 if (newname[0] == ':') {
6474 return NT_STATUS_NOT_SUPPORTED;
6478 * Strip off the last component (filename) of the path passed
6481 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6483 return NT_STATUS_NO_MEMORY;
6485 p = strrchr_m(base_name, '/');
6489 base_name = talloc_strdup(ctx, "");
6491 return NT_STATUS_NO_MEMORY;
6494 /* Append the new name. */
6495 base_name = talloc_asprintf_append(base_name,
6499 return NT_STATUS_NO_MEMORY;
6502 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6505 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6508 /* If an error we expect this to be
6509 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6511 if (!NT_STATUS_IS_OK(status)) {
6512 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6516 /* Create an smb_fname to call rename_internals_fsp() */
6517 smb_fname_dst = synthetic_smb_fname(
6518 ctx, base_name, NULL, NULL);
6519 if (smb_fname_dst == NULL) {
6520 status = NT_STATUS_NO_MEMORY;
6527 DEBUG(10,("smb_file_rename_information: "
6528 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6529 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6530 smb_fname_str_dbg(smb_fname_dst)));
6531 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6534 DEBUG(10,("smb_file_rename_information: "
6535 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6536 smb_fname_str_dbg(smb_fname_src),
6537 smb_fname_str_dbg(smb_fname_dst)));
6538 status = rename_internals(ctx, conn, req, smb_fname_src,
6539 smb_fname_dst, 0, overwrite, false,
6541 FILE_WRITE_ATTRIBUTES);
6544 TALLOC_FREE(smb_fname_dst);
6548 /****************************************************************************
6549 Deal with SMB_SET_POSIX_ACL.
6550 ****************************************************************************/
6552 #if defined(HAVE_POSIX_ACLS)
6553 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6557 const struct smb_filename *smb_fname)
6559 uint16 posix_acl_version;
6560 uint16 num_file_acls;
6561 uint16 num_def_acls;
6562 bool valid_file_acls = True;
6563 bool valid_def_acls = True;
6565 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6566 return NT_STATUS_INVALID_PARAMETER;
6568 posix_acl_version = SVAL(pdata,0);
6569 num_file_acls = SVAL(pdata,2);
6570 num_def_acls = SVAL(pdata,4);
6572 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6573 valid_file_acls = False;
6577 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6578 valid_def_acls = False;
6582 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6583 return NT_STATUS_INVALID_PARAMETER;
6586 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6587 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6588 return NT_STATUS_INVALID_PARAMETER;
6591 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6592 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6593 (unsigned int)num_file_acls,
6594 (unsigned int)num_def_acls));
6596 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6597 smb_fname->base_name, num_file_acls,
6598 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6599 return map_nt_error_from_unix(errno);
6602 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6603 smb_fname->base_name, &smb_fname->st, num_def_acls,
6604 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6605 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6606 return map_nt_error_from_unix(errno);
6608 return NT_STATUS_OK;
6612 /****************************************************************************
6613 Deal with SMB_SET_POSIX_LOCK.
6614 ****************************************************************************/
6616 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6617 struct smb_request *req,
6625 bool blocking_lock = False;
6626 enum brl_type lock_type;
6628 NTSTATUS status = NT_STATUS_OK;
6630 if (fsp == NULL || fsp->fh->fd == -1) {
6631 return NT_STATUS_INVALID_HANDLE;
6634 if (total_data != POSIX_LOCK_DATA_SIZE) {
6635 return NT_STATUS_INVALID_PARAMETER;
6638 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6639 case POSIX_LOCK_TYPE_READ:
6640 lock_type = READ_LOCK;
6642 case POSIX_LOCK_TYPE_WRITE:
6643 /* Return the right POSIX-mappable error code for files opened read-only. */
6644 if (!fsp->can_write) {
6645 return NT_STATUS_INVALID_HANDLE;
6647 lock_type = WRITE_LOCK;
6649 case POSIX_LOCK_TYPE_UNLOCK:
6650 lock_type = UNLOCK_LOCK;
6653 return NT_STATUS_INVALID_PARAMETER;
6656 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6657 blocking_lock = False;
6658 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6659 blocking_lock = True;
6661 return NT_STATUS_INVALID_PARAMETER;
6664 if (!lp_blocking_locks(SNUM(conn))) {
6665 blocking_lock = False;
6668 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6669 #if defined(HAVE_LONGLONG)
6670 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6671 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6672 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6673 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6674 #else /* HAVE_LONGLONG */
6675 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6676 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6677 #endif /* HAVE_LONGLONG */
6679 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6680 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6682 (unsigned int)lock_type,
6683 (unsigned long long)smblctx,
6687 if (lock_type == UNLOCK_LOCK) {
6688 status = do_unlock(req->sconn->msg_ctx,
6695 uint64_t block_smblctx;
6697 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6709 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6711 * A blocking lock was requested. Package up
6712 * this smb into a queued request and push it
6713 * onto the blocking lock queue.
6715 if(push_blocking_lock_request(br_lck,
6718 -1, /* infinite timeout. */
6726 TALLOC_FREE(br_lck);
6730 TALLOC_FREE(br_lck);
6736 /****************************************************************************
6737 Deal with SMB_SET_FILE_BASIC_INFO.
6738 ****************************************************************************/
6740 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6744 const struct smb_filename *smb_fname)
6746 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6747 struct smb_file_time ft;
6749 NTSTATUS status = NT_STATUS_OK;
6753 if (total_data < 36) {
6754 return NT_STATUS_INVALID_PARAMETER;
6757 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6758 if (!NT_STATUS_IS_OK(status)) {
6762 /* Set the attributes */
6763 dosmode = IVAL(pdata,32);
6764 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6765 if (!NT_STATUS_IS_OK(status)) {
6770 ft.create_time = interpret_long_date(pdata);
6773 ft.atime = interpret_long_date(pdata+8);
6776 ft.mtime = interpret_long_date(pdata+16);
6779 ft.ctime = interpret_long_date(pdata+24);
6781 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6782 smb_fname_str_dbg(smb_fname)));
6784 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6788 /****************************************************************************
6789 Deal with SMB_INFO_STANDARD.
6790 ****************************************************************************/
6792 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6796 const struct smb_filename *smb_fname)
6799 struct smb_file_time ft;
6803 if (total_data < 12) {
6804 return NT_STATUS_INVALID_PARAMETER;
6808 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6810 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6812 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6814 DEBUG(10,("smb_set_info_standard: file %s\n",
6815 smb_fname_str_dbg(smb_fname)));
6817 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6818 if (!NT_STATUS_IS_OK(status)) {
6822 return smb_set_file_time(conn,
6829 /****************************************************************************
6830 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6831 ****************************************************************************/
6833 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6834 struct smb_request *req,
6838 struct smb_filename *smb_fname)
6840 uint64_t allocation_size = 0;
6841 NTSTATUS status = NT_STATUS_OK;
6842 files_struct *new_fsp = NULL;
6844 if (!VALID_STAT(smb_fname->st)) {
6845 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6848 if (total_data < 8) {
6849 return NT_STATUS_INVALID_PARAMETER;
6852 allocation_size = (uint64_t)IVAL(pdata,0);
6853 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6854 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6855 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6856 (double)allocation_size));
6858 if (allocation_size) {
6859 allocation_size = smb_roundup(conn, allocation_size);
6862 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6863 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6864 (double)allocation_size));
6866 if (fsp && fsp->fh->fd != -1) {
6867 /* Open file handle. */
6868 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6869 return NT_STATUS_ACCESS_DENIED;
6872 /* Only change if needed. */
6873 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6874 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6875 return map_nt_error_from_unix(errno);
6878 /* But always update the time. */
6880 * This is equivalent to a write. Ensure it's seen immediately
6881 * if there are no pending writes.
6883 trigger_write_time_update_immediate(fsp);
6884 return NT_STATUS_OK;
6887 /* Pathname or stat or directory file. */
6888 status = SMB_VFS_CREATE_FILE(
6891 0, /* root_dir_fid */
6892 smb_fname, /* fname */
6893 FILE_WRITE_DATA, /* access_mask */
6894 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6896 FILE_OPEN, /* create_disposition*/
6897 0, /* create_options */
6898 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6899 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6900 0, /* allocation_size */
6901 0, /* private_flags */
6904 &new_fsp, /* result */
6907 if (!NT_STATUS_IS_OK(status)) {
6908 /* NB. We check for open_was_deferred in the caller. */
6912 /* Only change if needed. */
6913 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6914 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6915 status = map_nt_error_from_unix(errno);
6916 close_file(req, new_fsp, NORMAL_CLOSE);
6921 /* Changing the allocation size should set the last mod time. */
6923 * This is equivalent to a write. Ensure it's seen immediately
6924 * if there are no pending writes.
6926 trigger_write_time_update_immediate(new_fsp);
6928 close_file(req, new_fsp, NORMAL_CLOSE);
6929 return NT_STATUS_OK;
6932 /****************************************************************************
6933 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6934 ****************************************************************************/
6936 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6937 struct smb_request *req,
6941 const struct smb_filename *smb_fname,
6942 bool fail_after_createfile)
6946 if (total_data < 8) {
6947 return NT_STATUS_INVALID_PARAMETER;
6950 size = IVAL(pdata,0);
6951 size |= (((off_t)IVAL(pdata,4)) << 32);
6952 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6953 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6956 return smb_set_file_size(conn, req,
6961 fail_after_createfile);
6964 /****************************************************************************
6965 Allow a UNIX info mknod.
6966 ****************************************************************************/
6968 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6971 const struct smb_filename *smb_fname)
6973 uint32 file_type = IVAL(pdata,56);
6974 #if defined(HAVE_MAKEDEV)
6975 uint32 dev_major = IVAL(pdata,60);
6976 uint32 dev_minor = IVAL(pdata,68);
6978 SMB_DEV_T dev = (SMB_DEV_T)0;
6979 uint32 raw_unixmode = IVAL(pdata,84);
6983 if (total_data < 100) {
6984 return NT_STATUS_INVALID_PARAMETER;
6987 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6988 PERM_NEW_FILE, &unixmode);
6989 if (!NT_STATUS_IS_OK(status)) {
6993 #if defined(HAVE_MAKEDEV)
6994 dev = makedev(dev_major, dev_minor);
6997 switch (file_type) {
6998 #if defined(S_IFIFO)
6999 case UNIX_TYPE_FIFO:
7000 unixmode |= S_IFIFO;
7003 #if defined(S_IFSOCK)
7004 case UNIX_TYPE_SOCKET:
7005 unixmode |= S_IFSOCK;
7008 #if defined(S_IFCHR)
7009 case UNIX_TYPE_CHARDEV:
7010 unixmode |= S_IFCHR;
7013 #if defined(S_IFBLK)
7014 case UNIX_TYPE_BLKDEV:
7015 unixmode |= S_IFBLK;
7019 return NT_STATUS_INVALID_PARAMETER;
7022 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7023 "%.0f mode 0%o for file %s\n", (double)dev,
7024 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7026 /* Ok - do the mknod. */
7027 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7028 return map_nt_error_from_unix(errno);
7031 /* If any of the other "set" calls fail we
7032 * don't want to end up with a half-constructed mknod.
7035 if (lp_inherit_perms(SNUM(conn))) {
7037 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7039 return NT_STATUS_NO_MEMORY;
7041 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7043 TALLOC_FREE(parent);
7046 return NT_STATUS_OK;
7049 /****************************************************************************
7050 Deal with SMB_SET_FILE_UNIX_BASIC.
7051 ****************************************************************************/
7053 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7054 struct smb_request *req,
7058 const struct smb_filename *smb_fname)
7060 struct smb_file_time ft;
7061 uint32 raw_unixmode;
7064 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7065 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7066 NTSTATUS status = NT_STATUS_OK;
7067 bool delete_on_fail = False;
7068 enum perm_type ptype;
7069 files_struct *all_fsps = NULL;
7070 bool modify_mtime = true;
7072 struct smb_filename *smb_fname_tmp = NULL;
7073 SMB_STRUCT_STAT sbuf;
7077 if (total_data < 100) {
7078 return NT_STATUS_INVALID_PARAMETER;
7081 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7082 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7083 size=IVAL(pdata,0); /* first 8 Bytes are size */
7084 size |= (((off_t)IVAL(pdata,4)) << 32);
7087 ft.atime = interpret_long_date(pdata+24); /* access_time */
7088 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7089 set_owner = (uid_t)IVAL(pdata,40);
7090 set_grp = (gid_t)IVAL(pdata,48);
7091 raw_unixmode = IVAL(pdata,84);
7093 if (VALID_STAT(smb_fname->st)) {
7094 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7095 ptype = PERM_EXISTING_DIR;
7097 ptype = PERM_EXISTING_FILE;
7100 ptype = PERM_NEW_FILE;
7103 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7105 if (!NT_STATUS_IS_OK(status)) {
7109 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7110 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7111 smb_fname_str_dbg(smb_fname), (double)size,
7112 (unsigned int)set_owner, (unsigned int)set_grp,
7113 (int)raw_unixmode));
7115 sbuf = smb_fname->st;
7117 if (!VALID_STAT(sbuf)) {
7119 * The only valid use of this is to create character and block
7120 * devices, and named pipes. This is deprecated (IMHO) and
7121 * a new info level should be used for mknod. JRA.
7124 status = smb_unix_mknod(conn,
7128 if (!NT_STATUS_IS_OK(status)) {
7132 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7133 if (smb_fname_tmp == NULL) {
7134 return NT_STATUS_NO_MEMORY;
7137 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7138 status = map_nt_error_from_unix(errno);
7139 TALLOC_FREE(smb_fname_tmp);
7140 SMB_VFS_UNLINK(conn, smb_fname);
7144 sbuf = smb_fname_tmp->st;
7145 smb_fname = smb_fname_tmp;
7147 /* Ensure we don't try and change anything else. */
7148 raw_unixmode = SMB_MODE_NO_CHANGE;
7149 size = get_file_size_stat(&sbuf);
7150 ft.atime = sbuf.st_ex_atime;
7151 ft.mtime = sbuf.st_ex_mtime;
7153 * We continue here as we might want to change the
7156 delete_on_fail = True;
7160 /* Horrible backwards compatibility hack as an old server bug
7161 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7165 size = get_file_size_stat(&sbuf);
7170 * Deal with the UNIX specific mode set.
7173 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7174 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7175 "setting mode 0%o for file %s\n",
7176 (unsigned int)unixmode,
7177 smb_fname_str_dbg(smb_fname)));
7178 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7179 return map_nt_error_from_unix(errno);
7184 * Deal with the UNIX specific uid set.
7187 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7188 (sbuf.st_ex_uid != set_owner)) {
7191 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7192 "changing owner %u for path %s\n",
7193 (unsigned int)set_owner,
7194 smb_fname_str_dbg(smb_fname)));
7196 if (S_ISLNK(sbuf.st_ex_mode)) {
7197 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7198 set_owner, (gid_t)-1);
7200 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7201 set_owner, (gid_t)-1);
7205 status = map_nt_error_from_unix(errno);
7206 if (delete_on_fail) {
7207 SMB_VFS_UNLINK(conn, smb_fname);
7214 * Deal with the UNIX specific gid set.
7217 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7218 (sbuf.st_ex_gid != set_grp)) {
7219 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7220 "changing group %u for file %s\n",
7221 (unsigned int)set_owner,
7222 smb_fname_str_dbg(smb_fname)));
7223 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7225 status = map_nt_error_from_unix(errno);
7226 if (delete_on_fail) {
7227 SMB_VFS_UNLINK(conn, smb_fname);
7233 /* Deal with any size changes. */
7235 status = smb_set_file_size(conn, req,
7241 if (!NT_STATUS_IS_OK(status)) {
7245 /* Deal with any time changes. */
7246 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7247 /* No change, don't cancel anything. */
7251 id = vfs_file_id_from_sbuf(conn, &sbuf);
7252 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7253 all_fsps = file_find_di_next(all_fsps)) {
7255 * We're setting the time explicitly for UNIX.
7256 * Cancel any pending changes over all handles.
7258 all_fsps->update_write_time_on_close = false;
7259 TALLOC_FREE(all_fsps->update_write_time_event);
7263 * Override the "setting_write_time"
7264 * parameter here as it almost does what
7265 * we need. Just remember if we modified
7266 * mtime and send the notify ourselves.
7268 if (null_timespec(ft.mtime)) {
7269 modify_mtime = false;
7272 status = smb_set_file_time(conn,
7278 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7279 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7284 /****************************************************************************
7285 Deal with SMB_SET_FILE_UNIX_INFO2.
7286 ****************************************************************************/
7288 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7289 struct smb_request *req,
7293 const struct smb_filename *smb_fname)
7299 if (total_data < 116) {
7300 return NT_STATUS_INVALID_PARAMETER;
7303 /* Start by setting all the fields that are common between UNIX_BASIC
7306 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7308 if (!NT_STATUS_IS_OK(status)) {
7312 smb_fflags = IVAL(pdata, 108);
7313 smb_fmask = IVAL(pdata, 112);
7315 /* NB: We should only attempt to alter the file flags if the client
7316 * sends a non-zero mask.
7318 if (smb_fmask != 0) {
7319 int stat_fflags = 0;
7321 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7322 smb_fmask, &stat_fflags)) {
7323 /* Client asked to alter a flag we don't understand. */
7324 return NT_STATUS_INVALID_PARAMETER;
7327 if (fsp && fsp->fh->fd != -1) {
7328 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7329 return NT_STATUS_NOT_SUPPORTED;
7331 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7332 stat_fflags) != 0) {
7333 return map_nt_error_from_unix(errno);
7338 /* XXX: need to add support for changing the create_time here. You
7339 * can do this for paths on Darwin with setattrlist(2). The right way
7340 * to hook this up is probably by extending the VFS utimes interface.
7343 return NT_STATUS_OK;
7346 /****************************************************************************
7347 Create a directory with POSIX semantics.
7348 ****************************************************************************/
7350 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7351 struct smb_request *req,
7354 struct smb_filename *smb_fname,
7355 int *pdata_return_size)
7357 NTSTATUS status = NT_STATUS_OK;
7358 uint32 raw_unixmode = 0;
7359 uint32 mod_unixmode = 0;
7360 mode_t unixmode = (mode_t)0;
7361 files_struct *fsp = NULL;
7362 uint16 info_level_return = 0;
7364 char *pdata = *ppdata;
7366 if (total_data < 18) {
7367 return NT_STATUS_INVALID_PARAMETER;
7370 raw_unixmode = IVAL(pdata,8);
7371 /* Next 4 bytes are not yet defined. */
7373 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7374 PERM_NEW_DIR, &unixmode);
7375 if (!NT_STATUS_IS_OK(status)) {
7379 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7381 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7382 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7384 status = SMB_VFS_CREATE_FILE(
7387 0, /* root_dir_fid */
7388 smb_fname, /* fname */
7389 FILE_READ_ATTRIBUTES, /* access_mask */
7390 FILE_SHARE_NONE, /* share_access */
7391 FILE_CREATE, /* create_disposition*/
7392 FILE_DIRECTORY_FILE, /* create_options */
7393 mod_unixmode, /* file_attributes */
7394 0, /* oplock_request */
7395 0, /* allocation_size */
7396 0, /* private_flags */
7402 if (NT_STATUS_IS_OK(status)) {
7403 close_file(req, fsp, NORMAL_CLOSE);
7406 info_level_return = SVAL(pdata,16);
7408 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7409 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7410 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7411 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7413 *pdata_return_size = 12;
7416 /* Realloc the data size */
7417 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7418 if (*ppdata == NULL) {
7419 *pdata_return_size = 0;
7420 return NT_STATUS_NO_MEMORY;
7424 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7425 SSVAL(pdata,2,0); /* No fnum. */
7426 SIVAL(pdata,4,info); /* Was directory created. */
7428 switch (info_level_return) {
7429 case SMB_QUERY_FILE_UNIX_BASIC:
7430 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7431 SSVAL(pdata,10,0); /* Padding. */
7432 store_file_unix_basic(conn, pdata + 12, fsp,
7435 case SMB_QUERY_FILE_UNIX_INFO2:
7436 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7437 SSVAL(pdata,10,0); /* Padding. */
7438 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7442 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7443 SSVAL(pdata,10,0); /* Padding. */
7450 /****************************************************************************
7451 Open/Create a file with POSIX semantics.
7452 ****************************************************************************/
7454 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7455 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7457 static NTSTATUS smb_posix_open(connection_struct *conn,
7458 struct smb_request *req,
7461 struct smb_filename *smb_fname,
7462 int *pdata_return_size)
7464 bool extended_oplock_granted = False;
7465 char *pdata = *ppdata;
7467 uint32 wire_open_mode = 0;
7468 uint32 raw_unixmode = 0;
7469 uint32 mod_unixmode = 0;
7470 uint32 create_disp = 0;
7471 uint32 access_mask = 0;
7472 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7473 NTSTATUS status = NT_STATUS_OK;
7474 mode_t unixmode = (mode_t)0;
7475 files_struct *fsp = NULL;
7476 int oplock_request = 0;
7478 uint16 info_level_return = 0;
7480 if (total_data < 18) {
7481 return NT_STATUS_INVALID_PARAMETER;
7484 flags = IVAL(pdata,0);
7485 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7486 if (oplock_request) {
7487 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7490 wire_open_mode = IVAL(pdata,4);
7492 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7493 return smb_posix_mkdir(conn, req,
7500 switch (wire_open_mode & SMB_ACCMODE) {
7502 access_mask = SMB_O_RDONLY_MAPPING;
7505 access_mask = SMB_O_WRONLY_MAPPING;
7508 access_mask = (SMB_O_RDONLY_MAPPING|
7509 SMB_O_WRONLY_MAPPING);
7512 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7513 (unsigned int)wire_open_mode ));
7514 return NT_STATUS_INVALID_PARAMETER;
7517 wire_open_mode &= ~SMB_ACCMODE;
7519 /* First take care of O_CREAT|O_EXCL interactions. */
7520 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7521 case (SMB_O_CREAT | SMB_O_EXCL):
7522 /* File exists fail. File not exist create. */
7523 create_disp = FILE_CREATE;
7526 /* File exists open. File not exist create. */
7527 create_disp = FILE_OPEN_IF;
7530 /* O_EXCL on its own without O_CREAT is undefined.
7531 We deliberately ignore it as some versions of
7532 Linux CIFSFS can send a bare O_EXCL on the
7533 wire which other filesystems in the kernel
7534 ignore. See bug 9519 for details. */
7539 /* File exists open. File not exist fail. */
7540 create_disp = FILE_OPEN;
7543 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7544 (unsigned int)wire_open_mode ));
7545 return NT_STATUS_INVALID_PARAMETER;
7548 /* Next factor in the effects of O_TRUNC. */
7549 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7551 if (wire_open_mode & SMB_O_TRUNC) {
7552 switch (create_disp) {
7554 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7555 /* Leave create_disp alone as
7556 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7558 /* File exists fail. File not exist create. */
7561 /* SMB_O_CREAT | SMB_O_TRUNC */
7562 /* File exists overwrite. File not exist create. */
7563 create_disp = FILE_OVERWRITE_IF;
7567 /* File exists overwrite. File not exist fail. */
7568 create_disp = FILE_OVERWRITE;
7571 /* Cannot get here. */
7572 smb_panic("smb_posix_open: logic error");
7573 return NT_STATUS_INVALID_PARAMETER;
7577 raw_unixmode = IVAL(pdata,8);
7578 /* Next 4 bytes are not yet defined. */
7580 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7581 (VALID_STAT(smb_fname->st) ?
7582 PERM_EXISTING_FILE : PERM_NEW_FILE),
7585 if (!NT_STATUS_IS_OK(status)) {
7589 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7591 if (wire_open_mode & SMB_O_SYNC) {
7592 create_options |= FILE_WRITE_THROUGH;
7594 if (wire_open_mode & SMB_O_APPEND) {
7595 access_mask |= FILE_APPEND_DATA;
7597 if (wire_open_mode & SMB_O_DIRECT) {
7598 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7601 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7602 VALID_STAT_OF_DIR(smb_fname->st)) {
7603 if (access_mask != SMB_O_RDONLY_MAPPING) {
7604 return NT_STATUS_FILE_IS_A_DIRECTORY;
7606 create_options &= ~FILE_NON_DIRECTORY_FILE;
7607 create_options |= FILE_DIRECTORY_FILE;
7610 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7611 smb_fname_str_dbg(smb_fname),
7612 (unsigned int)wire_open_mode,
7613 (unsigned int)unixmode ));
7615 status = SMB_VFS_CREATE_FILE(
7618 0, /* root_dir_fid */
7619 smb_fname, /* fname */
7620 access_mask, /* access_mask */
7621 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7623 create_disp, /* create_disposition*/
7624 create_options, /* create_options */
7625 mod_unixmode, /* file_attributes */
7626 oplock_request, /* oplock_request */
7627 0, /* allocation_size */
7628 0, /* private_flags */
7634 if (!NT_STATUS_IS_OK(status)) {
7638 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7639 extended_oplock_granted = True;
7642 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7643 extended_oplock_granted = True;
7646 info_level_return = SVAL(pdata,16);
7648 /* Allocate the correct return size. */
7650 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7651 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7652 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7653 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7655 *pdata_return_size = 12;
7658 /* Realloc the data size */
7659 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7660 if (*ppdata == NULL) {
7661 close_file(req, fsp, ERROR_CLOSE);
7662 *pdata_return_size = 0;
7663 return NT_STATUS_NO_MEMORY;
7667 if (extended_oplock_granted) {
7668 if (flags & REQUEST_BATCH_OPLOCK) {
7669 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7671 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7673 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7674 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7676 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7679 SSVAL(pdata,2,fsp->fnum);
7680 SIVAL(pdata,4,info); /* Was file created etc. */
7682 switch (info_level_return) {
7683 case SMB_QUERY_FILE_UNIX_BASIC:
7684 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7685 SSVAL(pdata,10,0); /* padding. */
7686 store_file_unix_basic(conn, pdata + 12, fsp,
7689 case SMB_QUERY_FILE_UNIX_INFO2:
7690 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7691 SSVAL(pdata,10,0); /* padding. */
7692 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7696 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7697 SSVAL(pdata,10,0); /* padding. */
7700 return NT_STATUS_OK;
7703 /****************************************************************************
7704 Delete a file with POSIX semantics.
7705 ****************************************************************************/
7707 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7708 struct smb_request *req,
7711 struct smb_filename *smb_fname)
7713 NTSTATUS status = NT_STATUS_OK;
7714 files_struct *fsp = NULL;
7718 int create_options = 0;
7720 struct share_mode_lock *lck = NULL;
7722 if (total_data < 2) {
7723 return NT_STATUS_INVALID_PARAMETER;
7726 flags = SVAL(pdata,0);
7728 if (!VALID_STAT(smb_fname->st)) {
7729 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7732 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7733 !VALID_STAT_OF_DIR(smb_fname->st)) {
7734 return NT_STATUS_NOT_A_DIRECTORY;
7737 DEBUG(10,("smb_posix_unlink: %s %s\n",
7738 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7739 smb_fname_str_dbg(smb_fname)));
7741 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7742 create_options |= FILE_DIRECTORY_FILE;
7745 status = SMB_VFS_CREATE_FILE(
7748 0, /* root_dir_fid */
7749 smb_fname, /* fname */
7750 DELETE_ACCESS, /* access_mask */
7751 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7753 FILE_OPEN, /* create_disposition*/
7754 create_options, /* create_options */
7755 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7756 0, /* oplock_request */
7757 0, /* allocation_size */
7758 0, /* private_flags */
7764 if (!NT_STATUS_IS_OK(status)) {
7769 * Don't lie to client. If we can't really delete due to
7770 * non-POSIX opens return SHARING_VIOLATION.
7773 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7775 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7776 "lock for file %s\n", fsp_str_dbg(fsp)));
7777 close_file(req, fsp, NORMAL_CLOSE);
7778 return NT_STATUS_INVALID_PARAMETER;
7782 * See if others still have the file open. If this is the case, then
7783 * don't delete. If all opens are POSIX delete we can set the delete
7784 * on close disposition.
7786 for (i=0; i<lck->data->num_share_modes; i++) {
7787 struct share_mode_entry *e = &lck->data->share_modes[i];
7788 if (is_valid_share_mode_entry(e)) {
7789 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7792 if (share_mode_stale_pid(lck->data, i)) {
7795 /* Fail with sharing violation. */
7797 close_file(req, fsp, NORMAL_CLOSE);
7798 return NT_STATUS_SHARING_VIOLATION;
7803 * Set the delete on close.
7805 status = smb_set_file_disposition_info(conn,
7813 if (!NT_STATUS_IS_OK(status)) {
7814 close_file(req, fsp, NORMAL_CLOSE);
7817 return close_file(req, fsp, NORMAL_CLOSE);
7820 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7821 struct smb_request *req,
7822 TALLOC_CTX *mem_ctx,
7823 uint16_t info_level,
7825 struct smb_filename *smb_fname,
7826 char **ppdata, int total_data,
7829 char *pdata = *ppdata;
7830 NTSTATUS status = NT_STATUS_OK;
7831 int data_return_size = 0;
7835 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7836 return NT_STATUS_INVALID_LEVEL;
7839 if (!CAN_WRITE(conn)) {
7840 /* Allow POSIX opens. The open path will deny
7841 * any non-readonly opens. */
7842 if (info_level != SMB_POSIX_PATH_OPEN) {
7843 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7847 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7848 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7850 info_level, total_data));
7852 switch (info_level) {
7854 case SMB_INFO_STANDARD:
7856 status = smb_set_info_standard(conn,
7864 case SMB_INFO_SET_EA:
7866 status = smb_info_set_ea(conn,
7874 case SMB_SET_FILE_BASIC_INFO:
7875 case SMB_FILE_BASIC_INFORMATION:
7877 status = smb_set_file_basic_info(conn,
7885 case SMB_FILE_ALLOCATION_INFORMATION:
7886 case SMB_SET_FILE_ALLOCATION_INFO:
7888 status = smb_set_file_allocation_info(conn, req,
7896 case SMB_FILE_END_OF_FILE_INFORMATION:
7897 case SMB_SET_FILE_END_OF_FILE_INFO:
7900 * XP/Win7 both fail after the createfile with
7901 * SMB_SET_FILE_END_OF_FILE_INFO but not
7902 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7903 * The level is known here, so pass it down
7907 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7909 status = smb_set_file_end_of_file_info(conn, req,
7918 case SMB_FILE_DISPOSITION_INFORMATION:
7919 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7922 /* JRA - We used to just ignore this on a path ?
7923 * Shouldn't this be invalid level on a pathname
7926 if (tran_call != TRANSACT2_SETFILEINFO) {
7927 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7930 status = smb_set_file_disposition_info(conn,
7938 case SMB_FILE_POSITION_INFORMATION:
7940 status = smb_file_position_information(conn,
7947 case SMB_FILE_FULL_EA_INFORMATION:
7949 status = smb_set_file_full_ea_info(conn,
7956 /* From tridge Samba4 :
7957 * MODE_INFORMATION in setfileinfo (I have no
7958 * idea what "mode information" on a file is - it takes a value of 0,
7959 * 2, 4 or 6. What could it be?).
7962 case SMB_FILE_MODE_INFORMATION:
7964 status = smb_file_mode_information(conn,
7971 * CIFS UNIX extensions.
7974 case SMB_SET_FILE_UNIX_BASIC:
7976 status = smb_set_file_unix_basic(conn, req,
7984 case SMB_SET_FILE_UNIX_INFO2:
7986 status = smb_set_file_unix_info2(conn, req,
7994 case SMB_SET_FILE_UNIX_LINK:
7997 /* We must have a pathname for this. */
7998 return NT_STATUS_INVALID_LEVEL;
8000 status = smb_set_file_unix_link(conn, req, pdata,
8001 total_data, smb_fname);
8005 case SMB_SET_FILE_UNIX_HLINK:
8008 /* We must have a pathname for this. */
8009 return NT_STATUS_INVALID_LEVEL;
8011 status = smb_set_file_unix_hlink(conn, req,
8017 case SMB_FILE_RENAME_INFORMATION:
8019 status = smb_file_rename_information(conn, req,
8025 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8027 /* SMB2 rename information. */
8028 status = smb2_file_rename_information(conn, req,
8034 case SMB_FILE_LINK_INFORMATION:
8036 status = smb_file_link_information(conn, req,
8042 #if defined(HAVE_POSIX_ACLS)
8043 case SMB_SET_POSIX_ACL:
8045 status = smb_set_posix_acl(conn,
8054 case SMB_SET_POSIX_LOCK:
8057 return NT_STATUS_INVALID_LEVEL;
8059 status = smb_set_posix_lock(conn, req,
8060 pdata, total_data, fsp);
8064 case SMB_POSIX_PATH_OPEN:
8067 /* We must have a pathname for this. */
8068 return NT_STATUS_INVALID_LEVEL;
8071 status = smb_posix_open(conn, req,
8079 case SMB_POSIX_PATH_UNLINK:
8082 /* We must have a pathname for this. */
8083 return NT_STATUS_INVALID_LEVEL;
8086 status = smb_posix_unlink(conn, req,
8094 return NT_STATUS_INVALID_LEVEL;
8097 if (!NT_STATUS_IS_OK(status)) {
8101 *ret_data_size = data_return_size;
8102 return NT_STATUS_OK;
8105 /****************************************************************************
8106 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8107 ****************************************************************************/
8109 static void call_trans2setfilepathinfo(connection_struct *conn,
8110 struct smb_request *req,
8111 unsigned int tran_call,
8112 char **pparams, int total_params,
8113 char **ppdata, int total_data,
8114 unsigned int max_data_bytes)
8116 char *params = *pparams;
8117 char *pdata = *ppdata;
8119 struct smb_filename *smb_fname = NULL;
8120 files_struct *fsp = NULL;
8121 NTSTATUS status = NT_STATUS_OK;
8122 int data_return_size = 0;
8125 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8129 if (tran_call == TRANSACT2_SETFILEINFO) {
8130 if (total_params < 4) {
8131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8135 fsp = file_fsp(req, SVAL(params,0));
8136 /* Basic check for non-null fsp. */
8137 if (!check_fsp_open(conn, req, fsp)) {
8140 info_level = SVAL(params,2);
8142 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8143 if (smb_fname == NULL) {
8144 reply_nterror(req, NT_STATUS_NO_MEMORY);
8148 if(fsp->fh->fd == -1) {
8150 * This is actually a SETFILEINFO on a directory
8151 * handle (returned from an NT SMB). NT5.0 seems
8152 * to do this call. JRA.
8154 if (INFO_LEVEL_IS_UNIX(info_level)) {
8155 /* Always do lstat for UNIX calls. */
8156 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8157 DEBUG(3,("call_trans2setfilepathinfo: "
8158 "SMB_VFS_LSTAT of %s failed "
8160 smb_fname_str_dbg(smb_fname),
8162 reply_nterror(req, map_nt_error_from_unix(errno));
8166 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8167 DEBUG(3,("call_trans2setfilepathinfo: "
8168 "fileinfo of %s failed (%s)\n",
8169 smb_fname_str_dbg(smb_fname),
8171 reply_nterror(req, map_nt_error_from_unix(errno));
8175 } else if (fsp->print_file) {
8177 * Doing a DELETE_ON_CLOSE should cancel a print job.
8179 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8180 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8182 DEBUG(3,("call_trans2setfilepathinfo: "
8183 "Cancelling print job (%s)\n",
8187 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8193 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8198 * Original code - this is an open file.
8200 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8201 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8202 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8204 reply_nterror(req, map_nt_error_from_unix(errno));
8210 uint32_t ucf_flags = 0;
8213 if (total_params < 7) {
8214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8218 info_level = SVAL(params,0);
8219 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8220 total_params - 6, STR_TERMINATE,
8222 if (!NT_STATUS_IS_OK(status)) {
8223 reply_nterror(req, status);
8227 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8228 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8229 info_level == SMB_FILE_RENAME_INFORMATION ||
8230 info_level == SMB_POSIX_PATH_UNLINK) {
8231 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8234 status = filename_convert(req, conn,
8235 req->flags2 & FLAGS2_DFS_PATHNAMES,
8240 if (!NT_STATUS_IS_OK(status)) {
8241 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8242 reply_botherror(req,
8243 NT_STATUS_PATH_NOT_COVERED,
8244 ERRSRV, ERRbadpath);
8247 reply_nterror(req, status);
8251 if (INFO_LEVEL_IS_UNIX(info_level)) {
8253 * For CIFS UNIX extensions the target name may not exist.
8256 /* Always do lstat for UNIX calls. */
8257 SMB_VFS_LSTAT(conn, smb_fname);
8259 } else if (!VALID_STAT(smb_fname->st) &&
8260 SMB_VFS_STAT(conn, smb_fname)) {
8261 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8263 smb_fname_str_dbg(smb_fname),
8265 reply_nterror(req, map_nt_error_from_unix(errno));
8270 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8271 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8273 info_level,total_data));
8275 /* Realloc the parameter size */
8276 *pparams = (char *)SMB_REALLOC(*pparams,2);
8277 if (*pparams == NULL) {
8278 reply_nterror(req, NT_STATUS_NO_MEMORY);
8285 status = smbd_do_setfilepathinfo(conn, req, req,
8291 if (!NT_STATUS_IS_OK(status)) {
8292 if (open_was_deferred(req->sconn, req->mid)) {
8293 /* We have re-scheduled this call. */
8296 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8297 /* We have re-scheduled this call. */
8300 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8301 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8302 ERRSRV, ERRbadpath);
8305 if (info_level == SMB_POSIX_PATH_OPEN) {
8306 reply_openerror(req, status);
8311 * Invalid EA name needs to return 2 param bytes,
8312 * not a zero-length error packet.
8314 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8315 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8318 reply_nterror(req, status);
8323 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8329 /****************************************************************************
8330 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8331 ****************************************************************************/
8333 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8334 char **pparams, int total_params,
8335 char **ppdata, int total_data,
8336 unsigned int max_data_bytes)
8338 struct smb_filename *smb_dname = NULL;
8339 char *params = *pparams;
8340 char *pdata = *ppdata;
8341 char *directory = NULL;
8342 NTSTATUS status = NT_STATUS_OK;
8343 struct ea_list *ea_list = NULL;
8344 TALLOC_CTX *ctx = talloc_tos();
8346 if (!CAN_WRITE(conn)) {
8347 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8351 if (total_params < 5) {
8352 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8356 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8357 total_params - 4, STR_TERMINATE,
8359 if (!NT_STATUS_IS_OK(status)) {
8360 reply_nterror(req, status);
8364 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8366 status = filename_convert(ctx,
8368 req->flags2 & FLAGS2_DFS_PATHNAMES,
8374 if (!NT_STATUS_IS_OK(status)) {
8375 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8376 reply_botherror(req,
8377 NT_STATUS_PATH_NOT_COVERED,
8378 ERRSRV, ERRbadpath);
8381 reply_nterror(req, status);
8386 * OS/2 workplace shell seems to send SET_EA requests of "null"
8387 * length (4 bytes containing IVAL 4).
8388 * They seem to have no effect. Bug #3212. JRA.
8391 if (total_data && (total_data != 4)) {
8392 /* Any data in this call is an EA list. */
8393 if (total_data < 10) {
8394 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8398 if (IVAL(pdata,0) > total_data) {
8399 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8400 IVAL(pdata,0), (unsigned int)total_data));
8401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8405 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8412 if (!lp_ea_support(SNUM(conn))) {
8413 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8417 /* If total_data == 4 Windows doesn't care what values
8418 * are placed in that field, it just ignores them.
8419 * The System i QNTC IBM SMB client puts bad values here,
8420 * so ignore them. */
8422 status = create_directory(conn, req, smb_dname);
8424 if (!NT_STATUS_IS_OK(status)) {
8425 reply_nterror(req, status);
8429 /* Try and set any given EA. */
8431 status = set_ea(conn, NULL, smb_dname, ea_list);
8432 if (!NT_STATUS_IS_OK(status)) {
8433 reply_nterror(req, status);
8438 /* Realloc the parameter and data sizes */
8439 *pparams = (char *)SMB_REALLOC(*pparams,2);
8440 if(*pparams == NULL) {
8441 reply_nterror(req, NT_STATUS_NO_MEMORY);
8448 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8451 TALLOC_FREE(smb_dname);
8455 /****************************************************************************
8456 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8457 We don't actually do this - we just send a null response.
8458 ****************************************************************************/
8460 static void call_trans2findnotifyfirst(connection_struct *conn,
8461 struct smb_request *req,
8462 char **pparams, int total_params,
8463 char **ppdata, int total_data,
8464 unsigned int max_data_bytes)
8466 char *params = *pparams;
8469 if (total_params < 6) {
8470 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8474 info_level = SVAL(params,4);
8475 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8477 switch (info_level) {
8482 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8486 /* Realloc the parameter and data sizes */
8487 *pparams = (char *)SMB_REALLOC(*pparams,6);
8488 if (*pparams == NULL) {
8489 reply_nterror(req, NT_STATUS_NO_MEMORY);
8494 SSVAL(params,0,fnf_handle);
8495 SSVAL(params,2,0); /* No changes */
8496 SSVAL(params,4,0); /* No EA errors */
8503 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8508 /****************************************************************************
8509 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8510 changes). Currently this does nothing.
8511 ****************************************************************************/
8513 static void call_trans2findnotifynext(connection_struct *conn,
8514 struct smb_request *req,
8515 char **pparams, int total_params,
8516 char **ppdata, int total_data,
8517 unsigned int max_data_bytes)
8519 char *params = *pparams;
8521 DEBUG(3,("call_trans2findnotifynext\n"));
8523 /* Realloc the parameter and data sizes */
8524 *pparams = (char *)SMB_REALLOC(*pparams,4);
8525 if (*pparams == NULL) {
8526 reply_nterror(req, NT_STATUS_NO_MEMORY);
8531 SSVAL(params,0,0); /* No changes */
8532 SSVAL(params,2,0); /* No EA errors */
8534 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8539 /****************************************************************************
8540 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8541 ****************************************************************************/
8543 static void call_trans2getdfsreferral(connection_struct *conn,
8544 struct smb_request *req,
8545 char **pparams, int total_params,
8546 char **ppdata, int total_data,
8547 unsigned int max_data_bytes)
8549 char *params = *pparams;
8550 char *pathname = NULL;
8552 int max_referral_level;
8553 NTSTATUS status = NT_STATUS_OK;
8554 TALLOC_CTX *ctx = talloc_tos();
8556 DEBUG(10,("call_trans2getdfsreferral\n"));
8558 if (total_params < 3) {
8559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8563 max_referral_level = SVAL(params,0);
8565 if(!lp_host_msdfs()) {
8566 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8570 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8571 total_params - 2, STR_TERMINATE);
8573 reply_nterror(req, NT_STATUS_NOT_FOUND);
8576 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8577 ppdata,&status)) < 0) {
8578 reply_nterror(req, status);
8582 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8583 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8584 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8589 #define LMCAT_SPL 0x53
8590 #define LMFUNC_GETJOBID 0x60
8592 /****************************************************************************
8593 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8594 ****************************************************************************/
8596 static void call_trans2ioctl(connection_struct *conn,
8597 struct smb_request *req,
8598 char **pparams, int total_params,
8599 char **ppdata, int total_data,
8600 unsigned int max_data_bytes)
8602 char *pdata = *ppdata;
8603 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8605 /* check for an invalid fid before proceeding */
8608 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8612 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8613 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8614 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8615 if (*ppdata == NULL) {
8616 reply_nterror(req, NT_STATUS_NO_MEMORY);
8621 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8622 CAN ACCEPT THIS IN UNICODE. JRA. */
8625 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8627 srvstr_push(pdata, req->flags2, pdata + 2,
8628 lp_netbios_name(), 15,
8629 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8630 srvstr_push(pdata, req->flags2, pdata+18,
8631 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8632 STR_ASCII|STR_TERMINATE); /* Service name */
8633 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8638 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8639 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8642 /****************************************************************************
8643 Reply to a SMBfindclose (stop trans2 directory search).
8644 ****************************************************************************/
8646 void reply_findclose(struct smb_request *req)
8649 struct smbd_server_connection *sconn = req->sconn;
8651 START_PROFILE(SMBfindclose);
8654 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8655 END_PROFILE(SMBfindclose);
8659 dptr_num = SVALS(req->vwv+0, 0);
8661 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8663 dptr_close(sconn, &dptr_num);
8665 reply_outbuf(req, 0, 0);
8667 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8669 END_PROFILE(SMBfindclose);
8673 /****************************************************************************
8674 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8675 ****************************************************************************/
8677 void reply_findnclose(struct smb_request *req)
8681 START_PROFILE(SMBfindnclose);
8684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8685 END_PROFILE(SMBfindnclose);
8689 dptr_num = SVAL(req->vwv+0, 0);
8691 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8693 /* We never give out valid handles for a
8694 findnotifyfirst - so any dptr_num is ok here.
8697 reply_outbuf(req, 0, 0);
8699 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8701 END_PROFILE(SMBfindnclose);
8705 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8706 struct trans_state *state)
8708 if (get_Protocol() >= PROTOCOL_NT1) {
8709 req->flags2 |= 0x40; /* IS_LONG_NAME */
8710 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8713 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8714 if (state->call != TRANSACT2_QFSINFO &&
8715 state->call != TRANSACT2_SETFSINFO) {
8716 DEBUG(0,("handle_trans2: encryption required "
8718 (unsigned int)state->call));
8719 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8724 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8726 /* Now we must call the relevant TRANS2 function */
8727 switch(state->call) {
8728 case TRANSACT2_OPEN:
8730 START_PROFILE(Trans2_open);
8731 call_trans2open(conn, req,
8732 &state->param, state->total_param,
8733 &state->data, state->total_data,
8734 state->max_data_return);
8735 END_PROFILE(Trans2_open);
8739 case TRANSACT2_FINDFIRST:
8741 START_PROFILE(Trans2_findfirst);
8742 call_trans2findfirst(conn, req,
8743 &state->param, state->total_param,
8744 &state->data, state->total_data,
8745 state->max_data_return);
8746 END_PROFILE(Trans2_findfirst);
8750 case TRANSACT2_FINDNEXT:
8752 START_PROFILE(Trans2_findnext);
8753 call_trans2findnext(conn, req,
8754 &state->param, state->total_param,
8755 &state->data, state->total_data,
8756 state->max_data_return);
8757 END_PROFILE(Trans2_findnext);
8761 case TRANSACT2_QFSINFO:
8763 START_PROFILE(Trans2_qfsinfo);
8764 call_trans2qfsinfo(conn, req,
8765 &state->param, state->total_param,
8766 &state->data, state->total_data,
8767 state->max_data_return);
8768 END_PROFILE(Trans2_qfsinfo);
8772 case TRANSACT2_SETFSINFO:
8774 START_PROFILE(Trans2_setfsinfo);
8775 call_trans2setfsinfo(conn, req,
8776 &state->param, state->total_param,
8777 &state->data, state->total_data,
8778 state->max_data_return);
8779 END_PROFILE(Trans2_setfsinfo);
8783 case TRANSACT2_QPATHINFO:
8784 case TRANSACT2_QFILEINFO:
8786 START_PROFILE(Trans2_qpathinfo);
8787 call_trans2qfilepathinfo(conn, req, state->call,
8788 &state->param, state->total_param,
8789 &state->data, state->total_data,
8790 state->max_data_return);
8791 END_PROFILE(Trans2_qpathinfo);
8795 case TRANSACT2_SETPATHINFO:
8796 case TRANSACT2_SETFILEINFO:
8798 START_PROFILE(Trans2_setpathinfo);
8799 call_trans2setfilepathinfo(conn, req, state->call,
8800 &state->param, state->total_param,
8801 &state->data, state->total_data,
8802 state->max_data_return);
8803 END_PROFILE(Trans2_setpathinfo);
8807 case TRANSACT2_FINDNOTIFYFIRST:
8809 START_PROFILE(Trans2_findnotifyfirst);
8810 call_trans2findnotifyfirst(conn, req,
8811 &state->param, state->total_param,
8812 &state->data, state->total_data,
8813 state->max_data_return);
8814 END_PROFILE(Trans2_findnotifyfirst);
8818 case TRANSACT2_FINDNOTIFYNEXT:
8820 START_PROFILE(Trans2_findnotifynext);
8821 call_trans2findnotifynext(conn, req,
8822 &state->param, state->total_param,
8823 &state->data, state->total_data,
8824 state->max_data_return);
8825 END_PROFILE(Trans2_findnotifynext);
8829 case TRANSACT2_MKDIR:
8831 START_PROFILE(Trans2_mkdir);
8832 call_trans2mkdir(conn, req,
8833 &state->param, state->total_param,
8834 &state->data, state->total_data,
8835 state->max_data_return);
8836 END_PROFILE(Trans2_mkdir);
8840 case TRANSACT2_GET_DFS_REFERRAL:
8842 START_PROFILE(Trans2_get_dfs_referral);
8843 call_trans2getdfsreferral(conn, req,
8844 &state->param, state->total_param,
8845 &state->data, state->total_data,
8846 state->max_data_return);
8847 END_PROFILE(Trans2_get_dfs_referral);
8851 case TRANSACT2_IOCTL:
8853 START_PROFILE(Trans2_ioctl);
8854 call_trans2ioctl(conn, req,
8855 &state->param, state->total_param,
8856 &state->data, state->total_data,
8857 state->max_data_return);
8858 END_PROFILE(Trans2_ioctl);
8863 /* Error in request */
8864 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8865 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8869 /****************************************************************************
8870 Reply to a SMBtrans2.
8871 ****************************************************************************/
8873 void reply_trans2(struct smb_request *req)
8875 connection_struct *conn = req->conn;
8880 unsigned int tran_call;
8881 struct trans_state *state;
8884 START_PROFILE(SMBtrans2);
8886 if (req->wct < 14) {
8887 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8888 END_PROFILE(SMBtrans2);
8892 dsoff = SVAL(req->vwv+12, 0);
8893 dscnt = SVAL(req->vwv+11, 0);
8894 psoff = SVAL(req->vwv+10, 0);
8895 pscnt = SVAL(req->vwv+9, 0);
8896 tran_call = SVAL(req->vwv+14, 0);
8898 result = allow_new_trans(conn->pending_trans, req->mid);
8899 if (!NT_STATUS_IS_OK(result)) {
8900 DEBUG(2, ("Got invalid trans2 request: %s\n",
8901 nt_errstr(result)));
8902 reply_nterror(req, result);
8903 END_PROFILE(SMBtrans2);
8908 switch (tran_call) {
8909 /* List the allowed trans2 calls on IPC$ */
8910 case TRANSACT2_OPEN:
8911 case TRANSACT2_GET_DFS_REFERRAL:
8912 case TRANSACT2_QFILEINFO:
8913 case TRANSACT2_QFSINFO:
8914 case TRANSACT2_SETFSINFO:
8917 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8918 END_PROFILE(SMBtrans2);
8923 if ((state = talloc(conn, struct trans_state)) == NULL) {
8924 DEBUG(0, ("talloc failed\n"));
8925 reply_nterror(req, NT_STATUS_NO_MEMORY);
8926 END_PROFILE(SMBtrans2);
8930 state->cmd = SMBtrans2;
8932 state->mid = req->mid;
8933 state->vuid = req->vuid;
8934 state->setup_count = SVAL(req->vwv+13, 0);
8935 state->setup = NULL;
8936 state->total_param = SVAL(req->vwv+0, 0);
8937 state->param = NULL;
8938 state->total_data = SVAL(req->vwv+1, 0);
8940 state->max_param_return = SVAL(req->vwv+2, 0);
8941 state->max_data_return = SVAL(req->vwv+3, 0);
8942 state->max_setup_return = SVAL(req->vwv+4, 0);
8943 state->close_on_completion = BITSETW(req->vwv+5, 0);
8944 state->one_way = BITSETW(req->vwv+5, 1);
8946 state->call = tran_call;
8948 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8949 is so as a sanity check */
8950 if (state->setup_count != 1) {
8952 * Need to have rc=0 for ioctl to get job id for OS/2.
8953 * Network printing will fail if function is not successful.
8954 * Similar function in reply.c will be used if protocol
8955 * is LANMAN1.0 instead of LM1.2X002.
8956 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8957 * outbuf doesn't have to be set(only job id is used).
8959 if ( (state->setup_count == 4)
8960 && (tran_call == TRANSACT2_IOCTL)
8961 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8962 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8963 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8965 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8966 DEBUG(2,("Transaction is %d\n",tran_call));
8968 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8969 END_PROFILE(SMBtrans2);
8974 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8977 if (state->total_data) {
8979 if (trans_oob(state->total_data, 0, dscnt)
8980 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8984 /* Can't use talloc here, the core routines do realloc on the
8985 * params and data. */
8986 state->data = (char *)SMB_MALLOC(state->total_data);
8987 if (state->data == NULL) {
8988 DEBUG(0,("reply_trans2: data malloc fail for %u "
8989 "bytes !\n", (unsigned int)state->total_data));
8991 reply_nterror(req, NT_STATUS_NO_MEMORY);
8992 END_PROFILE(SMBtrans2);
8996 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8999 if (state->total_param) {
9001 if (trans_oob(state->total_param, 0, pscnt)
9002 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9006 /* Can't use talloc here, the core routines do realloc on the
9007 * params and data. */
9008 state->param = (char *)SMB_MALLOC(state->total_param);
9009 if (state->param == NULL) {
9010 DEBUG(0,("reply_trans: param malloc fail for %u "
9011 "bytes !\n", (unsigned int)state->total_param));
9012 SAFE_FREE(state->data);
9014 reply_nterror(req, NT_STATUS_NO_MEMORY);
9015 END_PROFILE(SMBtrans2);
9019 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9022 state->received_data = dscnt;
9023 state->received_param = pscnt;
9025 if ((state->received_param == state->total_param) &&
9026 (state->received_data == state->total_data)) {
9028 handle_trans2(conn, req, state);
9030 SAFE_FREE(state->data);
9031 SAFE_FREE(state->param);
9033 END_PROFILE(SMBtrans2);
9037 DLIST_ADD(conn->pending_trans, state);
9039 /* We need to send an interim response then receive the rest
9040 of the parameter/data bytes */
9041 reply_outbuf(req, 0, 0);
9042 show_msg((char *)req->outbuf);
9043 END_PROFILE(SMBtrans2);
9048 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9049 SAFE_FREE(state->data);
9050 SAFE_FREE(state->param);
9052 END_PROFILE(SMBtrans2);
9053 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9057 /****************************************************************************
9058 Reply to a SMBtranss2
9059 ****************************************************************************/
9061 void reply_transs2(struct smb_request *req)
9063 connection_struct *conn = req->conn;
9064 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9065 struct trans_state *state;
9067 START_PROFILE(SMBtranss2);
9069 show_msg((const char *)req->inbuf);
9071 /* Windows clients expect all replies to
9072 a transact secondary (SMBtranss2 0x33)
9073 to have a command code of transact
9074 (SMBtrans2 0x32). See bug #8989
9075 and also [MS-CIFS] section 2.2.4.47.2
9078 req->cmd = SMBtrans2;
9081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9082 END_PROFILE(SMBtranss2);
9086 for (state = conn->pending_trans; state != NULL;
9087 state = state->next) {
9088 if (state->mid == req->mid) {
9093 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9094 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9095 END_PROFILE(SMBtranss2);
9099 /* Revise state->total_param and state->total_data in case they have
9100 changed downwards */
9102 if (SVAL(req->vwv+0, 0) < state->total_param)
9103 state->total_param = SVAL(req->vwv+0, 0);
9104 if (SVAL(req->vwv+1, 0) < state->total_data)
9105 state->total_data = SVAL(req->vwv+1, 0);
9107 pcnt = SVAL(req->vwv+2, 0);
9108 poff = SVAL(req->vwv+3, 0);
9109 pdisp = SVAL(req->vwv+4, 0);
9111 dcnt = SVAL(req->vwv+5, 0);
9112 doff = SVAL(req->vwv+6, 0);
9113 ddisp = SVAL(req->vwv+7, 0);
9115 state->received_param += pcnt;
9116 state->received_data += dcnt;
9118 if ((state->received_data > state->total_data) ||
9119 (state->received_param > state->total_param))
9123 if (trans_oob(state->total_param, pdisp, pcnt)
9124 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9127 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9131 if (trans_oob(state->total_data, ddisp, dcnt)
9132 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9135 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9138 if ((state->received_param < state->total_param) ||
9139 (state->received_data < state->total_data)) {
9140 END_PROFILE(SMBtranss2);
9144 handle_trans2(conn, req, state);
9146 DLIST_REMOVE(conn->pending_trans, state);
9147 SAFE_FREE(state->data);
9148 SAFE_FREE(state->param);
9151 END_PROFILE(SMBtranss2);
9156 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9157 DLIST_REMOVE(conn->pending_trans, state);
9158 SAFE_FREE(state->data);
9159 SAFE_FREE(state->param);
9161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9162 END_PROFILE(SMBtranss2);