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]))
348 listp = talloc(mem_ctx, struct ea_list);
350 return NT_STATUS_NO_MEMORY;
353 status = get_ea_value(listp, conn, fsp,
357 if (!NT_STATUS_IS_OK(status)) {
362 if (listp->ea.value.length == 0) {
364 * We can never return a zero length EA.
365 * Windows reports the EA's as corrupted.
371 push_ascii_fstring(dos_ea_name, listp->ea.name);
374 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
376 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
377 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
378 (unsigned int)listp->ea.value.length));
380 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
384 /* Add on 4 for total length. */
385 if (*pea_total_len) {
389 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
390 (unsigned int)*pea_total_len));
392 *ea_list = ea_list_head;
396 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
397 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
402 if (!lp_ea_support(SNUM(conn))) {
406 if (is_ntfs_stream_smb_fname(smb_fname)) {
407 return NT_STATUS_INVALID_PARAMETER;
410 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
413 /****************************************************************************
414 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
416 ****************************************************************************/
418 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
419 connection_struct *conn, struct ea_list *ea_list)
421 unsigned int ret_data_size = 4;
424 SMB_ASSERT(total_data_size >= 4);
426 if (!lp_ea_support(SNUM(conn))) {
431 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
434 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
435 dos_namelen = strlen(dos_ea_name);
436 if (dos_namelen > 255 || dos_namelen == 0) {
439 if (ea_list->ea.value.length > 65535) {
442 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
446 /* We know we have room. */
447 SCVAL(p,0,ea_list->ea.flags);
448 SCVAL(p,1,dos_namelen);
449 SSVAL(p,2,ea_list->ea.value.length);
450 strlcpy(p+4, dos_ea_name, dos_namelen+1);
451 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
453 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
454 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
457 ret_data_size = PTR_DIFF(p, pdata);
458 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
459 SIVAL(pdata,0,ret_data_size);
460 return ret_data_size;
463 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
465 unsigned int total_data_size,
466 unsigned int *ret_data_size,
467 connection_struct *conn,
468 struct ea_list *ea_list)
470 uint8_t *p = (uint8_t *)pdata;
471 uint8_t *last_start = NULL;
472 bool do_store_data = (pdata != NULL);
476 if (!lp_ea_support(SNUM(conn))) {
477 return NT_STATUS_NO_EAS_ON_FILE;
480 for (; ea_list; ea_list = ea_list->next) {
486 if (last_start != NULL && do_store_data) {
487 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
491 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
492 dos_namelen = strlen(dos_ea_name);
493 if (dos_namelen > 255 || dos_namelen == 0) {
494 return NT_STATUS_INTERNAL_ERROR;
496 if (ea_list->ea.value.length > 65535) {
497 return NT_STATUS_INTERNAL_ERROR;
500 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
503 pad = (4 - (this_size % 4)) % 4;
508 if (this_size > total_data_size) {
509 return NT_STATUS_INFO_LENGTH_MISMATCH;
512 /* We know we have room. */
513 SIVAL(p, 0x00, 0); /* next offset */
514 SCVAL(p, 0x04, ea_list->ea.flags);
515 SCVAL(p, 0x05, dos_namelen);
516 SSVAL(p, 0x06, ea_list->ea.value.length);
517 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
518 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
520 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
524 total_data_size -= this_size;
530 *ret_data_size = PTR_DIFF(p, pdata);
531 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
535 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
537 size_t total_ea_len = 0;
539 struct ea_list *ea_list = NULL;
541 if (!lp_ea_support(SNUM(conn))) {
544 mem_ctx = talloc_stackframe();
546 /* If this is a stream fsp, then we need to instead find the
547 * estimated ea len from the main file, not the stream
548 * (streams cannot have EAs), but the estimate isn't just 0 in
550 if (is_ntfs_stream_smb_fname(smb_fname)) {
553 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
554 if(conn->sconn->using_smb2) {
556 unsigned int ret_data_size;
558 * We're going to be using fill_ea_chained_buffer() to
559 * marshall EA's - this size is significantly larger
560 * than the SMB1 buffer. Re-calculate the size without
563 status = fill_ea_chained_buffer(mem_ctx,
569 if (!NT_STATUS_IS_OK(status)) {
572 total_ea_len = ret_data_size;
574 TALLOC_FREE(mem_ctx);
578 /****************************************************************************
579 Ensure the EA name is case insensitive by matching any existing EA name.
580 ****************************************************************************/
582 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
585 TALLOC_CTX *mem_ctx = talloc_tos();
586 struct ea_list *ea_list;
587 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
588 if (!NT_STATUS_IS_OK(status)) {
592 for (; ea_list; ea_list = ea_list->next) {
593 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
594 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
595 &unix_ea_name[5], ea_list->ea.name));
596 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
602 /****************************************************************************
603 Set or delete an extended attribute.
604 ****************************************************************************/
606 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
607 const struct smb_filename *smb_fname, struct ea_list *ea_list)
612 if (!lp_ea_support(SNUM(conn))) {
613 return NT_STATUS_EAS_NOT_SUPPORTED;
616 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
617 if (!NT_STATUS_IS_OK(status)) {
621 /* Setting EAs on streams isn't supported. */
622 if (is_ntfs_stream_smb_fname(smb_fname)) {
623 return NT_STATUS_INVALID_PARAMETER;
627 * Filter out invalid Windows EA names - before
628 * we set *any* of them.
631 if (ea_list_has_invalid_name(ea_list)) {
632 return STATUS_INVALID_EA_NAME;
635 fname = smb_fname->base_name;
637 for (;ea_list; ea_list = ea_list->next) {
639 fstring unix_ea_name;
641 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
642 fstrcat(unix_ea_name, ea_list->ea.name);
644 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
646 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
648 if (samba_private_attr_name(unix_ea_name)) {
649 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
650 return NT_STATUS_ACCESS_DENIED;
653 if (ea_list->ea.value.length == 0) {
654 /* Remove the attribute. */
655 if (fsp && (fsp->fh->fd != -1)) {
656 DEBUG(10,("set_ea: deleting ea name %s on "
657 "file %s by file descriptor.\n",
658 unix_ea_name, fsp_str_dbg(fsp)));
659 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
661 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
662 unix_ea_name, fname));
663 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
666 /* Removing a non existent attribute always succeeds. */
667 if (ret == -1 && errno == ENOATTR) {
668 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
674 if (fsp && (fsp->fh->fd != -1)) {
675 DEBUG(10,("set_ea: setting ea name %s on file "
676 "%s by file descriptor.\n",
677 unix_ea_name, fsp_str_dbg(fsp)));
678 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
679 ea_list->ea.value.data, ea_list->ea.value.length, 0);
681 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
682 unix_ea_name, fname));
683 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
684 ea_list->ea.value.data, ea_list->ea.value.length, 0);
690 if (errno == ENOTSUP) {
691 return NT_STATUS_EAS_NOT_SUPPORTED;
694 return map_nt_error_from_unix(errno);
700 /****************************************************************************
701 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
702 ****************************************************************************/
704 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
706 struct ea_list *ea_list_head = NULL;
707 size_t converted_size, offset = 0;
709 while (offset + 2 < data_size) {
710 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
711 unsigned int namelen = CVAL(pdata,offset);
713 offset++; /* Go past the namelen byte. */
715 /* integer wrap paranioa. */
716 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
717 (offset > data_size) || (namelen > data_size) ||
718 (offset + namelen >= data_size)) {
721 /* Ensure the name is null terminated. */
722 if (pdata[offset + namelen] != '\0') {
725 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
727 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
728 "failed: %s", strerror(errno)));
734 offset += (namelen + 1); /* Go past the name + terminating zero. */
735 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
736 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
742 /****************************************************************************
743 Read one EA list entry from the buffer.
744 ****************************************************************************/
746 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
748 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
750 unsigned int namelen;
751 size_t converted_size;
761 eal->ea.flags = CVAL(pdata,0);
762 namelen = CVAL(pdata,1);
763 val_len = SVAL(pdata,2);
765 if (4 + namelen + 1 + val_len > data_size) {
769 /* Ensure the name is null terminated. */
770 if (pdata[namelen + 4] != '\0') {
773 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
774 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
781 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
782 if (!eal->ea.value.data) {
786 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
788 /* Ensure we're null terminated just in case we print the value. */
789 eal->ea.value.data[val_len] = '\0';
790 /* But don't count the null. */
791 eal->ea.value.length--;
794 *pbytes_used = 4 + namelen + 1 + val_len;
797 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
798 dump_data(10, eal->ea.value.data, eal->ea.value.length);
803 /****************************************************************************
804 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
805 ****************************************************************************/
807 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
809 struct ea_list *ea_list_head = NULL;
811 size_t bytes_used = 0;
813 while (offset < data_size) {
814 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
820 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
821 offset += bytes_used;
827 /****************************************************************************
828 Count the total EA size needed.
829 ****************************************************************************/
831 static size_t ea_list_size(struct ea_list *ealist)
834 struct ea_list *listp;
837 for (listp = ealist; listp; listp = listp->next) {
838 push_ascii_fstring(dos_ea_name, listp->ea.name);
839 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
841 /* Add on 4 for total length. */
849 /****************************************************************************
850 Return a union of EA's from a file list and a list of names.
851 The TALLOC context for the two lists *MUST* be identical as we steal
852 memory from one list to add to another. JRA.
853 ****************************************************************************/
855 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
857 struct ea_list *nlistp, *flistp;
859 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
860 for (flistp = file_list; flistp; flistp = flistp->next) {
861 if (strequal(nlistp->ea.name, flistp->ea.name)) {
867 /* Copy the data from this entry. */
868 nlistp->ea.flags = flistp->ea.flags;
869 nlistp->ea.value = flistp->ea.value;
872 nlistp->ea.flags = 0;
873 ZERO_STRUCT(nlistp->ea.value);
877 *total_ea_len = ea_list_size(name_list);
881 /****************************************************************************
882 Send the required number of replies back.
883 We assume all fields other than the data fields are
884 set correctly for the type of call.
885 HACK ! Always assumes smb_setup field is zero.
886 ****************************************************************************/
888 void send_trans2_replies(connection_struct *conn,
889 struct smb_request *req,
896 /* As we are using a protocol > LANMAN1 then the max_send
897 variable must have been set in the sessetupX call.
898 This takes precedence over the max_xmit field in the
899 global struct. These different max_xmit variables should
900 be merged as this is now too confusing */
902 int data_to_send = datasize;
903 int params_to_send = paramsize;
905 const char *pp = params;
906 const char *pd = pdata;
907 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
908 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
909 int data_alignment_offset = 0;
910 bool overflow = False;
911 struct smbd_server_connection *sconn = req->sconn;
912 int max_send = sconn->smb1.sessions.max_send;
914 /* Modify the data_to_send and datasize and set the error if
915 we're trying to send more than max_data_bytes. We still send
916 the part of the packet(s) that fit. Strange, but needed
919 if (max_data_bytes > 0 && datasize > max_data_bytes) {
920 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
921 max_data_bytes, datasize ));
922 datasize = data_to_send = max_data_bytes;
926 /* If there genuinely are no parameters or data to send just send the empty packet */
928 if(params_to_send == 0 && data_to_send == 0) {
929 reply_outbuf(req, 10, 0);
930 show_msg((char *)req->outbuf);
931 if (!srv_send_smb(sconn,
934 IS_CONN_ENCRYPTED(conn),
936 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
938 TALLOC_FREE(req->outbuf);
942 /* When sending params and data ensure that both are nicely aligned */
943 /* Only do this alignment when there is also data to send - else
944 can cause NT redirector problems. */
946 if (((params_to_send % 4) != 0) && (data_to_send != 0))
947 data_alignment_offset = 4 - (params_to_send % 4);
949 /* Space is bufsize minus Netbios over TCP header minus SMB header */
950 /* The alignment_offset is to align the param bytes on an even byte
951 boundary. NT 4.0 Beta needs this to work correctly. */
953 useable_space = max_send - (smb_size
956 + data_alignment_offset);
958 if (useable_space < 0) {
959 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
960 "= %d!!!", useable_space));
961 exit_server_cleanly("send_trans2_replies: Not enough space");
964 while (params_to_send || data_to_send) {
965 /* Calculate whether we will totally or partially fill this packet */
967 total_sent_thistime = params_to_send + data_to_send;
969 /* We can never send more than useable_space */
971 * Note that 'useable_space' does not include the alignment offsets,
972 * but we must include the alignment offsets in the calculation of
973 * the length of the data we send over the wire, as the alignment offsets
974 * are sent here. Fix from Marc_Jacobsen@hp.com.
977 total_sent_thistime = MIN(total_sent_thistime, useable_space);
979 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
980 + data_alignment_offset);
982 /* Set total params and data to be sent */
983 SSVAL(req->outbuf,smb_tprcnt,paramsize);
984 SSVAL(req->outbuf,smb_tdrcnt,datasize);
986 /* Calculate how many parameters and data we can fit into
987 * this packet. Parameters get precedence
990 params_sent_thistime = MIN(params_to_send,useable_space);
991 data_sent_thistime = useable_space - params_sent_thistime;
992 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
994 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
996 /* smb_proff is the offset from the start of the SMB header to the
997 parameter bytes, however the first 4 bytes of outbuf are
998 the Netbios over TCP header. Thus use smb_base() to subtract
999 them from the calculation */
1001 SSVAL(req->outbuf,smb_proff,
1002 ((smb_buf(req->outbuf)+alignment_offset)
1003 - smb_base(req->outbuf)));
1005 if(params_sent_thistime == 0)
1006 SSVAL(req->outbuf,smb_prdisp,0);
1008 /* Absolute displacement of param bytes sent in this packet */
1009 SSVAL(req->outbuf,smb_prdisp,pp - params);
1011 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1012 if(data_sent_thistime == 0) {
1013 SSVAL(req->outbuf,smb_droff,0);
1014 SSVAL(req->outbuf,smb_drdisp, 0);
1016 /* The offset of the data bytes is the offset of the
1017 parameter bytes plus the number of parameters being sent this time */
1018 SSVAL(req->outbuf, smb_droff,
1019 ((smb_buf(req->outbuf)+alignment_offset)
1020 - smb_base(req->outbuf))
1021 + params_sent_thistime + data_alignment_offset);
1022 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1025 /* Initialize the padding for alignment */
1027 if (alignment_offset != 0) {
1028 memset(smb_buf(req->outbuf), 0, alignment_offset);
1031 /* Copy the param bytes into the packet */
1033 if(params_sent_thistime) {
1034 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1035 params_sent_thistime);
1038 /* Copy in the data bytes */
1039 if(data_sent_thistime) {
1040 if (data_alignment_offset != 0) {
1041 memset((smb_buf(req->outbuf)+alignment_offset+
1042 params_sent_thistime), 0,
1043 data_alignment_offset);
1045 memcpy(smb_buf(req->outbuf)+alignment_offset
1046 +params_sent_thistime+data_alignment_offset,
1047 pd,data_sent_thistime);
1050 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1051 params_sent_thistime, data_sent_thistime, useable_space));
1052 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1053 params_to_send, data_to_send, paramsize, datasize));
1056 error_packet_set((char *)req->outbuf,
1057 ERRDOS,ERRbufferoverflow,
1058 STATUS_BUFFER_OVERFLOW,
1062 /* Send the packet */
1063 show_msg((char *)req->outbuf);
1064 if (!srv_send_smb(sconn,
1065 (char *)req->outbuf,
1066 true, req->seqnum+1,
1067 IS_CONN_ENCRYPTED(conn),
1069 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1071 TALLOC_FREE(req->outbuf);
1073 pp += params_sent_thistime;
1074 pd += data_sent_thistime;
1076 params_to_send -= params_sent_thistime;
1077 data_to_send -= data_sent_thistime;
1080 if(params_to_send < 0 || data_to_send < 0) {
1081 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1082 params_to_send, data_to_send));
1090 /****************************************************************************
1091 Reply to a TRANSACT2_OPEN.
1092 ****************************************************************************/
1094 static void call_trans2open(connection_struct *conn,
1095 struct smb_request *req,
1096 char **pparams, int total_params,
1097 char **ppdata, int total_data,
1098 unsigned int max_data_bytes)
1100 struct smb_filename *smb_fname = NULL;
1101 char *params = *pparams;
1102 char *pdata = *ppdata;
1105 bool oplock_request;
1107 bool return_additional_info;
1116 int fattr=0,mtime=0;
1117 SMB_INO_T inode = 0;
1120 struct ea_list *ea_list = NULL;
1125 uint32 create_disposition;
1126 uint32 create_options = 0;
1127 uint32_t private_flags = 0;
1128 TALLOC_CTX *ctx = talloc_tos();
1131 * Ensure we have enough parameters to perform the operation.
1134 if (total_params < 29) {
1135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1139 flags = SVAL(params, 0);
1140 deny_mode = SVAL(params, 2);
1141 open_attr = SVAL(params,6);
1142 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1143 if (oplock_request) {
1144 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1148 return_additional_info = BITSETW(params,0);
1149 open_sattr = SVAL(params, 4);
1150 open_time = make_unix_date3(params+8);
1152 open_ofun = SVAL(params,12);
1153 open_size = IVAL(params,14);
1154 pname = ¶ms[28];
1157 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1161 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1162 total_params - 28, STR_TERMINATE,
1164 if (!NT_STATUS_IS_OK(status)) {
1165 reply_nterror(req, status);
1169 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1170 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1171 (unsigned int)open_ofun, open_size));
1173 status = filename_convert(ctx,
1175 req->flags2 & FLAGS2_DFS_PATHNAMES,
1180 if (!NT_STATUS_IS_OK(status)) {
1181 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1182 reply_botherror(req,
1183 NT_STATUS_PATH_NOT_COVERED,
1184 ERRSRV, ERRbadpath);
1187 reply_nterror(req, status);
1191 if (open_ofun == 0) {
1192 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1196 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1198 &access_mask, &share_mode,
1199 &create_disposition,
1202 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1206 /* Any data in this call is an EA list. */
1207 if (total_data && (total_data != 4)) {
1208 if (total_data < 10) {
1209 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1213 if (IVAL(pdata,0) > total_data) {
1214 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1215 IVAL(pdata,0), (unsigned int)total_data));
1216 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1220 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1223 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1227 if (!lp_ea_support(SNUM(conn))) {
1228 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1233 status = SMB_VFS_CREATE_FILE(
1236 0, /* root_dir_fid */
1237 smb_fname, /* fname */
1238 access_mask, /* access_mask */
1239 share_mode, /* share_access */
1240 create_disposition, /* create_disposition*/
1241 create_options, /* create_options */
1242 open_attr, /* file_attributes */
1243 oplock_request, /* oplock_request */
1244 open_size, /* allocation_size */
1247 ea_list, /* ea_list */
1249 &smb_action); /* psbuf */
1251 if (!NT_STATUS_IS_OK(status)) {
1252 if (open_was_deferred(req->sconn, req->mid)) {
1253 /* We have re-scheduled this call. */
1256 reply_openerror(req, status);
1260 size = get_file_size_stat(&smb_fname->st);
1261 fattr = dos_mode(conn, smb_fname);
1262 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1263 inode = smb_fname->st.st_ex_ino;
1264 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1265 close_file(req, fsp, ERROR_CLOSE);
1266 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1270 /* Realloc the size of parameters and data we will return */
1271 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1272 if(*pparams == NULL ) {
1273 reply_nterror(req, NT_STATUS_NO_MEMORY);
1278 SSVAL(params,0,fsp->fnum);
1279 SSVAL(params,2,fattr);
1280 srv_put_dos_date2(params,4, mtime);
1281 SIVAL(params,8, (uint32)size);
1282 SSVAL(params,12,deny_mode);
1283 SSVAL(params,14,0); /* open_type - file or directory. */
1284 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1286 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1287 smb_action |= EXTENDED_OPLOCK_GRANTED;
1290 SSVAL(params,18,smb_action);
1293 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1295 SIVAL(params,20,inode);
1296 SSVAL(params,24,0); /* Padding. */
1298 uint32 ea_size = estimate_ea_size(conn, fsp,
1300 SIVAL(params, 26, ea_size);
1302 SIVAL(params, 26, 0);
1305 /* Send the required number of replies */
1306 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1308 TALLOC_FREE(smb_fname);
1311 /*********************************************************
1312 Routine to check if a given string matches exactly.
1313 as a special case a mask of "." does NOT match. That
1314 is required for correct wildcard semantics
1315 Case can be significant or not.
1316 **********************************************************/
1318 static bool exact_match(bool has_wild,
1319 bool case_sensitive,
1323 if (mask[0] == '.' && mask[1] == 0) {
1331 if (case_sensitive) {
1332 return strcmp(str,mask)==0;
1334 return strcasecmp_m(str,mask) == 0;
1338 /****************************************************************************
1339 Return the filetype for UNIX extensions.
1340 ****************************************************************************/
1342 static uint32 unix_filetype(mode_t mode)
1345 return UNIX_TYPE_FILE;
1346 else if(S_ISDIR(mode))
1347 return UNIX_TYPE_DIR;
1349 else if(S_ISLNK(mode))
1350 return UNIX_TYPE_SYMLINK;
1353 else if(S_ISCHR(mode))
1354 return UNIX_TYPE_CHARDEV;
1357 else if(S_ISBLK(mode))
1358 return UNIX_TYPE_BLKDEV;
1361 else if(S_ISFIFO(mode))
1362 return UNIX_TYPE_FIFO;
1365 else if(S_ISSOCK(mode))
1366 return UNIX_TYPE_SOCKET;
1369 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1370 return UNIX_TYPE_UNKNOWN;
1373 /****************************************************************************
1374 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1375 ****************************************************************************/
1377 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1379 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1380 const SMB_STRUCT_STAT *psbuf,
1382 enum perm_type ptype,
1387 if (perms == SMB_MODE_NO_CHANGE) {
1388 if (!VALID_STAT(*psbuf)) {
1389 return NT_STATUS_INVALID_PARAMETER;
1391 *ret_perms = psbuf->st_ex_mode;
1392 return NT_STATUS_OK;
1396 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1397 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1398 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1399 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1400 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1401 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1402 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1403 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1404 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1406 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1409 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1412 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1417 case PERM_EXISTING_FILE:
1418 /* Apply mode mask */
1419 ret &= lp_create_mask(SNUM(conn));
1420 /* Add in force bits */
1421 ret |= lp_force_create_mode(SNUM(conn));
1424 case PERM_EXISTING_DIR:
1425 ret &= lp_dir_mask(SNUM(conn));
1426 /* Add in force bits */
1427 ret |= lp_force_dir_mode(SNUM(conn));
1432 return NT_STATUS_OK;
1435 /****************************************************************************
1436 Needed to show the msdfs symlinks as directories. Modifies psbuf
1437 to be a directory if it's a msdfs link.
1438 ****************************************************************************/
1440 static bool check_msdfs_link(connection_struct *conn,
1441 const char *pathname,
1442 SMB_STRUCT_STAT *psbuf)
1444 int saved_errno = errno;
1445 if(lp_host_msdfs() &&
1446 lp_msdfs_root(SNUM(conn)) &&
1447 is_msdfs_link(conn, pathname, psbuf)) {
1449 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1452 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1453 errno = saved_errno;
1456 errno = saved_errno;
1461 /****************************************************************************
1462 Get a level dependent lanman2 dir entry.
1463 ****************************************************************************/
1465 struct smbd_dirptr_lanman2_state {
1466 connection_struct *conn;
1467 uint32_t info_level;
1468 bool check_mangled_names;
1470 bool got_exact_match;
1473 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1479 struct smbd_dirptr_lanman2_state *state =
1480 (struct smbd_dirptr_lanman2_state *)private_data;
1482 char mangled_name[13]; /* mangled 8.3 name. */
1486 /* Mangle fname if it's an illegal name. */
1487 if (mangle_must_mangle(dname, state->conn->params)) {
1488 ok = name_to_8_3(dname, mangled_name,
1489 true, state->conn->params);
1493 fname = mangled_name;
1498 got_match = exact_match(state->has_wild,
1499 state->conn->case_sensitive,
1501 state->got_exact_match = got_match;
1503 got_match = mask_match(fname, mask,
1504 state->conn->case_sensitive);
1507 if(!got_match && state->check_mangled_names &&
1508 !mangle_is_8_3(fname, false, state->conn->params)) {
1510 * It turns out that NT matches wildcards against
1511 * both long *and* short names. This may explain some
1512 * of the wildcard wierdness from old DOS clients
1513 * that some people have been seeing.... JRA.
1515 /* Force the mangling into 8.3. */
1516 ok = name_to_8_3(fname, mangled_name,
1517 false, state->conn->params);
1522 got_match = exact_match(state->has_wild,
1523 state->conn->case_sensitive,
1524 mangled_name, mask);
1525 state->got_exact_match = got_match;
1527 got_match = mask_match(mangled_name, mask,
1528 state->conn->case_sensitive);
1536 *_fname = talloc_strdup(ctx, fname);
1537 if (*_fname == NULL) {
1544 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1546 struct smb_filename *smb_fname,
1549 struct smbd_dirptr_lanman2_state *state =
1550 (struct smbd_dirptr_lanman2_state *)private_data;
1551 bool ms_dfs_link = false;
1554 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1555 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1556 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1557 "Couldn't lstat [%s] (%s)\n",
1558 smb_fname_str_dbg(smb_fname),
1562 } else if (!VALID_STAT(smb_fname->st) &&
1563 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1564 /* Needed to show the msdfs symlinks as
1567 ms_dfs_link = check_msdfs_link(state->conn,
1568 smb_fname->base_name,
1571 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1572 "Couldn't stat [%s] (%s)\n",
1573 smb_fname_str_dbg(smb_fname),
1580 mode = dos_mode_msdfs(state->conn, smb_fname);
1582 mode = dos_mode(state->conn, smb_fname);
1589 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1590 connection_struct *conn,
1592 uint32_t info_level,
1593 struct ea_list *name_list,
1594 bool check_mangled_names,
1595 bool requires_resume_key,
1598 const struct smb_filename *smb_fname,
1599 int space_remaining,
1606 uint64_t *last_entry_off)
1608 char *p, *q, *pdata = *ppdata;
1610 uint64_t file_size = 0;
1611 uint64_t allocation_size = 0;
1612 uint64_t file_index = 0;
1614 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1615 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1617 char *last_entry_ptr;
1622 *out_of_space = false;
1624 ZERO_STRUCT(mdate_ts);
1625 ZERO_STRUCT(adate_ts);
1626 ZERO_STRUCT(create_date_ts);
1627 ZERO_STRUCT(cdate_ts);
1629 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1630 file_size = get_file_size_stat(&smb_fname->st);
1632 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1634 file_index = get_FileIndex(conn, &smb_fname->st);
1636 mdate_ts = smb_fname->st.st_ex_mtime;
1637 adate_ts = smb_fname->st.st_ex_atime;
1638 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1639 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1641 if (lp_dos_filetime_resolution(SNUM(conn))) {
1642 dos_filetime_timespec(&create_date_ts);
1643 dos_filetime_timespec(&mdate_ts);
1644 dos_filetime_timespec(&adate_ts);
1645 dos_filetime_timespec(&cdate_ts);
1648 create_date = convert_timespec_to_time_t(create_date_ts);
1649 mdate = convert_timespec_to_time_t(mdate_ts);
1650 adate = convert_timespec_to_time_t(adate_ts);
1652 /* align the record */
1653 SMB_ASSERT(align >= 1);
1655 off = (int)PTR_DIFF(pdata, base_data);
1656 pad = (off + (align-1)) & ~(align-1);
1659 if (pad && pad > space_remaining) {
1660 *out_of_space = true;
1661 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1662 "for padding (wanted %u, had %d)\n",
1665 return false; /* Not finished - just out of space */
1669 /* initialize padding to 0 */
1671 memset(pdata, 0, pad);
1673 space_remaining -= pad;
1675 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1685 switch (info_level) {
1686 case SMB_FIND_INFO_STANDARD:
1687 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1688 if(requires_resume_key) {
1692 srv_put_dos_date2(p,0,create_date);
1693 srv_put_dos_date2(p,4,adate);
1694 srv_put_dos_date2(p,8,mdate);
1695 SIVAL(p,12,(uint32)file_size);
1696 SIVAL(p,16,(uint32)allocation_size);
1700 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1701 p += ucs2_align(base_data, p, 0);
1703 len = srvstr_push(base_data, flags2, p,
1704 fname, PTR_DIFF(end_data, p),
1706 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1708 SCVAL(nameptr, -1, len - 2);
1710 SCVAL(nameptr, -1, 0);
1714 SCVAL(nameptr, -1, len - 1);
1716 SCVAL(nameptr, -1, 0);
1722 case SMB_FIND_EA_SIZE:
1723 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1724 if (requires_resume_key) {
1728 srv_put_dos_date2(p,0,create_date);
1729 srv_put_dos_date2(p,4,adate);
1730 srv_put_dos_date2(p,8,mdate);
1731 SIVAL(p,12,(uint32)file_size);
1732 SIVAL(p,16,(uint32)allocation_size);
1735 unsigned int ea_size = estimate_ea_size(conn, NULL,
1737 SIVAL(p,22,ea_size); /* Extended attributes */
1741 len = srvstr_push(base_data, flags2,
1742 p, fname, PTR_DIFF(end_data, p),
1743 STR_TERMINATE | STR_NOALIGN);
1744 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1757 SCVAL(nameptr,0,len);
1759 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1762 case SMB_FIND_EA_LIST:
1764 struct ea_list *file_list = NULL;
1768 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1772 if (requires_resume_key) {
1776 srv_put_dos_date2(p,0,create_date);
1777 srv_put_dos_date2(p,4,adate);
1778 srv_put_dos_date2(p,8,mdate);
1779 SIVAL(p,12,(uint32)file_size);
1780 SIVAL(p,16,(uint32)allocation_size);
1782 p += 22; /* p now points to the EA area. */
1784 status = get_ea_list_from_file(ctx, conn, NULL,
1786 &ea_len, &file_list);
1787 if (!NT_STATUS_IS_OK(status)) {
1790 name_list = ea_list_union(name_list, file_list, &ea_len);
1792 /* We need to determine if this entry will fit in the space available. */
1793 /* Max string size is 255 bytes. */
1794 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1795 *out_of_space = true;
1796 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1797 "(wanted %u, had %d)\n",
1798 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1800 return False; /* Not finished - just out of space */
1803 /* Push the ea_data followed by the name. */
1804 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1806 len = srvstr_push(base_data, flags2,
1807 p + 1, fname, PTR_DIFF(end_data, p+1),
1808 STR_TERMINATE | STR_NOALIGN);
1809 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1822 SCVAL(nameptr,0,len);
1824 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1828 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1829 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1830 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1832 SIVAL(p,0,reskey); p += 4;
1833 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1834 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1835 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1836 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1837 SOFF_T(p,0,file_size); p += 8;
1838 SOFF_T(p,0,allocation_size); p += 8;
1839 SIVAL(p,0,mode); p += 4;
1840 q = p; p += 4; /* q is placeholder for name length. */
1842 unsigned int ea_size = estimate_ea_size(conn, NULL,
1844 SIVAL(p,0,ea_size); /* Extended attributes */
1847 /* Clear the short name buffer. This is
1848 * IMPORTANT as not doing so will trigger
1849 * a Win2k client bug. JRA.
1851 if (!was_8_3 && check_mangled_names) {
1852 char mangled_name[13]; /* mangled 8.3 name. */
1853 if (!name_to_8_3(fname,mangled_name,True,
1855 /* Error - mangle failed ! */
1856 memset(mangled_name,'\0',12);
1858 mangled_name[12] = 0;
1859 len = srvstr_push(base_data, flags2,
1860 p+2, mangled_name, 24,
1861 STR_UPPER|STR_UNICODE);
1863 memset(p + 2 + len,'\0',24 - len);
1870 len = srvstr_push(base_data, flags2, p,
1871 fname, PTR_DIFF(end_data, p),
1872 STR_TERMINATE_ASCII);
1876 len = PTR_DIFF(p, pdata);
1877 pad = (len + (align-1)) & ~(align-1);
1879 * offset to the next entry, the caller
1880 * will overwrite it for the last entry
1881 * that's why we always include the padding
1885 * set padding to zero
1888 memset(p, 0, pad - len);
1895 case SMB_FIND_FILE_DIRECTORY_INFO:
1896 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1898 SIVAL(p,0,reskey); p += 4;
1899 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1900 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1901 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1902 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1903 SOFF_T(p,0,file_size); p += 8;
1904 SOFF_T(p,0,allocation_size); p += 8;
1905 SIVAL(p,0,mode); p += 4;
1906 len = srvstr_push(base_data, flags2,
1907 p + 4, fname, PTR_DIFF(end_data, p+4),
1908 STR_TERMINATE_ASCII);
1912 len = PTR_DIFF(p, pdata);
1913 pad = (len + (align-1)) & ~(align-1);
1915 * offset to the next entry, the caller
1916 * will overwrite it for the last entry
1917 * that's why we always include the padding
1921 * set padding to zero
1924 memset(p, 0, pad - len);
1931 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1932 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1934 SIVAL(p,0,reskey); p += 4;
1935 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1936 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1937 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1938 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1939 SOFF_T(p,0,file_size); p += 8;
1940 SOFF_T(p,0,allocation_size); p += 8;
1941 SIVAL(p,0,mode); p += 4;
1942 q = p; p += 4; /* q is placeholder for name length. */
1944 unsigned int ea_size = estimate_ea_size(conn, NULL,
1946 SIVAL(p,0,ea_size); /* Extended attributes */
1949 len = srvstr_push(base_data, flags2, p,
1950 fname, PTR_DIFF(end_data, p),
1951 STR_TERMINATE_ASCII);
1955 len = PTR_DIFF(p, pdata);
1956 pad = (len + (align-1)) & ~(align-1);
1958 * offset to the next entry, the caller
1959 * will overwrite it for the last entry
1960 * that's why we always include the padding
1964 * set padding to zero
1967 memset(p, 0, pad - len);
1974 case SMB_FIND_FILE_NAMES_INFO:
1975 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1977 SIVAL(p,0,reskey); p += 4;
1979 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1980 acl on a dir (tridge) */
1981 len = srvstr_push(base_data, flags2, p,
1982 fname, PTR_DIFF(end_data, p),
1983 STR_TERMINATE_ASCII);
1987 len = PTR_DIFF(p, pdata);
1988 pad = (len + (align-1)) & ~(align-1);
1990 * offset to the next entry, the caller
1991 * will overwrite it for the last entry
1992 * that's why we always include the padding
1996 * set padding to zero
1999 memset(p, 0, pad - len);
2006 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2007 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2009 SIVAL(p,0,reskey); p += 4;
2010 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2011 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2012 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2013 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2014 SOFF_T(p,0,file_size); p += 8;
2015 SOFF_T(p,0,allocation_size); p += 8;
2016 SIVAL(p,0,mode); p += 4;
2017 q = p; p += 4; /* q is placeholder for name length. */
2019 unsigned int ea_size = estimate_ea_size(conn, NULL,
2021 SIVAL(p,0,ea_size); /* Extended attributes */
2024 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2025 SBVAL(p,0,file_index); p += 8;
2026 len = srvstr_push(base_data, flags2, p,
2027 fname, PTR_DIFF(end_data, p),
2028 STR_TERMINATE_ASCII);
2032 len = PTR_DIFF(p, pdata);
2033 pad = (len + (align-1)) & ~(align-1);
2035 * offset to the next entry, the caller
2036 * will overwrite it for the last entry
2037 * that's why we always include the padding
2041 * set padding to zero
2044 memset(p, 0, pad - len);
2051 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2052 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2053 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2055 SIVAL(p,0,reskey); p += 4;
2056 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2057 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2058 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2059 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2060 SOFF_T(p,0,file_size); p += 8;
2061 SOFF_T(p,0,allocation_size); p += 8;
2062 SIVAL(p,0,mode); p += 4;
2063 q = p; p += 4; /* q is placeholder for name length */
2065 unsigned int ea_size = estimate_ea_size(conn, NULL,
2067 SIVAL(p,0,ea_size); /* Extended attributes */
2070 /* Clear the short name buffer. This is
2071 * IMPORTANT as not doing so will trigger
2072 * a Win2k client bug. JRA.
2074 if (!was_8_3 && check_mangled_names) {
2075 char mangled_name[13]; /* mangled 8.3 name. */
2076 if (!name_to_8_3(fname,mangled_name,True,
2078 /* Error - mangle failed ! */
2079 memset(mangled_name,'\0',12);
2081 mangled_name[12] = 0;
2082 len = srvstr_push(base_data, flags2,
2083 p+2, mangled_name, 24,
2084 STR_UPPER|STR_UNICODE);
2087 memset(p + 2 + len,'\0',24 - len);
2094 SSVAL(p,0,0); p += 2; /* Reserved ? */
2095 SBVAL(p,0,file_index); p += 8;
2096 len = srvstr_push(base_data, flags2, p,
2097 fname, PTR_DIFF(end_data, p),
2098 STR_TERMINATE_ASCII);
2102 len = PTR_DIFF(p, pdata);
2103 pad = (len + (align-1)) & ~(align-1);
2105 * offset to the next entry, the caller
2106 * will overwrite it for the last entry
2107 * that's why we always include the padding
2111 * set padding to zero
2114 memset(p, 0, pad - len);
2121 /* CIFS UNIX Extension. */
2123 case SMB_FIND_FILE_UNIX:
2124 case SMB_FIND_FILE_UNIX_INFO2:
2126 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2128 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2130 if (info_level == SMB_FIND_FILE_UNIX) {
2131 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2132 p = store_file_unix_basic(conn, p,
2133 NULL, &smb_fname->st);
2134 len = srvstr_push(base_data, flags2, p,
2135 fname, PTR_DIFF(end_data, p),
2138 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2139 p = store_file_unix_basic_info2(conn, p,
2140 NULL, &smb_fname->st);
2143 len = srvstr_push(base_data, flags2, p, fname,
2144 PTR_DIFF(end_data, p), 0);
2145 SIVAL(nameptr, 0, len);
2150 len = PTR_DIFF(p, pdata);
2151 pad = (len + (align-1)) & ~(align-1);
2153 * offset to the next entry, the caller
2154 * will overwrite it for the last entry
2155 * that's why we always include the padding
2159 * set padding to zero
2162 memset(p, 0, pad - len);
2167 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2175 if (PTR_DIFF(p,pdata) > space_remaining) {
2176 *out_of_space = true;
2177 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2178 "(wanted %u, had %d)\n",
2179 (unsigned int)PTR_DIFF(p,pdata),
2181 return false; /* Not finished - just out of space */
2184 /* Setup the last entry pointer, as an offset from base_data */
2185 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2186 /* Advance the data pointer to the next slot */
2192 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2193 connection_struct *conn,
2194 struct dptr_struct *dirptr,
2196 const char *path_mask,
2199 int requires_resume_key,
2207 int space_remaining,
2209 bool *got_exact_match,
2210 int *_last_entry_off,
2211 struct ea_list *name_list)
2214 const char *mask = NULL;
2215 long prev_dirpos = 0;
2218 struct smb_filename *smb_fname = NULL;
2219 struct smbd_dirptr_lanman2_state state;
2221 uint64_t last_entry_off = 0;
2225 state.info_level = info_level;
2226 state.check_mangled_names = lp_manglednames(conn->params);
2227 state.has_wild = dptr_has_wild(dirptr);
2228 state.got_exact_match = false;
2230 *out_of_space = false;
2231 *got_exact_match = false;
2233 p = strrchr_m(path_mask,'/');
2244 ok = smbd_dirptr_get_entry(ctx,
2250 smbd_dirptr_lanman2_match_fn,
2251 smbd_dirptr_lanman2_mode_fn,
2261 *got_exact_match = state.got_exact_match;
2263 ok = smbd_marshall_dir_entry(ctx,
2268 state.check_mangled_names,
2269 requires_resume_key,
2282 TALLOC_FREE(smb_fname);
2283 if (*out_of_space) {
2284 dptr_SeekDir(dirptr, prev_dirpos);
2291 *_last_entry_off = last_entry_off;
2295 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2296 connection_struct *conn,
2297 struct dptr_struct *dirptr,
2299 const char *path_mask,
2302 bool requires_resume_key,
2308 int space_remaining,
2310 bool *got_exact_match,
2311 int *last_entry_off,
2312 struct ea_list *name_list)
2315 const bool do_pad = true;
2317 if (info_level >= 1 && info_level <= 3) {
2318 /* No alignment on earlier info levels. */
2322 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2323 path_mask, dirtype, info_level,
2324 requires_resume_key, dont_descend, ask_sharemode,
2326 ppdata, base_data, end_data,
2328 out_of_space, got_exact_match,
2329 last_entry_off, name_list);
2332 /****************************************************************************
2333 Reply to a TRANS2_FINDFIRST.
2334 ****************************************************************************/
2336 static void call_trans2findfirst(connection_struct *conn,
2337 struct smb_request *req,
2338 char **pparams, int total_params,
2339 char **ppdata, int total_data,
2340 unsigned int max_data_bytes)
2342 /* We must be careful here that we don't return more than the
2343 allowed number of data bytes. If this means returning fewer than
2344 maxentries then so be it. We assume that the redirector has
2345 enough room for the fixed number of parameter bytes it has
2347 struct smb_filename *smb_dname = NULL;
2348 char *params = *pparams;
2349 char *pdata = *ppdata;
2353 uint16 findfirst_flags;
2354 bool close_after_first;
2356 bool requires_resume_key;
2358 char *directory = NULL;
2361 int last_entry_off=0;
2365 bool finished = False;
2366 bool dont_descend = False;
2367 bool out_of_space = False;
2368 int space_remaining;
2369 bool mask_contains_wcard = False;
2370 struct ea_list *ea_list = NULL;
2371 NTSTATUS ntstatus = NT_STATUS_OK;
2372 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2373 TALLOC_CTX *ctx = talloc_tos();
2374 struct dptr_struct *dirptr = NULL;
2375 struct smbd_server_connection *sconn = req->sconn;
2376 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2377 bool backup_priv = false;
2379 if (total_params < 13) {
2380 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2384 dirtype = SVAL(params,0);
2385 maxentries = SVAL(params,2);
2386 findfirst_flags = SVAL(params,4);
2387 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2388 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2389 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2390 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2391 security_token_has_privilege(get_current_nttok(conn),
2394 info_level = SVAL(params,6);
2396 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2397 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2398 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2400 info_level, max_data_bytes));
2403 /* W2K3 seems to treat zero as 1. */
2407 switch (info_level) {
2408 case SMB_FIND_INFO_STANDARD:
2409 case SMB_FIND_EA_SIZE:
2410 case SMB_FIND_EA_LIST:
2411 case SMB_FIND_FILE_DIRECTORY_INFO:
2412 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2413 case SMB_FIND_FILE_NAMES_INFO:
2414 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2415 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2416 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2418 case SMB_FIND_FILE_UNIX:
2419 case SMB_FIND_FILE_UNIX_INFO2:
2420 /* Always use filesystem for UNIX mtime query. */
2421 ask_sharemode = false;
2422 if (!lp_unix_extensions()) {
2423 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2426 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2429 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2433 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2434 params+12, total_params - 12,
2435 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2436 if (!NT_STATUS_IS_OK(ntstatus)) {
2437 reply_nterror(req, ntstatus);
2443 ntstatus = filename_convert_with_privilege(ctx,
2448 &mask_contains_wcard,
2451 ntstatus = filename_convert(ctx, conn,
2452 req->flags2 & FLAGS2_DFS_PATHNAMES,
2455 &mask_contains_wcard,
2459 if (!NT_STATUS_IS_OK(ntstatus)) {
2460 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2461 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2462 ERRSRV, ERRbadpath);
2465 reply_nterror(req, ntstatus);
2469 mask = smb_dname->original_lcomp;
2471 directory = smb_dname->base_name;
2473 p = strrchr_m(directory,'/');
2475 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2476 if((directory[0] == '.') && (directory[1] == '\0')) {
2477 mask = talloc_strdup(ctx,"*");
2479 reply_nterror(req, NT_STATUS_NO_MEMORY);
2482 mask_contains_wcard = True;
2488 if (p == NULL || p == directory) {
2489 /* Ensure we don't have a directory name of "". */
2490 directory = talloc_strdup(talloc_tos(), ".");
2492 reply_nterror(req, NT_STATUS_NO_MEMORY);
2497 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2499 if (info_level == SMB_FIND_EA_LIST) {
2502 if (total_data < 4) {
2503 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2507 ea_size = IVAL(pdata,0);
2508 if (ea_size != total_data) {
2509 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2510 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2511 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2515 if (!lp_ea_support(SNUM(conn))) {
2516 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2520 /* Pull out the list of names. */
2521 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2523 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2528 *ppdata = (char *)SMB_REALLOC(
2529 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2530 if(*ppdata == NULL ) {
2531 reply_nterror(req, NT_STATUS_NO_MEMORY);
2535 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2537 /* Realloc the params space */
2538 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2539 if (*pparams == NULL) {
2540 reply_nterror(req, NT_STATUS_NO_MEMORY);
2545 /* Save the wildcard match and attribs we are using on this directory -
2546 needed as lanman2 assumes these are being saved between calls */
2548 ntstatus = dptr_create(conn,
2556 mask_contains_wcard,
2560 if (!NT_STATUS_IS_OK(ntstatus)) {
2561 reply_nterror(req, ntstatus);
2566 /* Remember this in case we have
2567 to do a findnext. */
2568 dptr_set_priv(dirptr);
2571 dptr_num = dptr_dnum(dirptr);
2572 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2574 /* Initialize per TRANS2_FIND_FIRST operation data */
2575 dptr_init_search_op(dirptr);
2577 /* We don't need to check for VOL here as this is returned by
2578 a different TRANS2 call. */
2580 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2581 directory,lp_dontdescend(ctx, SNUM(conn))));
2582 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2583 dont_descend = True;
2586 space_remaining = max_data_bytes;
2587 out_of_space = False;
2589 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2590 bool got_exact_match = False;
2592 /* this is a heuristic to avoid seeking the dirptr except when
2593 absolutely necessary. It allows for a filename of about 40 chars */
2594 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2595 out_of_space = True;
2598 finished = !get_lanman2_dir_entry(ctx,
2602 mask,dirtype,info_level,
2603 requires_resume_key,dont_descend,
2606 space_remaining, &out_of_space,
2608 &last_entry_off, ea_list);
2611 if (finished && out_of_space)
2614 if (!finished && !out_of_space)
2618 * As an optimisation if we know we aren't looking
2619 * for a wildcard name (ie. the name matches the wildcard exactly)
2620 * then we can finish on any (first) match.
2621 * This speeds up large directory searches. JRA.
2627 /* Ensure space_remaining never goes -ve. */
2628 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2629 space_remaining = 0;
2630 out_of_space = true;
2632 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2636 /* Check if we can close the dirptr */
2637 if(close_after_first || (finished && close_if_end)) {
2638 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2639 dptr_close(sconn, &dptr_num);
2643 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2644 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2645 * the protocol level is less than NT1. Tested with smbclient. JRA.
2646 * This should fix the OS/2 client bug #2335.
2649 if(numentries == 0) {
2650 dptr_close(sconn, &dptr_num);
2651 if (get_Protocol() < PROTOCOL_NT1) {
2652 reply_force_doserror(req, ERRDOS, ERRnofiles);
2655 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2656 ERRDOS, ERRbadfile);
2661 /* At this point pdata points to numentries directory entries. */
2663 /* Set up the return parameter block */
2664 SSVAL(params,0,dptr_num);
2665 SSVAL(params,2,numentries);
2666 SSVAL(params,4,finished);
2667 SSVAL(params,6,0); /* Never an EA error */
2668 SSVAL(params,8,last_entry_off);
2670 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2673 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2674 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2676 reply_nterror(req, NT_STATUS_NO_MEMORY);
2680 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2681 smb_fn_name(req->cmd),
2682 mask, directory, dirtype, numentries ) );
2685 * Force a name mangle here to ensure that the
2686 * mask as an 8.3 name is top of the mangled cache.
2687 * The reasons for this are subtle. Don't remove
2688 * this code unless you know what you are doing
2689 * (see PR#13758). JRA.
2692 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2693 char mangled_name[13];
2694 name_to_8_3(mask, mangled_name, True, conn->params);
2702 TALLOC_FREE(smb_dname);
2706 /****************************************************************************
2707 Reply to a TRANS2_FINDNEXT.
2708 ****************************************************************************/
2710 static void call_trans2findnext(connection_struct *conn,
2711 struct smb_request *req,
2712 char **pparams, int total_params,
2713 char **ppdata, int total_data,
2714 unsigned int max_data_bytes)
2716 /* We must be careful here that we don't return more than the
2717 allowed number of data bytes. If this means returning fewer than
2718 maxentries then so be it. We assume that the redirector has
2719 enough room for the fixed number of parameter bytes it has
2721 char *params = *pparams;
2722 char *pdata = *ppdata;
2728 uint16 findnext_flags;
2729 bool close_after_request;
2731 bool requires_resume_key;
2733 bool mask_contains_wcard = False;
2734 char *resume_name = NULL;
2735 const char *mask = NULL;
2736 const char *directory = NULL;
2740 int i, last_entry_off=0;
2741 bool finished = False;
2742 bool dont_descend = False;
2743 bool out_of_space = False;
2744 int space_remaining;
2745 struct ea_list *ea_list = NULL;
2746 NTSTATUS ntstatus = NT_STATUS_OK;
2747 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2748 TALLOC_CTX *ctx = talloc_tos();
2749 struct dptr_struct *dirptr;
2750 struct smbd_server_connection *sconn = req->sconn;
2751 bool backup_priv = false;
2753 if (total_params < 13) {
2754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2758 dptr_num = SVAL(params,0);
2759 maxentries = SVAL(params,2);
2760 info_level = SVAL(params,4);
2761 resume_key = IVAL(params,6);
2762 findnext_flags = SVAL(params,10);
2763 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2764 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2765 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2766 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2768 if (!continue_bit) {
2769 /* We only need resume_name if continue_bit is zero. */
2770 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2772 total_params - 12, STR_TERMINATE, &ntstatus,
2773 &mask_contains_wcard);
2774 if (!NT_STATUS_IS_OK(ntstatus)) {
2775 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2776 complain (it thinks we're asking for the directory above the shared
2777 path or an invalid name). Catch this as the resume name is only compared, never used in
2778 a file access. JRA. */
2779 srvstr_pull_talloc(ctx, params, req->flags2,
2780 &resume_name, params+12,
2784 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2785 reply_nterror(req, ntstatus);
2791 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2792 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2793 resume_key = %d resume name = %s continue=%d level = %d\n",
2794 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2795 requires_resume_key, resume_key,
2796 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2799 /* W2K3 seems to treat zero as 1. */
2803 switch (info_level) {
2804 case SMB_FIND_INFO_STANDARD:
2805 case SMB_FIND_EA_SIZE:
2806 case SMB_FIND_EA_LIST:
2807 case SMB_FIND_FILE_DIRECTORY_INFO:
2808 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2809 case SMB_FIND_FILE_NAMES_INFO:
2810 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2811 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2812 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2814 case SMB_FIND_FILE_UNIX:
2815 case SMB_FIND_FILE_UNIX_INFO2:
2816 /* Always use filesystem for UNIX mtime query. */
2817 ask_sharemode = false;
2818 if (!lp_unix_extensions()) {
2819 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2824 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2828 if (info_level == SMB_FIND_EA_LIST) {
2831 if (total_data < 4) {
2832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2836 ea_size = IVAL(pdata,0);
2837 if (ea_size != total_data) {
2838 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2839 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2844 if (!lp_ea_support(SNUM(conn))) {
2845 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2849 /* Pull out the list of names. */
2850 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2852 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2857 *ppdata = (char *)SMB_REALLOC(
2858 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2859 if(*ppdata == NULL) {
2860 reply_nterror(req, NT_STATUS_NO_MEMORY);
2865 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2867 /* Realloc the params space */
2868 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2869 if(*pparams == NULL ) {
2870 reply_nterror(req, NT_STATUS_NO_MEMORY);
2876 /* Check that the dptr is valid */
2877 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2878 reply_nterror(req, STATUS_NO_MORE_FILES);
2882 directory = dptr_path(sconn, dptr_num);
2884 /* Get the wildcard mask from the dptr */
2885 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2886 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2887 reply_nterror(req, STATUS_NO_MORE_FILES);
2891 /* Get the attr mask from the dptr */
2892 dirtype = dptr_attr(sconn, dptr_num);
2894 backup_priv = dptr_get_priv(dirptr);
2896 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2897 "backup_priv = %d\n",
2898 dptr_num, mask, dirtype,
2900 dptr_TellDir(dirptr),
2903 /* Initialize per TRANS2_FIND_NEXT operation data */
2904 dptr_init_search_op(dirptr);
2906 /* We don't need to check for VOL here as this is returned by
2907 a different TRANS2 call. */
2909 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2910 directory,lp_dontdescend(ctx, SNUM(conn))));
2911 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2912 dont_descend = True;
2915 space_remaining = max_data_bytes;
2916 out_of_space = False;
2923 * Seek to the correct position. We no longer use the resume key but
2924 * depend on the last file name instead.
2927 if(!continue_bit && resume_name && *resume_name) {
2930 long current_pos = 0;
2932 * Remember, name_to_8_3 is called by
2933 * get_lanman2_dir_entry(), so the resume name
2934 * could be mangled. Ensure we check the unmangled name.
2937 if (mangle_is_mangled(resume_name, conn->params)) {
2938 char *new_resume_name = NULL;
2939 mangle_lookup_name_from_8_3(ctx,
2943 if (new_resume_name) {
2944 resume_name = new_resume_name;
2949 * Fix for NT redirector problem triggered by resume key indexes
2950 * changing between directory scans. We now return a resume key of 0
2951 * and instead look for the filename to continue from (also given
2952 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2953 * findfirst/findnext (as is usual) then the directory pointer
2954 * should already be at the correct place.
2957 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2958 } /* end if resume_name && !continue_bit */
2960 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2961 bool got_exact_match = False;
2963 /* this is a heuristic to avoid seeking the dirptr except when
2964 absolutely necessary. It allows for a filename of about 40 chars */
2965 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2966 out_of_space = True;
2969 finished = !get_lanman2_dir_entry(ctx,
2973 mask,dirtype,info_level,
2974 requires_resume_key,dont_descend,
2977 space_remaining, &out_of_space,
2979 &last_entry_off, ea_list);
2982 if (finished && out_of_space)
2985 if (!finished && !out_of_space)
2989 * As an optimisation if we know we aren't looking
2990 * for a wildcard name (ie. the name matches the wildcard exactly)
2991 * then we can finish on any (first) match.
2992 * This speeds up large directory searches. JRA.
2998 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3001 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3002 smb_fn_name(req->cmd),
3003 mask, directory, dirtype, numentries ) );
3005 /* Check if we can close the dirptr */
3006 if(close_after_request || (finished && close_if_end)) {
3007 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3008 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3015 /* Set up the return parameter block */
3016 SSVAL(params,0,numentries);
3017 SSVAL(params,2,finished);
3018 SSVAL(params,4,0); /* Never an EA error */
3019 SSVAL(params,6,last_entry_off);
3021 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
3027 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3029 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3033 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3035 SMB_ASSERT(extended_info != NULL);
3037 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3038 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3039 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3040 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3041 #ifdef SAMBA_VERSION_REVISION
3042 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3044 extended_info->samba_subversion = 0;
3045 #ifdef SAMBA_VERSION_RC_RELEASE
3046 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3048 #ifdef SAMBA_VERSION_PRE_RELEASE
3049 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3052 #ifdef SAMBA_VERSION_VENDOR_PATCH
3053 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3055 extended_info->samba_gitcommitdate = 0;
3056 #ifdef SAMBA_VERSION_COMMIT_TIME
3057 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3060 memset(extended_info->samba_version_string, 0,
3061 sizeof(extended_info->samba_version_string));
3063 snprintf (extended_info->samba_version_string,
3064 sizeof(extended_info->samba_version_string),
3065 "%s", samba_version_string());
3068 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3069 TALLOC_CTX *mem_ctx,
3070 uint16_t info_level,
3072 unsigned int max_data_bytes,
3073 struct smb_filename *fname,
3077 char *pdata, *end_data;
3078 int data_len = 0, len;
3079 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3080 int snum = SNUM(conn);
3081 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3082 char *filename = NULL;
3083 uint32 additional_flags = 0;
3084 struct smb_filename smb_fname;
3087 if (fname == NULL || fname->base_name == NULL) {
3090 filename = fname->base_name;
3094 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3095 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3096 "info level (0x%x) on IPC$.\n",
3097 (unsigned int)info_level));
3098 return NT_STATUS_ACCESS_DENIED;
3102 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3104 ZERO_STRUCT(smb_fname);
3105 smb_fname.base_name = discard_const_p(char, filename);
3107 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3108 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3109 return map_nt_error_from_unix(errno);
3114 *ppdata = (char *)SMB_REALLOC(
3115 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3116 if (*ppdata == NULL) {
3117 return NT_STATUS_NO_MEMORY;
3121 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3122 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3124 switch (info_level) {
3125 case SMB_INFO_ALLOCATION:
3127 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3129 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3130 return map_nt_error_from_unix(errno);
3133 block_size = lp_block_size(snum);
3134 if (bsize < block_size) {
3135 uint64_t factor = block_size/bsize;
3140 if (bsize > block_size) {
3141 uint64_t factor = bsize/block_size;
3146 bytes_per_sector = 512;
3147 sectors_per_unit = bsize/bytes_per_sector;
3149 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3150 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3151 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3153 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3154 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3155 SIVAL(pdata,l1_cUnit,dsize);
3156 SIVAL(pdata,l1_cUnitAvail,dfree);
3157 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3161 case SMB_INFO_VOLUME:
3162 /* Return volume name */
3164 * Add volume serial number - hash of a combination of
3165 * the called hostname and the service name.
3167 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3169 * Win2k3 and previous mess this up by sending a name length
3170 * one byte short. I believe only older clients (OS/2 Win9x) use
3171 * this call so try fixing this by adding a terminating null to
3172 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3176 pdata+l2_vol_szVolLabel, vname,
3177 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3178 STR_NOALIGN|STR_TERMINATE);
3179 SCVAL(pdata,l2_vol_cch,len);
3180 data_len = l2_vol_szVolLabel + len;
3181 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3182 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3186 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3187 case SMB_FS_ATTRIBUTE_INFORMATION:
3189 additional_flags = 0;
3190 #if defined(HAVE_SYS_QUOTAS)
3191 additional_flags |= FILE_VOLUME_QUOTAS;
3194 if(lp_nt_acl_support(SNUM(conn))) {
3195 additional_flags |= FILE_PERSISTENT_ACLS;
3198 /* Capabilities are filled in at connection time through STATVFS call */
3199 additional_flags |= conn->fs_capabilities;
3200 additional_flags |= lp_parm_int(conn->params->service,
3201 "share", "fake_fscaps",
3204 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3205 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3206 additional_flags); /* FS ATTRIBUTES */
3208 SIVAL(pdata,4,255); /* Max filename component length */
3209 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3210 and will think we can't do long filenames */
3211 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3212 PTR_DIFF(end_data, pdata+12),
3215 data_len = 12 + len;
3218 case SMB_QUERY_FS_LABEL_INFO:
3219 case SMB_FS_LABEL_INFORMATION:
3220 len = srvstr_push(pdata, flags2, pdata+4, vname,
3221 PTR_DIFF(end_data, pdata+4), 0);
3226 case SMB_QUERY_FS_VOLUME_INFO:
3227 case SMB_FS_VOLUME_INFORMATION:
3230 * Add volume serial number - hash of a combination of
3231 * the called hostname and the service name.
3233 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3234 (str_checksum(get_local_machine_name())<<16));
3236 /* Max label len is 32 characters. */
3237 len = srvstr_push(pdata, flags2, pdata+18, vname,
3238 PTR_DIFF(end_data, pdata+18),
3240 SIVAL(pdata,12,len);
3243 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3244 (int)strlen(vname),vname,
3245 lp_servicename(talloc_tos(), snum)));
3248 case SMB_QUERY_FS_SIZE_INFO:
3249 case SMB_FS_SIZE_INFORMATION:
3251 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3253 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3254 return map_nt_error_from_unix(errno);
3256 block_size = lp_block_size(snum);
3257 if (bsize < block_size) {
3258 uint64_t factor = block_size/bsize;
3263 if (bsize > block_size) {
3264 uint64_t factor = bsize/block_size;
3269 bytes_per_sector = 512;
3270 sectors_per_unit = bsize/bytes_per_sector;
3271 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3272 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3273 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3274 SBIG_UINT(pdata,0,dsize);
3275 SBIG_UINT(pdata,8,dfree);
3276 SIVAL(pdata,16,sectors_per_unit);
3277 SIVAL(pdata,20,bytes_per_sector);
3281 case SMB_FS_FULL_SIZE_INFORMATION:
3283 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3285 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3286 return map_nt_error_from_unix(errno);
3288 block_size = lp_block_size(snum);
3289 if (bsize < block_size) {
3290 uint64_t factor = block_size/bsize;
3295 if (bsize > block_size) {
3296 uint64_t factor = bsize/block_size;
3301 bytes_per_sector = 512;
3302 sectors_per_unit = bsize/bytes_per_sector;
3303 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3304 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3305 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3306 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3307 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3308 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3309 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3310 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3314 case SMB_QUERY_FS_DEVICE_INFO:
3315 case SMB_FS_DEVICE_INFORMATION:
3317 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3319 if (!CAN_WRITE(conn)) {
3320 characteristics |= FILE_READ_ONLY_DEVICE;
3323 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3324 SIVAL(pdata,4,characteristics);
3328 #ifdef HAVE_SYS_QUOTAS
3329 case SMB_FS_QUOTA_INFORMATION:
3331 * what we have to send --metze:
3333 * Unknown1: 24 NULL bytes
3334 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3335 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3336 * Quota Flags: 2 byte :
3337 * Unknown3: 6 NULL bytes
3341 * details for Quota Flags:
3343 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3344 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3345 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3346 * 0x0001 Enable Quotas: enable quota for this fs
3350 /* we need to fake up a fsp here,
3351 * because its not send in this call
3354 SMB_NTQUOTA_STRUCT quotas;
3357 ZERO_STRUCT(quotas);
3360 fsp.fnum = FNUM_FIELD_INVALID;
3363 if (get_current_uid(conn) != 0) {
3364 DEBUG(0,("set_user_quota: access_denied "
3365 "service [%s] user [%s]\n",
3366 lp_servicename(talloc_tos(), SNUM(conn)),
3367 conn->session_info->unix_info->unix_name));
3368 return NT_STATUS_ACCESS_DENIED;
3371 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3372 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3373 return map_nt_error_from_unix(errno);
3378 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3379 lp_servicename(talloc_tos(), SNUM(conn))));
3381 /* Unknown1 24 NULL bytes*/
3382 SBIG_UINT(pdata,0,(uint64_t)0);
3383 SBIG_UINT(pdata,8,(uint64_t)0);
3384 SBIG_UINT(pdata,16,(uint64_t)0);
3386 /* Default Soft Quota 8 bytes */
3387 SBIG_UINT(pdata,24,quotas.softlim);
3389 /* Default Hard Quota 8 bytes */
3390 SBIG_UINT(pdata,32,quotas.hardlim);
3392 /* Quota flag 2 bytes */
3393 SSVAL(pdata,40,quotas.qflags);
3395 /* Unknown3 6 NULL bytes */
3401 #endif /* HAVE_SYS_QUOTAS */
3402 case SMB_FS_OBJECTID_INFORMATION:
3404 unsigned char objid[16];
3405 struct smb_extended_info extended_info;
3406 memcpy(pdata,create_volume_objectid(conn, objid),16);
3407 samba_extended_info_version (&extended_info);
3408 SIVAL(pdata,16,extended_info.samba_magic);
3409 SIVAL(pdata,20,extended_info.samba_version);
3410 SIVAL(pdata,24,extended_info.samba_subversion);
3411 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3412 memcpy(pdata+36,extended_info.samba_version_string,28);
3418 * Query the version and capabilities of the CIFS UNIX extensions
3422 case SMB_QUERY_CIFS_UNIX_INFO:
3424 bool large_write = lp_min_receive_file_size() &&
3425 !srv_is_signing_active(conn->sconn);
3426 bool large_read = !srv_is_signing_active(conn->sconn);
3427 int encrypt_caps = 0;
3429 if (!lp_unix_extensions()) {
3430 return NT_STATUS_INVALID_LEVEL;
3433 switch (conn->encrypt_level) {
3434 case SMB_SIGNING_OFF:
3437 case SMB_SIGNING_IF_REQUIRED:
3438 case SMB_SIGNING_DEFAULT:
3439 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3441 case SMB_SIGNING_REQUIRED:
3442 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3443 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3444 large_write = false;
3450 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3451 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3453 /* We have POSIX ACLs, pathname, encryption,
3454 * large read/write, and locking capability. */
3456 SBIG_UINT(pdata,4,((uint64_t)(
3457 CIFS_UNIX_POSIX_ACLS_CAP|
3458 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3459 CIFS_UNIX_FCNTL_LOCKS_CAP|
3460 CIFS_UNIX_EXTATTR_CAP|
3461 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3463 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3465 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3469 case SMB_QUERY_POSIX_FS_INFO:
3472 vfs_statvfs_struct svfs;
3474 if (!lp_unix_extensions()) {
3475 return NT_STATUS_INVALID_LEVEL;
3478 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3482 SIVAL(pdata,0,svfs.OptimalTransferSize);
3483 SIVAL(pdata,4,svfs.BlockSize);
3484 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3485 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3486 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3487 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3488 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3489 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3490 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3492 } else if (rc == EOPNOTSUPP) {
3493 return NT_STATUS_INVALID_LEVEL;
3494 #endif /* EOPNOTSUPP */
3496 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3497 return NT_STATUS_DOS(ERRSRV, ERRerror);
3502 case SMB_QUERY_POSIX_WHOAMI:
3508 if (!lp_unix_extensions()) {
3509 return NT_STATUS_INVALID_LEVEL;
3512 if (max_data_bytes < 40) {
3513 return NT_STATUS_BUFFER_TOO_SMALL;
3516 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3517 flags |= SMB_WHOAMI_GUEST;
3520 /* NOTE: 8 bytes for UID/GID, irrespective of native
3521 * platform size. This matches
3522 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3524 data_len = 4 /* flags */
3531 + 4 /* pad/reserved */
3532 + (conn->session_info->unix_token->ngroups * 8)
3534 + (conn->session_info->security_token->num_sids *
3538 SIVAL(pdata, 0, flags);
3539 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3541 (uint64_t)conn->session_info->unix_token->uid);
3542 SBIG_UINT(pdata, 16,
3543 (uint64_t)conn->session_info->unix_token->gid);
3546 if (data_len >= max_data_bytes) {
3547 /* Potential overflow, skip the GIDs and SIDs. */
3549 SIVAL(pdata, 24, 0); /* num_groups */
3550 SIVAL(pdata, 28, 0); /* num_sids */
3551 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3552 SIVAL(pdata, 36, 0); /* reserved */
3558 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3559 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3561 /* We walk the SID list twice, but this call is fairly
3562 * infrequent, and I don't expect that it's performance
3563 * sensitive -- jpeach
3565 for (i = 0, sid_bytes = 0;
3566 i < conn->session_info->security_token->num_sids; ++i) {
3567 sid_bytes += ndr_size_dom_sid(
3568 &conn->session_info->security_token->sids[i],
3572 /* SID list byte count */
3573 SIVAL(pdata, 32, sid_bytes);
3575 /* 4 bytes pad/reserved - must be zero */
3576 SIVAL(pdata, 36, 0);
3580 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3581 SBIG_UINT(pdata, data_len,
3582 (uint64_t)conn->session_info->unix_token->groups[i]);
3588 i < conn->session_info->security_token->num_sids; ++i) {
3589 int sid_len = ndr_size_dom_sid(
3590 &conn->session_info->security_token->sids[i],
3593 sid_linearize(pdata + data_len, sid_len,
3594 &conn->session_info->security_token->sids[i]);
3595 data_len += sid_len;
3601 case SMB_MAC_QUERY_FS_INFO:
3603 * Thursby MAC extension... ONLY on NTFS filesystems
3604 * once we do streams then we don't need this
3606 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3608 SIVAL(pdata,84,0x100); /* Don't support mac... */
3613 return NT_STATUS_INVALID_LEVEL;
3616 *ret_data_len = data_len;
3617 return NT_STATUS_OK;
3620 /****************************************************************************
3621 Reply to a TRANS2_QFSINFO (query filesystem info).
3622 ****************************************************************************/
3624 static void call_trans2qfsinfo(connection_struct *conn,
3625 struct smb_request *req,
3626 char **pparams, int total_params,
3627 char **ppdata, int total_data,
3628 unsigned int max_data_bytes)
3630 char *params = *pparams;
3631 uint16_t info_level;
3635 if (total_params < 2) {
3636 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3640 info_level = SVAL(params,0);
3642 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3643 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3644 DEBUG(0,("call_trans2qfsinfo: encryption required "
3645 "and info level 0x%x sent.\n",
3646 (unsigned int)info_level));
3647 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3652 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3654 status = smbd_do_qfsinfo(conn, req,
3660 if (!NT_STATUS_IS_OK(status)) {
3661 reply_nterror(req, status);
3665 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3668 DEBUG( 4, ( "%s info_level = %d\n",
3669 smb_fn_name(req->cmd), info_level) );
3674 /****************************************************************************
3675 Reply to a TRANS2_SETFSINFO (set filesystem info).
3676 ****************************************************************************/
3678 static void call_trans2setfsinfo(connection_struct *conn,
3679 struct smb_request *req,
3680 char **pparams, int total_params,
3681 char **ppdata, int total_data,
3682 unsigned int max_data_bytes)
3684 struct smbd_server_connection *sconn = req->sconn;
3685 char *pdata = *ppdata;
3686 char *params = *pparams;
3689 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3690 lp_servicename(talloc_tos(), SNUM(conn))));
3693 if (total_params < 4) {
3694 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3700 info_level = SVAL(params,2);
3703 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3704 info_level != SMB_SET_CIFS_UNIX_INFO) {
3705 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3706 "info level (0x%x) on IPC$.\n",
3707 (unsigned int)info_level));
3708 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3713 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3714 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3715 DEBUG(0,("call_trans2setfsinfo: encryption required "
3716 "and info level 0x%x sent.\n",
3717 (unsigned int)info_level));
3718 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3723 switch(info_level) {
3724 case SMB_SET_CIFS_UNIX_INFO:
3725 if (!lp_unix_extensions()) {
3726 DEBUG(2,("call_trans2setfsinfo: "
3727 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3728 "unix extensions off\n"));
3730 NT_STATUS_INVALID_LEVEL);
3734 /* There should be 12 bytes of capabilities set. */
3735 if (total_data < 12) {
3738 NT_STATUS_INVALID_PARAMETER);
3741 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3742 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3743 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3744 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3745 /* Just print these values for now. */
3746 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3747 "major = %u, minor = %u cap_low = 0x%x, "
3749 (unsigned int)sconn->
3750 smb1.unix_info.client_major,
3751 (unsigned int)sconn->
3752 smb1.unix_info.client_minor,
3753 (unsigned int)sconn->
3754 smb1.unix_info.client_cap_low,
3755 (unsigned int)sconn->
3756 smb1.unix_info.client_cap_high));
3758 /* Here is where we must switch to posix pathname processing... */
3759 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3760 lp_set_posix_pathnames();
3761 mangle_change_to_posix();
3764 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3765 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3766 /* Client that knows how to do posix locks,
3767 * but not posix open/mkdir operations. Set a
3768 * default type for read/write checks. */
3770 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3775 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3778 size_t param_len = 0;
3779 size_t data_len = total_data;
3781 if (!lp_unix_extensions()) {
3784 NT_STATUS_INVALID_LEVEL);
3788 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3791 NT_STATUS_NOT_SUPPORTED);
3795 if (req->sconn->smb1.echo_handler.trusted_fde) {
3796 DEBUG( 2,("call_trans2setfsinfo: "
3797 "request transport encryption disabled"
3798 "with 'fork echo handler = yes'\n"));
3801 NT_STATUS_NOT_SUPPORTED);
3805 DEBUG( 4,("call_trans2setfsinfo: "
3806 "request transport encryption.\n"));
3808 status = srv_request_encryption_setup(conn,
3809 (unsigned char **)ppdata,
3811 (unsigned char **)pparams,
3814 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3815 !NT_STATUS_IS_OK(status)) {
3816 reply_nterror(req, status);
3820 send_trans2_replies(conn, req,
3827 if (NT_STATUS_IS_OK(status)) {
3828 /* Server-side transport
3829 * encryption is now *on*. */
3830 status = srv_encryption_start(conn);
3831 if (!NT_STATUS_IS_OK(status)) {
3832 char *reason = talloc_asprintf(talloc_tos(),
3833 "Failure in setting "
3834 "up encrypted transport: %s",
3836 exit_server_cleanly(reason);
3842 case SMB_FS_QUOTA_INFORMATION:
3844 files_struct *fsp = NULL;
3845 SMB_NTQUOTA_STRUCT quotas;
3847 ZERO_STRUCT(quotas);
3850 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3851 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3852 lp_servicename(talloc_tos(), SNUM(conn)),
3853 conn->session_info->unix_info->unix_name));
3854 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3858 /* note: normaly there're 48 bytes,
3859 * but we didn't use the last 6 bytes for now
3862 fsp = file_fsp(req, SVAL(params,0));
3864 if (!check_fsp_ntquota_handle(conn, req,
3866 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3868 req, NT_STATUS_INVALID_HANDLE);
3872 if (total_data < 42) {
3873 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3877 NT_STATUS_INVALID_PARAMETER);
3881 /* unknown_1 24 NULL bytes in pdata*/
3883 /* the soft quotas 8 bytes (uint64_t)*/
3884 quotas.softlim = BVAL(pdata,24);
3886 /* the hard quotas 8 bytes (uint64_t)*/
3887 quotas.hardlim = BVAL(pdata,32);
3889 /* quota_flags 2 bytes **/
3890 quotas.qflags = SVAL(pdata,40);
3892 /* unknown_2 6 NULL bytes follow*/
3894 /* now set the quotas */
3895 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3896 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3897 reply_nterror(req, map_nt_error_from_unix(errno));
3904 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3906 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3912 * sending this reply works fine,
3913 * but I'm not sure it's the same
3914 * like windows do...
3917 reply_outbuf(req, 10, 0);
3920 #if defined(HAVE_POSIX_ACLS)
3921 /****************************************************************************
3922 Utility function to count the number of entries in a POSIX acl.
3923 ****************************************************************************/
3925 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3927 unsigned int ace_count = 0;
3928 int entry_id = SMB_ACL_FIRST_ENTRY;
3929 SMB_ACL_ENTRY_T entry;
3931 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3933 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3934 entry_id = SMB_ACL_NEXT_ENTRY;
3941 /****************************************************************************
3942 Utility function to marshall a POSIX acl into wire format.
3943 ****************************************************************************/
3945 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3947 int entry_id = SMB_ACL_FIRST_ENTRY;
3948 SMB_ACL_ENTRY_T entry;
3950 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3951 SMB_ACL_TAG_T tagtype;
3952 SMB_ACL_PERMSET_T permset;
3953 unsigned char perms = 0;
3954 unsigned int own_grp;
3957 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3958 entry_id = SMB_ACL_NEXT_ENTRY;
3961 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3962 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3966 if (sys_acl_get_permset(entry, &permset) == -1) {
3967 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3971 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3972 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3973 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3975 SCVAL(pdata,1,perms);
3978 case SMB_ACL_USER_OBJ:
3979 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3980 own_grp = (unsigned int)pst->st_ex_uid;
3981 SIVAL(pdata,2,own_grp);
3986 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3988 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3991 own_grp = (unsigned int)*puid;
3992 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3993 SIVAL(pdata,2,own_grp);
3997 case SMB_ACL_GROUP_OBJ:
3998 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3999 own_grp = (unsigned int)pst->st_ex_gid;
4000 SIVAL(pdata,2,own_grp);
4005 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4007 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4010 own_grp = (unsigned int)*pgid;
4011 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4012 SIVAL(pdata,2,own_grp);
4017 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4018 SIVAL(pdata,2,0xFFFFFFFF);
4019 SIVAL(pdata,6,0xFFFFFFFF);
4022 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4023 SIVAL(pdata,2,0xFFFFFFFF);
4024 SIVAL(pdata,6,0xFFFFFFFF);
4027 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4030 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4037 /****************************************************************************
4038 Store the FILE_UNIX_BASIC info.
4039 ****************************************************************************/
4041 static char *store_file_unix_basic(connection_struct *conn,
4044 const SMB_STRUCT_STAT *psbuf)
4046 uint64_t file_index = get_FileIndex(conn, psbuf);
4049 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4050 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4052 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4055 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4058 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4059 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4060 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4063 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4067 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4071 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4074 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4075 devno = psbuf->st_ex_rdev;
4077 devno = psbuf->st_ex_dev;
4080 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4084 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4088 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4091 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4095 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4102 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4103 * the chflags(2) (or equivalent) flags.
4105 * XXX: this really should be behind the VFS interface. To do this, we would
4106 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4107 * Each VFS module could then implement its own mapping as appropriate for the
4108 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4110 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4114 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4118 { UF_IMMUTABLE, EXT_IMMUTABLE },
4122 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4126 { UF_HIDDEN, EXT_HIDDEN },
4129 /* Do not remove. We need to guarantee that this array has at least one
4130 * entry to build on HP-UX.
4136 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4137 uint32 *smb_fflags, uint32 *smb_fmask)
4141 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4142 *smb_fmask |= info2_flags_map[i].smb_fflag;
4143 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4144 *smb_fflags |= info2_flags_map[i].smb_fflag;
4149 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4150 const uint32 smb_fflags,
4151 const uint32 smb_fmask,
4154 uint32 max_fmask = 0;
4157 *stat_fflags = psbuf->st_ex_flags;
4159 /* For each flags requested in smb_fmask, check the state of the
4160 * corresponding flag in smb_fflags and set or clear the matching
4164 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4165 max_fmask |= info2_flags_map[i].smb_fflag;
4166 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4167 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4168 *stat_fflags |= info2_flags_map[i].stat_fflag;
4170 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4175 /* If smb_fmask is asking to set any bits that are not supported by
4176 * our flag mappings, we should fail.
4178 if ((smb_fmask & max_fmask) != smb_fmask) {
4186 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4187 * of file flags and birth (create) time.
4189 static char *store_file_unix_basic_info2(connection_struct *conn,
4192 const SMB_STRUCT_STAT *psbuf)
4194 uint32 file_flags = 0;
4195 uint32 flags_mask = 0;
4197 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4199 /* Create (birth) time 64 bit */
4200 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4203 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4204 SIVAL(pdata, 0, file_flags); /* flags */
4205 SIVAL(pdata, 4, flags_mask); /* mask */
4211 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4212 const struct stream_struct *streams,
4214 unsigned int max_data_bytes,
4215 unsigned int *data_size)
4218 unsigned int ofs = 0;
4220 for (i = 0; i < num_streams; i++) {
4221 unsigned int next_offset;
4223 smb_ucs2_t *namebuf;
4225 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4226 streams[i].name, &namelen) ||
4229 return NT_STATUS_INVALID_PARAMETER;
4233 * name_buf is now null-terminated, we need to marshall as not
4240 * We cannot overflow ...
4242 if ((ofs + 24 + namelen) > max_data_bytes) {
4243 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4245 TALLOC_FREE(namebuf);
4246 return STATUS_BUFFER_OVERFLOW;
4249 SIVAL(data, ofs+4, namelen);
4250 SOFF_T(data, ofs+8, streams[i].size);
4251 SOFF_T(data, ofs+16, streams[i].alloc_size);
4252 memcpy(data+ofs+24, namebuf, namelen);
4253 TALLOC_FREE(namebuf);
4255 next_offset = ofs + 24 + namelen;
4257 if (i == num_streams-1) {
4258 SIVAL(data, ofs, 0);
4261 unsigned int align = ndr_align_size(next_offset, 8);
4263 if ((next_offset + align) > max_data_bytes) {
4264 DEBUG(10, ("refusing to overflow align "
4265 "reply at stream %u\n",
4267 TALLOC_FREE(namebuf);
4268 return STATUS_BUFFER_OVERFLOW;
4271 memset(data+next_offset, 0, align);
4272 next_offset += align;
4274 SIVAL(data, ofs, next_offset - ofs);
4281 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4285 return NT_STATUS_OK;
4288 /****************************************************************************
4289 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4290 ****************************************************************************/
4292 static void call_trans2qpipeinfo(connection_struct *conn,
4293 struct smb_request *req,
4294 unsigned int tran_call,
4295 char **pparams, int total_params,
4296 char **ppdata, int total_data,
4297 unsigned int max_data_bytes)
4299 char *params = *pparams;
4300 char *pdata = *ppdata;
4301 unsigned int data_size = 0;
4302 unsigned int param_size = 2;
4307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4311 if (total_params < 4) {
4312 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4316 fsp = file_fsp(req, SVAL(params,0));
4317 if (!fsp_is_np(fsp)) {
4318 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4322 info_level = SVAL(params,2);
4324 *pparams = (char *)SMB_REALLOC(*pparams,2);
4325 if (*pparams == NULL) {
4326 reply_nterror(req, NT_STATUS_NO_MEMORY);
4331 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4332 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4333 if (*ppdata == NULL ) {
4334 reply_nterror(req, NT_STATUS_NO_MEMORY);
4339 switch (info_level) {
4340 case SMB_FILE_STANDARD_INFORMATION:
4342 SOFF_T(pdata,0,4096LL);
4349 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4353 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4359 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4360 TALLOC_CTX *mem_ctx,
4361 uint16_t info_level,
4363 struct smb_filename *smb_fname,
4364 bool delete_pending,
4365 struct timespec write_time_ts,
4366 struct ea_list *ea_list,
4367 int lock_data_count,
4370 unsigned int max_data_bytes,
4372 unsigned int *pdata_size)
4374 char *pdata = *ppdata;
4375 char *dstart, *dend;
4376 unsigned int data_size;
4377 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4378 time_t create_time, mtime, atime, c_time;
4379 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4386 uint64_t file_size = 0;
4388 uint64_t allocation_size = 0;
4389 uint64_t file_index = 0;
4390 uint32_t access_mask = 0;
4392 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4393 return NT_STATUS_INVALID_LEVEL;
4396 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4397 smb_fname_str_dbg(smb_fname),
4399 info_level, max_data_bytes));
4401 mode = dos_mode(conn, smb_fname);
4402 nlink = psbuf->st_ex_nlink;
4404 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4408 if ((nlink > 0) && delete_pending) {
4412 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4413 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4414 if (*ppdata == NULL) {
4415 return NT_STATUS_NO_MEMORY;
4419 dend = dstart + data_size - 1;
4421 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4422 update_stat_ex_mtime(psbuf, write_time_ts);
4425 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4426 mtime_ts = psbuf->st_ex_mtime;
4427 atime_ts = psbuf->st_ex_atime;
4428 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4430 if (lp_dos_filetime_resolution(SNUM(conn))) {
4431 dos_filetime_timespec(&create_time_ts);
4432 dos_filetime_timespec(&mtime_ts);
4433 dos_filetime_timespec(&atime_ts);
4434 dos_filetime_timespec(&ctime_ts);
4437 create_time = convert_timespec_to_time_t(create_time_ts);
4438 mtime = convert_timespec_to_time_t(mtime_ts);
4439 atime = convert_timespec_to_time_t(atime_ts);
4440 c_time = convert_timespec_to_time_t(ctime_ts);
4442 p = strrchr_m(smb_fname->base_name,'/');
4444 base_name = smb_fname->base_name;
4448 /* NT expects the name to be in an exact form of the *full*
4449 filename. See the trans2 torture test */
4450 if (ISDOT(base_name)) {
4451 dos_fname = talloc_strdup(mem_ctx, "\\");
4453 return NT_STATUS_NO_MEMORY;
4456 dos_fname = talloc_asprintf(mem_ctx,
4458 smb_fname->base_name);
4460 return NT_STATUS_NO_MEMORY;
4462 if (is_ntfs_stream_smb_fname(smb_fname)) {
4463 dos_fname = talloc_asprintf(dos_fname, "%s",
4464 smb_fname->stream_name);
4466 return NT_STATUS_NO_MEMORY;
4470 string_replace(dos_fname, '/', '\\');
4473 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4476 /* Do we have this path open ? */
4478 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4479 fsp1 = file_find_di_first(conn->sconn, fileid);
4480 if (fsp1 && fsp1->initial_allocation_size) {
4481 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4485 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4486 file_size = get_file_size_stat(psbuf);
4490 pos = fsp->fh->position_information;
4494 access_mask = fsp->access_mask;
4496 /* GENERIC_EXECUTE mapping from Windows */
4497 access_mask = 0x12019F;
4500 /* This should be an index number - looks like
4503 I think this causes us to fail the IFSKIT
4504 BasicFileInformationTest. -tpot */
4505 file_index = get_FileIndex(conn, psbuf);
4507 switch (info_level) {
4508 case SMB_INFO_STANDARD:
4509 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4511 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4512 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4513 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4514 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4515 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4516 SSVAL(pdata,l1_attrFile,mode);
4519 case SMB_INFO_QUERY_EA_SIZE:
4521 unsigned int ea_size =
4522 estimate_ea_size(conn, fsp,
4524 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4526 srv_put_dos_date2(pdata,0,create_time);
4527 srv_put_dos_date2(pdata,4,atime);
4528 srv_put_dos_date2(pdata,8,mtime); /* write time */
4529 SIVAL(pdata,12,(uint32)file_size);
4530 SIVAL(pdata,16,(uint32)allocation_size);
4531 SSVAL(pdata,20,mode);
4532 SIVAL(pdata,22,ea_size);
4536 case SMB_INFO_IS_NAME_VALID:
4537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4539 /* os/2 needs this ? really ?*/
4540 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4542 /* This is only reached for qpathinfo */
4546 case SMB_INFO_QUERY_EAS_FROM_LIST:
4548 size_t total_ea_len = 0;
4549 struct ea_list *ea_file_list = NULL;
4550 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4553 get_ea_list_from_file(mem_ctx, conn, fsp,
4555 &total_ea_len, &ea_file_list);
4556 if (!NT_STATUS_IS_OK(status)) {
4560 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4562 if (!ea_list || (total_ea_len > data_size)) {
4564 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4568 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4572 case SMB_INFO_QUERY_ALL_EAS:
4574 /* We have data_size bytes to put EA's into. */
4575 size_t total_ea_len = 0;
4576 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4578 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4580 &total_ea_len, &ea_list);
4581 if (!NT_STATUS_IS_OK(status)) {
4585 if (!ea_list || (total_ea_len > data_size)) {
4587 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4591 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4595 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4597 /* This is FileFullEaInformation - 0xF which maps to
4598 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4600 /* We have data_size bytes to put EA's into. */
4601 size_t total_ea_len = 0;
4602 struct ea_list *ea_file_list = NULL;
4604 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4606 /*TODO: add filtering and index handling */
4609 get_ea_list_from_file(mem_ctx, conn, fsp,
4611 &total_ea_len, &ea_file_list);
4612 if (!NT_STATUS_IS_OK(status)) {
4615 if (!ea_file_list) {
4616 return NT_STATUS_NO_EAS_ON_FILE;
4619 status = fill_ea_chained_buffer(mem_ctx,
4623 conn, ea_file_list);
4624 if (!NT_STATUS_IS_OK(status)) {
4630 case SMB_FILE_BASIC_INFORMATION:
4631 case SMB_QUERY_FILE_BASIC_INFO:
4633 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4634 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4635 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4637 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4641 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4642 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4643 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4644 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4645 SIVAL(pdata,32,mode);
4647 DEBUG(5,("SMB_QFBI - "));
4648 DEBUG(5,("create: %s ", ctime(&create_time)));
4649 DEBUG(5,("access: %s ", ctime(&atime)));
4650 DEBUG(5,("write: %s ", ctime(&mtime)));
4651 DEBUG(5,("change: %s ", ctime(&c_time)));
4652 DEBUG(5,("mode: %x\n", mode));
4655 case SMB_FILE_STANDARD_INFORMATION:
4656 case SMB_QUERY_FILE_STANDARD_INFO:
4658 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4660 SOFF_T(pdata,0,allocation_size);
4661 SOFF_T(pdata,8,file_size);
4662 SIVAL(pdata,16,nlink);
4663 SCVAL(pdata,20,delete_pending?1:0);
4664 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4665 SSVAL(pdata,22,0); /* Padding. */
4668 case SMB_FILE_EA_INFORMATION:
4669 case SMB_QUERY_FILE_EA_INFO:
4671 unsigned int ea_size =
4672 estimate_ea_size(conn, fsp, smb_fname);
4673 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4675 SIVAL(pdata,0,ea_size);
4679 /* Get the 8.3 name - used if NT SMB was negotiated. */
4680 case SMB_QUERY_FILE_ALT_NAME_INFO:
4681 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4684 char mangled_name[13];
4685 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4686 if (!name_to_8_3(base_name,mangled_name,
4687 True,conn->params)) {
4688 return NT_STATUS_NO_MEMORY;
4690 len = srvstr_push(dstart, flags2,
4691 pdata+4, mangled_name,
4692 PTR_DIFF(dend, pdata+4),
4694 data_size = 4 + len;
4699 case SMB_QUERY_FILE_NAME_INFO:
4703 this must be *exactly* right for ACLs on mapped drives to work
4705 len = srvstr_push(dstart, flags2,
4707 PTR_DIFF(dend, pdata+4),
4709 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4710 data_size = 4 + len;
4715 case SMB_FILE_ALLOCATION_INFORMATION:
4716 case SMB_QUERY_FILE_ALLOCATION_INFO:
4717 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4719 SOFF_T(pdata,0,allocation_size);
4722 case SMB_FILE_END_OF_FILE_INFORMATION:
4723 case SMB_QUERY_FILE_END_OF_FILEINFO:
4724 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4726 SOFF_T(pdata,0,file_size);
4729 case SMB_QUERY_FILE_ALL_INFO:
4730 case SMB_FILE_ALL_INFORMATION:
4733 unsigned int ea_size =
4734 estimate_ea_size(conn, fsp, smb_fname);
4735 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4736 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4737 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4738 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4739 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4740 SIVAL(pdata,32,mode);
4741 SIVAL(pdata,36,0); /* padding. */
4743 SOFF_T(pdata,0,allocation_size);
4744 SOFF_T(pdata,8,file_size);
4745 SIVAL(pdata,16,nlink);
4746 SCVAL(pdata,20,delete_pending);
4747 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4750 SIVAL(pdata,0,ea_size);
4751 pdata += 4; /* EA info */
4752 len = srvstr_push(dstart, flags2,
4754 PTR_DIFF(dend, pdata+4),
4758 data_size = PTR_DIFF(pdata,(*ppdata));
4762 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4765 unsigned int ea_size =
4766 estimate_ea_size(conn, fsp, smb_fname);
4767 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4768 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4769 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4770 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4771 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4772 SIVAL(pdata, 0x20, mode);
4773 SIVAL(pdata, 0x24, 0); /* padding. */
4774 SBVAL(pdata, 0x28, allocation_size);
4775 SBVAL(pdata, 0x30, file_size);
4776 SIVAL(pdata, 0x38, nlink);
4777 SCVAL(pdata, 0x3C, delete_pending);
4778 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4779 SSVAL(pdata, 0x3E, 0); /* padding */
4780 SBVAL(pdata, 0x40, file_index);
4781 SIVAL(pdata, 0x48, ea_size);
4782 SIVAL(pdata, 0x4C, access_mask);
4783 SBVAL(pdata, 0x50, pos);
4784 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4785 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4789 len = srvstr_push(dstart, flags2,
4791 PTR_DIFF(dend, pdata+4),
4795 data_size = PTR_DIFF(pdata,(*ppdata));
4798 case SMB_FILE_INTERNAL_INFORMATION:
4800 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4801 SBVAL(pdata, 0, file_index);
4805 case SMB_FILE_ACCESS_INFORMATION:
4806 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4807 SIVAL(pdata, 0, access_mask);
4811 case SMB_FILE_NAME_INFORMATION:
4812 /* Pathname with leading '\'. */
4815 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4816 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4817 SIVAL(pdata,0,byte_len);
4818 data_size = 4 + byte_len;
4822 case SMB_FILE_DISPOSITION_INFORMATION:
4823 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4825 SCVAL(pdata,0,delete_pending);
4828 case SMB_FILE_POSITION_INFORMATION:
4829 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4831 SOFF_T(pdata,0,pos);
4834 case SMB_FILE_MODE_INFORMATION:
4835 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4836 SIVAL(pdata,0,mode);
4840 case SMB_FILE_ALIGNMENT_INFORMATION:
4841 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4842 SIVAL(pdata,0,0); /* No alignment needed. */
4847 * NT4 server just returns "invalid query" to this - if we try
4848 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4851 /* The first statement above is false - verified using Thursby
4852 * client against NT4 -- gcolley.
4854 case SMB_QUERY_FILE_STREAM_INFO:
4855 case SMB_FILE_STREAM_INFORMATION: {
4856 unsigned int num_streams = 0;
4857 struct stream_struct *streams = NULL;
4859 DEBUG(10,("smbd_do_qfilepathinfo: "
4860 "SMB_FILE_STREAM_INFORMATION\n"));
4862 if (is_ntfs_stream_smb_fname(smb_fname)) {
4863 return NT_STATUS_INVALID_PARAMETER;
4866 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4867 talloc_tos(), &num_streams, &streams);
4869 if (!NT_STATUS_IS_OK(status)) {
4870 DEBUG(10, ("could not get stream info: %s\n",
4871 nt_errstr(status)));
4875 status = marshall_stream_info(num_streams, streams,
4876 pdata, max_data_bytes,
4879 if (!NT_STATUS_IS_OK(status)) {
4880 DEBUG(10, ("marshall_stream_info failed: %s\n",
4881 nt_errstr(status)));
4882 TALLOC_FREE(streams);
4886 TALLOC_FREE(streams);
4890 case SMB_QUERY_COMPRESSION_INFO:
4891 case SMB_FILE_COMPRESSION_INFORMATION:
4892 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4893 SOFF_T(pdata,0,file_size);
4894 SIVAL(pdata,8,0); /* ??? */
4895 SIVAL(pdata,12,0); /* ??? */
4899 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4900 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4901 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4902 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4903 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4904 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4905 SOFF_T(pdata,32,allocation_size);
4906 SOFF_T(pdata,40,file_size);
4907 SIVAL(pdata,48,mode);
4908 SIVAL(pdata,52,0); /* ??? */
4912 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4913 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4914 SIVAL(pdata,0,mode);
4920 * CIFS UNIX Extensions.
4923 case SMB_QUERY_FILE_UNIX_BASIC:
4925 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4926 data_size = PTR_DIFF(pdata,(*ppdata));
4928 DEBUG(4,("smbd_do_qfilepathinfo: "
4929 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4930 dump_data(4, (uint8_t *)(*ppdata), data_size);
4934 case SMB_QUERY_FILE_UNIX_INFO2:
4936 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4937 data_size = PTR_DIFF(pdata,(*ppdata));
4941 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4943 for (i=0; i<100; i++)
4944 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4950 case SMB_QUERY_FILE_UNIX_LINK:
4953 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4956 return NT_STATUS_NO_MEMORY;
4959 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4961 if(!S_ISLNK(psbuf->st_ex_mode)) {
4962 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4965 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4967 len = SMB_VFS_READLINK(conn,
4968 smb_fname->base_name,
4971 return map_nt_error_from_unix(errno);
4974 len = srvstr_push(dstart, flags2,
4976 PTR_DIFF(dend, pdata),
4979 data_size = PTR_DIFF(pdata,(*ppdata));
4984 #if defined(HAVE_POSIX_ACLS)
4985 case SMB_QUERY_POSIX_ACL:
4987 SMB_ACL_T file_acl = NULL;
4988 SMB_ACL_T def_acl = NULL;
4989 uint16 num_file_acls = 0;
4990 uint16 num_def_acls = 0;
4992 if (fsp && fsp->fh->fd != -1) {
4993 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4997 SMB_VFS_SYS_ACL_GET_FILE(conn,
4998 smb_fname->base_name,
4999 SMB_ACL_TYPE_ACCESS,
5003 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5004 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5005 "not implemented on "
5006 "filesystem containing %s\n",
5007 smb_fname->base_name));
5008 return NT_STATUS_NOT_IMPLEMENTED;
5011 if (S_ISDIR(psbuf->st_ex_mode)) {
5012 if (fsp && fsp->is_directory) {
5014 SMB_VFS_SYS_ACL_GET_FILE(
5016 fsp->fsp_name->base_name,
5017 SMB_ACL_TYPE_DEFAULT,
5021 SMB_VFS_SYS_ACL_GET_FILE(
5023 smb_fname->base_name,
5024 SMB_ACL_TYPE_DEFAULT,
5027 def_acl = free_empty_sys_acl(conn, def_acl);
5030 num_file_acls = count_acl_entries(conn, file_acl);
5031 num_def_acls = count_acl_entries(conn, def_acl);
5033 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5034 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5036 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5037 SMB_POSIX_ACL_HEADER_SIZE) ));
5039 TALLOC_FREE(file_acl);
5042 TALLOC_FREE(def_acl);
5044 return NT_STATUS_BUFFER_TOO_SMALL;
5047 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5048 SSVAL(pdata,2,num_file_acls);
5049 SSVAL(pdata,4,num_def_acls);
5050 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5052 TALLOC_FREE(file_acl);
5055 TALLOC_FREE(def_acl);
5057 return NT_STATUS_INTERNAL_ERROR;
5059 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5061 TALLOC_FREE(file_acl);
5064 TALLOC_FREE(def_acl);
5066 return NT_STATUS_INTERNAL_ERROR;
5070 TALLOC_FREE(file_acl);
5073 TALLOC_FREE(def_acl);
5075 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5081 case SMB_QUERY_POSIX_LOCK:
5086 enum brl_type lock_type;
5088 /* We need an open file with a real fd for this. */
5089 if (!fsp || fsp->fh->fd == -1) {
5090 return NT_STATUS_INVALID_LEVEL;
5093 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5094 return NT_STATUS_INVALID_PARAMETER;
5097 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5098 case POSIX_LOCK_TYPE_READ:
5099 lock_type = READ_LOCK;
5101 case POSIX_LOCK_TYPE_WRITE:
5102 lock_type = WRITE_LOCK;
5104 case POSIX_LOCK_TYPE_UNLOCK:
5106 /* There's no point in asking for an unlock... */
5107 return NT_STATUS_INVALID_PARAMETER;
5110 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5111 #if defined(HAVE_LONGLONG)
5112 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5113 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5114 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5115 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5116 #else /* HAVE_LONGLONG */
5117 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5118 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5119 #endif /* HAVE_LONGLONG */
5121 status = query_lock(fsp,
5128 if (ERROR_WAS_LOCK_DENIED(status)) {
5129 /* Here we need to report who has it locked... */
5130 data_size = POSIX_LOCK_DATA_SIZE;
5132 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5133 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5134 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5135 #if defined(HAVE_LONGLONG)
5136 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5137 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5138 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5139 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5140 #else /* HAVE_LONGLONG */
5141 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5142 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5143 #endif /* HAVE_LONGLONG */
5145 } else if (NT_STATUS_IS_OK(status)) {
5146 /* For success we just return a copy of what we sent
5147 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5148 data_size = POSIX_LOCK_DATA_SIZE;
5149 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5150 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5158 return NT_STATUS_INVALID_LEVEL;
5161 *pdata_size = data_size;
5162 return NT_STATUS_OK;
5165 /****************************************************************************
5166 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5167 file name or file id).
5168 ****************************************************************************/
5170 static void call_trans2qfilepathinfo(connection_struct *conn,
5171 struct smb_request *req,
5172 unsigned int tran_call,
5173 char **pparams, int total_params,
5174 char **ppdata, int total_data,
5175 unsigned int max_data_bytes)
5177 char *params = *pparams;
5178 char *pdata = *ppdata;
5180 unsigned int data_size = 0;
5181 unsigned int param_size = 2;
5182 struct smb_filename *smb_fname = NULL;
5183 bool delete_pending = False;
5184 struct timespec write_time_ts;
5185 files_struct *fsp = NULL;
5186 struct file_id fileid;
5187 struct ea_list *ea_list = NULL;
5188 int lock_data_count = 0;
5189 char *lock_data = NULL;
5190 NTSTATUS status = NT_STATUS_OK;
5193 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5197 ZERO_STRUCT(write_time_ts);
5199 if (tran_call == TRANSACT2_QFILEINFO) {
5200 if (total_params < 4) {
5201 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5206 call_trans2qpipeinfo(conn, req, tran_call,
5207 pparams, total_params,
5213 fsp = file_fsp(req, SVAL(params,0));
5214 info_level = SVAL(params,2);
5216 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5218 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5219 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5223 /* Initial check for valid fsp ptr. */
5224 if (!check_fsp_open(conn, req, fsp)) {
5228 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5229 if (smb_fname == NULL) {
5230 reply_nterror(req, NT_STATUS_NO_MEMORY);
5234 if(fsp->fake_file_handle) {
5236 * This is actually for the QUOTA_FAKE_FILE --metze
5239 /* We know this name is ok, it's already passed the checks. */
5241 } else if(fsp->fh->fd == -1) {
5243 * This is actually a QFILEINFO on a directory
5244 * handle (returned from an NT SMB). NT5.0 seems
5245 * to do this call. JRA.
5248 if (INFO_LEVEL_IS_UNIX(info_level)) {
5249 /* Always do lstat for UNIX calls. */
5250 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5251 DEBUG(3,("call_trans2qfilepathinfo: "
5252 "SMB_VFS_LSTAT of %s failed "
5254 smb_fname_str_dbg(smb_fname),
5257 map_nt_error_from_unix(errno));
5260 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5261 DEBUG(3,("call_trans2qfilepathinfo: "
5262 "SMB_VFS_STAT of %s failed (%s)\n",
5263 smb_fname_str_dbg(smb_fname),
5266 map_nt_error_from_unix(errno));
5270 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5271 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5274 * Original code - this is an open file.
5276 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5277 DEBUG(3, ("fstat of %s failed (%s)\n",
5278 fsp_fnum_dbg(fsp), strerror(errno)));
5280 map_nt_error_from_unix(errno));
5283 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5284 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5290 uint32_t ucf_flags = 0;
5293 if (total_params < 7) {
5294 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5298 info_level = SVAL(params,0);
5300 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5302 if (INFO_LEVEL_IS_UNIX(info_level)) {
5303 if (!lp_unix_extensions()) {
5304 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5307 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5308 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5309 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5310 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5314 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5316 STR_TERMINATE, &status);
5317 if (!NT_STATUS_IS_OK(status)) {
5318 reply_nterror(req, status);
5322 status = filename_convert(req,
5324 req->flags2 & FLAGS2_DFS_PATHNAMES,
5329 if (!NT_STATUS_IS_OK(status)) {
5330 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5331 reply_botherror(req,
5332 NT_STATUS_PATH_NOT_COVERED,
5333 ERRSRV, ERRbadpath);
5336 reply_nterror(req, status);
5340 /* If this is a stream, check if there is a delete_pending. */
5341 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5342 && is_ntfs_stream_smb_fname(smb_fname)) {
5343 struct smb_filename *smb_fname_base;
5345 /* Create an smb_filename with stream_name == NULL. */
5346 smb_fname_base = synthetic_smb_fname(
5347 talloc_tos(), smb_fname->base_name,
5349 if (smb_fname_base == NULL) {
5350 reply_nterror(req, NT_STATUS_NO_MEMORY);
5354 if (INFO_LEVEL_IS_UNIX(info_level)) {
5355 /* Always do lstat for UNIX calls. */
5356 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5357 DEBUG(3,("call_trans2qfilepathinfo: "
5358 "SMB_VFS_LSTAT of %s failed "
5360 smb_fname_str_dbg(smb_fname_base),
5362 TALLOC_FREE(smb_fname_base);
5364 map_nt_error_from_unix(errno));
5368 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5369 DEBUG(3,("call_trans2qfilepathinfo: "
5370 "fileinfo of %s failed "
5372 smb_fname_str_dbg(smb_fname_base),
5374 TALLOC_FREE(smb_fname_base);
5376 map_nt_error_from_unix(errno));
5381 status = file_name_hash(conn,
5382 smb_fname_str_dbg(smb_fname_base),
5384 if (!NT_STATUS_IS_OK(status)) {
5385 TALLOC_FREE(smb_fname_base);
5386 reply_nterror(req, status);
5390 fileid = vfs_file_id_from_sbuf(conn,
5391 &smb_fname_base->st);
5392 TALLOC_FREE(smb_fname_base);
5393 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5394 if (delete_pending) {
5395 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5400 if (INFO_LEVEL_IS_UNIX(info_level)) {
5401 /* Always do lstat for UNIX calls. */
5402 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5403 DEBUG(3,("call_trans2qfilepathinfo: "
5404 "SMB_VFS_LSTAT of %s failed (%s)\n",
5405 smb_fname_str_dbg(smb_fname),
5408 map_nt_error_from_unix(errno));
5413 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5414 DEBUG(3,("call_trans2qfilepathinfo: "
5415 "SMB_VFS_STAT of %s failed (%s)\n",
5416 smb_fname_str_dbg(smb_fname),
5419 map_nt_error_from_unix(errno));
5424 status = file_name_hash(conn,
5425 smb_fname_str_dbg(smb_fname),
5427 if (!NT_STATUS_IS_OK(status)) {
5428 reply_nterror(req, status);
5432 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5433 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5434 if (delete_pending) {
5435 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5440 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5441 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5443 info_level,tran_call,total_data));
5445 /* Pull out any data sent here before we realloc. */
5446 switch (info_level) {
5447 case SMB_INFO_QUERY_EAS_FROM_LIST:
5449 /* Pull any EA list from the data portion. */
5452 if (total_data < 4) {
5454 req, NT_STATUS_INVALID_PARAMETER);
5457 ea_size = IVAL(pdata,0);
5459 if (total_data > 0 && ea_size != total_data) {
5460 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5461 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5463 req, NT_STATUS_INVALID_PARAMETER);
5467 if (!lp_ea_support(SNUM(conn))) {
5468 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5472 /* Pull out the list of names. */
5473 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5476 req, NT_STATUS_INVALID_PARAMETER);
5482 case SMB_QUERY_POSIX_LOCK:
5484 if (fsp == NULL || fsp->fh->fd == -1) {
5485 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5489 if (total_data != POSIX_LOCK_DATA_SIZE) {
5491 req, NT_STATUS_INVALID_PARAMETER);
5495 /* Copy the lock range data. */
5496 lock_data = (char *)talloc_memdup(
5497 req, pdata, total_data);
5499 reply_nterror(req, NT_STATUS_NO_MEMORY);
5502 lock_data_count = total_data;
5508 *pparams = (char *)SMB_REALLOC(*pparams,2);
5509 if (*pparams == NULL) {
5510 reply_nterror(req, NT_STATUS_NO_MEMORY);
5517 * draft-leach-cifs-v1-spec-02.txt
5518 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5521 * The requested information is placed in the Data portion of the
5522 * transaction response. For the information levels greater than 0x100,
5523 * the transaction response has 1 parameter word which should be
5524 * ignored by the client.
5526 * However Windows only follows this rule for the IS_NAME_VALID call.
5528 switch (info_level) {
5529 case SMB_INFO_IS_NAME_VALID:
5534 if ((info_level & 0xFF00) == 0xFF00) {
5536 * We use levels that start with 0xFF00
5537 * internally to represent SMB2 specific levels
5539 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5543 status = smbd_do_qfilepathinfo(conn, req, info_level,
5545 delete_pending, write_time_ts,
5547 lock_data_count, lock_data,
5548 req->flags2, max_data_bytes,
5549 ppdata, &data_size);
5550 if (!NT_STATUS_IS_OK(status)) {
5551 reply_nterror(req, status);
5555 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5561 /****************************************************************************
5562 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5564 ****************************************************************************/
5566 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5567 connection_struct *conn,
5568 struct smb_request *req,
5569 bool overwrite_if_exists,
5570 const struct smb_filename *smb_fname_old,
5571 struct smb_filename *smb_fname_new)
5573 NTSTATUS status = NT_STATUS_OK;
5575 /* source must already exist. */
5576 if (!VALID_STAT(smb_fname_old->st)) {
5577 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5580 if (VALID_STAT(smb_fname_new->st)) {
5581 if (overwrite_if_exists) {
5582 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5583 return NT_STATUS_FILE_IS_A_DIRECTORY;
5585 status = unlink_internals(conn,
5587 FILE_ATTRIBUTE_NORMAL,
5590 if (!NT_STATUS_IS_OK(status)) {
5594 /* Disallow if newname already exists. */
5595 return NT_STATUS_OBJECT_NAME_COLLISION;
5599 /* No links from a directory. */
5600 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5601 return NT_STATUS_FILE_IS_A_DIRECTORY;
5604 /* Setting a hardlink to/from a stream isn't currently supported. */
5605 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5606 is_ntfs_stream_smb_fname(smb_fname_new)) {
5607 return NT_STATUS_INVALID_PARAMETER;
5610 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5611 smb_fname_old->base_name, smb_fname_new->base_name));
5613 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5614 smb_fname_new->base_name) != 0) {
5615 status = map_nt_error_from_unix(errno);
5616 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5617 nt_errstr(status), smb_fname_old->base_name,
5618 smb_fname_new->base_name));
5623 /****************************************************************************
5624 Deal with setting the time from any of the setfilepathinfo functions.
5625 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5626 calling this function.
5627 ****************************************************************************/
5629 NTSTATUS smb_set_file_time(connection_struct *conn,
5631 const struct smb_filename *smb_fname,
5632 struct smb_file_time *ft,
5633 bool setting_write_time)
5635 struct smb_filename smb_fname_base;
5637 FILE_NOTIFY_CHANGE_LAST_ACCESS
5638 |FILE_NOTIFY_CHANGE_LAST_WRITE
5639 |FILE_NOTIFY_CHANGE_CREATION;
5641 if (!VALID_STAT(smb_fname->st)) {
5642 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5645 /* get some defaults (no modifications) if any info is zero or -1. */
5646 if (null_timespec(ft->create_time)) {
5647 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5650 if (null_timespec(ft->atime)) {
5651 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5654 if (null_timespec(ft->mtime)) {
5655 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5658 if (!setting_write_time) {
5659 /* ft->mtime comes from change time, not write time. */
5660 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5663 /* Ensure the resolution is the correct for
5664 * what we can store on this filesystem. */
5666 round_timespec(conn->ts_res, &ft->create_time);
5667 round_timespec(conn->ts_res, &ft->ctime);
5668 round_timespec(conn->ts_res, &ft->atime);
5669 round_timespec(conn->ts_res, &ft->mtime);
5671 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5672 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5673 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5674 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5675 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5676 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5677 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5678 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5680 if (setting_write_time) {
5682 * This was a Windows setfileinfo on an open file.
5683 * NT does this a lot. We also need to
5684 * set the time here, as it can be read by
5685 * FindFirst/FindNext and with the patch for bug #2045
5686 * in smbd/fileio.c it ensures that this timestamp is
5687 * kept sticky even after a write. We save the request
5688 * away and will set it on file close and after a write. JRA.
5691 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5692 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5695 if (fsp->base_fsp) {
5696 set_sticky_write_time_fsp(fsp->base_fsp,
5699 set_sticky_write_time_fsp(fsp, ft->mtime);
5702 set_sticky_write_time_path(
5703 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5708 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5710 /* Always call ntimes on the base, even if a stream was passed in. */
5711 smb_fname_base = *smb_fname;
5712 smb_fname_base.stream_name = NULL;
5714 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5715 return map_nt_error_from_unix(errno);
5718 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5719 smb_fname->base_name);
5720 return NT_STATUS_OK;
5723 /****************************************************************************
5724 Deal with setting the dosmode from any of the setfilepathinfo functions.
5725 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5726 done before calling this function.
5727 ****************************************************************************/
5729 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5730 const struct smb_filename *smb_fname,
5733 struct smb_filename *smb_fname_base;
5736 if (!VALID_STAT(smb_fname->st)) {
5737 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5740 /* Always operate on the base_name, even if a stream was passed in. */
5741 smb_fname_base = synthetic_smb_fname(
5742 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5743 if (smb_fname_base == NULL) {
5744 return NT_STATUS_NO_MEMORY;
5748 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5749 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5751 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5755 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5757 /* check the mode isn't different, before changing it */
5758 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5759 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5760 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5761 (unsigned int)dosmode));
5763 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5765 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5767 smb_fname_str_dbg(smb_fname_base),
5769 status = map_nt_error_from_unix(errno);
5773 status = NT_STATUS_OK;
5775 TALLOC_FREE(smb_fname_base);
5779 /****************************************************************************
5780 Deal with setting the size from any of the setfilepathinfo functions.
5781 ****************************************************************************/
5783 static NTSTATUS smb_set_file_size(connection_struct *conn,
5784 struct smb_request *req,
5786 const struct smb_filename *smb_fname,
5787 const SMB_STRUCT_STAT *psbuf,
5789 bool fail_after_createfile)
5791 NTSTATUS status = NT_STATUS_OK;
5792 struct smb_filename *smb_fname_tmp = NULL;
5793 files_struct *new_fsp = NULL;
5795 if (!VALID_STAT(*psbuf)) {
5796 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5799 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5801 if (size == get_file_size_stat(psbuf)) {
5802 return NT_STATUS_OK;
5805 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5806 smb_fname_str_dbg(smb_fname), (double)size));
5808 if (fsp && fsp->fh->fd != -1) {
5809 /* Handle based call. */
5810 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5811 return NT_STATUS_ACCESS_DENIED;
5814 if (vfs_set_filelen(fsp, size) == -1) {
5815 return map_nt_error_from_unix(errno);
5817 trigger_write_time_update_immediate(fsp);
5818 return NT_STATUS_OK;
5821 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5822 if (smb_fname_tmp == NULL) {
5823 return NT_STATUS_NO_MEMORY;
5826 smb_fname_tmp->st = *psbuf;
5828 status = SMB_VFS_CREATE_FILE(
5831 0, /* root_dir_fid */
5832 smb_fname_tmp, /* fname */
5833 FILE_WRITE_DATA, /* access_mask */
5834 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5836 FILE_OPEN, /* create_disposition*/
5837 0, /* create_options */
5838 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5839 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5840 0, /* allocation_size */
5841 0, /* private_flags */
5844 &new_fsp, /* result */
5847 TALLOC_FREE(smb_fname_tmp);
5849 if (!NT_STATUS_IS_OK(status)) {
5850 /* NB. We check for open_was_deferred in the caller. */
5854 /* See RAW-SFILEINFO-END-OF-FILE */
5855 if (fail_after_createfile) {
5856 close_file(req, new_fsp,NORMAL_CLOSE);
5857 return NT_STATUS_INVALID_LEVEL;
5860 if (vfs_set_filelen(new_fsp, size) == -1) {
5861 status = map_nt_error_from_unix(errno);
5862 close_file(req, new_fsp,NORMAL_CLOSE);
5866 trigger_write_time_update_immediate(new_fsp);
5867 close_file(req, new_fsp,NORMAL_CLOSE);
5868 return NT_STATUS_OK;
5871 /****************************************************************************
5872 Deal with SMB_INFO_SET_EA.
5873 ****************************************************************************/
5875 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5879 const struct smb_filename *smb_fname)
5881 struct ea_list *ea_list = NULL;
5882 TALLOC_CTX *ctx = NULL;
5883 NTSTATUS status = NT_STATUS_OK;
5885 if (total_data < 10) {
5887 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5888 length. They seem to have no effect. Bug #3212. JRA */
5890 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5891 /* We're done. We only get EA info in this call. */
5892 return NT_STATUS_OK;
5895 return NT_STATUS_INVALID_PARAMETER;
5898 if (IVAL(pdata,0) > total_data) {
5899 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5900 IVAL(pdata,0), (unsigned int)total_data));
5901 return NT_STATUS_INVALID_PARAMETER;
5905 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5907 return NT_STATUS_INVALID_PARAMETER;
5910 status = set_ea(conn, fsp, smb_fname, ea_list);
5915 /****************************************************************************
5916 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5917 ****************************************************************************/
5919 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5924 struct ea_list *ea_list = NULL;
5928 return NT_STATUS_INVALID_HANDLE;
5931 if (!lp_ea_support(SNUM(conn))) {
5932 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5933 "EA's not supported.\n",
5934 (unsigned int)total_data));
5935 return NT_STATUS_EAS_NOT_SUPPORTED;
5938 if (total_data < 10) {
5939 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5941 (unsigned int)total_data));
5942 return NT_STATUS_INVALID_PARAMETER;
5945 ea_list = read_nttrans_ea_list(talloc_tos(),
5950 return NT_STATUS_INVALID_PARAMETER;
5953 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5955 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5956 smb_fname_str_dbg(fsp->fsp_name),
5957 nt_errstr(status) ));
5963 /****************************************************************************
5964 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5965 ****************************************************************************/
5967 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5971 struct smb_filename *smb_fname)
5973 NTSTATUS status = NT_STATUS_OK;
5974 bool delete_on_close;
5977 if (total_data < 1) {
5978 return NT_STATUS_INVALID_PARAMETER;
5982 return NT_STATUS_INVALID_HANDLE;
5985 delete_on_close = (CVAL(pdata,0) ? True : False);
5986 dosmode = dos_mode(conn, smb_fname);
5988 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5989 "delete_on_close = %u\n",
5990 smb_fname_str_dbg(smb_fname),
5991 (unsigned int)dosmode,
5992 (unsigned int)delete_on_close ));
5994 if (delete_on_close) {
5995 status = can_set_delete_on_close(fsp, dosmode);
5996 if (!NT_STATUS_IS_OK(status)) {
6001 /* The set is across all open files on this dev/inode pair. */
6002 if (!set_delete_on_close(fsp, delete_on_close,
6003 conn->session_info->security_token,
6004 conn->session_info->unix_token)) {
6005 return NT_STATUS_ACCESS_DENIED;
6007 return NT_STATUS_OK;
6010 /****************************************************************************
6011 Deal with SMB_FILE_POSITION_INFORMATION.
6012 ****************************************************************************/
6014 static NTSTATUS smb_file_position_information(connection_struct *conn,
6019 uint64_t position_information;
6021 if (total_data < 8) {
6022 return NT_STATUS_INVALID_PARAMETER;
6026 /* Ignore on pathname based set. */
6027 return NT_STATUS_OK;
6030 position_information = (uint64_t)IVAL(pdata,0);
6031 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6033 DEBUG(10,("smb_file_position_information: Set file position "
6034 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6035 (double)position_information));
6036 fsp->fh->position_information = position_information;
6037 return NT_STATUS_OK;
6040 /****************************************************************************
6041 Deal with SMB_FILE_MODE_INFORMATION.
6042 ****************************************************************************/
6044 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6050 if (total_data < 4) {
6051 return NT_STATUS_INVALID_PARAMETER;
6053 mode = IVAL(pdata,0);
6054 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6055 return NT_STATUS_INVALID_PARAMETER;
6057 return NT_STATUS_OK;
6060 /****************************************************************************
6061 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6062 ****************************************************************************/
6064 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6065 struct smb_request *req,
6068 const struct smb_filename *smb_fname)
6070 char *link_target = NULL;
6071 const char *newname = smb_fname->base_name;
6072 TALLOC_CTX *ctx = talloc_tos();
6074 /* Set a symbolic link. */
6075 /* Don't allow this if follow links is false. */
6077 if (total_data == 0) {
6078 return NT_STATUS_INVALID_PARAMETER;
6081 if (!lp_symlinks(SNUM(conn))) {
6082 return NT_STATUS_ACCESS_DENIED;
6085 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6086 total_data, STR_TERMINATE);
6089 return NT_STATUS_INVALID_PARAMETER;
6092 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6093 newname, link_target ));
6095 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6096 return map_nt_error_from_unix(errno);
6099 return NT_STATUS_OK;
6102 /****************************************************************************
6103 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6104 ****************************************************************************/
6106 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6107 struct smb_request *req,
6108 const char *pdata, int total_data,
6109 struct smb_filename *smb_fname_new)
6111 char *oldname = NULL;
6112 struct smb_filename *smb_fname_old = NULL;
6113 TALLOC_CTX *ctx = talloc_tos();
6114 NTSTATUS status = NT_STATUS_OK;
6116 /* Set a hard link. */
6117 if (total_data == 0) {
6118 return NT_STATUS_INVALID_PARAMETER;
6121 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6122 total_data, STR_TERMINATE, &status);
6123 if (!NT_STATUS_IS_OK(status)) {
6127 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6128 smb_fname_str_dbg(smb_fname_new), oldname));
6130 status = filename_convert(ctx,
6132 req->flags2 & FLAGS2_DFS_PATHNAMES,
6137 if (!NT_STATUS_IS_OK(status)) {
6141 return hardlink_internals(ctx, conn, req, false,
6142 smb_fname_old, smb_fname_new);
6145 /****************************************************************************
6146 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6147 ****************************************************************************/
6149 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6150 struct smb_request *req,
6154 struct smb_filename *smb_fname_src)
6158 char *newname = NULL;
6159 struct smb_filename *smb_fname_dst = NULL;
6160 NTSTATUS status = NT_STATUS_OK;
6161 TALLOC_CTX *ctx = talloc_tos();
6164 return NT_STATUS_INVALID_HANDLE;
6167 if (total_data < 20) {
6168 return NT_STATUS_INVALID_PARAMETER;
6171 overwrite = (CVAL(pdata,0) ? True : False);
6172 len = IVAL(pdata,16);
6174 if (len > (total_data - 20) || (len == 0)) {
6175 return NT_STATUS_INVALID_PARAMETER;
6178 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6179 &pdata[20], len, STR_TERMINATE,
6181 if (!NT_STATUS_IS_OK(status)) {
6185 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6188 status = filename_convert(ctx,
6190 req->flags2 & FLAGS2_DFS_PATHNAMES,
6195 if (!NT_STATUS_IS_OK(status)) {
6199 if (fsp->base_fsp) {
6200 /* newname must be a stream name. */
6201 if (newname[0] != ':') {
6202 return NT_STATUS_NOT_SUPPORTED;
6205 /* Create an smb_fname to call rename_internals_fsp() with. */
6206 smb_fname_dst = synthetic_smb_fname(
6207 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6209 if (smb_fname_dst == NULL) {
6210 status = NT_STATUS_NO_MEMORY;
6215 * Set the original last component, since
6216 * rename_internals_fsp() requires it.
6218 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6220 if (smb_fname_dst->original_lcomp == NULL) {
6221 status = NT_STATUS_NO_MEMORY;
6227 DEBUG(10,("smb2_file_rename_information: "
6228 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6229 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6230 smb_fname_str_dbg(smb_fname_dst)));
6231 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6232 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6236 TALLOC_FREE(smb_fname_dst);
6240 static NTSTATUS smb_file_link_information(connection_struct *conn,
6241 struct smb_request *req,
6245 struct smb_filename *smb_fname_src)
6249 char *newname = NULL;
6250 struct smb_filename *smb_fname_dst = NULL;
6251 NTSTATUS status = NT_STATUS_OK;
6252 TALLOC_CTX *ctx = talloc_tos();
6255 return NT_STATUS_INVALID_HANDLE;
6258 if (total_data < 20) {
6259 return NT_STATUS_INVALID_PARAMETER;
6262 overwrite = (CVAL(pdata,0) ? true : false);
6263 len = IVAL(pdata,16);
6265 if (len > (total_data - 20) || (len == 0)) {
6266 return NT_STATUS_INVALID_PARAMETER;
6269 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6270 &pdata[20], len, STR_TERMINATE,
6272 if (!NT_STATUS_IS_OK(status)) {
6276 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6279 status = filename_convert(ctx,
6281 req->flags2 & FLAGS2_DFS_PATHNAMES,
6286 if (!NT_STATUS_IS_OK(status)) {
6290 if (fsp->base_fsp) {
6291 /* No stream names. */
6292 return NT_STATUS_NOT_SUPPORTED;
6295 DEBUG(10,("smb_file_link_information: "
6296 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6297 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6298 smb_fname_str_dbg(smb_fname_dst)));
6299 status = hardlink_internals(ctx,
6306 TALLOC_FREE(smb_fname_dst);
6310 /****************************************************************************
6311 Deal with SMB_FILE_RENAME_INFORMATION.
6312 ****************************************************************************/
6314 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6315 struct smb_request *req,
6319 struct smb_filename *smb_fname_src)
6324 char *newname = NULL;
6325 struct smb_filename *smb_fname_dst = NULL;
6326 bool dest_has_wcard = False;
6327 NTSTATUS status = NT_STATUS_OK;
6329 TALLOC_CTX *ctx = talloc_tos();
6331 if (total_data < 13) {
6332 return NT_STATUS_INVALID_PARAMETER;
6335 overwrite = (CVAL(pdata,0) ? True : False);
6336 root_fid = IVAL(pdata,4);
6337 len = IVAL(pdata,8);
6339 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6340 return NT_STATUS_INVALID_PARAMETER;
6343 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6346 if (!NT_STATUS_IS_OK(status)) {
6350 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6353 status = resolve_dfspath_wcard(ctx, conn,
6354 req->flags2 & FLAGS2_DFS_PATHNAMES,
6357 !conn->sconn->using_smb2,
6360 if (!NT_STATUS_IS_OK(status)) {
6364 /* Check the new name has no '/' characters. */
6365 if (strchr_m(newname, '/')) {
6366 return NT_STATUS_NOT_SUPPORTED;
6369 if (fsp && fsp->base_fsp) {
6370 /* newname must be a stream name. */
6371 if (newname[0] != ':') {
6372 return NT_STATUS_NOT_SUPPORTED;
6375 /* Create an smb_fname to call rename_internals_fsp() with. */
6376 smb_fname_dst = synthetic_smb_fname(
6377 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6379 if (smb_fname_dst == NULL) {
6380 status = NT_STATUS_NO_MEMORY;
6385 * Set the original last component, since
6386 * rename_internals_fsp() requires it.
6388 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6390 if (smb_fname_dst->original_lcomp == NULL) {
6391 status = NT_STATUS_NO_MEMORY;
6397 * Build up an smb_fname_dst based on the filename passed in.
6398 * We basically just strip off the last component, and put on
6399 * the newname instead.
6401 char *base_name = NULL;
6403 /* newname must *not* be a stream name. */
6404 if (newname[0] == ':') {
6405 return NT_STATUS_NOT_SUPPORTED;
6409 * Strip off the last component (filename) of the path passed
6412 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6414 return NT_STATUS_NO_MEMORY;
6416 p = strrchr_m(base_name, '/');
6420 base_name = talloc_strdup(ctx, "");
6422 return NT_STATUS_NO_MEMORY;
6425 /* Append the new name. */
6426 base_name = talloc_asprintf_append(base_name,
6430 return NT_STATUS_NO_MEMORY;
6433 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6436 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6439 /* If an error we expect this to be
6440 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6442 if (!NT_STATUS_IS_OK(status)) {
6443 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6447 /* Create an smb_fname to call rename_internals_fsp() */
6448 smb_fname_dst = synthetic_smb_fname(
6449 ctx, base_name, NULL, NULL);
6450 if (smb_fname_dst == NULL) {
6451 status = NT_STATUS_NO_MEMORY;
6458 DEBUG(10,("smb_file_rename_information: "
6459 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6460 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6461 smb_fname_str_dbg(smb_fname_dst)));
6462 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6465 DEBUG(10,("smb_file_rename_information: "
6466 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6467 smb_fname_str_dbg(smb_fname_src),
6468 smb_fname_str_dbg(smb_fname_dst)));
6469 status = rename_internals(ctx, conn, req, smb_fname_src,
6470 smb_fname_dst, 0, overwrite, false,
6472 FILE_WRITE_ATTRIBUTES);
6475 TALLOC_FREE(smb_fname_dst);
6479 /****************************************************************************
6480 Deal with SMB_SET_POSIX_ACL.
6481 ****************************************************************************/
6483 #if defined(HAVE_POSIX_ACLS)
6484 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6488 const struct smb_filename *smb_fname)
6490 uint16 posix_acl_version;
6491 uint16 num_file_acls;
6492 uint16 num_def_acls;
6493 bool valid_file_acls = True;
6494 bool valid_def_acls = True;
6496 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6497 return NT_STATUS_INVALID_PARAMETER;
6499 posix_acl_version = SVAL(pdata,0);
6500 num_file_acls = SVAL(pdata,2);
6501 num_def_acls = SVAL(pdata,4);
6503 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6504 valid_file_acls = False;
6508 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6509 valid_def_acls = False;
6513 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6514 return NT_STATUS_INVALID_PARAMETER;
6517 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6518 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6519 return NT_STATUS_INVALID_PARAMETER;
6522 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6523 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6524 (unsigned int)num_file_acls,
6525 (unsigned int)num_def_acls));
6527 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6528 smb_fname->base_name, num_file_acls,
6529 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6530 return map_nt_error_from_unix(errno);
6533 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6534 smb_fname->base_name, &smb_fname->st, num_def_acls,
6535 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6536 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6537 return map_nt_error_from_unix(errno);
6539 return NT_STATUS_OK;
6543 /****************************************************************************
6544 Deal with SMB_SET_POSIX_LOCK.
6545 ****************************************************************************/
6547 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6548 struct smb_request *req,
6556 bool blocking_lock = False;
6557 enum brl_type lock_type;
6559 NTSTATUS status = NT_STATUS_OK;
6561 if (fsp == NULL || fsp->fh->fd == -1) {
6562 return NT_STATUS_INVALID_HANDLE;
6565 if (total_data != POSIX_LOCK_DATA_SIZE) {
6566 return NT_STATUS_INVALID_PARAMETER;
6569 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6570 case POSIX_LOCK_TYPE_READ:
6571 lock_type = READ_LOCK;
6573 case POSIX_LOCK_TYPE_WRITE:
6574 /* Return the right POSIX-mappable error code for files opened read-only. */
6575 if (!fsp->can_write) {
6576 return NT_STATUS_INVALID_HANDLE;
6578 lock_type = WRITE_LOCK;
6580 case POSIX_LOCK_TYPE_UNLOCK:
6581 lock_type = UNLOCK_LOCK;
6584 return NT_STATUS_INVALID_PARAMETER;
6587 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6588 blocking_lock = False;
6589 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6590 blocking_lock = True;
6592 return NT_STATUS_INVALID_PARAMETER;
6595 if (!lp_blocking_locks(SNUM(conn))) {
6596 blocking_lock = False;
6599 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6600 #if defined(HAVE_LONGLONG)
6601 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6602 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6603 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6604 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6605 #else /* HAVE_LONGLONG */
6606 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6607 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6608 #endif /* HAVE_LONGLONG */
6610 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6611 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6613 (unsigned int)lock_type,
6614 (unsigned long long)smblctx,
6618 if (lock_type == UNLOCK_LOCK) {
6619 status = do_unlock(req->sconn->msg_ctx,
6626 uint64_t block_smblctx;
6628 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6640 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6642 * A blocking lock was requested. Package up
6643 * this smb into a queued request and push it
6644 * onto the blocking lock queue.
6646 if(push_blocking_lock_request(br_lck,
6649 -1, /* infinite timeout. */
6657 TALLOC_FREE(br_lck);
6661 TALLOC_FREE(br_lck);
6667 /****************************************************************************
6668 Deal with SMB_SET_FILE_BASIC_INFO.
6669 ****************************************************************************/
6671 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6675 const struct smb_filename *smb_fname)
6677 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6678 struct smb_file_time ft;
6680 NTSTATUS status = NT_STATUS_OK;
6684 if (total_data < 36) {
6685 return NT_STATUS_INVALID_PARAMETER;
6688 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6689 if (!NT_STATUS_IS_OK(status)) {
6693 /* Set the attributes */
6694 dosmode = IVAL(pdata,32);
6695 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6696 if (!NT_STATUS_IS_OK(status)) {
6701 ft.create_time = interpret_long_date(pdata);
6704 ft.atime = interpret_long_date(pdata+8);
6707 ft.mtime = interpret_long_date(pdata+16);
6710 ft.ctime = interpret_long_date(pdata+24);
6712 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6713 smb_fname_str_dbg(smb_fname)));
6715 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6719 /****************************************************************************
6720 Deal with SMB_INFO_STANDARD.
6721 ****************************************************************************/
6723 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6727 const struct smb_filename *smb_fname)
6730 struct smb_file_time ft;
6734 if (total_data < 12) {
6735 return NT_STATUS_INVALID_PARAMETER;
6739 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6741 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6743 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6745 DEBUG(10,("smb_set_info_standard: file %s\n",
6746 smb_fname_str_dbg(smb_fname)));
6748 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6749 if (!NT_STATUS_IS_OK(status)) {
6753 return smb_set_file_time(conn,
6760 /****************************************************************************
6761 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6762 ****************************************************************************/
6764 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6765 struct smb_request *req,
6769 struct smb_filename *smb_fname)
6771 uint64_t allocation_size = 0;
6772 NTSTATUS status = NT_STATUS_OK;
6773 files_struct *new_fsp = NULL;
6775 if (!VALID_STAT(smb_fname->st)) {
6776 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6779 if (total_data < 8) {
6780 return NT_STATUS_INVALID_PARAMETER;
6783 allocation_size = (uint64_t)IVAL(pdata,0);
6784 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6785 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6786 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6787 (double)allocation_size));
6789 if (allocation_size) {
6790 allocation_size = smb_roundup(conn, allocation_size);
6793 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6794 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6795 (double)allocation_size));
6797 if (fsp && fsp->fh->fd != -1) {
6798 /* Open file handle. */
6799 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6800 return NT_STATUS_ACCESS_DENIED;
6803 /* Only change if needed. */
6804 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6805 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6806 return map_nt_error_from_unix(errno);
6809 /* But always update the time. */
6811 * This is equivalent to a write. Ensure it's seen immediately
6812 * if there are no pending writes.
6814 trigger_write_time_update_immediate(fsp);
6815 return NT_STATUS_OK;
6818 /* Pathname or stat or directory file. */
6819 status = SMB_VFS_CREATE_FILE(
6822 0, /* root_dir_fid */
6823 smb_fname, /* fname */
6824 FILE_WRITE_DATA, /* access_mask */
6825 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6827 FILE_OPEN, /* create_disposition*/
6828 0, /* create_options */
6829 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6830 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6831 0, /* allocation_size */
6832 0, /* private_flags */
6835 &new_fsp, /* result */
6838 if (!NT_STATUS_IS_OK(status)) {
6839 /* NB. We check for open_was_deferred in the caller. */
6843 /* Only change if needed. */
6844 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6845 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6846 status = map_nt_error_from_unix(errno);
6847 close_file(req, new_fsp, NORMAL_CLOSE);
6852 /* Changing the allocation size should set the last mod time. */
6854 * This is equivalent to a write. Ensure it's seen immediately
6855 * if there are no pending writes.
6857 trigger_write_time_update_immediate(new_fsp);
6859 close_file(req, new_fsp, NORMAL_CLOSE);
6860 return NT_STATUS_OK;
6863 /****************************************************************************
6864 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6865 ****************************************************************************/
6867 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6868 struct smb_request *req,
6872 const struct smb_filename *smb_fname,
6873 bool fail_after_createfile)
6877 if (total_data < 8) {
6878 return NT_STATUS_INVALID_PARAMETER;
6881 size = IVAL(pdata,0);
6882 size |= (((off_t)IVAL(pdata,4)) << 32);
6883 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6884 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6887 return smb_set_file_size(conn, req,
6892 fail_after_createfile);
6895 /****************************************************************************
6896 Allow a UNIX info mknod.
6897 ****************************************************************************/
6899 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6902 const struct smb_filename *smb_fname)
6904 uint32 file_type = IVAL(pdata,56);
6905 #if defined(HAVE_MAKEDEV)
6906 uint32 dev_major = IVAL(pdata,60);
6907 uint32 dev_minor = IVAL(pdata,68);
6909 SMB_DEV_T dev = (SMB_DEV_T)0;
6910 uint32 raw_unixmode = IVAL(pdata,84);
6914 if (total_data < 100) {
6915 return NT_STATUS_INVALID_PARAMETER;
6918 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6919 PERM_NEW_FILE, &unixmode);
6920 if (!NT_STATUS_IS_OK(status)) {
6924 #if defined(HAVE_MAKEDEV)
6925 dev = makedev(dev_major, dev_minor);
6928 switch (file_type) {
6929 #if defined(S_IFIFO)
6930 case UNIX_TYPE_FIFO:
6931 unixmode |= S_IFIFO;
6934 #if defined(S_IFSOCK)
6935 case UNIX_TYPE_SOCKET:
6936 unixmode |= S_IFSOCK;
6939 #if defined(S_IFCHR)
6940 case UNIX_TYPE_CHARDEV:
6941 unixmode |= S_IFCHR;
6944 #if defined(S_IFBLK)
6945 case UNIX_TYPE_BLKDEV:
6946 unixmode |= S_IFBLK;
6950 return NT_STATUS_INVALID_PARAMETER;
6953 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6954 "%.0f mode 0%o for file %s\n", (double)dev,
6955 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6957 /* Ok - do the mknod. */
6958 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6959 return map_nt_error_from_unix(errno);
6962 /* If any of the other "set" calls fail we
6963 * don't want to end up with a half-constructed mknod.
6966 if (lp_inherit_perms(SNUM(conn))) {
6968 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6970 return NT_STATUS_NO_MEMORY;
6972 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6974 TALLOC_FREE(parent);
6977 return NT_STATUS_OK;
6980 /****************************************************************************
6981 Deal with SMB_SET_FILE_UNIX_BASIC.
6982 ****************************************************************************/
6984 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6985 struct smb_request *req,
6989 const struct smb_filename *smb_fname)
6991 struct smb_file_time ft;
6992 uint32 raw_unixmode;
6995 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6996 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6997 NTSTATUS status = NT_STATUS_OK;
6998 bool delete_on_fail = False;
6999 enum perm_type ptype;
7000 files_struct *all_fsps = NULL;
7001 bool modify_mtime = true;
7003 struct smb_filename *smb_fname_tmp = NULL;
7004 SMB_STRUCT_STAT sbuf;
7008 if (total_data < 100) {
7009 return NT_STATUS_INVALID_PARAMETER;
7012 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7013 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7014 size=IVAL(pdata,0); /* first 8 Bytes are size */
7015 size |= (((off_t)IVAL(pdata,4)) << 32);
7018 ft.atime = interpret_long_date(pdata+24); /* access_time */
7019 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7020 set_owner = (uid_t)IVAL(pdata,40);
7021 set_grp = (gid_t)IVAL(pdata,48);
7022 raw_unixmode = IVAL(pdata,84);
7024 if (VALID_STAT(smb_fname->st)) {
7025 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7026 ptype = PERM_EXISTING_DIR;
7028 ptype = PERM_EXISTING_FILE;
7031 ptype = PERM_NEW_FILE;
7034 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7036 if (!NT_STATUS_IS_OK(status)) {
7040 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7041 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7042 smb_fname_str_dbg(smb_fname), (double)size,
7043 (unsigned int)set_owner, (unsigned int)set_grp,
7044 (int)raw_unixmode));
7046 sbuf = smb_fname->st;
7048 if (!VALID_STAT(sbuf)) {
7050 * The only valid use of this is to create character and block
7051 * devices, and named pipes. This is deprecated (IMHO) and
7052 * a new info level should be used for mknod. JRA.
7055 status = smb_unix_mknod(conn,
7059 if (!NT_STATUS_IS_OK(status)) {
7063 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7064 if (smb_fname_tmp == NULL) {
7065 return NT_STATUS_NO_MEMORY;
7068 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7069 status = map_nt_error_from_unix(errno);
7070 TALLOC_FREE(smb_fname_tmp);
7071 SMB_VFS_UNLINK(conn, smb_fname);
7075 sbuf = smb_fname_tmp->st;
7076 smb_fname = smb_fname_tmp;
7078 /* Ensure we don't try and change anything else. */
7079 raw_unixmode = SMB_MODE_NO_CHANGE;
7080 size = get_file_size_stat(&sbuf);
7081 ft.atime = sbuf.st_ex_atime;
7082 ft.mtime = sbuf.st_ex_mtime;
7084 * We continue here as we might want to change the
7087 delete_on_fail = True;
7091 /* Horrible backwards compatibility hack as an old server bug
7092 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7096 size = get_file_size_stat(&sbuf);
7101 * Deal with the UNIX specific mode set.
7104 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7105 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7106 "setting mode 0%o for file %s\n",
7107 (unsigned int)unixmode,
7108 smb_fname_str_dbg(smb_fname)));
7109 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7110 return map_nt_error_from_unix(errno);
7115 * Deal with the UNIX specific uid set.
7118 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7119 (sbuf.st_ex_uid != set_owner)) {
7122 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7123 "changing owner %u for path %s\n",
7124 (unsigned int)set_owner,
7125 smb_fname_str_dbg(smb_fname)));
7127 if (S_ISLNK(sbuf.st_ex_mode)) {
7128 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7129 set_owner, (gid_t)-1);
7131 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7132 set_owner, (gid_t)-1);
7136 status = map_nt_error_from_unix(errno);
7137 if (delete_on_fail) {
7138 SMB_VFS_UNLINK(conn, smb_fname);
7145 * Deal with the UNIX specific gid set.
7148 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7149 (sbuf.st_ex_gid != set_grp)) {
7150 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7151 "changing group %u for file %s\n",
7152 (unsigned int)set_owner,
7153 smb_fname_str_dbg(smb_fname)));
7154 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7156 status = map_nt_error_from_unix(errno);
7157 if (delete_on_fail) {
7158 SMB_VFS_UNLINK(conn, smb_fname);
7164 /* Deal with any size changes. */
7166 status = smb_set_file_size(conn, req,
7172 if (!NT_STATUS_IS_OK(status)) {
7176 /* Deal with any time changes. */
7177 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7178 /* No change, don't cancel anything. */
7182 id = vfs_file_id_from_sbuf(conn, &sbuf);
7183 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7184 all_fsps = file_find_di_next(all_fsps)) {
7186 * We're setting the time explicitly for UNIX.
7187 * Cancel any pending changes over all handles.
7189 all_fsps->update_write_time_on_close = false;
7190 TALLOC_FREE(all_fsps->update_write_time_event);
7194 * Override the "setting_write_time"
7195 * parameter here as it almost does what
7196 * we need. Just remember if we modified
7197 * mtime and send the notify ourselves.
7199 if (null_timespec(ft.mtime)) {
7200 modify_mtime = false;
7203 status = smb_set_file_time(conn,
7209 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7210 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7215 /****************************************************************************
7216 Deal with SMB_SET_FILE_UNIX_INFO2.
7217 ****************************************************************************/
7219 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7220 struct smb_request *req,
7224 const struct smb_filename *smb_fname)
7230 if (total_data < 116) {
7231 return NT_STATUS_INVALID_PARAMETER;
7234 /* Start by setting all the fields that are common between UNIX_BASIC
7237 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7239 if (!NT_STATUS_IS_OK(status)) {
7243 smb_fflags = IVAL(pdata, 108);
7244 smb_fmask = IVAL(pdata, 112);
7246 /* NB: We should only attempt to alter the file flags if the client
7247 * sends a non-zero mask.
7249 if (smb_fmask != 0) {
7250 int stat_fflags = 0;
7252 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7253 smb_fmask, &stat_fflags)) {
7254 /* Client asked to alter a flag we don't understand. */
7255 return NT_STATUS_INVALID_PARAMETER;
7258 if (fsp && fsp->fh->fd != -1) {
7259 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7260 return NT_STATUS_NOT_SUPPORTED;
7262 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7263 stat_fflags) != 0) {
7264 return map_nt_error_from_unix(errno);
7269 /* XXX: need to add support for changing the create_time here. You
7270 * can do this for paths on Darwin with setattrlist(2). The right way
7271 * to hook this up is probably by extending the VFS utimes interface.
7274 return NT_STATUS_OK;
7277 /****************************************************************************
7278 Create a directory with POSIX semantics.
7279 ****************************************************************************/
7281 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7282 struct smb_request *req,
7285 struct smb_filename *smb_fname,
7286 int *pdata_return_size)
7288 NTSTATUS status = NT_STATUS_OK;
7289 uint32 raw_unixmode = 0;
7290 uint32 mod_unixmode = 0;
7291 mode_t unixmode = (mode_t)0;
7292 files_struct *fsp = NULL;
7293 uint16 info_level_return = 0;
7295 char *pdata = *ppdata;
7297 if (total_data < 18) {
7298 return NT_STATUS_INVALID_PARAMETER;
7301 raw_unixmode = IVAL(pdata,8);
7302 /* Next 4 bytes are not yet defined. */
7304 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7305 PERM_NEW_DIR, &unixmode);
7306 if (!NT_STATUS_IS_OK(status)) {
7310 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7312 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7313 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7315 status = SMB_VFS_CREATE_FILE(
7318 0, /* root_dir_fid */
7319 smb_fname, /* fname */
7320 FILE_READ_ATTRIBUTES, /* access_mask */
7321 FILE_SHARE_NONE, /* share_access */
7322 FILE_CREATE, /* create_disposition*/
7323 FILE_DIRECTORY_FILE, /* create_options */
7324 mod_unixmode, /* file_attributes */
7325 0, /* oplock_request */
7326 0, /* allocation_size */
7327 0, /* private_flags */
7333 if (NT_STATUS_IS_OK(status)) {
7334 close_file(req, fsp, NORMAL_CLOSE);
7337 info_level_return = SVAL(pdata,16);
7339 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7340 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7341 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7342 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7344 *pdata_return_size = 12;
7347 /* Realloc the data size */
7348 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7349 if (*ppdata == NULL) {
7350 *pdata_return_size = 0;
7351 return NT_STATUS_NO_MEMORY;
7355 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7356 SSVAL(pdata,2,0); /* No fnum. */
7357 SIVAL(pdata,4,info); /* Was directory created. */
7359 switch (info_level_return) {
7360 case SMB_QUERY_FILE_UNIX_BASIC:
7361 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7362 SSVAL(pdata,10,0); /* Padding. */
7363 store_file_unix_basic(conn, pdata + 12, fsp,
7366 case SMB_QUERY_FILE_UNIX_INFO2:
7367 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7368 SSVAL(pdata,10,0); /* Padding. */
7369 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7373 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7374 SSVAL(pdata,10,0); /* Padding. */
7381 /****************************************************************************
7382 Open/Create a file with POSIX semantics.
7383 ****************************************************************************/
7385 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7386 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7388 static NTSTATUS smb_posix_open(connection_struct *conn,
7389 struct smb_request *req,
7392 struct smb_filename *smb_fname,
7393 int *pdata_return_size)
7395 bool extended_oplock_granted = False;
7396 char *pdata = *ppdata;
7398 uint32 wire_open_mode = 0;
7399 uint32 raw_unixmode = 0;
7400 uint32 mod_unixmode = 0;
7401 uint32 create_disp = 0;
7402 uint32 access_mask = 0;
7403 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7404 NTSTATUS status = NT_STATUS_OK;
7405 mode_t unixmode = (mode_t)0;
7406 files_struct *fsp = NULL;
7407 int oplock_request = 0;
7409 uint16 info_level_return = 0;
7411 if (total_data < 18) {
7412 return NT_STATUS_INVALID_PARAMETER;
7415 flags = IVAL(pdata,0);
7416 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7417 if (oplock_request) {
7418 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7421 wire_open_mode = IVAL(pdata,4);
7423 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7424 return smb_posix_mkdir(conn, req,
7431 switch (wire_open_mode & SMB_ACCMODE) {
7433 access_mask = SMB_O_RDONLY_MAPPING;
7436 access_mask = SMB_O_WRONLY_MAPPING;
7439 access_mask = (SMB_O_RDONLY_MAPPING|
7440 SMB_O_WRONLY_MAPPING);
7443 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7444 (unsigned int)wire_open_mode ));
7445 return NT_STATUS_INVALID_PARAMETER;
7448 wire_open_mode &= ~SMB_ACCMODE;
7450 /* First take care of O_CREAT|O_EXCL interactions. */
7451 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7452 case (SMB_O_CREAT | SMB_O_EXCL):
7453 /* File exists fail. File not exist create. */
7454 create_disp = FILE_CREATE;
7457 /* File exists open. File not exist create. */
7458 create_disp = FILE_OPEN_IF;
7461 /* O_EXCL on its own without O_CREAT is undefined.
7462 We deliberately ignore it as some versions of
7463 Linux CIFSFS can send a bare O_EXCL on the
7464 wire which other filesystems in the kernel
7465 ignore. See bug 9519 for details. */
7470 /* File exists open. File not exist fail. */
7471 create_disp = FILE_OPEN;
7474 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7475 (unsigned int)wire_open_mode ));
7476 return NT_STATUS_INVALID_PARAMETER;
7479 /* Next factor in the effects of O_TRUNC. */
7480 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7482 if (wire_open_mode & SMB_O_TRUNC) {
7483 switch (create_disp) {
7485 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7486 /* Leave create_disp alone as
7487 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7489 /* File exists fail. File not exist create. */
7492 /* SMB_O_CREAT | SMB_O_TRUNC */
7493 /* File exists overwrite. File not exist create. */
7494 create_disp = FILE_OVERWRITE_IF;
7498 /* File exists overwrite. File not exist fail. */
7499 create_disp = FILE_OVERWRITE;
7502 /* Cannot get here. */
7503 smb_panic("smb_posix_open: logic error");
7504 return NT_STATUS_INVALID_PARAMETER;
7508 raw_unixmode = IVAL(pdata,8);
7509 /* Next 4 bytes are not yet defined. */
7511 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7512 (VALID_STAT(smb_fname->st) ?
7513 PERM_EXISTING_FILE : PERM_NEW_FILE),
7516 if (!NT_STATUS_IS_OK(status)) {
7520 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7522 if (wire_open_mode & SMB_O_SYNC) {
7523 create_options |= FILE_WRITE_THROUGH;
7525 if (wire_open_mode & SMB_O_APPEND) {
7526 access_mask |= FILE_APPEND_DATA;
7528 if (wire_open_mode & SMB_O_DIRECT) {
7529 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7532 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7533 VALID_STAT_OF_DIR(smb_fname->st)) {
7534 if (access_mask != SMB_O_RDONLY_MAPPING) {
7535 return NT_STATUS_FILE_IS_A_DIRECTORY;
7537 create_options &= ~FILE_NON_DIRECTORY_FILE;
7538 create_options |= FILE_DIRECTORY_FILE;
7541 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7542 smb_fname_str_dbg(smb_fname),
7543 (unsigned int)wire_open_mode,
7544 (unsigned int)unixmode ));
7546 status = SMB_VFS_CREATE_FILE(
7549 0, /* root_dir_fid */
7550 smb_fname, /* fname */
7551 access_mask, /* access_mask */
7552 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7554 create_disp, /* create_disposition*/
7555 create_options, /* create_options */
7556 mod_unixmode, /* file_attributes */
7557 oplock_request, /* oplock_request */
7558 0, /* allocation_size */
7559 0, /* private_flags */
7565 if (!NT_STATUS_IS_OK(status)) {
7569 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7570 extended_oplock_granted = True;
7573 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7574 extended_oplock_granted = True;
7577 info_level_return = SVAL(pdata,16);
7579 /* Allocate the correct return size. */
7581 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7582 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7583 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7584 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7586 *pdata_return_size = 12;
7589 /* Realloc the data size */
7590 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7591 if (*ppdata == NULL) {
7592 close_file(req, fsp, ERROR_CLOSE);
7593 *pdata_return_size = 0;
7594 return NT_STATUS_NO_MEMORY;
7598 if (extended_oplock_granted) {
7599 if (flags & REQUEST_BATCH_OPLOCK) {
7600 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7602 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7604 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7605 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7607 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7610 SSVAL(pdata,2,fsp->fnum);
7611 SIVAL(pdata,4,info); /* Was file created etc. */
7613 switch (info_level_return) {
7614 case SMB_QUERY_FILE_UNIX_BASIC:
7615 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7616 SSVAL(pdata,10,0); /* padding. */
7617 store_file_unix_basic(conn, pdata + 12, fsp,
7620 case SMB_QUERY_FILE_UNIX_INFO2:
7621 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7622 SSVAL(pdata,10,0); /* padding. */
7623 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7627 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7628 SSVAL(pdata,10,0); /* padding. */
7631 return NT_STATUS_OK;
7634 /****************************************************************************
7635 Delete a file with POSIX semantics.
7636 ****************************************************************************/
7638 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7639 struct smb_request *req,
7642 struct smb_filename *smb_fname)
7644 NTSTATUS status = NT_STATUS_OK;
7645 files_struct *fsp = NULL;
7649 int create_options = 0;
7651 struct share_mode_lock *lck = NULL;
7653 if (total_data < 2) {
7654 return NT_STATUS_INVALID_PARAMETER;
7657 flags = SVAL(pdata,0);
7659 if (!VALID_STAT(smb_fname->st)) {
7660 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7663 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7664 !VALID_STAT_OF_DIR(smb_fname->st)) {
7665 return NT_STATUS_NOT_A_DIRECTORY;
7668 DEBUG(10,("smb_posix_unlink: %s %s\n",
7669 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7670 smb_fname_str_dbg(smb_fname)));
7672 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7673 create_options |= FILE_DIRECTORY_FILE;
7676 status = SMB_VFS_CREATE_FILE(
7679 0, /* root_dir_fid */
7680 smb_fname, /* fname */
7681 DELETE_ACCESS, /* access_mask */
7682 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7684 FILE_OPEN, /* create_disposition*/
7685 create_options, /* create_options */
7686 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7687 0, /* oplock_request */
7688 0, /* allocation_size */
7689 0, /* private_flags */
7695 if (!NT_STATUS_IS_OK(status)) {
7700 * Don't lie to client. If we can't really delete due to
7701 * non-POSIX opens return SHARING_VIOLATION.
7704 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7706 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7707 "lock for file %s\n", fsp_str_dbg(fsp)));
7708 close_file(req, fsp, NORMAL_CLOSE);
7709 return NT_STATUS_INVALID_PARAMETER;
7713 * See if others still have the file open. If this is the case, then
7714 * don't delete. If all opens are POSIX delete we can set the delete
7715 * on close disposition.
7717 for (i=0; i<lck->data->num_share_modes; i++) {
7718 struct share_mode_entry *e = &lck->data->share_modes[i];
7719 if (is_valid_share_mode_entry(e)) {
7720 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7723 if (share_mode_stale_pid(lck->data, i)) {
7726 /* Fail with sharing violation. */
7728 close_file(req, fsp, NORMAL_CLOSE);
7729 return NT_STATUS_SHARING_VIOLATION;
7734 * Set the delete on close.
7736 status = smb_set_file_disposition_info(conn,
7744 if (!NT_STATUS_IS_OK(status)) {
7745 close_file(req, fsp, NORMAL_CLOSE);
7748 return close_file(req, fsp, NORMAL_CLOSE);
7751 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7752 struct smb_request *req,
7753 TALLOC_CTX *mem_ctx,
7754 uint16_t info_level,
7756 struct smb_filename *smb_fname,
7757 char **ppdata, int total_data,
7760 char *pdata = *ppdata;
7761 NTSTATUS status = NT_STATUS_OK;
7762 int data_return_size = 0;
7766 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7767 return NT_STATUS_INVALID_LEVEL;
7770 if (!CAN_WRITE(conn)) {
7771 /* Allow POSIX opens. The open path will deny
7772 * any non-readonly opens. */
7773 if (info_level != SMB_POSIX_PATH_OPEN) {
7774 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7778 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7779 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7781 info_level, total_data));
7783 switch (info_level) {
7785 case SMB_INFO_STANDARD:
7787 status = smb_set_info_standard(conn,
7795 case SMB_INFO_SET_EA:
7797 status = smb_info_set_ea(conn,
7805 case SMB_SET_FILE_BASIC_INFO:
7806 case SMB_FILE_BASIC_INFORMATION:
7808 status = smb_set_file_basic_info(conn,
7816 case SMB_FILE_ALLOCATION_INFORMATION:
7817 case SMB_SET_FILE_ALLOCATION_INFO:
7819 status = smb_set_file_allocation_info(conn, req,
7827 case SMB_FILE_END_OF_FILE_INFORMATION:
7828 case SMB_SET_FILE_END_OF_FILE_INFO:
7831 * XP/Win7 both fail after the createfile with
7832 * SMB_SET_FILE_END_OF_FILE_INFO but not
7833 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7834 * The level is known here, so pass it down
7838 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7840 status = smb_set_file_end_of_file_info(conn, req,
7849 case SMB_FILE_DISPOSITION_INFORMATION:
7850 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7853 /* JRA - We used to just ignore this on a path ?
7854 * Shouldn't this be invalid level on a pathname
7857 if (tran_call != TRANSACT2_SETFILEINFO) {
7858 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7861 status = smb_set_file_disposition_info(conn,
7869 case SMB_FILE_POSITION_INFORMATION:
7871 status = smb_file_position_information(conn,
7878 case SMB_FILE_FULL_EA_INFORMATION:
7880 status = smb_set_file_full_ea_info(conn,
7887 /* From tridge Samba4 :
7888 * MODE_INFORMATION in setfileinfo (I have no
7889 * idea what "mode information" on a file is - it takes a value of 0,
7890 * 2, 4 or 6. What could it be?).
7893 case SMB_FILE_MODE_INFORMATION:
7895 status = smb_file_mode_information(conn,
7902 * CIFS UNIX extensions.
7905 case SMB_SET_FILE_UNIX_BASIC:
7907 status = smb_set_file_unix_basic(conn, req,
7915 case SMB_SET_FILE_UNIX_INFO2:
7917 status = smb_set_file_unix_info2(conn, req,
7925 case SMB_SET_FILE_UNIX_LINK:
7928 /* We must have a pathname for this. */
7929 return NT_STATUS_INVALID_LEVEL;
7931 status = smb_set_file_unix_link(conn, req, pdata,
7932 total_data, smb_fname);
7936 case SMB_SET_FILE_UNIX_HLINK:
7939 /* We must have a pathname for this. */
7940 return NT_STATUS_INVALID_LEVEL;
7942 status = smb_set_file_unix_hlink(conn, req,
7948 case SMB_FILE_RENAME_INFORMATION:
7950 status = smb_file_rename_information(conn, req,
7956 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7958 /* SMB2 rename information. */
7959 status = smb2_file_rename_information(conn, req,
7965 case SMB_FILE_LINK_INFORMATION:
7967 status = smb_file_link_information(conn, req,
7973 #if defined(HAVE_POSIX_ACLS)
7974 case SMB_SET_POSIX_ACL:
7976 status = smb_set_posix_acl(conn,
7985 case SMB_SET_POSIX_LOCK:
7988 return NT_STATUS_INVALID_LEVEL;
7990 status = smb_set_posix_lock(conn, req,
7991 pdata, total_data, fsp);
7995 case SMB_POSIX_PATH_OPEN:
7998 /* We must have a pathname for this. */
7999 return NT_STATUS_INVALID_LEVEL;
8002 status = smb_posix_open(conn, req,
8010 case SMB_POSIX_PATH_UNLINK:
8013 /* We must have a pathname for this. */
8014 return NT_STATUS_INVALID_LEVEL;
8017 status = smb_posix_unlink(conn, req,
8025 return NT_STATUS_INVALID_LEVEL;
8028 if (!NT_STATUS_IS_OK(status)) {
8032 *ret_data_size = data_return_size;
8033 return NT_STATUS_OK;
8036 /****************************************************************************
8037 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8038 ****************************************************************************/
8040 static void call_trans2setfilepathinfo(connection_struct *conn,
8041 struct smb_request *req,
8042 unsigned int tran_call,
8043 char **pparams, int total_params,
8044 char **ppdata, int total_data,
8045 unsigned int max_data_bytes)
8047 char *params = *pparams;
8048 char *pdata = *ppdata;
8050 struct smb_filename *smb_fname = NULL;
8051 files_struct *fsp = NULL;
8052 NTSTATUS status = NT_STATUS_OK;
8053 int data_return_size = 0;
8056 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8060 if (tran_call == TRANSACT2_SETFILEINFO) {
8061 if (total_params < 4) {
8062 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8066 fsp = file_fsp(req, SVAL(params,0));
8067 /* Basic check for non-null fsp. */
8068 if (!check_fsp_open(conn, req, fsp)) {
8071 info_level = SVAL(params,2);
8073 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8074 if (smb_fname == NULL) {
8075 reply_nterror(req, NT_STATUS_NO_MEMORY);
8079 if(fsp->fh->fd == -1) {
8081 * This is actually a SETFILEINFO on a directory
8082 * handle (returned from an NT SMB). NT5.0 seems
8083 * to do this call. JRA.
8085 if (INFO_LEVEL_IS_UNIX(info_level)) {
8086 /* Always do lstat for UNIX calls. */
8087 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8088 DEBUG(3,("call_trans2setfilepathinfo: "
8089 "SMB_VFS_LSTAT of %s failed "
8091 smb_fname_str_dbg(smb_fname),
8093 reply_nterror(req, map_nt_error_from_unix(errno));
8097 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8098 DEBUG(3,("call_trans2setfilepathinfo: "
8099 "fileinfo of %s failed (%s)\n",
8100 smb_fname_str_dbg(smb_fname),
8102 reply_nterror(req, map_nt_error_from_unix(errno));
8106 } else if (fsp->print_file) {
8108 * Doing a DELETE_ON_CLOSE should cancel a print job.
8110 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8111 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8113 DEBUG(3,("call_trans2setfilepathinfo: "
8114 "Cancelling print job (%s)\n",
8118 send_trans2_replies(conn, req, params, 2,
8124 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8129 * Original code - this is an open file.
8131 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8132 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8133 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8135 reply_nterror(req, map_nt_error_from_unix(errno));
8141 uint32_t ucf_flags = 0;
8144 if (total_params < 7) {
8145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8149 info_level = SVAL(params,0);
8150 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8151 total_params - 6, STR_TERMINATE,
8153 if (!NT_STATUS_IS_OK(status)) {
8154 reply_nterror(req, status);
8158 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8159 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8160 info_level == SMB_FILE_RENAME_INFORMATION ||
8161 info_level == SMB_POSIX_PATH_UNLINK) {
8162 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8165 status = filename_convert(req, conn,
8166 req->flags2 & FLAGS2_DFS_PATHNAMES,
8171 if (!NT_STATUS_IS_OK(status)) {
8172 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8173 reply_botherror(req,
8174 NT_STATUS_PATH_NOT_COVERED,
8175 ERRSRV, ERRbadpath);
8178 reply_nterror(req, status);
8182 if (INFO_LEVEL_IS_UNIX(info_level)) {
8184 * For CIFS UNIX extensions the target name may not exist.
8187 /* Always do lstat for UNIX calls. */
8188 SMB_VFS_LSTAT(conn, smb_fname);
8190 } else if (!VALID_STAT(smb_fname->st) &&
8191 SMB_VFS_STAT(conn, smb_fname)) {
8192 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8194 smb_fname_str_dbg(smb_fname),
8196 reply_nterror(req, map_nt_error_from_unix(errno));
8201 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8202 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8204 info_level,total_data));
8206 /* Realloc the parameter size */
8207 *pparams = (char *)SMB_REALLOC(*pparams,2);
8208 if (*pparams == NULL) {
8209 reply_nterror(req, NT_STATUS_NO_MEMORY);
8216 status = smbd_do_setfilepathinfo(conn, req, req,
8222 if (!NT_STATUS_IS_OK(status)) {
8223 if (open_was_deferred(req->sconn, req->mid)) {
8224 /* We have re-scheduled this call. */
8227 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8228 /* We have re-scheduled this call. */
8231 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8232 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8233 ERRSRV, ERRbadpath);
8236 if (info_level == SMB_POSIX_PATH_OPEN) {
8237 reply_openerror(req, status);
8241 reply_nterror(req, status);
8245 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8251 /****************************************************************************
8252 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8253 ****************************************************************************/
8255 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8256 char **pparams, int total_params,
8257 char **ppdata, int total_data,
8258 unsigned int max_data_bytes)
8260 struct smb_filename *smb_dname = NULL;
8261 char *params = *pparams;
8262 char *pdata = *ppdata;
8263 char *directory = NULL;
8264 NTSTATUS status = NT_STATUS_OK;
8265 struct ea_list *ea_list = NULL;
8266 TALLOC_CTX *ctx = talloc_tos();
8268 if (!CAN_WRITE(conn)) {
8269 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8273 if (total_params < 5) {
8274 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8278 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8279 total_params - 4, STR_TERMINATE,
8281 if (!NT_STATUS_IS_OK(status)) {
8282 reply_nterror(req, status);
8286 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8288 status = filename_convert(ctx,
8290 req->flags2 & FLAGS2_DFS_PATHNAMES,
8296 if (!NT_STATUS_IS_OK(status)) {
8297 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8298 reply_botherror(req,
8299 NT_STATUS_PATH_NOT_COVERED,
8300 ERRSRV, ERRbadpath);
8303 reply_nterror(req, status);
8308 * OS/2 workplace shell seems to send SET_EA requests of "null"
8309 * length (4 bytes containing IVAL 4).
8310 * They seem to have no effect. Bug #3212. JRA.
8313 if (total_data && (total_data != 4)) {
8314 /* Any data in this call is an EA list. */
8315 if (total_data < 10) {
8316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8320 if (IVAL(pdata,0) > total_data) {
8321 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8322 IVAL(pdata,0), (unsigned int)total_data));
8323 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8327 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8334 if (!lp_ea_support(SNUM(conn))) {
8335 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8339 /* If total_data == 4 Windows doesn't care what values
8340 * are placed in that field, it just ignores them.
8341 * The System i QNTC IBM SMB client puts bad values here,
8342 * so ignore them. */
8344 status = create_directory(conn, req, smb_dname);
8346 if (!NT_STATUS_IS_OK(status)) {
8347 reply_nterror(req, status);
8351 /* Try and set any given EA. */
8353 status = set_ea(conn, NULL, smb_dname, ea_list);
8354 if (!NT_STATUS_IS_OK(status)) {
8355 reply_nterror(req, status);
8360 /* Realloc the parameter and data sizes */
8361 *pparams = (char *)SMB_REALLOC(*pparams,2);
8362 if(*pparams == NULL) {
8363 reply_nterror(req, NT_STATUS_NO_MEMORY);
8370 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8373 TALLOC_FREE(smb_dname);
8377 /****************************************************************************
8378 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8379 We don't actually do this - we just send a null response.
8380 ****************************************************************************/
8382 static void call_trans2findnotifyfirst(connection_struct *conn,
8383 struct smb_request *req,
8384 char **pparams, int total_params,
8385 char **ppdata, int total_data,
8386 unsigned int max_data_bytes)
8388 char *params = *pparams;
8391 if (total_params < 6) {
8392 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8396 info_level = SVAL(params,4);
8397 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8399 switch (info_level) {
8404 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8408 /* Realloc the parameter and data sizes */
8409 *pparams = (char *)SMB_REALLOC(*pparams,6);
8410 if (*pparams == NULL) {
8411 reply_nterror(req, NT_STATUS_NO_MEMORY);
8416 SSVAL(params,0,fnf_handle);
8417 SSVAL(params,2,0); /* No changes */
8418 SSVAL(params,4,0); /* No EA errors */
8425 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8430 /****************************************************************************
8431 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8432 changes). Currently this does nothing.
8433 ****************************************************************************/
8435 static void call_trans2findnotifynext(connection_struct *conn,
8436 struct smb_request *req,
8437 char **pparams, int total_params,
8438 char **ppdata, int total_data,
8439 unsigned int max_data_bytes)
8441 char *params = *pparams;
8443 DEBUG(3,("call_trans2findnotifynext\n"));
8445 /* Realloc the parameter and data sizes */
8446 *pparams = (char *)SMB_REALLOC(*pparams,4);
8447 if (*pparams == NULL) {
8448 reply_nterror(req, NT_STATUS_NO_MEMORY);
8453 SSVAL(params,0,0); /* No changes */
8454 SSVAL(params,2,0); /* No EA errors */
8456 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8461 /****************************************************************************
8462 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8463 ****************************************************************************/
8465 static void call_trans2getdfsreferral(connection_struct *conn,
8466 struct smb_request *req,
8467 char **pparams, int total_params,
8468 char **ppdata, int total_data,
8469 unsigned int max_data_bytes)
8471 char *params = *pparams;
8472 char *pathname = NULL;
8474 int max_referral_level;
8475 NTSTATUS status = NT_STATUS_OK;
8476 TALLOC_CTX *ctx = talloc_tos();
8478 DEBUG(10,("call_trans2getdfsreferral\n"));
8480 if (total_params < 3) {
8481 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8485 max_referral_level = SVAL(params,0);
8487 if(!lp_host_msdfs()) {
8488 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8492 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8493 total_params - 2, STR_TERMINATE);
8495 reply_nterror(req, NT_STATUS_NOT_FOUND);
8498 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8499 ppdata,&status)) < 0) {
8500 reply_nterror(req, status);
8504 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8505 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8506 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8511 #define LMCAT_SPL 0x53
8512 #define LMFUNC_GETJOBID 0x60
8514 /****************************************************************************
8515 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8516 ****************************************************************************/
8518 static void call_trans2ioctl(connection_struct *conn,
8519 struct smb_request *req,
8520 char **pparams, int total_params,
8521 char **ppdata, int total_data,
8522 unsigned int max_data_bytes)
8524 char *pdata = *ppdata;
8525 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8527 /* check for an invalid fid before proceeding */
8530 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8534 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8535 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8536 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8537 if (*ppdata == NULL) {
8538 reply_nterror(req, NT_STATUS_NO_MEMORY);
8543 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8544 CAN ACCEPT THIS IN UNICODE. JRA. */
8547 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8549 srvstr_push(pdata, req->flags2, pdata + 2,
8550 lp_netbios_name(), 15,
8551 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8552 srvstr_push(pdata, req->flags2, pdata+18,
8553 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8554 STR_ASCII|STR_TERMINATE); /* Service name */
8555 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8560 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8561 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8564 /****************************************************************************
8565 Reply to a SMBfindclose (stop trans2 directory search).
8566 ****************************************************************************/
8568 void reply_findclose(struct smb_request *req)
8571 struct smbd_server_connection *sconn = req->sconn;
8573 START_PROFILE(SMBfindclose);
8576 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8577 END_PROFILE(SMBfindclose);
8581 dptr_num = SVALS(req->vwv+0, 0);
8583 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8585 dptr_close(sconn, &dptr_num);
8587 reply_outbuf(req, 0, 0);
8589 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8591 END_PROFILE(SMBfindclose);
8595 /****************************************************************************
8596 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8597 ****************************************************************************/
8599 void reply_findnclose(struct smb_request *req)
8603 START_PROFILE(SMBfindnclose);
8606 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8607 END_PROFILE(SMBfindnclose);
8611 dptr_num = SVAL(req->vwv+0, 0);
8613 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8615 /* We never give out valid handles for a
8616 findnotifyfirst - so any dptr_num is ok here.
8619 reply_outbuf(req, 0, 0);
8621 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8623 END_PROFILE(SMBfindnclose);
8627 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8628 struct trans_state *state)
8630 if (get_Protocol() >= PROTOCOL_NT1) {
8631 req->flags2 |= 0x40; /* IS_LONG_NAME */
8632 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8635 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8636 if (state->call != TRANSACT2_QFSINFO &&
8637 state->call != TRANSACT2_SETFSINFO) {
8638 DEBUG(0,("handle_trans2: encryption required "
8640 (unsigned int)state->call));
8641 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8646 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8648 /* Now we must call the relevant TRANS2 function */
8649 switch(state->call) {
8650 case TRANSACT2_OPEN:
8652 START_PROFILE(Trans2_open);
8653 call_trans2open(conn, req,
8654 &state->param, state->total_param,
8655 &state->data, state->total_data,
8656 state->max_data_return);
8657 END_PROFILE(Trans2_open);
8661 case TRANSACT2_FINDFIRST:
8663 START_PROFILE(Trans2_findfirst);
8664 call_trans2findfirst(conn, req,
8665 &state->param, state->total_param,
8666 &state->data, state->total_data,
8667 state->max_data_return);
8668 END_PROFILE(Trans2_findfirst);
8672 case TRANSACT2_FINDNEXT:
8674 START_PROFILE(Trans2_findnext);
8675 call_trans2findnext(conn, req,
8676 &state->param, state->total_param,
8677 &state->data, state->total_data,
8678 state->max_data_return);
8679 END_PROFILE(Trans2_findnext);
8683 case TRANSACT2_QFSINFO:
8685 START_PROFILE(Trans2_qfsinfo);
8686 call_trans2qfsinfo(conn, req,
8687 &state->param, state->total_param,
8688 &state->data, state->total_data,
8689 state->max_data_return);
8690 END_PROFILE(Trans2_qfsinfo);
8694 case TRANSACT2_SETFSINFO:
8696 START_PROFILE(Trans2_setfsinfo);
8697 call_trans2setfsinfo(conn, req,
8698 &state->param, state->total_param,
8699 &state->data, state->total_data,
8700 state->max_data_return);
8701 END_PROFILE(Trans2_setfsinfo);
8705 case TRANSACT2_QPATHINFO:
8706 case TRANSACT2_QFILEINFO:
8708 START_PROFILE(Trans2_qpathinfo);
8709 call_trans2qfilepathinfo(conn, req, state->call,
8710 &state->param, state->total_param,
8711 &state->data, state->total_data,
8712 state->max_data_return);
8713 END_PROFILE(Trans2_qpathinfo);
8717 case TRANSACT2_SETPATHINFO:
8718 case TRANSACT2_SETFILEINFO:
8720 START_PROFILE(Trans2_setpathinfo);
8721 call_trans2setfilepathinfo(conn, req, state->call,
8722 &state->param, state->total_param,
8723 &state->data, state->total_data,
8724 state->max_data_return);
8725 END_PROFILE(Trans2_setpathinfo);
8729 case TRANSACT2_FINDNOTIFYFIRST:
8731 START_PROFILE(Trans2_findnotifyfirst);
8732 call_trans2findnotifyfirst(conn, req,
8733 &state->param, state->total_param,
8734 &state->data, state->total_data,
8735 state->max_data_return);
8736 END_PROFILE(Trans2_findnotifyfirst);
8740 case TRANSACT2_FINDNOTIFYNEXT:
8742 START_PROFILE(Trans2_findnotifynext);
8743 call_trans2findnotifynext(conn, req,
8744 &state->param, state->total_param,
8745 &state->data, state->total_data,
8746 state->max_data_return);
8747 END_PROFILE(Trans2_findnotifynext);
8751 case TRANSACT2_MKDIR:
8753 START_PROFILE(Trans2_mkdir);
8754 call_trans2mkdir(conn, req,
8755 &state->param, state->total_param,
8756 &state->data, state->total_data,
8757 state->max_data_return);
8758 END_PROFILE(Trans2_mkdir);
8762 case TRANSACT2_GET_DFS_REFERRAL:
8764 START_PROFILE(Trans2_get_dfs_referral);
8765 call_trans2getdfsreferral(conn, req,
8766 &state->param, state->total_param,
8767 &state->data, state->total_data,
8768 state->max_data_return);
8769 END_PROFILE(Trans2_get_dfs_referral);
8773 case TRANSACT2_IOCTL:
8775 START_PROFILE(Trans2_ioctl);
8776 call_trans2ioctl(conn, req,
8777 &state->param, state->total_param,
8778 &state->data, state->total_data,
8779 state->max_data_return);
8780 END_PROFILE(Trans2_ioctl);
8785 /* Error in request */
8786 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8787 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8791 /****************************************************************************
8792 Reply to a SMBtrans2.
8793 ****************************************************************************/
8795 void reply_trans2(struct smb_request *req)
8797 connection_struct *conn = req->conn;
8802 unsigned int tran_call;
8803 struct trans_state *state;
8806 START_PROFILE(SMBtrans2);
8808 if (req->wct < 14) {
8809 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8810 END_PROFILE(SMBtrans2);
8814 dsoff = SVAL(req->vwv+12, 0);
8815 dscnt = SVAL(req->vwv+11, 0);
8816 psoff = SVAL(req->vwv+10, 0);
8817 pscnt = SVAL(req->vwv+9, 0);
8818 tran_call = SVAL(req->vwv+14, 0);
8820 result = allow_new_trans(conn->pending_trans, req->mid);
8821 if (!NT_STATUS_IS_OK(result)) {
8822 DEBUG(2, ("Got invalid trans2 request: %s\n",
8823 nt_errstr(result)));
8824 reply_nterror(req, result);
8825 END_PROFILE(SMBtrans2);
8830 switch (tran_call) {
8831 /* List the allowed trans2 calls on IPC$ */
8832 case TRANSACT2_OPEN:
8833 case TRANSACT2_GET_DFS_REFERRAL:
8834 case TRANSACT2_QFILEINFO:
8835 case TRANSACT2_QFSINFO:
8836 case TRANSACT2_SETFSINFO:
8839 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8840 END_PROFILE(SMBtrans2);
8845 if ((state = talloc(conn, struct trans_state)) == NULL) {
8846 DEBUG(0, ("talloc failed\n"));
8847 reply_nterror(req, NT_STATUS_NO_MEMORY);
8848 END_PROFILE(SMBtrans2);
8852 state->cmd = SMBtrans2;
8854 state->mid = req->mid;
8855 state->vuid = req->vuid;
8856 state->setup_count = SVAL(req->vwv+13, 0);
8857 state->setup = NULL;
8858 state->total_param = SVAL(req->vwv+0, 0);
8859 state->param = NULL;
8860 state->total_data = SVAL(req->vwv+1, 0);
8862 state->max_param_return = SVAL(req->vwv+2, 0);
8863 state->max_data_return = SVAL(req->vwv+3, 0);
8864 state->max_setup_return = SVAL(req->vwv+4, 0);
8865 state->close_on_completion = BITSETW(req->vwv+5, 0);
8866 state->one_way = BITSETW(req->vwv+5, 1);
8868 state->call = tran_call;
8870 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8871 is so as a sanity check */
8872 if (state->setup_count != 1) {
8874 * Need to have rc=0 for ioctl to get job id for OS/2.
8875 * Network printing will fail if function is not successful.
8876 * Similar function in reply.c will be used if protocol
8877 * is LANMAN1.0 instead of LM1.2X002.
8878 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8879 * outbuf doesn't have to be set(only job id is used).
8881 if ( (state->setup_count == 4)
8882 && (tran_call == TRANSACT2_IOCTL)
8883 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8884 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8885 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8887 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8888 DEBUG(2,("Transaction is %d\n",tran_call));
8890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8891 END_PROFILE(SMBtrans2);
8896 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8899 if (state->total_data) {
8901 if (trans_oob(state->total_data, 0, dscnt)
8902 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8906 /* Can't use talloc here, the core routines do realloc on the
8907 * params and data. */
8908 state->data = (char *)SMB_MALLOC(state->total_data);
8909 if (state->data == NULL) {
8910 DEBUG(0,("reply_trans2: data malloc fail for %u "
8911 "bytes !\n", (unsigned int)state->total_data));
8913 reply_nterror(req, NT_STATUS_NO_MEMORY);
8914 END_PROFILE(SMBtrans2);
8918 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8921 if (state->total_param) {
8923 if (trans_oob(state->total_param, 0, pscnt)
8924 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8928 /* Can't use talloc here, the core routines do realloc on the
8929 * params and data. */
8930 state->param = (char *)SMB_MALLOC(state->total_param);
8931 if (state->param == NULL) {
8932 DEBUG(0,("reply_trans: param malloc fail for %u "
8933 "bytes !\n", (unsigned int)state->total_param));
8934 SAFE_FREE(state->data);
8936 reply_nterror(req, NT_STATUS_NO_MEMORY);
8937 END_PROFILE(SMBtrans2);
8941 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8944 state->received_data = dscnt;
8945 state->received_param = pscnt;
8947 if ((state->received_param == state->total_param) &&
8948 (state->received_data == state->total_data)) {
8950 handle_trans2(conn, req, state);
8952 SAFE_FREE(state->data);
8953 SAFE_FREE(state->param);
8955 END_PROFILE(SMBtrans2);
8959 DLIST_ADD(conn->pending_trans, state);
8961 /* We need to send an interim response then receive the rest
8962 of the parameter/data bytes */
8963 reply_outbuf(req, 0, 0);
8964 show_msg((char *)req->outbuf);
8965 END_PROFILE(SMBtrans2);
8970 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8971 SAFE_FREE(state->data);
8972 SAFE_FREE(state->param);
8974 END_PROFILE(SMBtrans2);
8975 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8979 /****************************************************************************
8980 Reply to a SMBtranss2
8981 ****************************************************************************/
8983 void reply_transs2(struct smb_request *req)
8985 connection_struct *conn = req->conn;
8986 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8987 struct trans_state *state;
8989 START_PROFILE(SMBtranss2);
8991 show_msg((const char *)req->inbuf);
8993 /* Windows clients expect all replies to
8994 a transact secondary (SMBtranss2 0x33)
8995 to have a command code of transact
8996 (SMBtrans2 0x32). See bug #8989
8997 and also [MS-CIFS] section 2.2.4.47.2
9000 req->cmd = SMBtrans2;
9003 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9004 END_PROFILE(SMBtranss2);
9008 for (state = conn->pending_trans; state != NULL;
9009 state = state->next) {
9010 if (state->mid == req->mid) {
9015 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9017 END_PROFILE(SMBtranss2);
9021 /* Revise state->total_param and state->total_data in case they have
9022 changed downwards */
9024 if (SVAL(req->vwv+0, 0) < state->total_param)
9025 state->total_param = SVAL(req->vwv+0, 0);
9026 if (SVAL(req->vwv+1, 0) < state->total_data)
9027 state->total_data = SVAL(req->vwv+1, 0);
9029 pcnt = SVAL(req->vwv+2, 0);
9030 poff = SVAL(req->vwv+3, 0);
9031 pdisp = SVAL(req->vwv+4, 0);
9033 dcnt = SVAL(req->vwv+5, 0);
9034 doff = SVAL(req->vwv+6, 0);
9035 ddisp = SVAL(req->vwv+7, 0);
9037 state->received_param += pcnt;
9038 state->received_data += dcnt;
9040 if ((state->received_data > state->total_data) ||
9041 (state->received_param > state->total_param))
9045 if (trans_oob(state->total_param, pdisp, pcnt)
9046 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9049 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9053 if (trans_oob(state->total_data, ddisp, dcnt)
9054 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9057 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9060 if ((state->received_param < state->total_param) ||
9061 (state->received_data < state->total_data)) {
9062 END_PROFILE(SMBtranss2);
9066 handle_trans2(conn, req, state);
9068 DLIST_REMOVE(conn->pending_trans, state);
9069 SAFE_FREE(state->data);
9070 SAFE_FREE(state->param);
9073 END_PROFILE(SMBtranss2);
9078 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9079 DLIST_REMOVE(conn->pending_trans, state);
9080 SAFE_FREE(state->data);
9081 SAFE_FREE(state->param);
9083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9084 END_PROFILE(SMBtranss2);