2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
43 #define DIR_ENTRY_SAFETY_MARGIN 4096
45 static char *store_file_unix_basic(connection_struct *conn,
48 const SMB_STRUCT_STAT *psbuf);
50 static char *store_file_unix_basic_info2(connection_struct *conn,
53 const SMB_STRUCT_STAT *psbuf);
55 /********************************************************************
56 The canonical "check access" based on object handle or path function.
57 ********************************************************************/
59 NTSTATUS check_access(connection_struct *conn,
61 const struct smb_filename *smb_fname,
65 if (!(fsp->access_mask & access_mask)) {
66 return NT_STATUS_ACCESS_DENIED;
69 NTSTATUS status = smbd_check_access_rights(conn,
73 if (!NT_STATUS_IS_OK(status)) {
80 /********************************************************************
81 Roundup a value to the nearest allocation roundup size boundary.
82 Only do this for Windows clients.
83 ********************************************************************/
85 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
87 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
89 /* Only roundup for Windows clients. */
90 enum remote_arch_types ra_type = get_remote_arch();
91 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
92 val = SMB_ROUNDUP(val,rval);
97 /********************************************************************
98 Create a 64 bit FileIndex. If the file is on the same device as
99 the root of the share, just return the 64-bit inode. If it isn't,
100 mangle as we used to do.
101 ********************************************************************/
103 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
106 if (conn->base_share_dev == psbuf->st_ex_dev) {
107 return (uint64_t)psbuf->st_ex_ino;
109 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
110 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
114 /****************************************************************************
115 Utility functions for dealing with extended attributes.
116 ****************************************************************************/
118 /****************************************************************************
119 Refuse to allow clients to overwrite our private xattrs.
120 ****************************************************************************/
122 static bool samba_private_attr_name(const char *unix_ea_name)
124 static const char * const prohibited_ea_names[] = {
125 SAMBA_POSIX_INHERITANCE_EA_NAME,
126 SAMBA_XATTR_DOS_ATTRIB,
134 for (i = 0; prohibited_ea_names[i]; i++) {
135 if (strequal( prohibited_ea_names[i], unix_ea_name))
138 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
139 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
145 /****************************************************************************
146 Get one EA value. Fill in a struct ea_struct.
147 ****************************************************************************/
149 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
150 files_struct *fsp, const char *fname,
151 const char *ea_name, struct ea_struct *pea)
153 /* Get the value of this xattr. Max size is 64k. */
154 size_t attr_size = 256;
160 val = talloc_realloc(mem_ctx, val, char, attr_size);
162 return NT_STATUS_NO_MEMORY;
165 if (fsp && fsp->fh->fd != -1) {
166 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
168 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
171 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
177 return map_nt_error_from_unix(errno);
180 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
181 dump_data(10, (uint8 *)val, sizeret);
184 if (strnequal(ea_name, "user.", 5)) {
185 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
187 pea->name = talloc_strdup(mem_ctx, ea_name);
189 if (pea->name == NULL) {
191 return NT_STATUS_NO_MEMORY;
193 pea->value.data = (unsigned char *)val;
194 pea->value.length = (size_t)sizeret;
198 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
199 files_struct *fsp, const char *fname,
200 char ***pnames, size_t *pnum_names)
202 /* Get a list of all xattrs. Max namesize is 64k. */
203 size_t ea_namelist_size = 1024;
204 char *ea_namelist = NULL;
209 ssize_t sizeret = -1;
211 if (!lp_ea_support(SNUM(conn))) {
220 * TALLOC the result early to get the talloc hierarchy right.
223 names = talloc_array(mem_ctx, char *, 1);
225 DEBUG(0, ("talloc failed\n"));
226 return NT_STATUS_NO_MEMORY;
229 while (ea_namelist_size <= 65536) {
231 ea_namelist = talloc_realloc(
232 names, ea_namelist, char, ea_namelist_size);
233 if (ea_namelist == NULL) {
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY;
239 if (fsp && fsp->fh->fd != -1) {
240 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
243 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
247 if ((sizeret == -1) && (errno == ERANGE)) {
248 ea_namelist_size *= 2;
257 return map_nt_error_from_unix(errno);
260 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
261 (unsigned int)sizeret));
273 * Ensure the result is 0-terminated
276 if (ea_namelist[sizeret-1] != '\0') {
278 return NT_STATUS_INTERNAL_ERROR;
286 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
290 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
292 DEBUG(0, ("talloc failed\n"));
294 return NT_STATUS_NO_MEMORY;
300 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
301 names[num_names++] = p;
309 *pnum_names = num_names;
313 /****************************************************************************
314 Return a linked list of the total EA's. Plus the total size
315 ****************************************************************************/
317 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
318 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
320 /* Get a list of all xattrs. Max namesize is 64k. */
323 struct ea_list *ea_list_head = NULL;
329 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
332 if (!NT_STATUS_IS_OK(status)) {
336 if (num_names == 0) {
341 for (i=0; i<num_names; i++) {
342 struct ea_list *listp;
345 if (strnequal(names[i], "system.", 7)
346 || samba_private_attr_name(names[i]))
350 * Filter out any underlying POSIX EA names
351 * that a Windows client can't handle.
353 if (!lp_posix_pathnames() &&
354 is_invalid_windows_ea_name(names[i])) {
358 listp = talloc(mem_ctx, struct ea_list);
360 return NT_STATUS_NO_MEMORY;
363 status = get_ea_value(listp, conn, fsp,
367 if (!NT_STATUS_IS_OK(status)) {
372 if (listp->ea.value.length == 0) {
374 * We can never return a zero length EA.
375 * Windows reports the EA's as corrupted.
381 push_ascii_fstring(dos_ea_name, listp->ea.name);
384 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
386 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
387 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
388 (unsigned int)listp->ea.value.length));
390 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
394 /* Add on 4 for total length. */
395 if (*pea_total_len) {
399 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
400 (unsigned int)*pea_total_len));
402 *ea_list = ea_list_head;
406 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
407 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
412 if (!lp_ea_support(SNUM(conn))) {
416 if (is_ntfs_stream_smb_fname(smb_fname)) {
417 return NT_STATUS_INVALID_PARAMETER;
420 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
423 /****************************************************************************
424 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
426 ****************************************************************************/
428 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
429 connection_struct *conn, struct ea_list *ea_list)
431 unsigned int ret_data_size = 4;
434 SMB_ASSERT(total_data_size >= 4);
436 if (!lp_ea_support(SNUM(conn))) {
441 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
444 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
445 dos_namelen = strlen(dos_ea_name);
446 if (dos_namelen > 255 || dos_namelen == 0) {
449 if (ea_list->ea.value.length > 65535) {
452 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
456 /* We know we have room. */
457 SCVAL(p,0,ea_list->ea.flags);
458 SCVAL(p,1,dos_namelen);
459 SSVAL(p,2,ea_list->ea.value.length);
460 strlcpy(p+4, dos_ea_name, dos_namelen+1);
461 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
463 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
464 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
467 ret_data_size = PTR_DIFF(p, pdata);
468 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
469 SIVAL(pdata,0,ret_data_size);
470 return ret_data_size;
473 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
475 unsigned int total_data_size,
476 unsigned int *ret_data_size,
477 connection_struct *conn,
478 struct ea_list *ea_list)
480 uint8_t *p = (uint8_t *)pdata;
481 uint8_t *last_start = NULL;
482 bool do_store_data = (pdata != NULL);
486 if (!lp_ea_support(SNUM(conn))) {
487 return NT_STATUS_NO_EAS_ON_FILE;
490 for (; ea_list; ea_list = ea_list->next) {
496 if (last_start != NULL && do_store_data) {
497 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
501 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
502 dos_namelen = strlen(dos_ea_name);
503 if (dos_namelen > 255 || dos_namelen == 0) {
504 return NT_STATUS_INTERNAL_ERROR;
506 if (ea_list->ea.value.length > 65535) {
507 return NT_STATUS_INTERNAL_ERROR;
510 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
513 pad = (4 - (this_size % 4)) % 4;
518 if (this_size > total_data_size) {
519 return NT_STATUS_INFO_LENGTH_MISMATCH;
522 /* We know we have room. */
523 SIVAL(p, 0x00, 0); /* next offset */
524 SCVAL(p, 0x04, ea_list->ea.flags);
525 SCVAL(p, 0x05, dos_namelen);
526 SSVAL(p, 0x06, ea_list->ea.value.length);
527 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
528 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
530 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
534 total_data_size -= this_size;
540 *ret_data_size = PTR_DIFF(p, pdata);
541 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
545 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
547 size_t total_ea_len = 0;
549 struct ea_list *ea_list = NULL;
551 if (!lp_ea_support(SNUM(conn))) {
554 mem_ctx = talloc_stackframe();
556 /* If this is a stream fsp, then we need to instead find the
557 * estimated ea len from the main file, not the stream
558 * (streams cannot have EAs), but the estimate isn't just 0 in
560 if (is_ntfs_stream_smb_fname(smb_fname)) {
563 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
564 if(conn->sconn->using_smb2) {
566 unsigned int ret_data_size;
568 * We're going to be using fill_ea_chained_buffer() to
569 * marshall EA's - this size is significantly larger
570 * than the SMB1 buffer. Re-calculate the size without
573 status = fill_ea_chained_buffer(mem_ctx,
579 if (!NT_STATUS_IS_OK(status)) {
582 total_ea_len = ret_data_size;
584 TALLOC_FREE(mem_ctx);
588 /****************************************************************************
589 Ensure the EA name is case insensitive by matching any existing EA name.
590 ****************************************************************************/
592 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
595 TALLOC_CTX *mem_ctx = talloc_tos();
596 struct ea_list *ea_list;
597 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
598 if (!NT_STATUS_IS_OK(status)) {
602 for (; ea_list; ea_list = ea_list->next) {
603 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
604 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
605 &unix_ea_name[5], ea_list->ea.name));
606 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
612 /****************************************************************************
613 Set or delete an extended attribute.
614 ****************************************************************************/
616 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
617 const struct smb_filename *smb_fname, struct ea_list *ea_list)
622 if (!lp_ea_support(SNUM(conn))) {
623 return NT_STATUS_EAS_NOT_SUPPORTED;
626 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
627 if (!NT_STATUS_IS_OK(status)) {
631 /* Setting EAs on streams isn't supported. */
632 if (is_ntfs_stream_smb_fname(smb_fname)) {
633 return NT_STATUS_INVALID_PARAMETER;
637 * Filter out invalid Windows EA names - before
638 * we set *any* of them.
641 if (ea_list_has_invalid_name(ea_list)) {
642 return STATUS_INVALID_EA_NAME;
645 fname = smb_fname->base_name;
647 for (;ea_list; ea_list = ea_list->next) {
649 fstring unix_ea_name;
651 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
652 fstrcat(unix_ea_name, ea_list->ea.name);
654 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
656 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
658 if (samba_private_attr_name(unix_ea_name)) {
659 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
660 return NT_STATUS_ACCESS_DENIED;
663 if (ea_list->ea.value.length == 0) {
664 /* Remove the attribute. */
665 if (fsp && (fsp->fh->fd != -1)) {
666 DEBUG(10,("set_ea: deleting ea name %s on "
667 "file %s by file descriptor.\n",
668 unix_ea_name, fsp_str_dbg(fsp)));
669 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
671 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
672 unix_ea_name, fname));
673 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
676 /* Removing a non existent attribute always succeeds. */
677 if (ret == -1 && errno == ENOATTR) {
678 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
684 if (fsp && (fsp->fh->fd != -1)) {
685 DEBUG(10,("set_ea: setting ea name %s on file "
686 "%s by file descriptor.\n",
687 unix_ea_name, fsp_str_dbg(fsp)));
688 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
689 ea_list->ea.value.data, ea_list->ea.value.length, 0);
691 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
692 unix_ea_name, fname));
693 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
694 ea_list->ea.value.data, ea_list->ea.value.length, 0);
700 if (errno == ENOTSUP) {
701 return NT_STATUS_EAS_NOT_SUPPORTED;
704 return map_nt_error_from_unix(errno);
710 /****************************************************************************
711 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
712 ****************************************************************************/
714 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
716 struct ea_list *ea_list_head = NULL;
717 size_t converted_size, offset = 0;
719 while (offset + 2 < data_size) {
720 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
721 unsigned int namelen = CVAL(pdata,offset);
723 offset++; /* Go past the namelen byte. */
725 /* integer wrap paranioa. */
726 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
727 (offset > data_size) || (namelen > data_size) ||
728 (offset + namelen >= data_size)) {
731 /* Ensure the name is null terminated. */
732 if (pdata[offset + namelen] != '\0') {
735 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
737 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
738 "failed: %s", strerror(errno)));
744 offset += (namelen + 1); /* Go past the name + terminating zero. */
745 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
746 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
752 /****************************************************************************
753 Read one EA list entry from the buffer.
754 ****************************************************************************/
756 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
758 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
760 unsigned int namelen;
761 size_t converted_size;
771 eal->ea.flags = CVAL(pdata,0);
772 namelen = CVAL(pdata,1);
773 val_len = SVAL(pdata,2);
775 if (4 + namelen + 1 + val_len > data_size) {
779 /* Ensure the name is null terminated. */
780 if (pdata[namelen + 4] != '\0') {
783 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
784 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
791 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
792 if (!eal->ea.value.data) {
796 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
798 /* Ensure we're null terminated just in case we print the value. */
799 eal->ea.value.data[val_len] = '\0';
800 /* But don't count the null. */
801 eal->ea.value.length--;
804 *pbytes_used = 4 + namelen + 1 + val_len;
807 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
808 dump_data(10, eal->ea.value.data, eal->ea.value.length);
813 /****************************************************************************
814 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
815 ****************************************************************************/
817 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
819 struct ea_list *ea_list_head = NULL;
821 size_t bytes_used = 0;
823 while (offset < data_size) {
824 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
830 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
831 offset += bytes_used;
837 /****************************************************************************
838 Count the total EA size needed.
839 ****************************************************************************/
841 static size_t ea_list_size(struct ea_list *ealist)
844 struct ea_list *listp;
847 for (listp = ealist; listp; listp = listp->next) {
848 push_ascii_fstring(dos_ea_name, listp->ea.name);
849 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
851 /* Add on 4 for total length. */
859 /****************************************************************************
860 Return a union of EA's from a file list and a list of names.
861 The TALLOC context for the two lists *MUST* be identical as we steal
862 memory from one list to add to another. JRA.
863 ****************************************************************************/
865 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
867 struct ea_list *nlistp, *flistp;
869 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
870 for (flistp = file_list; flistp; flistp = flistp->next) {
871 if (strequal(nlistp->ea.name, flistp->ea.name)) {
877 /* Copy the data from this entry. */
878 nlistp->ea.flags = flistp->ea.flags;
879 nlistp->ea.value = flistp->ea.value;
882 nlistp->ea.flags = 0;
883 ZERO_STRUCT(nlistp->ea.value);
887 *total_ea_len = ea_list_size(name_list);
891 /****************************************************************************
892 Send the required number of replies back.
893 We assume all fields other than the data fields are
894 set correctly for the type of call.
895 HACK ! Always assumes smb_setup field is zero.
896 ****************************************************************************/
898 void send_trans2_replies(connection_struct *conn,
899 struct smb_request *req,
907 /* As we are using a protocol > LANMAN1 then the max_send
908 variable must have been set in the sessetupX call.
909 This takes precedence over the max_xmit field in the
910 global struct. These different max_xmit variables should
911 be merged as this is now too confusing */
913 int data_to_send = datasize;
914 int params_to_send = paramsize;
916 const char *pp = params;
917 const char *pd = pdata;
918 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
919 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
920 int data_alignment_offset = 0;
921 bool overflow = False;
922 struct smbd_server_connection *sconn = req->sconn;
923 int max_send = sconn->smb1.sessions.max_send;
925 /* Modify the data_to_send and datasize and set the error if
926 we're trying to send more than max_data_bytes. We still send
927 the part of the packet(s) that fit. Strange, but needed
930 if (max_data_bytes > 0 && datasize > max_data_bytes) {
931 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
932 max_data_bytes, datasize ));
933 datasize = data_to_send = max_data_bytes;
937 /* If there genuinely are no parameters or data to send just send the empty packet */
939 if(params_to_send == 0 && data_to_send == 0) {
940 reply_outbuf(req, 10, 0);
941 if (NT_STATUS_V(status)) {
944 ntstatus_to_dos(status, &eclass, &ecode);
945 error_packet_set((char *)req->outbuf,
946 eclass, ecode, status,
949 show_msg((char *)req->outbuf);
950 if (!srv_send_smb(sconn,
953 IS_CONN_ENCRYPTED(conn),
955 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
957 TALLOC_FREE(req->outbuf);
961 /* When sending params and data ensure that both are nicely aligned */
962 /* Only do this alignment when there is also data to send - else
963 can cause NT redirector problems. */
965 if (((params_to_send % 4) != 0) && (data_to_send != 0))
966 data_alignment_offset = 4 - (params_to_send % 4);
968 /* Space is bufsize minus Netbios over TCP header minus SMB header */
969 /* The alignment_offset is to align the param bytes on an even byte
970 boundary. NT 4.0 Beta needs this to work correctly. */
972 useable_space = max_send - (smb_size
975 + data_alignment_offset);
977 if (useable_space < 0) {
978 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
979 "= %d!!!", useable_space));
980 exit_server_cleanly("send_trans2_replies: Not enough space");
983 while (params_to_send || data_to_send) {
984 /* Calculate whether we will totally or partially fill this packet */
986 total_sent_thistime = params_to_send + data_to_send;
988 /* We can never send more than useable_space */
990 * Note that 'useable_space' does not include the alignment offsets,
991 * but we must include the alignment offsets in the calculation of
992 * the length of the data we send over the wire, as the alignment offsets
993 * are sent here. Fix from Marc_Jacobsen@hp.com.
996 total_sent_thistime = MIN(total_sent_thistime, useable_space);
998 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
999 + data_alignment_offset);
1001 /* Set total params and data to be sent */
1002 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1003 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1005 /* Calculate how many parameters and data we can fit into
1006 * this packet. Parameters get precedence
1009 params_sent_thistime = MIN(params_to_send,useable_space);
1010 data_sent_thistime = useable_space - params_sent_thistime;
1011 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1013 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1015 /* smb_proff is the offset from the start of the SMB header to the
1016 parameter bytes, however the first 4 bytes of outbuf are
1017 the Netbios over TCP header. Thus use smb_base() to subtract
1018 them from the calculation */
1020 SSVAL(req->outbuf,smb_proff,
1021 ((smb_buf(req->outbuf)+alignment_offset)
1022 - smb_base(req->outbuf)));
1024 if(params_sent_thistime == 0)
1025 SSVAL(req->outbuf,smb_prdisp,0);
1027 /* Absolute displacement of param bytes sent in this packet */
1028 SSVAL(req->outbuf,smb_prdisp,pp - params);
1030 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1031 if(data_sent_thistime == 0) {
1032 SSVAL(req->outbuf,smb_droff,0);
1033 SSVAL(req->outbuf,smb_drdisp, 0);
1035 /* The offset of the data bytes is the offset of the
1036 parameter bytes plus the number of parameters being sent this time */
1037 SSVAL(req->outbuf, smb_droff,
1038 ((smb_buf(req->outbuf)+alignment_offset)
1039 - smb_base(req->outbuf))
1040 + params_sent_thistime + data_alignment_offset);
1041 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1044 /* Initialize the padding for alignment */
1046 if (alignment_offset != 0) {
1047 memset(smb_buf(req->outbuf), 0, alignment_offset);
1050 /* Copy the param bytes into the packet */
1052 if(params_sent_thistime) {
1053 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1054 params_sent_thistime);
1057 /* Copy in the data bytes */
1058 if(data_sent_thistime) {
1059 if (data_alignment_offset != 0) {
1060 memset((smb_buf(req->outbuf)+alignment_offset+
1061 params_sent_thistime), 0,
1062 data_alignment_offset);
1064 memcpy(smb_buf(req->outbuf)+alignment_offset
1065 +params_sent_thistime+data_alignment_offset,
1066 pd,data_sent_thistime);
1069 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1070 params_sent_thistime, data_sent_thistime, useable_space));
1071 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1072 params_to_send, data_to_send, paramsize, datasize));
1075 error_packet_set((char *)req->outbuf,
1076 ERRDOS,ERRbufferoverflow,
1077 STATUS_BUFFER_OVERFLOW,
1079 } else if (NT_STATUS_V(status)) {
1082 ntstatus_to_dos(status, &eclass, &ecode);
1083 error_packet_set((char *)req->outbuf,
1084 eclass, ecode, status,
1088 /* Send the packet */
1089 show_msg((char *)req->outbuf);
1090 if (!srv_send_smb(sconn,
1091 (char *)req->outbuf,
1092 true, req->seqnum+1,
1093 IS_CONN_ENCRYPTED(conn),
1095 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1097 TALLOC_FREE(req->outbuf);
1099 pp += params_sent_thistime;
1100 pd += data_sent_thistime;
1102 params_to_send -= params_sent_thistime;
1103 data_to_send -= data_sent_thistime;
1106 if(params_to_send < 0 || data_to_send < 0) {
1107 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1108 params_to_send, data_to_send));
1116 /****************************************************************************
1117 Reply to a TRANSACT2_OPEN.
1118 ****************************************************************************/
1120 static void call_trans2open(connection_struct *conn,
1121 struct smb_request *req,
1122 char **pparams, int total_params,
1123 char **ppdata, int total_data,
1124 unsigned int max_data_bytes)
1126 struct smb_filename *smb_fname = NULL;
1127 char *params = *pparams;
1128 char *pdata = *ppdata;
1131 bool oplock_request;
1133 bool return_additional_info;
1142 int fattr=0,mtime=0;
1143 SMB_INO_T inode = 0;
1146 struct ea_list *ea_list = NULL;
1151 uint32 create_disposition;
1152 uint32 create_options = 0;
1153 uint32_t private_flags = 0;
1154 TALLOC_CTX *ctx = talloc_tos();
1157 * Ensure we have enough parameters to perform the operation.
1160 if (total_params < 29) {
1161 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1165 flags = SVAL(params, 0);
1166 deny_mode = SVAL(params, 2);
1167 open_attr = SVAL(params,6);
1168 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1169 if (oplock_request) {
1170 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1174 return_additional_info = BITSETW(params,0);
1175 open_sattr = SVAL(params, 4);
1176 open_time = make_unix_date3(params+8);
1178 open_ofun = SVAL(params,12);
1179 open_size = IVAL(params,14);
1180 pname = ¶ms[28];
1183 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1187 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1188 total_params - 28, STR_TERMINATE,
1190 if (!NT_STATUS_IS_OK(status)) {
1191 reply_nterror(req, status);
1195 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1196 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1197 (unsigned int)open_ofun, open_size));
1199 status = filename_convert(ctx,
1201 req->flags2 & FLAGS2_DFS_PATHNAMES,
1206 if (!NT_STATUS_IS_OK(status)) {
1207 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1208 reply_botherror(req,
1209 NT_STATUS_PATH_NOT_COVERED,
1210 ERRSRV, ERRbadpath);
1213 reply_nterror(req, status);
1217 if (open_ofun == 0) {
1218 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1222 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1224 &access_mask, &share_mode,
1225 &create_disposition,
1228 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1232 /* Any data in this call is an EA list. */
1233 if (total_data && (total_data != 4)) {
1234 if (total_data < 10) {
1235 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1239 if (IVAL(pdata,0) > total_data) {
1240 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1241 IVAL(pdata,0), (unsigned int)total_data));
1242 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1246 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1249 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1253 if (!lp_ea_support(SNUM(conn))) {
1254 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1258 if (ea_list_has_invalid_name(ea_list)) {
1260 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1261 if(*pparams == NULL ) {
1262 reply_nterror(req, NT_STATUS_NO_MEMORY);
1266 memset(params, '\0', param_len);
1267 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1268 params, param_len, NULL, 0, max_data_bytes);
1273 status = SMB_VFS_CREATE_FILE(
1276 0, /* root_dir_fid */
1277 smb_fname, /* fname */
1278 access_mask, /* access_mask */
1279 share_mode, /* share_access */
1280 create_disposition, /* create_disposition*/
1281 create_options, /* create_options */
1282 open_attr, /* file_attributes */
1283 oplock_request, /* oplock_request */
1284 open_size, /* allocation_size */
1287 ea_list, /* ea_list */
1289 &smb_action); /* psbuf */
1291 if (!NT_STATUS_IS_OK(status)) {
1292 if (open_was_deferred(req->sconn, req->mid)) {
1293 /* We have re-scheduled this call. */
1296 reply_openerror(req, status);
1300 size = get_file_size_stat(&smb_fname->st);
1301 fattr = dos_mode(conn, smb_fname);
1302 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1303 inode = smb_fname->st.st_ex_ino;
1304 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1305 close_file(req, fsp, ERROR_CLOSE);
1306 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1310 /* Realloc the size of parameters and data we will return */
1311 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1312 if(*pparams == NULL ) {
1313 reply_nterror(req, NT_STATUS_NO_MEMORY);
1318 SSVAL(params,0,fsp->fnum);
1319 SSVAL(params,2,fattr);
1320 srv_put_dos_date2(params,4, mtime);
1321 SIVAL(params,8, (uint32)size);
1322 SSVAL(params,12,deny_mode);
1323 SSVAL(params,14,0); /* open_type - file or directory. */
1324 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1326 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1327 smb_action |= EXTENDED_OPLOCK_GRANTED;
1330 SSVAL(params,18,smb_action);
1333 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1335 SIVAL(params,20,inode);
1336 SSVAL(params,24,0); /* Padding. */
1338 uint32 ea_size = estimate_ea_size(conn, fsp,
1340 SIVAL(params, 26, ea_size);
1342 SIVAL(params, 26, 0);
1345 /* Send the required number of replies */
1346 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1348 TALLOC_FREE(smb_fname);
1351 /*********************************************************
1352 Routine to check if a given string matches exactly.
1353 as a special case a mask of "." does NOT match. That
1354 is required for correct wildcard semantics
1355 Case can be significant or not.
1356 **********************************************************/
1358 static bool exact_match(bool has_wild,
1359 bool case_sensitive,
1363 if (mask[0] == '.' && mask[1] == 0) {
1371 if (case_sensitive) {
1372 return strcmp(str,mask)==0;
1374 return strcasecmp_m(str,mask) == 0;
1378 /****************************************************************************
1379 Return the filetype for UNIX extensions.
1380 ****************************************************************************/
1382 static uint32 unix_filetype(mode_t mode)
1385 return UNIX_TYPE_FILE;
1386 else if(S_ISDIR(mode))
1387 return UNIX_TYPE_DIR;
1389 else if(S_ISLNK(mode))
1390 return UNIX_TYPE_SYMLINK;
1393 else if(S_ISCHR(mode))
1394 return UNIX_TYPE_CHARDEV;
1397 else if(S_ISBLK(mode))
1398 return UNIX_TYPE_BLKDEV;
1401 else if(S_ISFIFO(mode))
1402 return UNIX_TYPE_FIFO;
1405 else if(S_ISSOCK(mode))
1406 return UNIX_TYPE_SOCKET;
1409 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1410 return UNIX_TYPE_UNKNOWN;
1413 /****************************************************************************
1414 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1415 ****************************************************************************/
1417 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1419 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1420 const SMB_STRUCT_STAT *psbuf,
1422 enum perm_type ptype,
1427 if (perms == SMB_MODE_NO_CHANGE) {
1428 if (!VALID_STAT(*psbuf)) {
1429 return NT_STATUS_INVALID_PARAMETER;
1431 *ret_perms = psbuf->st_ex_mode;
1432 return NT_STATUS_OK;
1436 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1437 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1438 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1439 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1440 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1441 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1442 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1443 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1444 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1446 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1449 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1452 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1455 if (ptype == PERM_NEW_FILE) {
1457 * "create mask"/"force create mode" are
1458 * only applied to new files, not existing ones.
1460 ret &= lp_create_mask(SNUM(conn));
1461 /* Add in force bits */
1462 ret |= lp_force_create_mode(SNUM(conn));
1463 } else if (ptype == PERM_NEW_DIR) {
1465 * "directory mask"/"force directory mode" are
1466 * only applied to new directories, not existing ones.
1468 ret &= lp_dir_mask(SNUM(conn));
1469 /* Add in force bits */
1470 ret |= lp_force_dir_mode(SNUM(conn));
1474 return NT_STATUS_OK;
1477 /****************************************************************************
1478 Needed to show the msdfs symlinks as directories. Modifies psbuf
1479 to be a directory if it's a msdfs link.
1480 ****************************************************************************/
1482 static bool check_msdfs_link(connection_struct *conn,
1483 const char *pathname,
1484 SMB_STRUCT_STAT *psbuf)
1486 int saved_errno = errno;
1487 if(lp_host_msdfs() &&
1488 lp_msdfs_root(SNUM(conn)) &&
1489 is_msdfs_link(conn, pathname, psbuf)) {
1491 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1494 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1495 errno = saved_errno;
1498 errno = saved_errno;
1503 /****************************************************************************
1504 Get a level dependent lanman2 dir entry.
1505 ****************************************************************************/
1507 struct smbd_dirptr_lanman2_state {
1508 connection_struct *conn;
1509 uint32_t info_level;
1510 bool check_mangled_names;
1512 bool got_exact_match;
1515 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1521 struct smbd_dirptr_lanman2_state *state =
1522 (struct smbd_dirptr_lanman2_state *)private_data;
1524 char mangled_name[13]; /* mangled 8.3 name. */
1528 /* Mangle fname if it's an illegal name. */
1529 if (mangle_must_mangle(dname, state->conn->params)) {
1530 ok = name_to_8_3(dname, mangled_name,
1531 true, state->conn->params);
1535 fname = mangled_name;
1540 got_match = exact_match(state->has_wild,
1541 state->conn->case_sensitive,
1543 state->got_exact_match = got_match;
1545 got_match = mask_match(fname, mask,
1546 state->conn->case_sensitive);
1549 if(!got_match && state->check_mangled_names &&
1550 !mangle_is_8_3(fname, false, state->conn->params)) {
1552 * It turns out that NT matches wildcards against
1553 * both long *and* short names. This may explain some
1554 * of the wildcard wierdness from old DOS clients
1555 * that some people have been seeing.... JRA.
1557 /* Force the mangling into 8.3. */
1558 ok = name_to_8_3(fname, mangled_name,
1559 false, state->conn->params);
1564 got_match = exact_match(state->has_wild,
1565 state->conn->case_sensitive,
1566 mangled_name, mask);
1567 state->got_exact_match = got_match;
1569 got_match = mask_match(mangled_name, mask,
1570 state->conn->case_sensitive);
1578 *_fname = talloc_strdup(ctx, fname);
1579 if (*_fname == NULL) {
1586 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1588 struct smb_filename *smb_fname,
1591 struct smbd_dirptr_lanman2_state *state =
1592 (struct smbd_dirptr_lanman2_state *)private_data;
1593 bool ms_dfs_link = false;
1596 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1597 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1598 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1599 "Couldn't lstat [%s] (%s)\n",
1600 smb_fname_str_dbg(smb_fname),
1604 } else if (!VALID_STAT(smb_fname->st) &&
1605 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1606 /* Needed to show the msdfs symlinks as
1609 ms_dfs_link = check_msdfs_link(state->conn,
1610 smb_fname->base_name,
1613 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1614 "Couldn't stat [%s] (%s)\n",
1615 smb_fname_str_dbg(smb_fname),
1622 mode = dos_mode_msdfs(state->conn, smb_fname);
1624 mode = dos_mode(state->conn, smb_fname);
1631 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1632 connection_struct *conn,
1634 uint32_t info_level,
1635 struct ea_list *name_list,
1636 bool check_mangled_names,
1637 bool requires_resume_key,
1640 const struct smb_filename *smb_fname,
1641 int space_remaining,
1648 uint64_t *last_entry_off)
1650 char *p, *q, *pdata = *ppdata;
1652 uint64_t file_size = 0;
1653 uint64_t allocation_size = 0;
1654 uint64_t file_index = 0;
1656 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1657 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1659 char *last_entry_ptr;
1664 *out_of_space = false;
1666 ZERO_STRUCT(mdate_ts);
1667 ZERO_STRUCT(adate_ts);
1668 ZERO_STRUCT(create_date_ts);
1669 ZERO_STRUCT(cdate_ts);
1671 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1672 file_size = get_file_size_stat(&smb_fname->st);
1674 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1676 file_index = get_FileIndex(conn, &smb_fname->st);
1678 mdate_ts = smb_fname->st.st_ex_mtime;
1679 adate_ts = smb_fname->st.st_ex_atime;
1680 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1681 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1683 if (lp_dos_filetime_resolution(SNUM(conn))) {
1684 dos_filetime_timespec(&create_date_ts);
1685 dos_filetime_timespec(&mdate_ts);
1686 dos_filetime_timespec(&adate_ts);
1687 dos_filetime_timespec(&cdate_ts);
1690 create_date = convert_timespec_to_time_t(create_date_ts);
1691 mdate = convert_timespec_to_time_t(mdate_ts);
1692 adate = convert_timespec_to_time_t(adate_ts);
1694 /* align the record */
1695 SMB_ASSERT(align >= 1);
1697 off = (int)PTR_DIFF(pdata, base_data);
1698 pad = (off + (align-1)) & ~(align-1);
1701 if (pad && pad > space_remaining) {
1702 *out_of_space = true;
1703 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1704 "for padding (wanted %u, had %d)\n",
1707 return false; /* Not finished - just out of space */
1711 /* initialize padding to 0 */
1713 memset(pdata, 0, pad);
1715 space_remaining -= pad;
1717 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1727 switch (info_level) {
1728 case SMB_FIND_INFO_STANDARD:
1729 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1730 if(requires_resume_key) {
1734 srv_put_dos_date2(p,0,create_date);
1735 srv_put_dos_date2(p,4,adate);
1736 srv_put_dos_date2(p,8,mdate);
1737 SIVAL(p,12,(uint32)file_size);
1738 SIVAL(p,16,(uint32)allocation_size);
1742 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1743 p += ucs2_align(base_data, p, 0);
1745 len = srvstr_push(base_data, flags2, p,
1746 fname, PTR_DIFF(end_data, p),
1748 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1750 SCVAL(nameptr, -1, len - 2);
1752 SCVAL(nameptr, -1, 0);
1756 SCVAL(nameptr, -1, len - 1);
1758 SCVAL(nameptr, -1, 0);
1764 case SMB_FIND_EA_SIZE:
1765 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1766 if (requires_resume_key) {
1770 srv_put_dos_date2(p,0,create_date);
1771 srv_put_dos_date2(p,4,adate);
1772 srv_put_dos_date2(p,8,mdate);
1773 SIVAL(p,12,(uint32)file_size);
1774 SIVAL(p,16,(uint32)allocation_size);
1777 unsigned int ea_size = estimate_ea_size(conn, NULL,
1779 SIVAL(p,22,ea_size); /* Extended attributes */
1783 len = srvstr_push(base_data, flags2,
1784 p, fname, PTR_DIFF(end_data, p),
1785 STR_TERMINATE | STR_NOALIGN);
1786 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1799 SCVAL(nameptr,0,len);
1801 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1804 case SMB_FIND_EA_LIST:
1806 struct ea_list *file_list = NULL;
1810 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1814 if (requires_resume_key) {
1818 srv_put_dos_date2(p,0,create_date);
1819 srv_put_dos_date2(p,4,adate);
1820 srv_put_dos_date2(p,8,mdate);
1821 SIVAL(p,12,(uint32)file_size);
1822 SIVAL(p,16,(uint32)allocation_size);
1824 p += 22; /* p now points to the EA area. */
1826 status = get_ea_list_from_file(ctx, conn, NULL,
1828 &ea_len, &file_list);
1829 if (!NT_STATUS_IS_OK(status)) {
1832 name_list = ea_list_union(name_list, file_list, &ea_len);
1834 /* We need to determine if this entry will fit in the space available. */
1835 /* Max string size is 255 bytes. */
1836 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1837 *out_of_space = true;
1838 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1839 "(wanted %u, had %d)\n",
1840 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1842 return False; /* Not finished - just out of space */
1845 /* Push the ea_data followed by the name. */
1846 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1848 len = srvstr_push(base_data, flags2,
1849 p + 1, fname, PTR_DIFF(end_data, p+1),
1850 STR_TERMINATE | STR_NOALIGN);
1851 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1864 SCVAL(nameptr,0,len);
1866 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1870 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1871 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1872 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1874 SIVAL(p,0,reskey); p += 4;
1875 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1876 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1877 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1878 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1879 SOFF_T(p,0,file_size); p += 8;
1880 SOFF_T(p,0,allocation_size); p += 8;
1881 SIVAL(p,0,mode); p += 4;
1882 q = p; p += 4; /* q is placeholder for name length. */
1883 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1884 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1886 unsigned int ea_size = estimate_ea_size(conn, NULL,
1888 SIVAL(p,0,ea_size); /* Extended attributes */
1891 /* Clear the short name buffer. This is
1892 * IMPORTANT as not doing so will trigger
1893 * a Win2k client bug. JRA.
1895 if (!was_8_3 && check_mangled_names) {
1896 char mangled_name[13]; /* mangled 8.3 name. */
1897 if (!name_to_8_3(fname,mangled_name,True,
1899 /* Error - mangle failed ! */
1900 memset(mangled_name,'\0',12);
1902 mangled_name[12] = 0;
1903 len = srvstr_push(base_data, flags2,
1904 p+2, mangled_name, 24,
1905 STR_UPPER|STR_UNICODE);
1907 memset(p + 2 + len,'\0',24 - len);
1914 len = srvstr_push(base_data, flags2, p,
1915 fname, PTR_DIFF(end_data, p),
1916 STR_TERMINATE_ASCII);
1920 len = PTR_DIFF(p, pdata);
1921 pad = (len + (align-1)) & ~(align-1);
1923 * offset to the next entry, the caller
1924 * will overwrite it for the last entry
1925 * that's why we always include the padding
1929 * set padding to zero
1932 memset(p, 0, pad - len);
1939 case SMB_FIND_FILE_DIRECTORY_INFO:
1940 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1942 SIVAL(p,0,reskey); p += 4;
1943 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1944 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1945 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1946 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1947 SOFF_T(p,0,file_size); p += 8;
1948 SOFF_T(p,0,allocation_size); p += 8;
1949 SIVAL(p,0,mode); p += 4;
1950 len = srvstr_push(base_data, flags2,
1951 p + 4, fname, PTR_DIFF(end_data, p+4),
1952 STR_TERMINATE_ASCII);
1956 len = PTR_DIFF(p, pdata);
1957 pad = (len + (align-1)) & ~(align-1);
1959 * offset to the next entry, the caller
1960 * will overwrite it for the last entry
1961 * that's why we always include the padding
1965 * set padding to zero
1968 memset(p, 0, pad - len);
1975 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1976 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1978 SIVAL(p,0,reskey); p += 4;
1979 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1980 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1981 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1982 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1983 SOFF_T(p,0,file_size); p += 8;
1984 SOFF_T(p,0,allocation_size); p += 8;
1985 SIVAL(p,0,mode); p += 4;
1986 q = p; p += 4; /* q is placeholder for name length. */
1988 unsigned int ea_size = estimate_ea_size(conn, NULL,
1990 SIVAL(p,0,ea_size); /* Extended attributes */
1993 len = srvstr_push(base_data, flags2, p,
1994 fname, PTR_DIFF(end_data, p),
1995 STR_TERMINATE_ASCII);
1999 len = PTR_DIFF(p, pdata);
2000 pad = (len + (align-1)) & ~(align-1);
2002 * offset to the next entry, the caller
2003 * will overwrite it for the last entry
2004 * that's why we always include the padding
2008 * set padding to zero
2011 memset(p, 0, pad - len);
2018 case SMB_FIND_FILE_NAMES_INFO:
2019 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2021 SIVAL(p,0,reskey); p += 4;
2023 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2024 acl on a dir (tridge) */
2025 len = srvstr_push(base_data, flags2, p,
2026 fname, PTR_DIFF(end_data, p),
2027 STR_TERMINATE_ASCII);
2031 len = PTR_DIFF(p, pdata);
2032 pad = (len + (align-1)) & ~(align-1);
2034 * offset to the next entry, the caller
2035 * will overwrite it for the last entry
2036 * that's why we always include the padding
2040 * set padding to zero
2043 memset(p, 0, pad - len);
2050 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2051 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2053 SIVAL(p,0,reskey); p += 4;
2054 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2055 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2056 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2057 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2058 SOFF_T(p,0,file_size); p += 8;
2059 SOFF_T(p,0,allocation_size); p += 8;
2060 SIVAL(p,0,mode); p += 4;
2061 q = p; p += 4; /* q is placeholder for name length. */
2062 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2063 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2065 unsigned int ea_size = estimate_ea_size(conn, NULL,
2067 SIVAL(p,0,ea_size); /* Extended attributes */
2070 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2071 SBVAL(p,0,file_index); p += 8;
2072 len = srvstr_push(base_data, flags2, p,
2073 fname, PTR_DIFF(end_data, p),
2074 STR_TERMINATE_ASCII);
2078 len = PTR_DIFF(p, pdata);
2079 pad = (len + (align-1)) & ~(align-1);
2081 * offset to the next entry, the caller
2082 * will overwrite it for the last entry
2083 * that's why we always include the padding
2087 * set padding to zero
2090 memset(p, 0, pad - len);
2097 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2098 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2099 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2101 SIVAL(p,0,reskey); p += 4;
2102 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2103 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2104 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2105 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2106 SOFF_T(p,0,file_size); p += 8;
2107 SOFF_T(p,0,allocation_size); p += 8;
2108 SIVAL(p,0,mode); p += 4;
2109 q = p; p += 4; /* q is placeholder for name length */
2110 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2111 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2113 unsigned int ea_size = estimate_ea_size(conn, NULL,
2115 SIVAL(p,0,ea_size); /* Extended attributes */
2118 /* Clear the short name buffer. This is
2119 * IMPORTANT as not doing so will trigger
2120 * a Win2k client bug. JRA.
2122 if (!was_8_3 && check_mangled_names) {
2123 char mangled_name[13]; /* mangled 8.3 name. */
2124 if (!name_to_8_3(fname,mangled_name,True,
2126 /* Error - mangle failed ! */
2127 memset(mangled_name,'\0',12);
2129 mangled_name[12] = 0;
2130 len = srvstr_push(base_data, flags2,
2131 p+2, mangled_name, 24,
2132 STR_UPPER|STR_UNICODE);
2135 memset(p + 2 + len,'\0',24 - len);
2142 SSVAL(p,0,0); p += 2; /* Reserved ? */
2143 SBVAL(p,0,file_index); p += 8;
2144 len = srvstr_push(base_data, flags2, p,
2145 fname, PTR_DIFF(end_data, p),
2146 STR_TERMINATE_ASCII);
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);
2169 /* CIFS UNIX Extension. */
2171 case SMB_FIND_FILE_UNIX:
2172 case SMB_FIND_FILE_UNIX_INFO2:
2174 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2176 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2178 if (info_level == SMB_FIND_FILE_UNIX) {
2179 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2180 p = store_file_unix_basic(conn, p,
2181 NULL, &smb_fname->st);
2182 len = srvstr_push(base_data, flags2, p,
2183 fname, PTR_DIFF(end_data, p),
2186 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2187 p = store_file_unix_basic_info2(conn, p,
2188 NULL, &smb_fname->st);
2191 len = srvstr_push(base_data, flags2, p, fname,
2192 PTR_DIFF(end_data, p), 0);
2193 SIVAL(nameptr, 0, len);
2198 len = PTR_DIFF(p, pdata);
2199 pad = (len + (align-1)) & ~(align-1);
2201 * offset to the next entry, the caller
2202 * will overwrite it for the last entry
2203 * that's why we always include the padding
2207 * set padding to zero
2210 memset(p, 0, pad - len);
2215 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2223 if (PTR_DIFF(p,pdata) > space_remaining) {
2224 *out_of_space = true;
2225 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2226 "(wanted %u, had %d)\n",
2227 (unsigned int)PTR_DIFF(p,pdata),
2229 return false; /* Not finished - just out of space */
2232 /* Setup the last entry pointer, as an offset from base_data */
2233 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2234 /* Advance the data pointer to the next slot */
2240 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2241 connection_struct *conn,
2242 struct dptr_struct *dirptr,
2244 const char *path_mask,
2247 int requires_resume_key,
2255 int space_remaining,
2257 bool *got_exact_match,
2258 int *_last_entry_off,
2259 struct ea_list *name_list)
2262 const char *mask = NULL;
2263 long prev_dirpos = 0;
2266 struct smb_filename *smb_fname = NULL;
2267 struct smbd_dirptr_lanman2_state state;
2269 uint64_t last_entry_off = 0;
2273 state.info_level = info_level;
2274 state.check_mangled_names = lp_manglednames(conn->params);
2275 state.has_wild = dptr_has_wild(dirptr);
2276 state.got_exact_match = false;
2278 *out_of_space = false;
2279 *got_exact_match = false;
2281 p = strrchr_m(path_mask,'/');
2292 ok = smbd_dirptr_get_entry(ctx,
2298 smbd_dirptr_lanman2_match_fn,
2299 smbd_dirptr_lanman2_mode_fn,
2309 *got_exact_match = state.got_exact_match;
2311 ok = smbd_marshall_dir_entry(ctx,
2316 state.check_mangled_names,
2317 requires_resume_key,
2330 TALLOC_FREE(smb_fname);
2331 if (*out_of_space) {
2332 dptr_SeekDir(dirptr, prev_dirpos);
2339 *_last_entry_off = last_entry_off;
2343 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2344 connection_struct *conn,
2345 struct dptr_struct *dirptr,
2347 const char *path_mask,
2350 bool requires_resume_key,
2356 int space_remaining,
2358 bool *got_exact_match,
2359 int *last_entry_off,
2360 struct ea_list *name_list)
2363 const bool do_pad = true;
2365 if (info_level >= 1 && info_level <= 3) {
2366 /* No alignment on earlier info levels. */
2370 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2371 path_mask, dirtype, info_level,
2372 requires_resume_key, dont_descend, ask_sharemode,
2374 ppdata, base_data, end_data,
2376 out_of_space, got_exact_match,
2377 last_entry_off, name_list);
2380 /****************************************************************************
2381 Reply to a TRANS2_FINDFIRST.
2382 ****************************************************************************/
2384 static void call_trans2findfirst(connection_struct *conn,
2385 struct smb_request *req,
2386 char **pparams, int total_params,
2387 char **ppdata, int total_data,
2388 unsigned int max_data_bytes)
2390 /* We must be careful here that we don't return more than the
2391 allowed number of data bytes. If this means returning fewer than
2392 maxentries then so be it. We assume that the redirector has
2393 enough room for the fixed number of parameter bytes it has
2395 struct smb_filename *smb_dname = NULL;
2396 char *params = *pparams;
2397 char *pdata = *ppdata;
2401 uint16 findfirst_flags;
2402 bool close_after_first;
2404 bool requires_resume_key;
2406 char *directory = NULL;
2409 int last_entry_off=0;
2413 bool finished = False;
2414 bool dont_descend = False;
2415 bool out_of_space = False;
2416 int space_remaining;
2417 bool mask_contains_wcard = False;
2418 struct ea_list *ea_list = NULL;
2419 NTSTATUS ntstatus = NT_STATUS_OK;
2420 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2421 TALLOC_CTX *ctx = talloc_tos();
2422 struct dptr_struct *dirptr = NULL;
2423 struct smbd_server_connection *sconn = req->sconn;
2424 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2425 bool backup_priv = false;
2427 if (total_params < 13) {
2428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2432 dirtype = SVAL(params,0);
2433 maxentries = SVAL(params,2);
2434 findfirst_flags = SVAL(params,4);
2435 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2436 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2437 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2438 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2439 security_token_has_privilege(get_current_nttok(conn),
2442 info_level = SVAL(params,6);
2444 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2445 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2446 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2448 info_level, max_data_bytes));
2451 /* W2K3 seems to treat zero as 1. */
2455 switch (info_level) {
2456 case SMB_FIND_INFO_STANDARD:
2457 case SMB_FIND_EA_SIZE:
2458 case SMB_FIND_EA_LIST:
2459 case SMB_FIND_FILE_DIRECTORY_INFO:
2460 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2461 case SMB_FIND_FILE_NAMES_INFO:
2462 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2463 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2464 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2466 case SMB_FIND_FILE_UNIX:
2467 case SMB_FIND_FILE_UNIX_INFO2:
2468 /* Always use filesystem for UNIX mtime query. */
2469 ask_sharemode = false;
2470 if (!lp_unix_extensions()) {
2471 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2474 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2477 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2481 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2482 params+12, total_params - 12,
2483 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2484 if (!NT_STATUS_IS_OK(ntstatus)) {
2485 reply_nterror(req, ntstatus);
2491 ntstatus = filename_convert_with_privilege(ctx,
2496 &mask_contains_wcard,
2499 ntstatus = filename_convert(ctx, conn,
2500 req->flags2 & FLAGS2_DFS_PATHNAMES,
2503 &mask_contains_wcard,
2507 if (!NT_STATUS_IS_OK(ntstatus)) {
2508 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2509 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2510 ERRSRV, ERRbadpath);
2513 reply_nterror(req, ntstatus);
2517 mask = smb_dname->original_lcomp;
2519 directory = smb_dname->base_name;
2521 p = strrchr_m(directory,'/');
2523 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2524 if((directory[0] == '.') && (directory[1] == '\0')) {
2525 mask = talloc_strdup(ctx,"*");
2527 reply_nterror(req, NT_STATUS_NO_MEMORY);
2530 mask_contains_wcard = True;
2536 if (p == NULL || p == directory) {
2537 /* Ensure we don't have a directory name of "". */
2538 directory = talloc_strdup(talloc_tos(), ".");
2540 reply_nterror(req, NT_STATUS_NO_MEMORY);
2545 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2547 if (info_level == SMB_FIND_EA_LIST) {
2550 if (total_data < 4) {
2551 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2555 ea_size = IVAL(pdata,0);
2556 if (ea_size != total_data) {
2557 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2558 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2563 if (!lp_ea_support(SNUM(conn))) {
2564 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2568 /* Pull out the list of names. */
2569 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2576 *ppdata = (char *)SMB_REALLOC(
2577 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2578 if(*ppdata == NULL ) {
2579 reply_nterror(req, NT_STATUS_NO_MEMORY);
2583 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2585 /* Realloc the params space */
2586 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2587 if (*pparams == NULL) {
2588 reply_nterror(req, NT_STATUS_NO_MEMORY);
2593 /* Save the wildcard match and attribs we are using on this directory -
2594 needed as lanman2 assumes these are being saved between calls */
2596 ntstatus = dptr_create(conn,
2604 mask_contains_wcard,
2608 if (!NT_STATUS_IS_OK(ntstatus)) {
2609 reply_nterror(req, ntstatus);
2614 /* Remember this in case we have
2615 to do a findnext. */
2616 dptr_set_priv(dirptr);
2619 dptr_num = dptr_dnum(dirptr);
2620 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2622 /* Initialize per TRANS2_FIND_FIRST operation data */
2623 dptr_init_search_op(dirptr);
2625 /* We don't need to check for VOL here as this is returned by
2626 a different TRANS2 call. */
2628 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2629 directory,lp_dontdescend(ctx, SNUM(conn))));
2630 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2631 dont_descend = True;
2634 space_remaining = max_data_bytes;
2635 out_of_space = False;
2637 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2638 bool got_exact_match = False;
2640 /* this is a heuristic to avoid seeking the dirptr except when
2641 absolutely necessary. It allows for a filename of about 40 chars */
2642 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2643 out_of_space = True;
2646 finished = !get_lanman2_dir_entry(ctx,
2650 mask,dirtype,info_level,
2651 requires_resume_key,dont_descend,
2654 space_remaining, &out_of_space,
2656 &last_entry_off, ea_list);
2659 if (finished && out_of_space)
2662 if (!finished && !out_of_space)
2666 * As an optimisation if we know we aren't looking
2667 * for a wildcard name (ie. the name matches the wildcard exactly)
2668 * then we can finish on any (first) match.
2669 * This speeds up large directory searches. JRA.
2675 /* Ensure space_remaining never goes -ve. */
2676 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2677 space_remaining = 0;
2678 out_of_space = true;
2680 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2684 /* Check if we can close the dirptr */
2685 if(close_after_first || (finished && close_if_end)) {
2686 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2687 dptr_close(sconn, &dptr_num);
2691 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2692 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2693 * the protocol level is less than NT1. Tested with smbclient. JRA.
2694 * This should fix the OS/2 client bug #2335.
2697 if(numentries == 0) {
2698 dptr_close(sconn, &dptr_num);
2699 if (get_Protocol() < PROTOCOL_NT1) {
2700 reply_force_doserror(req, ERRDOS, ERRnofiles);
2703 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2704 ERRDOS, ERRbadfile);
2709 /* At this point pdata points to numentries directory entries. */
2711 /* Set up the return parameter block */
2712 SSVAL(params,0,dptr_num);
2713 SSVAL(params,2,numentries);
2714 SSVAL(params,4,finished);
2715 SSVAL(params,6,0); /* Never an EA error */
2716 SSVAL(params,8,last_entry_off);
2718 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2721 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2722 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2724 reply_nterror(req, NT_STATUS_NO_MEMORY);
2728 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2729 smb_fn_name(req->cmd),
2730 mask, directory, dirtype, numentries ) );
2733 * Force a name mangle here to ensure that the
2734 * mask as an 8.3 name is top of the mangled cache.
2735 * The reasons for this are subtle. Don't remove
2736 * this code unless you know what you are doing
2737 * (see PR#13758). JRA.
2740 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2741 char mangled_name[13];
2742 name_to_8_3(mask, mangled_name, True, conn->params);
2750 TALLOC_FREE(smb_dname);
2754 /****************************************************************************
2755 Reply to a TRANS2_FINDNEXT.
2756 ****************************************************************************/
2758 static void call_trans2findnext(connection_struct *conn,
2759 struct smb_request *req,
2760 char **pparams, int total_params,
2761 char **ppdata, int total_data,
2762 unsigned int max_data_bytes)
2764 /* We must be careful here that we don't return more than the
2765 allowed number of data bytes. If this means returning fewer than
2766 maxentries then so be it. We assume that the redirector has
2767 enough room for the fixed number of parameter bytes it has
2769 char *params = *pparams;
2770 char *pdata = *ppdata;
2776 uint16 findnext_flags;
2777 bool close_after_request;
2779 bool requires_resume_key;
2781 bool mask_contains_wcard = False;
2782 char *resume_name = NULL;
2783 const char *mask = NULL;
2784 const char *directory = NULL;
2788 int i, last_entry_off=0;
2789 bool finished = False;
2790 bool dont_descend = False;
2791 bool out_of_space = False;
2792 int space_remaining;
2793 struct ea_list *ea_list = NULL;
2794 NTSTATUS ntstatus = NT_STATUS_OK;
2795 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2796 TALLOC_CTX *ctx = talloc_tos();
2797 struct dptr_struct *dirptr;
2798 struct smbd_server_connection *sconn = req->sconn;
2799 bool backup_priv = false;
2801 if (total_params < 13) {
2802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2806 dptr_num = SVAL(params,0);
2807 maxentries = SVAL(params,2);
2808 info_level = SVAL(params,4);
2809 resume_key = IVAL(params,6);
2810 findnext_flags = SVAL(params,10);
2811 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2812 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2813 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2814 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2816 if (!continue_bit) {
2817 /* We only need resume_name if continue_bit is zero. */
2818 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2820 total_params - 12, STR_TERMINATE, &ntstatus,
2821 &mask_contains_wcard);
2822 if (!NT_STATUS_IS_OK(ntstatus)) {
2823 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2824 complain (it thinks we're asking for the directory above the shared
2825 path or an invalid name). Catch this as the resume name is only compared, never used in
2826 a file access. JRA. */
2827 srvstr_pull_talloc(ctx, params, req->flags2,
2828 &resume_name, params+12,
2832 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2833 reply_nterror(req, ntstatus);
2839 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2840 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2841 resume_key = %d resume name = %s continue=%d level = %d\n",
2842 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2843 requires_resume_key, resume_key,
2844 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2847 /* W2K3 seems to treat zero as 1. */
2851 switch (info_level) {
2852 case SMB_FIND_INFO_STANDARD:
2853 case SMB_FIND_EA_SIZE:
2854 case SMB_FIND_EA_LIST:
2855 case SMB_FIND_FILE_DIRECTORY_INFO:
2856 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2857 case SMB_FIND_FILE_NAMES_INFO:
2858 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2859 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2860 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2862 case SMB_FIND_FILE_UNIX:
2863 case SMB_FIND_FILE_UNIX_INFO2:
2864 /* Always use filesystem for UNIX mtime query. */
2865 ask_sharemode = false;
2866 if (!lp_unix_extensions()) {
2867 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2872 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2876 if (info_level == SMB_FIND_EA_LIST) {
2879 if (total_data < 4) {
2880 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2884 ea_size = IVAL(pdata,0);
2885 if (ea_size != total_data) {
2886 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2887 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2892 if (!lp_ea_support(SNUM(conn))) {
2893 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2897 /* Pull out the list of names. */
2898 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2900 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2905 *ppdata = (char *)SMB_REALLOC(
2906 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2907 if(*ppdata == NULL) {
2908 reply_nterror(req, NT_STATUS_NO_MEMORY);
2913 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2915 /* Realloc the params space */
2916 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2917 if(*pparams == NULL ) {
2918 reply_nterror(req, NT_STATUS_NO_MEMORY);
2924 /* Check that the dptr is valid */
2925 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2926 reply_nterror(req, STATUS_NO_MORE_FILES);
2930 directory = dptr_path(sconn, dptr_num);
2932 /* Get the wildcard mask from the dptr */
2933 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2934 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2935 reply_nterror(req, STATUS_NO_MORE_FILES);
2939 /* Get the attr mask from the dptr */
2940 dirtype = dptr_attr(sconn, dptr_num);
2942 backup_priv = dptr_get_priv(dirptr);
2944 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2945 "backup_priv = %d\n",
2946 dptr_num, mask, dirtype,
2948 dptr_TellDir(dirptr),
2951 /* Initialize per TRANS2_FIND_NEXT operation data */
2952 dptr_init_search_op(dirptr);
2954 /* We don't need to check for VOL here as this is returned by
2955 a different TRANS2 call. */
2957 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2958 directory,lp_dontdescend(ctx, SNUM(conn))));
2959 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2960 dont_descend = True;
2963 space_remaining = max_data_bytes;
2964 out_of_space = False;
2971 * Seek to the correct position. We no longer use the resume key but
2972 * depend on the last file name instead.
2975 if(!continue_bit && resume_name && *resume_name) {
2978 long current_pos = 0;
2980 * Remember, name_to_8_3 is called by
2981 * get_lanman2_dir_entry(), so the resume name
2982 * could be mangled. Ensure we check the unmangled name.
2985 if (mangle_is_mangled(resume_name, conn->params)) {
2986 char *new_resume_name = NULL;
2987 mangle_lookup_name_from_8_3(ctx,
2991 if (new_resume_name) {
2992 resume_name = new_resume_name;
2997 * Fix for NT redirector problem triggered by resume key indexes
2998 * changing between directory scans. We now return a resume key of 0
2999 * and instead look for the filename to continue from (also given
3000 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3001 * findfirst/findnext (as is usual) then the directory pointer
3002 * should already be at the correct place.
3005 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3006 } /* end if resume_name && !continue_bit */
3008 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3009 bool got_exact_match = False;
3011 /* this is a heuristic to avoid seeking the dirptr except when
3012 absolutely necessary. It allows for a filename of about 40 chars */
3013 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3014 out_of_space = True;
3017 finished = !get_lanman2_dir_entry(ctx,
3021 mask,dirtype,info_level,
3022 requires_resume_key,dont_descend,
3025 space_remaining, &out_of_space,
3027 &last_entry_off, ea_list);
3030 if (finished && out_of_space)
3033 if (!finished && !out_of_space)
3037 * As an optimisation if we know we aren't looking
3038 * for a wildcard name (ie. the name matches the wildcard exactly)
3039 * then we can finish on any (first) match.
3040 * This speeds up large directory searches. JRA.
3046 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3049 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3050 smb_fn_name(req->cmd),
3051 mask, directory, dirtype, numentries ) );
3053 /* Check if we can close the dirptr */
3054 if(close_after_request || (finished && close_if_end)) {
3055 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3056 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3063 /* Set up the return parameter block */
3064 SSVAL(params,0,numentries);
3065 SSVAL(params,2,finished);
3066 SSVAL(params,4,0); /* Never an EA error */
3067 SSVAL(params,6,last_entry_off);
3069 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3075 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3077 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3081 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3083 SMB_ASSERT(extended_info != NULL);
3085 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3086 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3087 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3088 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3089 #ifdef SAMBA_VERSION_REVISION
3090 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3092 extended_info->samba_subversion = 0;
3093 #ifdef SAMBA_VERSION_RC_RELEASE
3094 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3096 #ifdef SAMBA_VERSION_PRE_RELEASE
3097 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3100 #ifdef SAMBA_VERSION_VENDOR_PATCH
3101 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3103 extended_info->samba_gitcommitdate = 0;
3104 #ifdef SAMBA_VERSION_COMMIT_TIME
3105 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3108 memset(extended_info->samba_version_string, 0,
3109 sizeof(extended_info->samba_version_string));
3111 snprintf (extended_info->samba_version_string,
3112 sizeof(extended_info->samba_version_string),
3113 "%s", samba_version_string());
3116 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3117 TALLOC_CTX *mem_ctx,
3118 uint16_t info_level,
3120 unsigned int max_data_bytes,
3121 struct smb_filename *fname,
3125 char *pdata, *end_data;
3126 int data_len = 0, len;
3127 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3128 int snum = SNUM(conn);
3129 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3130 char *filename = NULL;
3131 uint32 additional_flags = 0;
3132 struct smb_filename smb_fname;
3135 if (fname == NULL || fname->base_name == NULL) {
3138 filename = fname->base_name;
3142 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3143 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3144 "info level (0x%x) on IPC$.\n",
3145 (unsigned int)info_level));
3146 return NT_STATUS_ACCESS_DENIED;
3150 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3152 ZERO_STRUCT(smb_fname);
3153 smb_fname.base_name = discard_const_p(char, filename);
3155 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3156 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3157 return map_nt_error_from_unix(errno);
3162 *ppdata = (char *)SMB_REALLOC(
3163 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3164 if (*ppdata == NULL) {
3165 return NT_STATUS_NO_MEMORY;
3169 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3170 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3172 switch (info_level) {
3173 case SMB_INFO_ALLOCATION:
3175 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3177 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3178 return map_nt_error_from_unix(errno);
3181 block_size = lp_block_size(snum);
3182 if (bsize < block_size) {
3183 uint64_t factor = block_size/bsize;
3188 if (bsize > block_size) {
3189 uint64_t factor = bsize/block_size;
3194 bytes_per_sector = 512;
3195 sectors_per_unit = bsize/bytes_per_sector;
3197 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3198 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3199 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3201 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3202 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3203 SIVAL(pdata,l1_cUnit,dsize);
3204 SIVAL(pdata,l1_cUnitAvail,dfree);
3205 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3209 case SMB_INFO_VOLUME:
3210 /* Return volume name */
3212 * Add volume serial number - hash of a combination of
3213 * the called hostname and the service name.
3215 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3217 * Win2k3 and previous mess this up by sending a name length
3218 * one byte short. I believe only older clients (OS/2 Win9x) use
3219 * this call so try fixing this by adding a terminating null to
3220 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3224 pdata+l2_vol_szVolLabel, vname,
3225 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3226 STR_NOALIGN|STR_TERMINATE);
3227 SCVAL(pdata,l2_vol_cch,len);
3228 data_len = l2_vol_szVolLabel + len;
3229 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3230 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3234 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3235 case SMB_FS_ATTRIBUTE_INFORMATION:
3237 additional_flags = 0;
3238 #if defined(HAVE_SYS_QUOTAS)
3239 additional_flags |= FILE_VOLUME_QUOTAS;
3242 if(lp_nt_acl_support(SNUM(conn))) {
3243 additional_flags |= FILE_PERSISTENT_ACLS;
3246 /* Capabilities are filled in at connection time through STATVFS call */
3247 additional_flags |= conn->fs_capabilities;
3248 additional_flags |= lp_parm_int(conn->params->service,
3249 "share", "fake_fscaps",
3252 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3253 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3254 additional_flags); /* FS ATTRIBUTES */
3256 SIVAL(pdata,4,255); /* Max filename component length */
3257 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3258 and will think we can't do long filenames */
3259 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3260 PTR_DIFF(end_data, pdata+12),
3263 data_len = 12 + len;
3266 case SMB_QUERY_FS_LABEL_INFO:
3267 case SMB_FS_LABEL_INFORMATION:
3268 len = srvstr_push(pdata, flags2, pdata+4, vname,
3269 PTR_DIFF(end_data, pdata+4), 0);
3274 case SMB_QUERY_FS_VOLUME_INFO:
3275 case SMB_FS_VOLUME_INFORMATION:
3278 * Add volume serial number - hash of a combination of
3279 * the called hostname and the service name.
3281 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3282 (str_checksum(get_local_machine_name())<<16));
3284 /* Max label len is 32 characters. */
3285 len = srvstr_push(pdata, flags2, pdata+18, vname,
3286 PTR_DIFF(end_data, pdata+18),
3288 SIVAL(pdata,12,len);
3291 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3292 (int)strlen(vname),vname,
3293 lp_servicename(talloc_tos(), snum)));
3296 case SMB_QUERY_FS_SIZE_INFO:
3297 case SMB_FS_SIZE_INFORMATION:
3299 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3301 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3302 return map_nt_error_from_unix(errno);
3304 block_size = lp_block_size(snum);
3305 if (bsize < block_size) {
3306 uint64_t factor = block_size/bsize;
3311 if (bsize > block_size) {
3312 uint64_t factor = bsize/block_size;
3317 bytes_per_sector = 512;
3318 sectors_per_unit = bsize/bytes_per_sector;
3319 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3320 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3321 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3322 SBIG_UINT(pdata,0,dsize);
3323 SBIG_UINT(pdata,8,dfree);
3324 SIVAL(pdata,16,sectors_per_unit);
3325 SIVAL(pdata,20,bytes_per_sector);
3329 case SMB_FS_FULL_SIZE_INFORMATION:
3331 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3333 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3334 return map_nt_error_from_unix(errno);
3336 block_size = lp_block_size(snum);
3337 if (bsize < block_size) {
3338 uint64_t factor = block_size/bsize;
3343 if (bsize > block_size) {
3344 uint64_t factor = bsize/block_size;
3349 bytes_per_sector = 512;
3350 sectors_per_unit = bsize/bytes_per_sector;
3351 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3352 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3353 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3354 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3355 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3356 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3357 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3358 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3362 case SMB_QUERY_FS_DEVICE_INFO:
3363 case SMB_FS_DEVICE_INFORMATION:
3365 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3367 if (!CAN_WRITE(conn)) {
3368 characteristics |= FILE_READ_ONLY_DEVICE;
3371 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3372 SIVAL(pdata,4,characteristics);
3376 #ifdef HAVE_SYS_QUOTAS
3377 case SMB_FS_QUOTA_INFORMATION:
3379 * what we have to send --metze:
3381 * Unknown1: 24 NULL bytes
3382 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3383 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3384 * Quota Flags: 2 byte :
3385 * Unknown3: 6 NULL bytes
3389 * details for Quota Flags:
3391 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3392 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3393 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3394 * 0x0001 Enable Quotas: enable quota for this fs
3398 /* we need to fake up a fsp here,
3399 * because its not send in this call
3402 SMB_NTQUOTA_STRUCT quotas;
3405 ZERO_STRUCT(quotas);
3408 fsp.fnum = FNUM_FIELD_INVALID;
3411 if (get_current_uid(conn) != 0) {
3412 DEBUG(0,("set_user_quota: access_denied "
3413 "service [%s] user [%s]\n",
3414 lp_servicename(talloc_tos(), SNUM(conn)),
3415 conn->session_info->unix_info->unix_name));
3416 return NT_STATUS_ACCESS_DENIED;
3419 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3420 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3421 return map_nt_error_from_unix(errno);
3426 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3427 lp_servicename(talloc_tos(), SNUM(conn))));
3429 /* Unknown1 24 NULL bytes*/
3430 SBIG_UINT(pdata,0,(uint64_t)0);
3431 SBIG_UINT(pdata,8,(uint64_t)0);
3432 SBIG_UINT(pdata,16,(uint64_t)0);
3434 /* Default Soft Quota 8 bytes */
3435 SBIG_UINT(pdata,24,quotas.softlim);
3437 /* Default Hard Quota 8 bytes */
3438 SBIG_UINT(pdata,32,quotas.hardlim);
3440 /* Quota flag 2 bytes */
3441 SSVAL(pdata,40,quotas.qflags);
3443 /* Unknown3 6 NULL bytes */
3449 #endif /* HAVE_SYS_QUOTAS */
3450 case SMB_FS_OBJECTID_INFORMATION:
3452 unsigned char objid[16];
3453 struct smb_extended_info extended_info;
3454 memcpy(pdata,create_volume_objectid(conn, objid),16);
3455 samba_extended_info_version (&extended_info);
3456 SIVAL(pdata,16,extended_info.samba_magic);
3457 SIVAL(pdata,20,extended_info.samba_version);
3458 SIVAL(pdata,24,extended_info.samba_subversion);
3459 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3460 memcpy(pdata+36,extended_info.samba_version_string,28);
3466 * Query the version and capabilities of the CIFS UNIX extensions
3470 case SMB_QUERY_CIFS_UNIX_INFO:
3472 bool large_write = lp_min_receive_file_size() &&
3473 !srv_is_signing_active(conn->sconn);
3474 bool large_read = !srv_is_signing_active(conn->sconn);
3475 int encrypt_caps = 0;
3477 if (!lp_unix_extensions()) {
3478 return NT_STATUS_INVALID_LEVEL;
3481 switch (conn->encrypt_level) {
3482 case SMB_SIGNING_OFF:
3485 case SMB_SIGNING_IF_REQUIRED:
3486 case SMB_SIGNING_DEFAULT:
3487 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3489 case SMB_SIGNING_REQUIRED:
3490 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3491 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3492 large_write = false;
3498 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3499 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3501 /* We have POSIX ACLs, pathname, encryption,
3502 * large read/write, and locking capability. */
3504 SBIG_UINT(pdata,4,((uint64_t)(
3505 CIFS_UNIX_POSIX_ACLS_CAP|
3506 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3507 CIFS_UNIX_FCNTL_LOCKS_CAP|
3508 CIFS_UNIX_EXTATTR_CAP|
3509 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3511 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3513 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3517 case SMB_QUERY_POSIX_FS_INFO:
3520 vfs_statvfs_struct svfs;
3522 if (!lp_unix_extensions()) {
3523 return NT_STATUS_INVALID_LEVEL;
3526 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3530 SIVAL(pdata,0,svfs.OptimalTransferSize);
3531 SIVAL(pdata,4,svfs.BlockSize);
3532 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3533 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3534 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3535 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3536 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3537 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3538 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3540 } else if (rc == EOPNOTSUPP) {
3541 return NT_STATUS_INVALID_LEVEL;
3542 #endif /* EOPNOTSUPP */
3544 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3545 return NT_STATUS_DOS(ERRSRV, ERRerror);
3550 case SMB_QUERY_POSIX_WHOAMI:
3556 if (!lp_unix_extensions()) {
3557 return NT_STATUS_INVALID_LEVEL;
3560 if (max_data_bytes < 40) {
3561 return NT_STATUS_BUFFER_TOO_SMALL;
3564 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3565 flags |= SMB_WHOAMI_GUEST;
3568 /* NOTE: 8 bytes for UID/GID, irrespective of native
3569 * platform size. This matches
3570 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3572 data_len = 4 /* flags */
3579 + 4 /* pad/reserved */
3580 + (conn->session_info->unix_token->ngroups * 8)
3582 + (conn->session_info->security_token->num_sids *
3586 SIVAL(pdata, 0, flags);
3587 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3589 (uint64_t)conn->session_info->unix_token->uid);
3590 SBIG_UINT(pdata, 16,
3591 (uint64_t)conn->session_info->unix_token->gid);
3594 if (data_len >= max_data_bytes) {
3595 /* Potential overflow, skip the GIDs and SIDs. */
3597 SIVAL(pdata, 24, 0); /* num_groups */
3598 SIVAL(pdata, 28, 0); /* num_sids */
3599 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3600 SIVAL(pdata, 36, 0); /* reserved */
3606 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3607 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3609 /* We walk the SID list twice, but this call is fairly
3610 * infrequent, and I don't expect that it's performance
3611 * sensitive -- jpeach
3613 for (i = 0, sid_bytes = 0;
3614 i < conn->session_info->security_token->num_sids; ++i) {
3615 sid_bytes += ndr_size_dom_sid(
3616 &conn->session_info->security_token->sids[i],
3620 /* SID list byte count */
3621 SIVAL(pdata, 32, sid_bytes);
3623 /* 4 bytes pad/reserved - must be zero */
3624 SIVAL(pdata, 36, 0);
3628 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3629 SBIG_UINT(pdata, data_len,
3630 (uint64_t)conn->session_info->unix_token->groups[i]);
3636 i < conn->session_info->security_token->num_sids; ++i) {
3637 int sid_len = ndr_size_dom_sid(
3638 &conn->session_info->security_token->sids[i],
3641 sid_linearize(pdata + data_len, sid_len,
3642 &conn->session_info->security_token->sids[i]);
3643 data_len += sid_len;
3649 case SMB_MAC_QUERY_FS_INFO:
3651 * Thursby MAC extension... ONLY on NTFS filesystems
3652 * once we do streams then we don't need this
3654 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3656 SIVAL(pdata,84,0x100); /* Don't support mac... */
3661 return NT_STATUS_INVALID_LEVEL;
3664 *ret_data_len = data_len;
3665 return NT_STATUS_OK;
3668 /****************************************************************************
3669 Reply to a TRANS2_QFSINFO (query filesystem info).
3670 ****************************************************************************/
3672 static void call_trans2qfsinfo(connection_struct *conn,
3673 struct smb_request *req,
3674 char **pparams, int total_params,
3675 char **ppdata, int total_data,
3676 unsigned int max_data_bytes)
3678 char *params = *pparams;
3679 uint16_t info_level;
3683 if (total_params < 2) {
3684 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3688 info_level = SVAL(params,0);
3690 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3691 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3692 DEBUG(0,("call_trans2qfsinfo: encryption required "
3693 "and info level 0x%x sent.\n",
3694 (unsigned int)info_level));
3695 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3700 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3702 status = smbd_do_qfsinfo(conn, req,
3708 if (!NT_STATUS_IS_OK(status)) {
3709 reply_nterror(req, status);
3713 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3716 DEBUG( 4, ( "%s info_level = %d\n",
3717 smb_fn_name(req->cmd), info_level) );
3722 /****************************************************************************
3723 Reply to a TRANS2_SETFSINFO (set filesystem info).
3724 ****************************************************************************/
3726 static void call_trans2setfsinfo(connection_struct *conn,
3727 struct smb_request *req,
3728 char **pparams, int total_params,
3729 char **ppdata, int total_data,
3730 unsigned int max_data_bytes)
3732 struct smbd_server_connection *sconn = req->sconn;
3733 char *pdata = *ppdata;
3734 char *params = *pparams;
3737 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3738 lp_servicename(talloc_tos(), SNUM(conn))));
3741 if (total_params < 4) {
3742 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3744 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3748 info_level = SVAL(params,2);
3751 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3752 info_level != SMB_SET_CIFS_UNIX_INFO) {
3753 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3754 "info level (0x%x) on IPC$.\n",
3755 (unsigned int)info_level));
3756 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3761 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3762 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3763 DEBUG(0,("call_trans2setfsinfo: encryption required "
3764 "and info level 0x%x sent.\n",
3765 (unsigned int)info_level));
3766 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3771 switch(info_level) {
3772 case SMB_SET_CIFS_UNIX_INFO:
3773 if (!lp_unix_extensions()) {
3774 DEBUG(2,("call_trans2setfsinfo: "
3775 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3776 "unix extensions off\n"));
3778 NT_STATUS_INVALID_LEVEL);
3782 /* There should be 12 bytes of capabilities set. */
3783 if (total_data < 12) {
3786 NT_STATUS_INVALID_PARAMETER);
3789 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3790 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3791 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3792 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3793 /* Just print these values for now. */
3794 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3795 "major = %u, minor = %u cap_low = 0x%x, "
3797 (unsigned int)sconn->
3798 smb1.unix_info.client_major,
3799 (unsigned int)sconn->
3800 smb1.unix_info.client_minor,
3801 (unsigned int)sconn->
3802 smb1.unix_info.client_cap_low,
3803 (unsigned int)sconn->
3804 smb1.unix_info.client_cap_high));
3806 /* Here is where we must switch to posix pathname processing... */
3807 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3808 lp_set_posix_pathnames();
3809 mangle_change_to_posix();
3812 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3813 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3814 /* Client that knows how to do posix locks,
3815 * but not posix open/mkdir operations. Set a
3816 * default type for read/write checks. */
3818 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3823 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3826 size_t param_len = 0;
3827 size_t data_len = total_data;
3829 if (!lp_unix_extensions()) {
3832 NT_STATUS_INVALID_LEVEL);
3836 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3839 NT_STATUS_NOT_SUPPORTED);
3843 if (req->sconn->smb1.echo_handler.trusted_fde) {
3844 DEBUG( 2,("call_trans2setfsinfo: "
3845 "request transport encryption disabled"
3846 "with 'fork echo handler = yes'\n"));
3849 NT_STATUS_NOT_SUPPORTED);
3853 DEBUG( 4,("call_trans2setfsinfo: "
3854 "request transport encryption.\n"));
3856 status = srv_request_encryption_setup(conn,
3857 (unsigned char **)ppdata,
3859 (unsigned char **)pparams,
3862 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3863 !NT_STATUS_IS_OK(status)) {
3864 reply_nterror(req, status);
3868 send_trans2_replies(conn, req,
3876 if (NT_STATUS_IS_OK(status)) {
3877 /* Server-side transport
3878 * encryption is now *on*. */
3879 status = srv_encryption_start(conn);
3880 if (!NT_STATUS_IS_OK(status)) {
3881 char *reason = talloc_asprintf(talloc_tos(),
3882 "Failure in setting "
3883 "up encrypted transport: %s",
3885 exit_server_cleanly(reason);
3891 case SMB_FS_QUOTA_INFORMATION:
3893 files_struct *fsp = NULL;
3894 SMB_NTQUOTA_STRUCT quotas;
3896 ZERO_STRUCT(quotas);
3899 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3900 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3901 lp_servicename(talloc_tos(), SNUM(conn)),
3902 conn->session_info->unix_info->unix_name));
3903 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3907 /* note: normaly there're 48 bytes,
3908 * but we didn't use the last 6 bytes for now
3911 fsp = file_fsp(req, SVAL(params,0));
3913 if (!check_fsp_ntquota_handle(conn, req,
3915 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3917 req, NT_STATUS_INVALID_HANDLE);
3921 if (total_data < 42) {
3922 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3926 NT_STATUS_INVALID_PARAMETER);
3930 /* unknown_1 24 NULL bytes in pdata*/
3932 /* the soft quotas 8 bytes (uint64_t)*/
3933 quotas.softlim = BVAL(pdata,24);
3935 /* the hard quotas 8 bytes (uint64_t)*/
3936 quotas.hardlim = BVAL(pdata,32);
3938 /* quota_flags 2 bytes **/
3939 quotas.qflags = SVAL(pdata,40);
3941 /* unknown_2 6 NULL bytes follow*/
3943 /* now set the quotas */
3944 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3945 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3946 reply_nterror(req, map_nt_error_from_unix(errno));
3953 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3955 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3961 * sending this reply works fine,
3962 * but I'm not sure it's the same
3963 * like windows do...
3966 reply_outbuf(req, 10, 0);
3969 #if defined(HAVE_POSIX_ACLS)
3970 /****************************************************************************
3971 Utility function to count the number of entries in a POSIX acl.
3972 ****************************************************************************/
3974 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3976 unsigned int ace_count = 0;
3977 int entry_id = SMB_ACL_FIRST_ENTRY;
3978 SMB_ACL_ENTRY_T entry;
3980 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3982 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3983 entry_id = SMB_ACL_NEXT_ENTRY;
3990 /****************************************************************************
3991 Utility function to marshall a POSIX acl into wire format.
3992 ****************************************************************************/
3994 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3996 int entry_id = SMB_ACL_FIRST_ENTRY;
3997 SMB_ACL_ENTRY_T entry;
3999 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4000 SMB_ACL_TAG_T tagtype;
4001 SMB_ACL_PERMSET_T permset;
4002 unsigned char perms = 0;
4003 unsigned int own_grp;
4006 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4007 entry_id = SMB_ACL_NEXT_ENTRY;
4010 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4011 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4015 if (sys_acl_get_permset(entry, &permset) == -1) {
4016 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4020 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4021 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4022 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4024 SCVAL(pdata,1,perms);
4027 case SMB_ACL_USER_OBJ:
4028 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4029 own_grp = (unsigned int)pst->st_ex_uid;
4030 SIVAL(pdata,2,own_grp);
4035 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4037 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4040 own_grp = (unsigned int)*puid;
4041 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4042 SIVAL(pdata,2,own_grp);
4046 case SMB_ACL_GROUP_OBJ:
4047 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4048 own_grp = (unsigned int)pst->st_ex_gid;
4049 SIVAL(pdata,2,own_grp);
4054 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4056 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4059 own_grp = (unsigned int)*pgid;
4060 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4061 SIVAL(pdata,2,own_grp);
4066 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4067 SIVAL(pdata,2,0xFFFFFFFF);
4068 SIVAL(pdata,6,0xFFFFFFFF);
4071 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4072 SIVAL(pdata,2,0xFFFFFFFF);
4073 SIVAL(pdata,6,0xFFFFFFFF);
4076 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4079 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4086 /****************************************************************************
4087 Store the FILE_UNIX_BASIC info.
4088 ****************************************************************************/
4090 static char *store_file_unix_basic(connection_struct *conn,
4093 const SMB_STRUCT_STAT *psbuf)
4095 uint64_t file_index = get_FileIndex(conn, psbuf);
4098 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4099 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4101 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4104 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4107 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4108 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4109 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4112 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4116 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4120 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4123 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4124 devno = psbuf->st_ex_rdev;
4126 devno = psbuf->st_ex_dev;
4129 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4133 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4137 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4140 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4144 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4151 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4152 * the chflags(2) (or equivalent) flags.
4154 * XXX: this really should be behind the VFS interface. To do this, we would
4155 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4156 * Each VFS module could then implement its own mapping as appropriate for the
4157 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4159 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4163 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4167 { UF_IMMUTABLE, EXT_IMMUTABLE },
4171 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4175 { UF_HIDDEN, EXT_HIDDEN },
4178 /* Do not remove. We need to guarantee that this array has at least one
4179 * entry to build on HP-UX.
4185 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4186 uint32 *smb_fflags, uint32 *smb_fmask)
4190 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4191 *smb_fmask |= info2_flags_map[i].smb_fflag;
4192 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4193 *smb_fflags |= info2_flags_map[i].smb_fflag;
4198 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4199 const uint32 smb_fflags,
4200 const uint32 smb_fmask,
4203 uint32 max_fmask = 0;
4206 *stat_fflags = psbuf->st_ex_flags;
4208 /* For each flags requested in smb_fmask, check the state of the
4209 * corresponding flag in smb_fflags and set or clear the matching
4213 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4214 max_fmask |= info2_flags_map[i].smb_fflag;
4215 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4216 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4217 *stat_fflags |= info2_flags_map[i].stat_fflag;
4219 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4224 /* If smb_fmask is asking to set any bits that are not supported by
4225 * our flag mappings, we should fail.
4227 if ((smb_fmask & max_fmask) != smb_fmask) {
4235 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4236 * of file flags and birth (create) time.
4238 static char *store_file_unix_basic_info2(connection_struct *conn,
4241 const SMB_STRUCT_STAT *psbuf)
4243 uint32 file_flags = 0;
4244 uint32 flags_mask = 0;
4246 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4248 /* Create (birth) time 64 bit */
4249 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4252 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4253 SIVAL(pdata, 0, file_flags); /* flags */
4254 SIVAL(pdata, 4, flags_mask); /* mask */
4260 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4261 const struct stream_struct *streams,
4263 unsigned int max_data_bytes,
4264 unsigned int *data_size)
4267 unsigned int ofs = 0;
4269 for (i = 0; i < num_streams; i++) {
4270 unsigned int next_offset;
4272 smb_ucs2_t *namebuf;
4274 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4275 streams[i].name, &namelen) ||
4278 return NT_STATUS_INVALID_PARAMETER;
4282 * name_buf is now null-terminated, we need to marshall as not
4289 * We cannot overflow ...
4291 if ((ofs + 24 + namelen) > max_data_bytes) {
4292 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4294 TALLOC_FREE(namebuf);
4295 return STATUS_BUFFER_OVERFLOW;
4298 SIVAL(data, ofs+4, namelen);
4299 SOFF_T(data, ofs+8, streams[i].size);
4300 SOFF_T(data, ofs+16, streams[i].alloc_size);
4301 memcpy(data+ofs+24, namebuf, namelen);
4302 TALLOC_FREE(namebuf);
4304 next_offset = ofs + 24 + namelen;
4306 if (i == num_streams-1) {
4307 SIVAL(data, ofs, 0);
4310 unsigned int align = ndr_align_size(next_offset, 8);
4312 if ((next_offset + align) > max_data_bytes) {
4313 DEBUG(10, ("refusing to overflow align "
4314 "reply at stream %u\n",
4316 TALLOC_FREE(namebuf);
4317 return STATUS_BUFFER_OVERFLOW;
4320 memset(data+next_offset, 0, align);
4321 next_offset += align;
4323 SIVAL(data, ofs, next_offset - ofs);
4330 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4334 return NT_STATUS_OK;
4337 /****************************************************************************
4338 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4339 ****************************************************************************/
4341 static void call_trans2qpipeinfo(connection_struct *conn,
4342 struct smb_request *req,
4343 unsigned int tran_call,
4344 char **pparams, int total_params,
4345 char **ppdata, int total_data,
4346 unsigned int max_data_bytes)
4348 char *params = *pparams;
4349 char *pdata = *ppdata;
4350 unsigned int data_size = 0;
4351 unsigned int param_size = 2;
4356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4360 if (total_params < 4) {
4361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4365 fsp = file_fsp(req, SVAL(params,0));
4366 if (!fsp_is_np(fsp)) {
4367 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4371 info_level = SVAL(params,2);
4373 *pparams = (char *)SMB_REALLOC(*pparams,2);
4374 if (*pparams == NULL) {
4375 reply_nterror(req, NT_STATUS_NO_MEMORY);
4380 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4381 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4382 if (*ppdata == NULL ) {
4383 reply_nterror(req, NT_STATUS_NO_MEMORY);
4388 switch (info_level) {
4389 case SMB_FILE_STANDARD_INFORMATION:
4391 SOFF_T(pdata,0,4096LL);
4398 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4402 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4408 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4409 TALLOC_CTX *mem_ctx,
4410 uint16_t info_level,
4412 struct smb_filename *smb_fname,
4413 bool delete_pending,
4414 struct timespec write_time_ts,
4415 struct ea_list *ea_list,
4416 int lock_data_count,
4419 unsigned int max_data_bytes,
4421 unsigned int *pdata_size)
4423 char *pdata = *ppdata;
4424 char *dstart, *dend;
4425 unsigned int data_size;
4426 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4427 time_t create_time, mtime, atime, c_time;
4428 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4435 uint64_t file_size = 0;
4437 uint64_t allocation_size = 0;
4438 uint64_t file_index = 0;
4439 uint32_t access_mask = 0;
4441 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4442 return NT_STATUS_INVALID_LEVEL;
4445 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4446 smb_fname_str_dbg(smb_fname),
4448 info_level, max_data_bytes));
4450 mode = dos_mode(conn, smb_fname);
4451 nlink = psbuf->st_ex_nlink;
4453 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4457 if ((nlink > 0) && delete_pending) {
4461 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4462 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4463 if (*ppdata == NULL) {
4464 return NT_STATUS_NO_MEMORY;
4468 dend = dstart + data_size - 1;
4470 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4471 update_stat_ex_mtime(psbuf, write_time_ts);
4474 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4475 mtime_ts = psbuf->st_ex_mtime;
4476 atime_ts = psbuf->st_ex_atime;
4477 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4479 if (lp_dos_filetime_resolution(SNUM(conn))) {
4480 dos_filetime_timespec(&create_time_ts);
4481 dos_filetime_timespec(&mtime_ts);
4482 dos_filetime_timespec(&atime_ts);
4483 dos_filetime_timespec(&ctime_ts);
4486 create_time = convert_timespec_to_time_t(create_time_ts);
4487 mtime = convert_timespec_to_time_t(mtime_ts);
4488 atime = convert_timespec_to_time_t(atime_ts);
4489 c_time = convert_timespec_to_time_t(ctime_ts);
4491 p = strrchr_m(smb_fname->base_name,'/');
4493 base_name = smb_fname->base_name;
4497 /* NT expects the name to be in an exact form of the *full*
4498 filename. See the trans2 torture test */
4499 if (ISDOT(base_name)) {
4500 dos_fname = talloc_strdup(mem_ctx, "\\");
4502 return NT_STATUS_NO_MEMORY;
4505 dos_fname = talloc_asprintf(mem_ctx,
4507 smb_fname->base_name);
4509 return NT_STATUS_NO_MEMORY;
4511 if (is_ntfs_stream_smb_fname(smb_fname)) {
4512 dos_fname = talloc_asprintf(dos_fname, "%s",
4513 smb_fname->stream_name);
4515 return NT_STATUS_NO_MEMORY;
4519 string_replace(dos_fname, '/', '\\');
4522 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4525 /* Do we have this path open ? */
4527 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4528 fsp1 = file_find_di_first(conn->sconn, fileid);
4529 if (fsp1 && fsp1->initial_allocation_size) {
4530 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4534 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4535 file_size = get_file_size_stat(psbuf);
4539 pos = fsp->fh->position_information;
4543 access_mask = fsp->access_mask;
4545 /* GENERIC_EXECUTE mapping from Windows */
4546 access_mask = 0x12019F;
4549 /* This should be an index number - looks like
4552 I think this causes us to fail the IFSKIT
4553 BasicFileInformationTest. -tpot */
4554 file_index = get_FileIndex(conn, psbuf);
4556 switch (info_level) {
4557 case SMB_INFO_STANDARD:
4558 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4560 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4561 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4562 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4563 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4564 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4565 SSVAL(pdata,l1_attrFile,mode);
4568 case SMB_INFO_QUERY_EA_SIZE:
4570 unsigned int ea_size =
4571 estimate_ea_size(conn, fsp,
4573 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4575 srv_put_dos_date2(pdata,0,create_time);
4576 srv_put_dos_date2(pdata,4,atime);
4577 srv_put_dos_date2(pdata,8,mtime); /* write time */
4578 SIVAL(pdata,12,(uint32)file_size);
4579 SIVAL(pdata,16,(uint32)allocation_size);
4580 SSVAL(pdata,20,mode);
4581 SIVAL(pdata,22,ea_size);
4585 case SMB_INFO_IS_NAME_VALID:
4586 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4588 /* os/2 needs this ? really ?*/
4589 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4591 /* This is only reached for qpathinfo */
4595 case SMB_INFO_QUERY_EAS_FROM_LIST:
4597 size_t total_ea_len = 0;
4598 struct ea_list *ea_file_list = NULL;
4599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4602 get_ea_list_from_file(mem_ctx, conn, fsp,
4604 &total_ea_len, &ea_file_list);
4605 if (!NT_STATUS_IS_OK(status)) {
4609 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4611 if (!ea_list || (total_ea_len > data_size)) {
4613 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4617 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4621 case SMB_INFO_QUERY_ALL_EAS:
4623 /* We have data_size bytes to put EA's into. */
4624 size_t total_ea_len = 0;
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4627 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4629 &total_ea_len, &ea_list);
4630 if (!NT_STATUS_IS_OK(status)) {
4634 if (!ea_list || (total_ea_len > data_size)) {
4636 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4640 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4644 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4646 /* This is FileFullEaInformation - 0xF which maps to
4647 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4649 /* We have data_size bytes to put EA's into. */
4650 size_t total_ea_len = 0;
4651 struct ea_list *ea_file_list = NULL;
4653 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4655 /*TODO: add filtering and index handling */
4658 get_ea_list_from_file(mem_ctx, conn, fsp,
4660 &total_ea_len, &ea_file_list);
4661 if (!NT_STATUS_IS_OK(status)) {
4664 if (!ea_file_list) {
4665 return NT_STATUS_NO_EAS_ON_FILE;
4668 status = fill_ea_chained_buffer(mem_ctx,
4672 conn, ea_file_list);
4673 if (!NT_STATUS_IS_OK(status)) {
4679 case SMB_FILE_BASIC_INFORMATION:
4680 case SMB_QUERY_FILE_BASIC_INFO:
4682 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4683 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4684 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4686 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4690 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4691 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4692 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4693 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4694 SIVAL(pdata,32,mode);
4696 DEBUG(5,("SMB_QFBI - "));
4697 DEBUG(5,("create: %s ", ctime(&create_time)));
4698 DEBUG(5,("access: %s ", ctime(&atime)));
4699 DEBUG(5,("write: %s ", ctime(&mtime)));
4700 DEBUG(5,("change: %s ", ctime(&c_time)));
4701 DEBUG(5,("mode: %x\n", mode));
4704 case SMB_FILE_STANDARD_INFORMATION:
4705 case SMB_QUERY_FILE_STANDARD_INFO:
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4709 SOFF_T(pdata,0,allocation_size);
4710 SOFF_T(pdata,8,file_size);
4711 SIVAL(pdata,16,nlink);
4712 SCVAL(pdata,20,delete_pending?1:0);
4713 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4714 SSVAL(pdata,22,0); /* Padding. */
4717 case SMB_FILE_EA_INFORMATION:
4718 case SMB_QUERY_FILE_EA_INFO:
4720 unsigned int ea_size =
4721 estimate_ea_size(conn, fsp, smb_fname);
4722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4724 SIVAL(pdata,0,ea_size);
4728 /* Get the 8.3 name - used if NT SMB was negotiated. */
4729 case SMB_QUERY_FILE_ALT_NAME_INFO:
4730 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4733 char mangled_name[13];
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4735 if (!name_to_8_3(base_name,mangled_name,
4736 True,conn->params)) {
4737 return NT_STATUS_NO_MEMORY;
4739 len = srvstr_push(dstart, flags2,
4740 pdata+4, mangled_name,
4741 PTR_DIFF(dend, pdata+4),
4743 data_size = 4 + len;
4748 case SMB_QUERY_FILE_NAME_INFO:
4752 this must be *exactly* right for ACLs on mapped drives to work
4754 len = srvstr_push(dstart, flags2,
4756 PTR_DIFF(dend, pdata+4),
4758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4759 data_size = 4 + len;
4764 case SMB_FILE_ALLOCATION_INFORMATION:
4765 case SMB_QUERY_FILE_ALLOCATION_INFO:
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4768 SOFF_T(pdata,0,allocation_size);
4771 case SMB_FILE_END_OF_FILE_INFORMATION:
4772 case SMB_QUERY_FILE_END_OF_FILEINFO:
4773 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4775 SOFF_T(pdata,0,file_size);
4778 case SMB_QUERY_FILE_ALL_INFO:
4779 case SMB_FILE_ALL_INFORMATION:
4782 unsigned int ea_size =
4783 estimate_ea_size(conn, fsp, smb_fname);
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4785 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4786 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4787 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4788 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4789 SIVAL(pdata,32,mode);
4790 SIVAL(pdata,36,0); /* padding. */
4792 SOFF_T(pdata,0,allocation_size);
4793 SOFF_T(pdata,8,file_size);
4794 SIVAL(pdata,16,nlink);
4795 SCVAL(pdata,20,delete_pending);
4796 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4799 SIVAL(pdata,0,ea_size);
4800 pdata += 4; /* EA info */
4801 len = srvstr_push(dstart, flags2,
4803 PTR_DIFF(dend, pdata+4),
4807 data_size = PTR_DIFF(pdata,(*ppdata));
4811 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4814 unsigned int ea_size =
4815 estimate_ea_size(conn, fsp, smb_fname);
4816 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4817 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4818 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4819 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4820 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4821 SIVAL(pdata, 0x20, mode);
4822 SIVAL(pdata, 0x24, 0); /* padding. */
4823 SBVAL(pdata, 0x28, allocation_size);
4824 SBVAL(pdata, 0x30, file_size);
4825 SIVAL(pdata, 0x38, nlink);
4826 SCVAL(pdata, 0x3C, delete_pending);
4827 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4828 SSVAL(pdata, 0x3E, 0); /* padding */
4829 SBVAL(pdata, 0x40, file_index);
4830 SIVAL(pdata, 0x48, ea_size);
4831 SIVAL(pdata, 0x4C, access_mask);
4832 SBVAL(pdata, 0x50, pos);
4833 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4834 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4838 len = srvstr_push(dstart, flags2,
4840 PTR_DIFF(dend, pdata+4),
4844 data_size = PTR_DIFF(pdata,(*ppdata));
4847 case SMB_FILE_INTERNAL_INFORMATION:
4849 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4850 SBVAL(pdata, 0, file_index);
4854 case SMB_FILE_ACCESS_INFORMATION:
4855 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4856 SIVAL(pdata, 0, access_mask);
4860 case SMB_FILE_NAME_INFORMATION:
4861 /* Pathname with leading '\'. */
4864 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4865 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4866 SIVAL(pdata,0,byte_len);
4867 data_size = 4 + byte_len;
4871 case SMB_FILE_DISPOSITION_INFORMATION:
4872 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4874 SCVAL(pdata,0,delete_pending);
4877 case SMB_FILE_POSITION_INFORMATION:
4878 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4880 SOFF_T(pdata,0,pos);
4883 case SMB_FILE_MODE_INFORMATION:
4884 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4885 SIVAL(pdata,0,mode);
4889 case SMB_FILE_ALIGNMENT_INFORMATION:
4890 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4891 SIVAL(pdata,0,0); /* No alignment needed. */
4896 * NT4 server just returns "invalid query" to this - if we try
4897 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4900 /* The first statement above is false - verified using Thursby
4901 * client against NT4 -- gcolley.
4903 case SMB_QUERY_FILE_STREAM_INFO:
4904 case SMB_FILE_STREAM_INFORMATION: {
4905 unsigned int num_streams = 0;
4906 struct stream_struct *streams = NULL;
4908 DEBUG(10,("smbd_do_qfilepathinfo: "
4909 "SMB_FILE_STREAM_INFORMATION\n"));
4911 if (is_ntfs_stream_smb_fname(smb_fname)) {
4912 return NT_STATUS_INVALID_PARAMETER;
4915 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4916 talloc_tos(), &num_streams, &streams);
4918 if (!NT_STATUS_IS_OK(status)) {
4919 DEBUG(10, ("could not get stream info: %s\n",
4920 nt_errstr(status)));
4924 status = marshall_stream_info(num_streams, streams,
4925 pdata, max_data_bytes,
4928 if (!NT_STATUS_IS_OK(status)) {
4929 DEBUG(10, ("marshall_stream_info failed: %s\n",
4930 nt_errstr(status)));
4931 TALLOC_FREE(streams);
4935 TALLOC_FREE(streams);
4939 case SMB_QUERY_COMPRESSION_INFO:
4940 case SMB_FILE_COMPRESSION_INFORMATION:
4941 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4942 SOFF_T(pdata,0,file_size);
4943 SIVAL(pdata,8,0); /* ??? */
4944 SIVAL(pdata,12,0); /* ??? */
4948 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4949 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4950 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4951 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4952 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4953 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4954 SOFF_T(pdata,32,allocation_size);
4955 SOFF_T(pdata,40,file_size);
4956 SIVAL(pdata,48,mode);
4957 SIVAL(pdata,52,0); /* ??? */
4961 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4962 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4963 SIVAL(pdata,0,mode);
4969 * CIFS UNIX Extensions.
4972 case SMB_QUERY_FILE_UNIX_BASIC:
4974 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4975 data_size = PTR_DIFF(pdata,(*ppdata));
4977 DEBUG(4,("smbd_do_qfilepathinfo: "
4978 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4979 dump_data(4, (uint8_t *)(*ppdata), data_size);
4983 case SMB_QUERY_FILE_UNIX_INFO2:
4985 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4986 data_size = PTR_DIFF(pdata,(*ppdata));
4990 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4992 for (i=0; i<100; i++)
4993 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4999 case SMB_QUERY_FILE_UNIX_LINK:
5002 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5005 return NT_STATUS_NO_MEMORY;
5008 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5010 if(!S_ISLNK(psbuf->st_ex_mode)) {
5011 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5014 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5016 len = SMB_VFS_READLINK(conn,
5017 smb_fname->base_name,
5020 return map_nt_error_from_unix(errno);
5023 len = srvstr_push(dstart, flags2,
5025 PTR_DIFF(dend, pdata),
5028 data_size = PTR_DIFF(pdata,(*ppdata));
5033 #if defined(HAVE_POSIX_ACLS)
5034 case SMB_QUERY_POSIX_ACL:
5036 SMB_ACL_T file_acl = NULL;
5037 SMB_ACL_T def_acl = NULL;
5038 uint16 num_file_acls = 0;
5039 uint16 num_def_acls = 0;
5041 if (fsp && fsp->fh->fd != -1) {
5042 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5046 SMB_VFS_SYS_ACL_GET_FILE(conn,
5047 smb_fname->base_name,
5048 SMB_ACL_TYPE_ACCESS,
5052 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5053 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5054 "not implemented on "
5055 "filesystem containing %s\n",
5056 smb_fname->base_name));
5057 return NT_STATUS_NOT_IMPLEMENTED;
5060 if (S_ISDIR(psbuf->st_ex_mode)) {
5061 if (fsp && fsp->is_directory) {
5063 SMB_VFS_SYS_ACL_GET_FILE(
5065 fsp->fsp_name->base_name,
5066 SMB_ACL_TYPE_DEFAULT,
5070 SMB_VFS_SYS_ACL_GET_FILE(
5072 smb_fname->base_name,
5073 SMB_ACL_TYPE_DEFAULT,
5076 def_acl = free_empty_sys_acl(conn, def_acl);
5079 num_file_acls = count_acl_entries(conn, file_acl);
5080 num_def_acls = count_acl_entries(conn, def_acl);
5082 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5083 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5085 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5086 SMB_POSIX_ACL_HEADER_SIZE) ));
5088 TALLOC_FREE(file_acl);
5091 TALLOC_FREE(def_acl);
5093 return NT_STATUS_BUFFER_TOO_SMALL;
5096 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5097 SSVAL(pdata,2,num_file_acls);
5098 SSVAL(pdata,4,num_def_acls);
5099 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5101 TALLOC_FREE(file_acl);
5104 TALLOC_FREE(def_acl);
5106 return NT_STATUS_INTERNAL_ERROR;
5108 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5110 TALLOC_FREE(file_acl);
5113 TALLOC_FREE(def_acl);
5115 return NT_STATUS_INTERNAL_ERROR;
5119 TALLOC_FREE(file_acl);
5122 TALLOC_FREE(def_acl);
5124 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5130 case SMB_QUERY_POSIX_LOCK:
5135 enum brl_type lock_type;
5137 /* We need an open file with a real fd for this. */
5138 if (!fsp || fsp->fh->fd == -1) {
5139 return NT_STATUS_INVALID_LEVEL;
5142 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5143 return NT_STATUS_INVALID_PARAMETER;
5146 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5147 case POSIX_LOCK_TYPE_READ:
5148 lock_type = READ_LOCK;
5150 case POSIX_LOCK_TYPE_WRITE:
5151 lock_type = WRITE_LOCK;
5153 case POSIX_LOCK_TYPE_UNLOCK:
5155 /* There's no point in asking for an unlock... */
5156 return NT_STATUS_INVALID_PARAMETER;
5159 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5160 #if defined(HAVE_LONGLONG)
5161 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5162 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5163 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5164 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5165 #else /* HAVE_LONGLONG */
5166 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5167 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5168 #endif /* HAVE_LONGLONG */
5170 status = query_lock(fsp,
5177 if (ERROR_WAS_LOCK_DENIED(status)) {
5178 /* Here we need to report who has it locked... */
5179 data_size = POSIX_LOCK_DATA_SIZE;
5181 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5182 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5183 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5184 #if defined(HAVE_LONGLONG)
5185 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5186 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5187 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5188 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5189 #else /* HAVE_LONGLONG */
5190 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5191 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5192 #endif /* HAVE_LONGLONG */
5194 } else if (NT_STATUS_IS_OK(status)) {
5195 /* For success we just return a copy of what we sent
5196 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5197 data_size = POSIX_LOCK_DATA_SIZE;
5198 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5199 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5207 return NT_STATUS_INVALID_LEVEL;
5210 *pdata_size = data_size;
5211 return NT_STATUS_OK;
5214 /****************************************************************************
5215 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5216 file name or file id).
5217 ****************************************************************************/
5219 static void call_trans2qfilepathinfo(connection_struct *conn,
5220 struct smb_request *req,
5221 unsigned int tran_call,
5222 char **pparams, int total_params,
5223 char **ppdata, int total_data,
5224 unsigned int max_data_bytes)
5226 char *params = *pparams;
5227 char *pdata = *ppdata;
5229 unsigned int data_size = 0;
5230 unsigned int param_size = 2;
5231 struct smb_filename *smb_fname = NULL;
5232 bool delete_pending = False;
5233 struct timespec write_time_ts;
5234 files_struct *fsp = NULL;
5235 struct file_id fileid;
5236 struct ea_list *ea_list = NULL;
5237 int lock_data_count = 0;
5238 char *lock_data = NULL;
5239 NTSTATUS status = NT_STATUS_OK;
5242 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5246 ZERO_STRUCT(write_time_ts);
5248 if (tran_call == TRANSACT2_QFILEINFO) {
5249 if (total_params < 4) {
5250 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5255 call_trans2qpipeinfo(conn, req, tran_call,
5256 pparams, total_params,
5262 fsp = file_fsp(req, SVAL(params,0));
5263 info_level = SVAL(params,2);
5265 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5267 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5268 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5272 /* Initial check for valid fsp ptr. */
5273 if (!check_fsp_open(conn, req, fsp)) {
5277 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5278 if (smb_fname == NULL) {
5279 reply_nterror(req, NT_STATUS_NO_MEMORY);
5283 if(fsp->fake_file_handle) {
5285 * This is actually for the QUOTA_FAKE_FILE --metze
5288 /* We know this name is ok, it's already passed the checks. */
5290 } else if(fsp->fh->fd == -1) {
5292 * This is actually a QFILEINFO on a directory
5293 * handle (returned from an NT SMB). NT5.0 seems
5294 * to do this call. JRA.
5297 if (INFO_LEVEL_IS_UNIX(info_level)) {
5298 /* Always do lstat for UNIX calls. */
5299 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5300 DEBUG(3,("call_trans2qfilepathinfo: "
5301 "SMB_VFS_LSTAT of %s failed "
5303 smb_fname_str_dbg(smb_fname),
5306 map_nt_error_from_unix(errno));
5309 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5310 DEBUG(3,("call_trans2qfilepathinfo: "
5311 "SMB_VFS_STAT of %s failed (%s)\n",
5312 smb_fname_str_dbg(smb_fname),
5315 map_nt_error_from_unix(errno));
5319 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5320 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5323 * Original code - this is an open file.
5325 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5326 DEBUG(3, ("fstat of %s failed (%s)\n",
5327 fsp_fnum_dbg(fsp), strerror(errno)));
5329 map_nt_error_from_unix(errno));
5332 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5333 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5339 uint32_t ucf_flags = 0;
5342 if (total_params < 7) {
5343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5347 info_level = SVAL(params,0);
5349 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5351 if (INFO_LEVEL_IS_UNIX(info_level)) {
5352 if (!lp_unix_extensions()) {
5353 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5356 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5357 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5358 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5359 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5363 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5365 STR_TERMINATE, &status);
5366 if (!NT_STATUS_IS_OK(status)) {
5367 reply_nterror(req, status);
5371 status = filename_convert(req,
5373 req->flags2 & FLAGS2_DFS_PATHNAMES,
5378 if (!NT_STATUS_IS_OK(status)) {
5379 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5380 reply_botherror(req,
5381 NT_STATUS_PATH_NOT_COVERED,
5382 ERRSRV, ERRbadpath);
5385 reply_nterror(req, status);
5389 /* If this is a stream, check if there is a delete_pending. */
5390 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5391 && is_ntfs_stream_smb_fname(smb_fname)) {
5392 struct smb_filename *smb_fname_base;
5394 /* Create an smb_filename with stream_name == NULL. */
5395 smb_fname_base = synthetic_smb_fname(
5396 talloc_tos(), smb_fname->base_name,
5398 if (smb_fname_base == NULL) {
5399 reply_nterror(req, NT_STATUS_NO_MEMORY);
5403 if (INFO_LEVEL_IS_UNIX(info_level)) {
5404 /* Always do lstat for UNIX calls. */
5405 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5406 DEBUG(3,("call_trans2qfilepathinfo: "
5407 "SMB_VFS_LSTAT of %s failed "
5409 smb_fname_str_dbg(smb_fname_base),
5411 TALLOC_FREE(smb_fname_base);
5413 map_nt_error_from_unix(errno));
5417 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5418 DEBUG(3,("call_trans2qfilepathinfo: "
5419 "fileinfo of %s failed "
5421 smb_fname_str_dbg(smb_fname_base),
5423 TALLOC_FREE(smb_fname_base);
5425 map_nt_error_from_unix(errno));
5430 status = file_name_hash(conn,
5431 smb_fname_str_dbg(smb_fname_base),
5433 if (!NT_STATUS_IS_OK(status)) {
5434 TALLOC_FREE(smb_fname_base);
5435 reply_nterror(req, status);
5439 fileid = vfs_file_id_from_sbuf(conn,
5440 &smb_fname_base->st);
5441 TALLOC_FREE(smb_fname_base);
5442 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5443 if (delete_pending) {
5444 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5449 if (INFO_LEVEL_IS_UNIX(info_level)) {
5450 /* Always do lstat for UNIX calls. */
5451 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5452 DEBUG(3,("call_trans2qfilepathinfo: "
5453 "SMB_VFS_LSTAT of %s failed (%s)\n",
5454 smb_fname_str_dbg(smb_fname),
5457 map_nt_error_from_unix(errno));
5462 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5463 DEBUG(3,("call_trans2qfilepathinfo: "
5464 "SMB_VFS_STAT of %s failed (%s)\n",
5465 smb_fname_str_dbg(smb_fname),
5468 map_nt_error_from_unix(errno));
5473 status = file_name_hash(conn,
5474 smb_fname_str_dbg(smb_fname),
5476 if (!NT_STATUS_IS_OK(status)) {
5477 reply_nterror(req, status);
5481 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5482 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5483 if (delete_pending) {
5484 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5489 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5490 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5492 info_level,tran_call,total_data));
5494 /* Pull out any data sent here before we realloc. */
5495 switch (info_level) {
5496 case SMB_INFO_QUERY_EAS_FROM_LIST:
5498 /* Pull any EA list from the data portion. */
5501 if (total_data < 4) {
5503 req, NT_STATUS_INVALID_PARAMETER);
5506 ea_size = IVAL(pdata,0);
5508 if (total_data > 0 && ea_size != total_data) {
5509 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5510 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5512 req, NT_STATUS_INVALID_PARAMETER);
5516 if (!lp_ea_support(SNUM(conn))) {
5517 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5521 /* Pull out the list of names. */
5522 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5525 req, NT_STATUS_INVALID_PARAMETER);
5531 case SMB_QUERY_POSIX_LOCK:
5533 if (fsp == NULL || fsp->fh->fd == -1) {
5534 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5538 if (total_data != POSIX_LOCK_DATA_SIZE) {
5540 req, NT_STATUS_INVALID_PARAMETER);
5544 /* Copy the lock range data. */
5545 lock_data = (char *)talloc_memdup(
5546 req, pdata, total_data);
5548 reply_nterror(req, NT_STATUS_NO_MEMORY);
5551 lock_data_count = total_data;
5557 *pparams = (char *)SMB_REALLOC(*pparams,2);
5558 if (*pparams == NULL) {
5559 reply_nterror(req, NT_STATUS_NO_MEMORY);
5566 * draft-leach-cifs-v1-spec-02.txt
5567 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5570 * The requested information is placed in the Data portion of the
5571 * transaction response. For the information levels greater than 0x100,
5572 * the transaction response has 1 parameter word which should be
5573 * ignored by the client.
5575 * However Windows only follows this rule for the IS_NAME_VALID call.
5577 switch (info_level) {
5578 case SMB_INFO_IS_NAME_VALID:
5583 if ((info_level & 0xFF00) == 0xFF00) {
5585 * We use levels that start with 0xFF00
5586 * internally to represent SMB2 specific levels
5588 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5592 status = smbd_do_qfilepathinfo(conn, req, info_level,
5594 delete_pending, write_time_ts,
5596 lock_data_count, lock_data,
5597 req->flags2, max_data_bytes,
5598 ppdata, &data_size);
5599 if (!NT_STATUS_IS_OK(status)) {
5600 reply_nterror(req, status);
5604 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5610 /****************************************************************************
5611 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5613 ****************************************************************************/
5615 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5616 connection_struct *conn,
5617 struct smb_request *req,
5618 bool overwrite_if_exists,
5619 const struct smb_filename *smb_fname_old,
5620 struct smb_filename *smb_fname_new)
5622 NTSTATUS status = NT_STATUS_OK;
5624 /* source must already exist. */
5625 if (!VALID_STAT(smb_fname_old->st)) {
5626 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5629 if (VALID_STAT(smb_fname_new->st)) {
5630 if (overwrite_if_exists) {
5631 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5632 return NT_STATUS_FILE_IS_A_DIRECTORY;
5634 status = unlink_internals(conn,
5636 FILE_ATTRIBUTE_NORMAL,
5639 if (!NT_STATUS_IS_OK(status)) {
5643 /* Disallow if newname already exists. */
5644 return NT_STATUS_OBJECT_NAME_COLLISION;
5648 /* No links from a directory. */
5649 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5650 return NT_STATUS_FILE_IS_A_DIRECTORY;
5653 /* Setting a hardlink to/from a stream isn't currently supported. */
5654 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5655 is_ntfs_stream_smb_fname(smb_fname_new)) {
5656 return NT_STATUS_INVALID_PARAMETER;
5659 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5660 smb_fname_old->base_name, smb_fname_new->base_name));
5662 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5663 smb_fname_new->base_name) != 0) {
5664 status = map_nt_error_from_unix(errno);
5665 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5666 nt_errstr(status), smb_fname_old->base_name,
5667 smb_fname_new->base_name));
5672 /****************************************************************************
5673 Deal with setting the time from any of the setfilepathinfo functions.
5674 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5675 calling this function.
5676 ****************************************************************************/
5678 NTSTATUS smb_set_file_time(connection_struct *conn,
5680 const struct smb_filename *smb_fname,
5681 struct smb_file_time *ft,
5682 bool setting_write_time)
5684 struct smb_filename smb_fname_base;
5686 FILE_NOTIFY_CHANGE_LAST_ACCESS
5687 |FILE_NOTIFY_CHANGE_LAST_WRITE
5688 |FILE_NOTIFY_CHANGE_CREATION;
5690 if (!VALID_STAT(smb_fname->st)) {
5691 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5694 /* get some defaults (no modifications) if any info is zero or -1. */
5695 if (null_timespec(ft->create_time)) {
5696 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5699 if (null_timespec(ft->atime)) {
5700 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5703 if (null_timespec(ft->mtime)) {
5704 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5707 if (!setting_write_time) {
5708 /* ft->mtime comes from change time, not write time. */
5709 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5712 /* Ensure the resolution is the correct for
5713 * what we can store on this filesystem. */
5715 round_timespec(conn->ts_res, &ft->create_time);
5716 round_timespec(conn->ts_res, &ft->ctime);
5717 round_timespec(conn->ts_res, &ft->atime);
5718 round_timespec(conn->ts_res, &ft->mtime);
5720 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5721 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5722 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5723 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5724 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5725 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5726 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5727 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5729 if (setting_write_time) {
5731 * This was a Windows setfileinfo on an open file.
5732 * NT does this a lot. We also need to
5733 * set the time here, as it can be read by
5734 * FindFirst/FindNext and with the patch for bug #2045
5735 * in smbd/fileio.c it ensures that this timestamp is
5736 * kept sticky even after a write. We save the request
5737 * away and will set it on file close and after a write. JRA.
5740 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5741 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5744 if (fsp->base_fsp) {
5745 set_sticky_write_time_fsp(fsp->base_fsp,
5748 set_sticky_write_time_fsp(fsp, ft->mtime);
5751 set_sticky_write_time_path(
5752 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5757 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5759 /* Always call ntimes on the base, even if a stream was passed in. */
5760 smb_fname_base = *smb_fname;
5761 smb_fname_base.stream_name = NULL;
5763 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5764 return map_nt_error_from_unix(errno);
5767 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5768 smb_fname->base_name);
5769 return NT_STATUS_OK;
5772 /****************************************************************************
5773 Deal with setting the dosmode from any of the setfilepathinfo functions.
5774 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5775 done before calling this function.
5776 ****************************************************************************/
5778 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5779 const struct smb_filename *smb_fname,
5782 struct smb_filename *smb_fname_base;
5785 if (!VALID_STAT(smb_fname->st)) {
5786 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5789 /* Always operate on the base_name, even if a stream was passed in. */
5790 smb_fname_base = synthetic_smb_fname(
5791 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5792 if (smb_fname_base == NULL) {
5793 return NT_STATUS_NO_MEMORY;
5797 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5798 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5800 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5804 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5806 /* check the mode isn't different, before changing it */
5807 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5808 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5809 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5810 (unsigned int)dosmode));
5812 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5814 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5816 smb_fname_str_dbg(smb_fname_base),
5818 status = map_nt_error_from_unix(errno);
5822 status = NT_STATUS_OK;
5824 TALLOC_FREE(smb_fname_base);
5828 /****************************************************************************
5829 Deal with setting the size from any of the setfilepathinfo functions.
5830 ****************************************************************************/
5832 static NTSTATUS smb_set_file_size(connection_struct *conn,
5833 struct smb_request *req,
5835 const struct smb_filename *smb_fname,
5836 const SMB_STRUCT_STAT *psbuf,
5838 bool fail_after_createfile)
5840 NTSTATUS status = NT_STATUS_OK;
5841 struct smb_filename *smb_fname_tmp = NULL;
5842 files_struct *new_fsp = NULL;
5844 if (!VALID_STAT(*psbuf)) {
5845 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5848 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5850 if (size == get_file_size_stat(psbuf)) {
5851 return NT_STATUS_OK;
5854 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5855 smb_fname_str_dbg(smb_fname), (double)size));
5857 if (fsp && fsp->fh->fd != -1) {
5858 /* Handle based call. */
5859 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5860 return NT_STATUS_ACCESS_DENIED;
5863 if (vfs_set_filelen(fsp, size) == -1) {
5864 return map_nt_error_from_unix(errno);
5866 trigger_write_time_update_immediate(fsp);
5867 return NT_STATUS_OK;
5870 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5871 if (smb_fname_tmp == NULL) {
5872 return NT_STATUS_NO_MEMORY;
5875 smb_fname_tmp->st = *psbuf;
5877 status = SMB_VFS_CREATE_FILE(
5880 0, /* root_dir_fid */
5881 smb_fname_tmp, /* fname */
5882 FILE_WRITE_DATA, /* access_mask */
5883 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5885 FILE_OPEN, /* create_disposition*/
5886 0, /* create_options */
5887 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5888 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5889 0, /* allocation_size */
5890 0, /* private_flags */
5893 &new_fsp, /* result */
5896 TALLOC_FREE(smb_fname_tmp);
5898 if (!NT_STATUS_IS_OK(status)) {
5899 /* NB. We check for open_was_deferred in the caller. */
5903 /* See RAW-SFILEINFO-END-OF-FILE */
5904 if (fail_after_createfile) {
5905 close_file(req, new_fsp,NORMAL_CLOSE);
5906 return NT_STATUS_INVALID_LEVEL;
5909 if (vfs_set_filelen(new_fsp, size) == -1) {
5910 status = map_nt_error_from_unix(errno);
5911 close_file(req, new_fsp,NORMAL_CLOSE);
5915 trigger_write_time_update_immediate(new_fsp);
5916 close_file(req, new_fsp,NORMAL_CLOSE);
5917 return NT_STATUS_OK;
5920 /****************************************************************************
5921 Deal with SMB_INFO_SET_EA.
5922 ****************************************************************************/
5924 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5928 const struct smb_filename *smb_fname)
5930 struct ea_list *ea_list = NULL;
5931 TALLOC_CTX *ctx = NULL;
5932 NTSTATUS status = NT_STATUS_OK;
5934 if (total_data < 10) {
5936 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5937 length. They seem to have no effect. Bug #3212. JRA */
5939 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5940 /* We're done. We only get EA info in this call. */
5941 return NT_STATUS_OK;
5944 return NT_STATUS_INVALID_PARAMETER;
5947 if (IVAL(pdata,0) > total_data) {
5948 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5949 IVAL(pdata,0), (unsigned int)total_data));
5950 return NT_STATUS_INVALID_PARAMETER;
5954 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5956 return NT_STATUS_INVALID_PARAMETER;
5959 status = set_ea(conn, fsp, smb_fname, ea_list);
5964 /****************************************************************************
5965 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5966 ****************************************************************************/
5968 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5973 struct ea_list *ea_list = NULL;
5977 return NT_STATUS_INVALID_HANDLE;
5980 if (!lp_ea_support(SNUM(conn))) {
5981 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5982 "EA's not supported.\n",
5983 (unsigned int)total_data));
5984 return NT_STATUS_EAS_NOT_SUPPORTED;
5987 if (total_data < 10) {
5988 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5990 (unsigned int)total_data));
5991 return NT_STATUS_INVALID_PARAMETER;
5994 ea_list = read_nttrans_ea_list(talloc_tos(),
5999 return NT_STATUS_INVALID_PARAMETER;
6002 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6004 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6005 smb_fname_str_dbg(fsp->fsp_name),
6006 nt_errstr(status) ));
6012 /****************************************************************************
6013 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6014 ****************************************************************************/
6016 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6020 struct smb_filename *smb_fname)
6022 NTSTATUS status = NT_STATUS_OK;
6023 bool delete_on_close;
6026 if (total_data < 1) {
6027 return NT_STATUS_INVALID_PARAMETER;
6031 return NT_STATUS_INVALID_HANDLE;
6034 delete_on_close = (CVAL(pdata,0) ? True : False);
6035 dosmode = dos_mode(conn, smb_fname);
6037 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6038 "delete_on_close = %u\n",
6039 smb_fname_str_dbg(smb_fname),
6040 (unsigned int)dosmode,
6041 (unsigned int)delete_on_close ));
6043 if (delete_on_close) {
6044 status = can_set_delete_on_close(fsp, dosmode);
6045 if (!NT_STATUS_IS_OK(status)) {
6050 /* The set is across all open files on this dev/inode pair. */
6051 if (!set_delete_on_close(fsp, delete_on_close,
6052 conn->session_info->security_token,
6053 conn->session_info->unix_token)) {
6054 return NT_STATUS_ACCESS_DENIED;
6056 return NT_STATUS_OK;
6059 /****************************************************************************
6060 Deal with SMB_FILE_POSITION_INFORMATION.
6061 ****************************************************************************/
6063 static NTSTATUS smb_file_position_information(connection_struct *conn,
6068 uint64_t position_information;
6070 if (total_data < 8) {
6071 return NT_STATUS_INVALID_PARAMETER;
6075 /* Ignore on pathname based set. */
6076 return NT_STATUS_OK;
6079 position_information = (uint64_t)IVAL(pdata,0);
6080 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6082 DEBUG(10,("smb_file_position_information: Set file position "
6083 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6084 (double)position_information));
6085 fsp->fh->position_information = position_information;
6086 return NT_STATUS_OK;
6089 /****************************************************************************
6090 Deal with SMB_FILE_MODE_INFORMATION.
6091 ****************************************************************************/
6093 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6099 if (total_data < 4) {
6100 return NT_STATUS_INVALID_PARAMETER;
6102 mode = IVAL(pdata,0);
6103 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6104 return NT_STATUS_INVALID_PARAMETER;
6106 return NT_STATUS_OK;
6109 /****************************************************************************
6110 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6111 ****************************************************************************/
6113 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6114 struct smb_request *req,
6117 const struct smb_filename *smb_fname)
6119 char *link_target = NULL;
6120 const char *newname = smb_fname->base_name;
6121 TALLOC_CTX *ctx = talloc_tos();
6123 /* Set a symbolic link. */
6124 /* Don't allow this if follow links is false. */
6126 if (total_data == 0) {
6127 return NT_STATUS_INVALID_PARAMETER;
6130 if (!lp_symlinks(SNUM(conn))) {
6131 return NT_STATUS_ACCESS_DENIED;
6134 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6135 total_data, STR_TERMINATE);
6138 return NT_STATUS_INVALID_PARAMETER;
6141 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6142 newname, link_target ));
6144 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6145 return map_nt_error_from_unix(errno);
6148 return NT_STATUS_OK;
6151 /****************************************************************************
6152 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6153 ****************************************************************************/
6155 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6156 struct smb_request *req,
6157 const char *pdata, int total_data,
6158 struct smb_filename *smb_fname_new)
6160 char *oldname = NULL;
6161 struct smb_filename *smb_fname_old = NULL;
6162 TALLOC_CTX *ctx = talloc_tos();
6163 NTSTATUS status = NT_STATUS_OK;
6165 /* Set a hard link. */
6166 if (total_data == 0) {
6167 return NT_STATUS_INVALID_PARAMETER;
6170 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6171 total_data, STR_TERMINATE, &status);
6172 if (!NT_STATUS_IS_OK(status)) {
6176 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6177 smb_fname_str_dbg(smb_fname_new), oldname));
6179 status = filename_convert(ctx,
6181 req->flags2 & FLAGS2_DFS_PATHNAMES,
6186 if (!NT_STATUS_IS_OK(status)) {
6190 return hardlink_internals(ctx, conn, req, false,
6191 smb_fname_old, smb_fname_new);
6194 /****************************************************************************
6195 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6196 ****************************************************************************/
6198 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6199 struct smb_request *req,
6203 struct smb_filename *smb_fname_src)
6207 char *newname = NULL;
6208 struct smb_filename *smb_fname_dst = NULL;
6209 NTSTATUS status = NT_STATUS_OK;
6210 TALLOC_CTX *ctx = talloc_tos();
6213 return NT_STATUS_INVALID_HANDLE;
6216 if (total_data < 20) {
6217 return NT_STATUS_INVALID_PARAMETER;
6220 overwrite = (CVAL(pdata,0) ? True : False);
6221 len = IVAL(pdata,16);
6223 if (len > (total_data - 20) || (len == 0)) {
6224 return NT_STATUS_INVALID_PARAMETER;
6227 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6228 &pdata[20], len, STR_TERMINATE,
6230 if (!NT_STATUS_IS_OK(status)) {
6234 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6237 status = filename_convert(ctx,
6239 req->flags2 & FLAGS2_DFS_PATHNAMES,
6244 if (!NT_STATUS_IS_OK(status)) {
6248 if (fsp->base_fsp) {
6249 /* newname must be a stream name. */
6250 if (newname[0] != ':') {
6251 return NT_STATUS_NOT_SUPPORTED;
6254 /* Create an smb_fname to call rename_internals_fsp() with. */
6255 smb_fname_dst = synthetic_smb_fname(
6256 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6258 if (smb_fname_dst == NULL) {
6259 status = NT_STATUS_NO_MEMORY;
6264 * Set the original last component, since
6265 * rename_internals_fsp() requires it.
6267 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6269 if (smb_fname_dst->original_lcomp == NULL) {
6270 status = NT_STATUS_NO_MEMORY;
6276 DEBUG(10,("smb2_file_rename_information: "
6277 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6278 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6279 smb_fname_str_dbg(smb_fname_dst)));
6280 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6281 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6285 TALLOC_FREE(smb_fname_dst);
6289 static NTSTATUS smb_file_link_information(connection_struct *conn,
6290 struct smb_request *req,
6294 struct smb_filename *smb_fname_src)
6298 char *newname = NULL;
6299 struct smb_filename *smb_fname_dst = NULL;
6300 NTSTATUS status = NT_STATUS_OK;
6301 TALLOC_CTX *ctx = talloc_tos();
6304 return NT_STATUS_INVALID_HANDLE;
6307 if (total_data < 20) {
6308 return NT_STATUS_INVALID_PARAMETER;
6311 overwrite = (CVAL(pdata,0) ? true : false);
6312 len = IVAL(pdata,16);
6314 if (len > (total_data - 20) || (len == 0)) {
6315 return NT_STATUS_INVALID_PARAMETER;
6318 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6319 &pdata[20], len, STR_TERMINATE,
6321 if (!NT_STATUS_IS_OK(status)) {
6325 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6328 status = filename_convert(ctx,
6330 req->flags2 & FLAGS2_DFS_PATHNAMES,
6335 if (!NT_STATUS_IS_OK(status)) {
6339 if (fsp->base_fsp) {
6340 /* No stream names. */
6341 return NT_STATUS_NOT_SUPPORTED;
6344 DEBUG(10,("smb_file_link_information: "
6345 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6346 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6347 smb_fname_str_dbg(smb_fname_dst)));
6348 status = hardlink_internals(ctx,
6355 TALLOC_FREE(smb_fname_dst);
6359 /****************************************************************************
6360 Deal with SMB_FILE_RENAME_INFORMATION.
6361 ****************************************************************************/
6363 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6364 struct smb_request *req,
6368 struct smb_filename *smb_fname_src)
6373 char *newname = NULL;
6374 struct smb_filename *smb_fname_dst = NULL;
6375 bool dest_has_wcard = False;
6376 NTSTATUS status = NT_STATUS_OK;
6378 TALLOC_CTX *ctx = talloc_tos();
6380 if (total_data < 13) {
6381 return NT_STATUS_INVALID_PARAMETER;
6384 overwrite = (CVAL(pdata,0) ? True : False);
6385 root_fid = IVAL(pdata,4);
6386 len = IVAL(pdata,8);
6388 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6389 return NT_STATUS_INVALID_PARAMETER;
6392 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6395 if (!NT_STATUS_IS_OK(status)) {
6399 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6402 status = resolve_dfspath_wcard(ctx, conn,
6403 req->flags2 & FLAGS2_DFS_PATHNAMES,
6406 !conn->sconn->using_smb2,
6409 if (!NT_STATUS_IS_OK(status)) {
6413 /* Check the new name has no '/' characters. */
6414 if (strchr_m(newname, '/')) {
6415 return NT_STATUS_NOT_SUPPORTED;
6418 if (fsp && fsp->base_fsp) {
6419 /* newname must be a stream name. */
6420 if (newname[0] != ':') {
6421 return NT_STATUS_NOT_SUPPORTED;
6424 /* Create an smb_fname to call rename_internals_fsp() with. */
6425 smb_fname_dst = synthetic_smb_fname(
6426 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6428 if (smb_fname_dst == NULL) {
6429 status = NT_STATUS_NO_MEMORY;
6434 * Set the original last component, since
6435 * rename_internals_fsp() requires it.
6437 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6439 if (smb_fname_dst->original_lcomp == NULL) {
6440 status = NT_STATUS_NO_MEMORY;
6446 * Build up an smb_fname_dst based on the filename passed in.
6447 * We basically just strip off the last component, and put on
6448 * the newname instead.
6450 char *base_name = NULL;
6452 /* newname must *not* be a stream name. */
6453 if (newname[0] == ':') {
6454 return NT_STATUS_NOT_SUPPORTED;
6458 * Strip off the last component (filename) of the path passed
6461 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6463 return NT_STATUS_NO_MEMORY;
6465 p = strrchr_m(base_name, '/');
6469 base_name = talloc_strdup(ctx, "");
6471 return NT_STATUS_NO_MEMORY;
6474 /* Append the new name. */
6475 base_name = talloc_asprintf_append(base_name,
6479 return NT_STATUS_NO_MEMORY;
6482 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6485 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6488 /* If an error we expect this to be
6489 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6491 if (!NT_STATUS_IS_OK(status)) {
6492 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6496 /* Create an smb_fname to call rename_internals_fsp() */
6497 smb_fname_dst = synthetic_smb_fname(
6498 ctx, base_name, NULL, NULL);
6499 if (smb_fname_dst == NULL) {
6500 status = NT_STATUS_NO_MEMORY;
6507 DEBUG(10,("smb_file_rename_information: "
6508 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6509 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6510 smb_fname_str_dbg(smb_fname_dst)));
6511 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6514 DEBUG(10,("smb_file_rename_information: "
6515 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6516 smb_fname_str_dbg(smb_fname_src),
6517 smb_fname_str_dbg(smb_fname_dst)));
6518 status = rename_internals(ctx, conn, req, smb_fname_src,
6519 smb_fname_dst, 0, overwrite, false,
6521 FILE_WRITE_ATTRIBUTES);
6524 TALLOC_FREE(smb_fname_dst);
6528 /****************************************************************************
6529 Deal with SMB_SET_POSIX_ACL.
6530 ****************************************************************************/
6532 #if defined(HAVE_POSIX_ACLS)
6533 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6537 const struct smb_filename *smb_fname)
6539 uint16 posix_acl_version;
6540 uint16 num_file_acls;
6541 uint16 num_def_acls;
6542 bool valid_file_acls = True;
6543 bool valid_def_acls = True;
6545 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6546 return NT_STATUS_INVALID_PARAMETER;
6548 posix_acl_version = SVAL(pdata,0);
6549 num_file_acls = SVAL(pdata,2);
6550 num_def_acls = SVAL(pdata,4);
6552 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6553 valid_file_acls = False;
6557 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6558 valid_def_acls = False;
6562 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6563 return NT_STATUS_INVALID_PARAMETER;
6566 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6567 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6568 return NT_STATUS_INVALID_PARAMETER;
6571 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6572 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6573 (unsigned int)num_file_acls,
6574 (unsigned int)num_def_acls));
6576 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6577 smb_fname->base_name, num_file_acls,
6578 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6579 return map_nt_error_from_unix(errno);
6582 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6583 smb_fname->base_name, &smb_fname->st, num_def_acls,
6584 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6585 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6586 return map_nt_error_from_unix(errno);
6588 return NT_STATUS_OK;
6592 /****************************************************************************
6593 Deal with SMB_SET_POSIX_LOCK.
6594 ****************************************************************************/
6596 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6597 struct smb_request *req,
6605 bool blocking_lock = False;
6606 enum brl_type lock_type;
6608 NTSTATUS status = NT_STATUS_OK;
6610 if (fsp == NULL || fsp->fh->fd == -1) {
6611 return NT_STATUS_INVALID_HANDLE;
6614 if (total_data != POSIX_LOCK_DATA_SIZE) {
6615 return NT_STATUS_INVALID_PARAMETER;
6618 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6619 case POSIX_LOCK_TYPE_READ:
6620 lock_type = READ_LOCK;
6622 case POSIX_LOCK_TYPE_WRITE:
6623 /* Return the right POSIX-mappable error code for files opened read-only. */
6624 if (!fsp->can_write) {
6625 return NT_STATUS_INVALID_HANDLE;
6627 lock_type = WRITE_LOCK;
6629 case POSIX_LOCK_TYPE_UNLOCK:
6630 lock_type = UNLOCK_LOCK;
6633 return NT_STATUS_INVALID_PARAMETER;
6636 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6637 blocking_lock = False;
6638 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6639 blocking_lock = True;
6641 return NT_STATUS_INVALID_PARAMETER;
6644 if (!lp_blocking_locks(SNUM(conn))) {
6645 blocking_lock = False;
6648 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6649 #if defined(HAVE_LONGLONG)
6650 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6651 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6652 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6653 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6654 #else /* HAVE_LONGLONG */
6655 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6656 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6657 #endif /* HAVE_LONGLONG */
6659 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6660 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6662 (unsigned int)lock_type,
6663 (unsigned long long)smblctx,
6667 if (lock_type == UNLOCK_LOCK) {
6668 status = do_unlock(req->sconn->msg_ctx,
6675 uint64_t block_smblctx;
6677 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6689 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6691 * A blocking lock was requested. Package up
6692 * this smb into a queued request and push it
6693 * onto the blocking lock queue.
6695 if(push_blocking_lock_request(br_lck,
6698 -1, /* infinite timeout. */
6706 TALLOC_FREE(br_lck);
6710 TALLOC_FREE(br_lck);
6716 /****************************************************************************
6717 Deal with SMB_SET_FILE_BASIC_INFO.
6718 ****************************************************************************/
6720 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6724 const struct smb_filename *smb_fname)
6726 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6727 struct smb_file_time ft;
6729 NTSTATUS status = NT_STATUS_OK;
6733 if (total_data < 36) {
6734 return NT_STATUS_INVALID_PARAMETER;
6737 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6738 if (!NT_STATUS_IS_OK(status)) {
6742 /* Set the attributes */
6743 dosmode = IVAL(pdata,32);
6744 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6745 if (!NT_STATUS_IS_OK(status)) {
6750 ft.create_time = interpret_long_date(pdata);
6753 ft.atime = interpret_long_date(pdata+8);
6756 ft.mtime = interpret_long_date(pdata+16);
6759 ft.ctime = interpret_long_date(pdata+24);
6761 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6762 smb_fname_str_dbg(smb_fname)));
6764 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6768 /****************************************************************************
6769 Deal with SMB_INFO_STANDARD.
6770 ****************************************************************************/
6772 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6776 const struct smb_filename *smb_fname)
6779 struct smb_file_time ft;
6783 if (total_data < 12) {
6784 return NT_STATUS_INVALID_PARAMETER;
6788 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6790 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6792 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6794 DEBUG(10,("smb_set_info_standard: file %s\n",
6795 smb_fname_str_dbg(smb_fname)));
6797 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6798 if (!NT_STATUS_IS_OK(status)) {
6802 return smb_set_file_time(conn,
6809 /****************************************************************************
6810 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6811 ****************************************************************************/
6813 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6814 struct smb_request *req,
6818 struct smb_filename *smb_fname)
6820 uint64_t allocation_size = 0;
6821 NTSTATUS status = NT_STATUS_OK;
6822 files_struct *new_fsp = NULL;
6824 if (!VALID_STAT(smb_fname->st)) {
6825 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6828 if (total_data < 8) {
6829 return NT_STATUS_INVALID_PARAMETER;
6832 allocation_size = (uint64_t)IVAL(pdata,0);
6833 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6834 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6835 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6836 (double)allocation_size));
6838 if (allocation_size) {
6839 allocation_size = smb_roundup(conn, allocation_size);
6842 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6843 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6844 (double)allocation_size));
6846 if (fsp && fsp->fh->fd != -1) {
6847 /* Open file handle. */
6848 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6849 return NT_STATUS_ACCESS_DENIED;
6852 /* Only change if needed. */
6853 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6854 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6855 return map_nt_error_from_unix(errno);
6858 /* But always update the time. */
6860 * This is equivalent to a write. Ensure it's seen immediately
6861 * if there are no pending writes.
6863 trigger_write_time_update_immediate(fsp);
6864 return NT_STATUS_OK;
6867 /* Pathname or stat or directory file. */
6868 status = SMB_VFS_CREATE_FILE(
6871 0, /* root_dir_fid */
6872 smb_fname, /* fname */
6873 FILE_WRITE_DATA, /* access_mask */
6874 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6876 FILE_OPEN, /* create_disposition*/
6877 0, /* create_options */
6878 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6879 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6880 0, /* allocation_size */
6881 0, /* private_flags */
6884 &new_fsp, /* result */
6887 if (!NT_STATUS_IS_OK(status)) {
6888 /* NB. We check for open_was_deferred in the caller. */
6892 /* Only change if needed. */
6893 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6894 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6895 status = map_nt_error_from_unix(errno);
6896 close_file(req, new_fsp, NORMAL_CLOSE);
6901 /* Changing the allocation size should set the last mod time. */
6903 * This is equivalent to a write. Ensure it's seen immediately
6904 * if there are no pending writes.
6906 trigger_write_time_update_immediate(new_fsp);
6908 close_file(req, new_fsp, NORMAL_CLOSE);
6909 return NT_STATUS_OK;
6912 /****************************************************************************
6913 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6914 ****************************************************************************/
6916 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6917 struct smb_request *req,
6921 const struct smb_filename *smb_fname,
6922 bool fail_after_createfile)
6926 if (total_data < 8) {
6927 return NT_STATUS_INVALID_PARAMETER;
6930 size = IVAL(pdata,0);
6931 size |= (((off_t)IVAL(pdata,4)) << 32);
6932 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6933 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6936 return smb_set_file_size(conn, req,
6941 fail_after_createfile);
6944 /****************************************************************************
6945 Allow a UNIX info mknod.
6946 ****************************************************************************/
6948 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6951 const struct smb_filename *smb_fname)
6953 uint32 file_type = IVAL(pdata,56);
6954 #if defined(HAVE_MAKEDEV)
6955 uint32 dev_major = IVAL(pdata,60);
6956 uint32 dev_minor = IVAL(pdata,68);
6958 SMB_DEV_T dev = (SMB_DEV_T)0;
6959 uint32 raw_unixmode = IVAL(pdata,84);
6963 if (total_data < 100) {
6964 return NT_STATUS_INVALID_PARAMETER;
6967 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6968 PERM_NEW_FILE, &unixmode);
6969 if (!NT_STATUS_IS_OK(status)) {
6973 #if defined(HAVE_MAKEDEV)
6974 dev = makedev(dev_major, dev_minor);
6977 switch (file_type) {
6978 #if defined(S_IFIFO)
6979 case UNIX_TYPE_FIFO:
6980 unixmode |= S_IFIFO;
6983 #if defined(S_IFSOCK)
6984 case UNIX_TYPE_SOCKET:
6985 unixmode |= S_IFSOCK;
6988 #if defined(S_IFCHR)
6989 case UNIX_TYPE_CHARDEV:
6990 unixmode |= S_IFCHR;
6993 #if defined(S_IFBLK)
6994 case UNIX_TYPE_BLKDEV:
6995 unixmode |= S_IFBLK;
6999 return NT_STATUS_INVALID_PARAMETER;
7002 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7003 "%.0f mode 0%o for file %s\n", (double)dev,
7004 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7006 /* Ok - do the mknod. */
7007 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7008 return map_nt_error_from_unix(errno);
7011 /* If any of the other "set" calls fail we
7012 * don't want to end up with a half-constructed mknod.
7015 if (lp_inherit_perms(SNUM(conn))) {
7017 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7019 return NT_STATUS_NO_MEMORY;
7021 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7023 TALLOC_FREE(parent);
7026 return NT_STATUS_OK;
7029 /****************************************************************************
7030 Deal with SMB_SET_FILE_UNIX_BASIC.
7031 ****************************************************************************/
7033 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7034 struct smb_request *req,
7038 const struct smb_filename *smb_fname)
7040 struct smb_file_time ft;
7041 uint32 raw_unixmode;
7044 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7045 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7046 NTSTATUS status = NT_STATUS_OK;
7047 bool delete_on_fail = False;
7048 enum perm_type ptype;
7049 files_struct *all_fsps = NULL;
7050 bool modify_mtime = true;
7052 struct smb_filename *smb_fname_tmp = NULL;
7053 SMB_STRUCT_STAT sbuf;
7057 if (total_data < 100) {
7058 return NT_STATUS_INVALID_PARAMETER;
7061 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7062 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7063 size=IVAL(pdata,0); /* first 8 Bytes are size */
7064 size |= (((off_t)IVAL(pdata,4)) << 32);
7067 ft.atime = interpret_long_date(pdata+24); /* access_time */
7068 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7069 set_owner = (uid_t)IVAL(pdata,40);
7070 set_grp = (gid_t)IVAL(pdata,48);
7071 raw_unixmode = IVAL(pdata,84);
7073 if (VALID_STAT(smb_fname->st)) {
7074 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7075 ptype = PERM_EXISTING_DIR;
7077 ptype = PERM_EXISTING_FILE;
7080 ptype = PERM_NEW_FILE;
7083 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7085 if (!NT_STATUS_IS_OK(status)) {
7089 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7090 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7091 smb_fname_str_dbg(smb_fname), (double)size,
7092 (unsigned int)set_owner, (unsigned int)set_grp,
7093 (int)raw_unixmode));
7095 sbuf = smb_fname->st;
7097 if (!VALID_STAT(sbuf)) {
7099 * The only valid use of this is to create character and block
7100 * devices, and named pipes. This is deprecated (IMHO) and
7101 * a new info level should be used for mknod. JRA.
7104 status = smb_unix_mknod(conn,
7108 if (!NT_STATUS_IS_OK(status)) {
7112 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7113 if (smb_fname_tmp == NULL) {
7114 return NT_STATUS_NO_MEMORY;
7117 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7118 status = map_nt_error_from_unix(errno);
7119 TALLOC_FREE(smb_fname_tmp);
7120 SMB_VFS_UNLINK(conn, smb_fname);
7124 sbuf = smb_fname_tmp->st;
7125 smb_fname = smb_fname_tmp;
7127 /* Ensure we don't try and change anything else. */
7128 raw_unixmode = SMB_MODE_NO_CHANGE;
7129 size = get_file_size_stat(&sbuf);
7130 ft.atime = sbuf.st_ex_atime;
7131 ft.mtime = sbuf.st_ex_mtime;
7133 * We continue here as we might want to change the
7136 delete_on_fail = True;
7140 /* Horrible backwards compatibility hack as an old server bug
7141 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7145 size = get_file_size_stat(&sbuf);
7150 * Deal with the UNIX specific mode set.
7153 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7156 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7157 "setting mode 0%o for file %s\n",
7158 (unsigned int)unixmode,
7159 smb_fname_str_dbg(smb_fname)));
7160 if (fsp && fsp->fh->fd != -1) {
7161 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7163 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7166 return map_nt_error_from_unix(errno);
7171 * Deal with the UNIX specific uid set.
7174 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7175 (sbuf.st_ex_uid != set_owner)) {
7178 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7179 "changing owner %u for path %s\n",
7180 (unsigned int)set_owner,
7181 smb_fname_str_dbg(smb_fname)));
7183 if (fsp && fsp->fh->fd != -1) {
7184 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7187 * UNIX extensions calls must always operate
7190 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7191 set_owner, (gid_t)-1);
7195 status = map_nt_error_from_unix(errno);
7196 if (delete_on_fail) {
7197 SMB_VFS_UNLINK(conn, smb_fname);
7204 * Deal with the UNIX specific gid set.
7207 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7208 (sbuf.st_ex_gid != set_grp)) {
7211 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7212 "changing group %u for file %s\n",
7213 (unsigned int)set_owner,
7214 smb_fname_str_dbg(smb_fname)));
7215 if (fsp && fsp->fh->fd != -1) {
7216 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7219 * UNIX extensions calls must always operate
7222 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7226 status = map_nt_error_from_unix(errno);
7227 if (delete_on_fail) {
7228 SMB_VFS_UNLINK(conn, smb_fname);
7234 /* Deal with any size changes. */
7236 status = smb_set_file_size(conn, req,
7242 if (!NT_STATUS_IS_OK(status)) {
7246 /* Deal with any time changes. */
7247 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7248 /* No change, don't cancel anything. */
7252 id = vfs_file_id_from_sbuf(conn, &sbuf);
7253 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7254 all_fsps = file_find_di_next(all_fsps)) {
7256 * We're setting the time explicitly for UNIX.
7257 * Cancel any pending changes over all handles.
7259 all_fsps->update_write_time_on_close = false;
7260 TALLOC_FREE(all_fsps->update_write_time_event);
7264 * Override the "setting_write_time"
7265 * parameter here as it almost does what
7266 * we need. Just remember if we modified
7267 * mtime and send the notify ourselves.
7269 if (null_timespec(ft.mtime)) {
7270 modify_mtime = false;
7273 status = smb_set_file_time(conn,
7279 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7280 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7285 /****************************************************************************
7286 Deal with SMB_SET_FILE_UNIX_INFO2.
7287 ****************************************************************************/
7289 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7290 struct smb_request *req,
7294 const struct smb_filename *smb_fname)
7300 if (total_data < 116) {
7301 return NT_STATUS_INVALID_PARAMETER;
7304 /* Start by setting all the fields that are common between UNIX_BASIC
7307 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7309 if (!NT_STATUS_IS_OK(status)) {
7313 smb_fflags = IVAL(pdata, 108);
7314 smb_fmask = IVAL(pdata, 112);
7316 /* NB: We should only attempt to alter the file flags if the client
7317 * sends a non-zero mask.
7319 if (smb_fmask != 0) {
7320 int stat_fflags = 0;
7322 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7323 smb_fmask, &stat_fflags)) {
7324 /* Client asked to alter a flag we don't understand. */
7325 return NT_STATUS_INVALID_PARAMETER;
7328 if (fsp && fsp->fh->fd != -1) {
7329 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7330 return NT_STATUS_NOT_SUPPORTED;
7332 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7333 stat_fflags) != 0) {
7334 return map_nt_error_from_unix(errno);
7339 /* XXX: need to add support for changing the create_time here. You
7340 * can do this for paths on Darwin with setattrlist(2). The right way
7341 * to hook this up is probably by extending the VFS utimes interface.
7344 return NT_STATUS_OK;
7347 /****************************************************************************
7348 Create a directory with POSIX semantics.
7349 ****************************************************************************/
7351 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7352 struct smb_request *req,
7355 struct smb_filename *smb_fname,
7356 int *pdata_return_size)
7358 NTSTATUS status = NT_STATUS_OK;
7359 uint32 raw_unixmode = 0;
7360 uint32 mod_unixmode = 0;
7361 mode_t unixmode = (mode_t)0;
7362 files_struct *fsp = NULL;
7363 uint16 info_level_return = 0;
7365 char *pdata = *ppdata;
7367 if (total_data < 18) {
7368 return NT_STATUS_INVALID_PARAMETER;
7371 raw_unixmode = IVAL(pdata,8);
7372 /* Next 4 bytes are not yet defined. */
7374 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7375 PERM_NEW_DIR, &unixmode);
7376 if (!NT_STATUS_IS_OK(status)) {
7380 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7382 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7383 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7385 status = SMB_VFS_CREATE_FILE(
7388 0, /* root_dir_fid */
7389 smb_fname, /* fname */
7390 FILE_READ_ATTRIBUTES, /* access_mask */
7391 FILE_SHARE_NONE, /* share_access */
7392 FILE_CREATE, /* create_disposition*/
7393 FILE_DIRECTORY_FILE, /* create_options */
7394 mod_unixmode, /* file_attributes */
7395 0, /* oplock_request */
7396 0, /* allocation_size */
7397 0, /* private_flags */
7403 if (NT_STATUS_IS_OK(status)) {
7404 close_file(req, fsp, NORMAL_CLOSE);
7407 info_level_return = SVAL(pdata,16);
7409 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7410 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7411 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7412 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7414 *pdata_return_size = 12;
7417 /* Realloc the data size */
7418 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7419 if (*ppdata == NULL) {
7420 *pdata_return_size = 0;
7421 return NT_STATUS_NO_MEMORY;
7425 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7426 SSVAL(pdata,2,0); /* No fnum. */
7427 SIVAL(pdata,4,info); /* Was directory created. */
7429 switch (info_level_return) {
7430 case SMB_QUERY_FILE_UNIX_BASIC:
7431 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7432 SSVAL(pdata,10,0); /* Padding. */
7433 store_file_unix_basic(conn, pdata + 12, fsp,
7436 case SMB_QUERY_FILE_UNIX_INFO2:
7437 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7438 SSVAL(pdata,10,0); /* Padding. */
7439 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7443 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7444 SSVAL(pdata,10,0); /* Padding. */
7451 /****************************************************************************
7452 Open/Create a file with POSIX semantics.
7453 ****************************************************************************/
7455 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7456 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7458 static NTSTATUS smb_posix_open(connection_struct *conn,
7459 struct smb_request *req,
7462 struct smb_filename *smb_fname,
7463 int *pdata_return_size)
7465 bool extended_oplock_granted = False;
7466 char *pdata = *ppdata;
7468 uint32 wire_open_mode = 0;
7469 uint32 raw_unixmode = 0;
7470 uint32 mod_unixmode = 0;
7471 uint32 create_disp = 0;
7472 uint32 access_mask = 0;
7473 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7474 NTSTATUS status = NT_STATUS_OK;
7475 mode_t unixmode = (mode_t)0;
7476 files_struct *fsp = NULL;
7477 int oplock_request = 0;
7479 uint16 info_level_return = 0;
7481 if (total_data < 18) {
7482 return NT_STATUS_INVALID_PARAMETER;
7485 flags = IVAL(pdata,0);
7486 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7487 if (oplock_request) {
7488 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7491 wire_open_mode = IVAL(pdata,4);
7493 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7494 return smb_posix_mkdir(conn, req,
7501 switch (wire_open_mode & SMB_ACCMODE) {
7503 access_mask = SMB_O_RDONLY_MAPPING;
7506 access_mask = SMB_O_WRONLY_MAPPING;
7509 access_mask = (SMB_O_RDONLY_MAPPING|
7510 SMB_O_WRONLY_MAPPING);
7513 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7514 (unsigned int)wire_open_mode ));
7515 return NT_STATUS_INVALID_PARAMETER;
7518 wire_open_mode &= ~SMB_ACCMODE;
7520 /* First take care of O_CREAT|O_EXCL interactions. */
7521 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7522 case (SMB_O_CREAT | SMB_O_EXCL):
7523 /* File exists fail. File not exist create. */
7524 create_disp = FILE_CREATE;
7527 /* File exists open. File not exist create. */
7528 create_disp = FILE_OPEN_IF;
7531 /* O_EXCL on its own without O_CREAT is undefined.
7532 We deliberately ignore it as some versions of
7533 Linux CIFSFS can send a bare O_EXCL on the
7534 wire which other filesystems in the kernel
7535 ignore. See bug 9519 for details. */
7540 /* File exists open. File not exist fail. */
7541 create_disp = FILE_OPEN;
7544 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7545 (unsigned int)wire_open_mode ));
7546 return NT_STATUS_INVALID_PARAMETER;
7549 /* Next factor in the effects of O_TRUNC. */
7550 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7552 if (wire_open_mode & SMB_O_TRUNC) {
7553 switch (create_disp) {
7555 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7556 /* Leave create_disp alone as
7557 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7559 /* File exists fail. File not exist create. */
7562 /* SMB_O_CREAT | SMB_O_TRUNC */
7563 /* File exists overwrite. File not exist create. */
7564 create_disp = FILE_OVERWRITE_IF;
7568 /* File exists overwrite. File not exist fail. */
7569 create_disp = FILE_OVERWRITE;
7572 /* Cannot get here. */
7573 smb_panic("smb_posix_open: logic error");
7574 return NT_STATUS_INVALID_PARAMETER;
7578 raw_unixmode = IVAL(pdata,8);
7579 /* Next 4 bytes are not yet defined. */
7581 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7582 (VALID_STAT(smb_fname->st) ?
7583 PERM_EXISTING_FILE : PERM_NEW_FILE),
7586 if (!NT_STATUS_IS_OK(status)) {
7590 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7592 if (wire_open_mode & SMB_O_SYNC) {
7593 create_options |= FILE_WRITE_THROUGH;
7595 if (wire_open_mode & SMB_O_APPEND) {
7596 access_mask |= FILE_APPEND_DATA;
7598 if (wire_open_mode & SMB_O_DIRECT) {
7599 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7602 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7603 VALID_STAT_OF_DIR(smb_fname->st)) {
7604 if (access_mask != SMB_O_RDONLY_MAPPING) {
7605 return NT_STATUS_FILE_IS_A_DIRECTORY;
7607 create_options &= ~FILE_NON_DIRECTORY_FILE;
7608 create_options |= FILE_DIRECTORY_FILE;
7611 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7612 smb_fname_str_dbg(smb_fname),
7613 (unsigned int)wire_open_mode,
7614 (unsigned int)unixmode ));
7616 status = SMB_VFS_CREATE_FILE(
7619 0, /* root_dir_fid */
7620 smb_fname, /* fname */
7621 access_mask, /* access_mask */
7622 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7624 create_disp, /* create_disposition*/
7625 create_options, /* create_options */
7626 mod_unixmode, /* file_attributes */
7627 oplock_request, /* oplock_request */
7628 0, /* allocation_size */
7629 0, /* private_flags */
7635 if (!NT_STATUS_IS_OK(status)) {
7639 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7640 extended_oplock_granted = True;
7643 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7644 extended_oplock_granted = True;
7647 info_level_return = SVAL(pdata,16);
7649 /* Allocate the correct return size. */
7651 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7652 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7653 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7654 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7656 *pdata_return_size = 12;
7659 /* Realloc the data size */
7660 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7661 if (*ppdata == NULL) {
7662 close_file(req, fsp, ERROR_CLOSE);
7663 *pdata_return_size = 0;
7664 return NT_STATUS_NO_MEMORY;
7668 if (extended_oplock_granted) {
7669 if (flags & REQUEST_BATCH_OPLOCK) {
7670 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7672 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7674 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7675 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7677 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7680 SSVAL(pdata,2,fsp->fnum);
7681 SIVAL(pdata,4,info); /* Was file created etc. */
7683 switch (info_level_return) {
7684 case SMB_QUERY_FILE_UNIX_BASIC:
7685 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7686 SSVAL(pdata,10,0); /* padding. */
7687 store_file_unix_basic(conn, pdata + 12, fsp,
7690 case SMB_QUERY_FILE_UNIX_INFO2:
7691 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7692 SSVAL(pdata,10,0); /* padding. */
7693 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7697 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7698 SSVAL(pdata,10,0); /* padding. */
7701 return NT_STATUS_OK;
7704 /****************************************************************************
7705 Delete a file with POSIX semantics.
7706 ****************************************************************************/
7708 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7709 struct smb_request *req,
7712 struct smb_filename *smb_fname)
7714 NTSTATUS status = NT_STATUS_OK;
7715 files_struct *fsp = NULL;
7719 int create_options = 0;
7721 struct share_mode_lock *lck = NULL;
7723 if (total_data < 2) {
7724 return NT_STATUS_INVALID_PARAMETER;
7727 flags = SVAL(pdata,0);
7729 if (!VALID_STAT(smb_fname->st)) {
7730 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7733 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7734 !VALID_STAT_OF_DIR(smb_fname->st)) {
7735 return NT_STATUS_NOT_A_DIRECTORY;
7738 DEBUG(10,("smb_posix_unlink: %s %s\n",
7739 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7740 smb_fname_str_dbg(smb_fname)));
7742 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7743 create_options |= FILE_DIRECTORY_FILE;
7746 status = SMB_VFS_CREATE_FILE(
7749 0, /* root_dir_fid */
7750 smb_fname, /* fname */
7751 DELETE_ACCESS, /* access_mask */
7752 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7754 FILE_OPEN, /* create_disposition*/
7755 create_options, /* create_options */
7756 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7757 0, /* oplock_request */
7758 0, /* allocation_size */
7759 0, /* private_flags */
7765 if (!NT_STATUS_IS_OK(status)) {
7770 * Don't lie to client. If we can't really delete due to
7771 * non-POSIX opens return SHARING_VIOLATION.
7774 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7776 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7777 "lock for file %s\n", fsp_str_dbg(fsp)));
7778 close_file(req, fsp, NORMAL_CLOSE);
7779 return NT_STATUS_INVALID_PARAMETER;
7783 * See if others still have the file open. If this is the case, then
7784 * don't delete. If all opens are POSIX delete we can set the delete
7785 * on close disposition.
7787 for (i=0; i<lck->data->num_share_modes; i++) {
7788 struct share_mode_entry *e = &lck->data->share_modes[i];
7789 if (is_valid_share_mode_entry(e)) {
7790 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7793 if (share_mode_stale_pid(lck->data, i)) {
7796 /* Fail with sharing violation. */
7798 close_file(req, fsp, NORMAL_CLOSE);
7799 return NT_STATUS_SHARING_VIOLATION;
7804 * Set the delete on close.
7806 status = smb_set_file_disposition_info(conn,
7814 if (!NT_STATUS_IS_OK(status)) {
7815 close_file(req, fsp, NORMAL_CLOSE);
7818 return close_file(req, fsp, NORMAL_CLOSE);
7821 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7822 struct smb_request *req,
7823 TALLOC_CTX *mem_ctx,
7824 uint16_t info_level,
7826 struct smb_filename *smb_fname,
7827 char **ppdata, int total_data,
7830 char *pdata = *ppdata;
7831 NTSTATUS status = NT_STATUS_OK;
7832 int data_return_size = 0;
7836 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7837 return NT_STATUS_INVALID_LEVEL;
7840 if (!CAN_WRITE(conn)) {
7841 /* Allow POSIX opens. The open path will deny
7842 * any non-readonly opens. */
7843 if (info_level != SMB_POSIX_PATH_OPEN) {
7844 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7848 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7849 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7851 info_level, total_data));
7853 switch (info_level) {
7855 case SMB_INFO_STANDARD:
7857 status = smb_set_info_standard(conn,
7865 case SMB_INFO_SET_EA:
7867 status = smb_info_set_ea(conn,
7875 case SMB_SET_FILE_BASIC_INFO:
7876 case SMB_FILE_BASIC_INFORMATION:
7878 status = smb_set_file_basic_info(conn,
7886 case SMB_FILE_ALLOCATION_INFORMATION:
7887 case SMB_SET_FILE_ALLOCATION_INFO:
7889 status = smb_set_file_allocation_info(conn, req,
7897 case SMB_FILE_END_OF_FILE_INFORMATION:
7898 case SMB_SET_FILE_END_OF_FILE_INFO:
7901 * XP/Win7 both fail after the createfile with
7902 * SMB_SET_FILE_END_OF_FILE_INFO but not
7903 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7904 * The level is known here, so pass it down
7908 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7910 status = smb_set_file_end_of_file_info(conn, req,
7919 case SMB_FILE_DISPOSITION_INFORMATION:
7920 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7923 /* JRA - We used to just ignore this on a path ?
7924 * Shouldn't this be invalid level on a pathname
7927 if (tran_call != TRANSACT2_SETFILEINFO) {
7928 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7931 status = smb_set_file_disposition_info(conn,
7939 case SMB_FILE_POSITION_INFORMATION:
7941 status = smb_file_position_information(conn,
7948 case SMB_FILE_FULL_EA_INFORMATION:
7950 status = smb_set_file_full_ea_info(conn,
7957 /* From tridge Samba4 :
7958 * MODE_INFORMATION in setfileinfo (I have no
7959 * idea what "mode information" on a file is - it takes a value of 0,
7960 * 2, 4 or 6. What could it be?).
7963 case SMB_FILE_MODE_INFORMATION:
7965 status = smb_file_mode_information(conn,
7972 * CIFS UNIX extensions.
7975 case SMB_SET_FILE_UNIX_BASIC:
7977 status = smb_set_file_unix_basic(conn, req,
7985 case SMB_SET_FILE_UNIX_INFO2:
7987 status = smb_set_file_unix_info2(conn, req,
7995 case SMB_SET_FILE_UNIX_LINK:
7998 /* We must have a pathname for this. */
7999 return NT_STATUS_INVALID_LEVEL;
8001 status = smb_set_file_unix_link(conn, req, pdata,
8002 total_data, smb_fname);
8006 case SMB_SET_FILE_UNIX_HLINK:
8009 /* We must have a pathname for this. */
8010 return NT_STATUS_INVALID_LEVEL;
8012 status = smb_set_file_unix_hlink(conn, req,
8018 case SMB_FILE_RENAME_INFORMATION:
8020 status = smb_file_rename_information(conn, req,
8026 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8028 /* SMB2 rename information. */
8029 status = smb2_file_rename_information(conn, req,
8035 case SMB_FILE_LINK_INFORMATION:
8037 status = smb_file_link_information(conn, req,
8043 #if defined(HAVE_POSIX_ACLS)
8044 case SMB_SET_POSIX_ACL:
8046 status = smb_set_posix_acl(conn,
8055 case SMB_SET_POSIX_LOCK:
8058 return NT_STATUS_INVALID_LEVEL;
8060 status = smb_set_posix_lock(conn, req,
8061 pdata, total_data, fsp);
8065 case SMB_POSIX_PATH_OPEN:
8068 /* We must have a pathname for this. */
8069 return NT_STATUS_INVALID_LEVEL;
8072 status = smb_posix_open(conn, req,
8080 case SMB_POSIX_PATH_UNLINK:
8083 /* We must have a pathname for this. */
8084 return NT_STATUS_INVALID_LEVEL;
8087 status = smb_posix_unlink(conn, req,
8095 return NT_STATUS_INVALID_LEVEL;
8098 if (!NT_STATUS_IS_OK(status)) {
8102 *ret_data_size = data_return_size;
8103 return NT_STATUS_OK;
8106 /****************************************************************************
8107 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8108 ****************************************************************************/
8110 static void call_trans2setfilepathinfo(connection_struct *conn,
8111 struct smb_request *req,
8112 unsigned int tran_call,
8113 char **pparams, int total_params,
8114 char **ppdata, int total_data,
8115 unsigned int max_data_bytes)
8117 char *params = *pparams;
8118 char *pdata = *ppdata;
8120 struct smb_filename *smb_fname = NULL;
8121 files_struct *fsp = NULL;
8122 NTSTATUS status = NT_STATUS_OK;
8123 int data_return_size = 0;
8126 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8130 if (tran_call == TRANSACT2_SETFILEINFO) {
8131 if (total_params < 4) {
8132 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8136 fsp = file_fsp(req, SVAL(params,0));
8137 /* Basic check for non-null fsp. */
8138 if (!check_fsp_open(conn, req, fsp)) {
8141 info_level = SVAL(params,2);
8143 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8144 if (smb_fname == NULL) {
8145 reply_nterror(req, NT_STATUS_NO_MEMORY);
8149 if(fsp->fh->fd == -1) {
8151 * This is actually a SETFILEINFO on a directory
8152 * handle (returned from an NT SMB). NT5.0 seems
8153 * to do this call. JRA.
8155 if (INFO_LEVEL_IS_UNIX(info_level)) {
8156 /* Always do lstat for UNIX calls. */
8157 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8158 DEBUG(3,("call_trans2setfilepathinfo: "
8159 "SMB_VFS_LSTAT of %s failed "
8161 smb_fname_str_dbg(smb_fname),
8163 reply_nterror(req, map_nt_error_from_unix(errno));
8167 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8168 DEBUG(3,("call_trans2setfilepathinfo: "
8169 "fileinfo of %s failed (%s)\n",
8170 smb_fname_str_dbg(smb_fname),
8172 reply_nterror(req, map_nt_error_from_unix(errno));
8176 } else if (fsp->print_file) {
8178 * Doing a DELETE_ON_CLOSE should cancel a print job.
8180 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8181 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8183 DEBUG(3,("call_trans2setfilepathinfo: "
8184 "Cancelling print job (%s)\n",
8188 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8194 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8199 * Original code - this is an open file.
8201 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8202 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8203 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8205 reply_nterror(req, map_nt_error_from_unix(errno));
8211 uint32_t ucf_flags = 0;
8214 if (total_params < 7) {
8215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8219 info_level = SVAL(params,0);
8220 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8221 total_params - 6, STR_TERMINATE,
8223 if (!NT_STATUS_IS_OK(status)) {
8224 reply_nterror(req, status);
8228 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8229 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8230 info_level == SMB_FILE_RENAME_INFORMATION ||
8231 info_level == SMB_POSIX_PATH_UNLINK) {
8232 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8235 status = filename_convert(req, conn,
8236 req->flags2 & FLAGS2_DFS_PATHNAMES,
8241 if (!NT_STATUS_IS_OK(status)) {
8242 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8243 reply_botherror(req,
8244 NT_STATUS_PATH_NOT_COVERED,
8245 ERRSRV, ERRbadpath);
8248 reply_nterror(req, status);
8252 if (INFO_LEVEL_IS_UNIX(info_level)) {
8254 * For CIFS UNIX extensions the target name may not exist.
8257 /* Always do lstat for UNIX calls. */
8258 SMB_VFS_LSTAT(conn, smb_fname);
8260 } else if (!VALID_STAT(smb_fname->st) &&
8261 SMB_VFS_STAT(conn, smb_fname)) {
8262 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8264 smb_fname_str_dbg(smb_fname),
8266 reply_nterror(req, map_nt_error_from_unix(errno));
8271 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8272 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8274 info_level,total_data));
8276 /* Realloc the parameter size */
8277 *pparams = (char *)SMB_REALLOC(*pparams,2);
8278 if (*pparams == NULL) {
8279 reply_nterror(req, NT_STATUS_NO_MEMORY);
8286 status = smbd_do_setfilepathinfo(conn, req, req,
8292 if (!NT_STATUS_IS_OK(status)) {
8293 if (open_was_deferred(req->sconn, req->mid)) {
8294 /* We have re-scheduled this call. */
8297 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8298 /* We have re-scheduled this call. */
8301 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8302 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8303 ERRSRV, ERRbadpath);
8306 if (info_level == SMB_POSIX_PATH_OPEN) {
8307 reply_openerror(req, status);
8312 * Invalid EA name needs to return 2 param bytes,
8313 * not a zero-length error packet.
8315 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8316 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8319 reply_nterror(req, status);
8324 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8330 /****************************************************************************
8331 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8332 ****************************************************************************/
8334 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8335 char **pparams, int total_params,
8336 char **ppdata, int total_data,
8337 unsigned int max_data_bytes)
8339 struct smb_filename *smb_dname = NULL;
8340 char *params = *pparams;
8341 char *pdata = *ppdata;
8342 char *directory = NULL;
8343 NTSTATUS status = NT_STATUS_OK;
8344 struct ea_list *ea_list = NULL;
8345 TALLOC_CTX *ctx = talloc_tos();
8347 if (!CAN_WRITE(conn)) {
8348 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8352 if (total_params < 5) {
8353 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8357 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8358 total_params - 4, STR_TERMINATE,
8360 if (!NT_STATUS_IS_OK(status)) {
8361 reply_nterror(req, status);
8365 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8367 status = filename_convert(ctx,
8369 req->flags2 & FLAGS2_DFS_PATHNAMES,
8375 if (!NT_STATUS_IS_OK(status)) {
8376 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8377 reply_botherror(req,
8378 NT_STATUS_PATH_NOT_COVERED,
8379 ERRSRV, ERRbadpath);
8382 reply_nterror(req, status);
8387 * OS/2 workplace shell seems to send SET_EA requests of "null"
8388 * length (4 bytes containing IVAL 4).
8389 * They seem to have no effect. Bug #3212. JRA.
8392 if (total_data && (total_data != 4)) {
8393 /* Any data in this call is an EA list. */
8394 if (total_data < 10) {
8395 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8399 if (IVAL(pdata,0) > total_data) {
8400 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8401 IVAL(pdata,0), (unsigned int)total_data));
8402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8406 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8413 if (!lp_ea_support(SNUM(conn))) {
8414 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8418 /* If total_data == 4 Windows doesn't care what values
8419 * are placed in that field, it just ignores them.
8420 * The System i QNTC IBM SMB client puts bad values here,
8421 * so ignore them. */
8423 status = create_directory(conn, req, smb_dname);
8425 if (!NT_STATUS_IS_OK(status)) {
8426 reply_nterror(req, status);
8430 /* Try and set any given EA. */
8432 status = set_ea(conn, NULL, smb_dname, ea_list);
8433 if (!NT_STATUS_IS_OK(status)) {
8434 reply_nterror(req, status);
8439 /* Realloc the parameter and data sizes */
8440 *pparams = (char *)SMB_REALLOC(*pparams,2);
8441 if(*pparams == NULL) {
8442 reply_nterror(req, NT_STATUS_NO_MEMORY);
8449 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8452 TALLOC_FREE(smb_dname);
8456 /****************************************************************************
8457 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8458 We don't actually do this - we just send a null response.
8459 ****************************************************************************/
8461 static void call_trans2findnotifyfirst(connection_struct *conn,
8462 struct smb_request *req,
8463 char **pparams, int total_params,
8464 char **ppdata, int total_data,
8465 unsigned int max_data_bytes)
8467 char *params = *pparams;
8470 if (total_params < 6) {
8471 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8475 info_level = SVAL(params,4);
8476 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8478 switch (info_level) {
8483 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8487 /* Realloc the parameter and data sizes */
8488 *pparams = (char *)SMB_REALLOC(*pparams,6);
8489 if (*pparams == NULL) {
8490 reply_nterror(req, NT_STATUS_NO_MEMORY);
8495 SSVAL(params,0,fnf_handle);
8496 SSVAL(params,2,0); /* No changes */
8497 SSVAL(params,4,0); /* No EA errors */
8504 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8509 /****************************************************************************
8510 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8511 changes). Currently this does nothing.
8512 ****************************************************************************/
8514 static void call_trans2findnotifynext(connection_struct *conn,
8515 struct smb_request *req,
8516 char **pparams, int total_params,
8517 char **ppdata, int total_data,
8518 unsigned int max_data_bytes)
8520 char *params = *pparams;
8522 DEBUG(3,("call_trans2findnotifynext\n"));
8524 /* Realloc the parameter and data sizes */
8525 *pparams = (char *)SMB_REALLOC(*pparams,4);
8526 if (*pparams == NULL) {
8527 reply_nterror(req, NT_STATUS_NO_MEMORY);
8532 SSVAL(params,0,0); /* No changes */
8533 SSVAL(params,2,0); /* No EA errors */
8535 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8540 /****************************************************************************
8541 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8542 ****************************************************************************/
8544 static void call_trans2getdfsreferral(connection_struct *conn,
8545 struct smb_request *req,
8546 char **pparams, int total_params,
8547 char **ppdata, int total_data,
8548 unsigned int max_data_bytes)
8550 char *params = *pparams;
8551 char *pathname = NULL;
8553 int max_referral_level;
8554 NTSTATUS status = NT_STATUS_OK;
8555 TALLOC_CTX *ctx = talloc_tos();
8557 DEBUG(10,("call_trans2getdfsreferral\n"));
8559 if (total_params < 3) {
8560 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8564 max_referral_level = SVAL(params,0);
8566 if(!lp_host_msdfs()) {
8567 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8571 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8572 total_params - 2, STR_TERMINATE);
8574 reply_nterror(req, NT_STATUS_NOT_FOUND);
8577 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8578 ppdata,&status)) < 0) {
8579 reply_nterror(req, status);
8583 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8584 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8585 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8590 #define LMCAT_SPL 0x53
8591 #define LMFUNC_GETJOBID 0x60
8593 /****************************************************************************
8594 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8595 ****************************************************************************/
8597 static void call_trans2ioctl(connection_struct *conn,
8598 struct smb_request *req,
8599 char **pparams, int total_params,
8600 char **ppdata, int total_data,
8601 unsigned int max_data_bytes)
8603 char *pdata = *ppdata;
8604 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8606 /* check for an invalid fid before proceeding */
8609 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8613 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8614 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8615 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8616 if (*ppdata == NULL) {
8617 reply_nterror(req, NT_STATUS_NO_MEMORY);
8622 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8623 CAN ACCEPT THIS IN UNICODE. JRA. */
8626 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8628 srvstr_push(pdata, req->flags2, pdata + 2,
8629 lp_netbios_name(), 15,
8630 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8631 srvstr_push(pdata, req->flags2, pdata+18,
8632 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8633 STR_ASCII|STR_TERMINATE); /* Service name */
8634 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8639 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8640 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8643 /****************************************************************************
8644 Reply to a SMBfindclose (stop trans2 directory search).
8645 ****************************************************************************/
8647 void reply_findclose(struct smb_request *req)
8650 struct smbd_server_connection *sconn = req->sconn;
8652 START_PROFILE(SMBfindclose);
8655 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8656 END_PROFILE(SMBfindclose);
8660 dptr_num = SVALS(req->vwv+0, 0);
8662 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8664 dptr_close(sconn, &dptr_num);
8666 reply_outbuf(req, 0, 0);
8668 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8670 END_PROFILE(SMBfindclose);
8674 /****************************************************************************
8675 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8676 ****************************************************************************/
8678 void reply_findnclose(struct smb_request *req)
8682 START_PROFILE(SMBfindnclose);
8685 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8686 END_PROFILE(SMBfindnclose);
8690 dptr_num = SVAL(req->vwv+0, 0);
8692 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8694 /* We never give out valid handles for a
8695 findnotifyfirst - so any dptr_num is ok here.
8698 reply_outbuf(req, 0, 0);
8700 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8702 END_PROFILE(SMBfindnclose);
8706 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8707 struct trans_state *state)
8709 if (get_Protocol() >= PROTOCOL_NT1) {
8710 req->flags2 |= 0x40; /* IS_LONG_NAME */
8711 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8714 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8715 if (state->call != TRANSACT2_QFSINFO &&
8716 state->call != TRANSACT2_SETFSINFO) {
8717 DEBUG(0,("handle_trans2: encryption required "
8719 (unsigned int)state->call));
8720 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8725 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8727 /* Now we must call the relevant TRANS2 function */
8728 switch(state->call) {
8729 case TRANSACT2_OPEN:
8731 START_PROFILE(Trans2_open);
8732 call_trans2open(conn, req,
8733 &state->param, state->total_param,
8734 &state->data, state->total_data,
8735 state->max_data_return);
8736 END_PROFILE(Trans2_open);
8740 case TRANSACT2_FINDFIRST:
8742 START_PROFILE(Trans2_findfirst);
8743 call_trans2findfirst(conn, req,
8744 &state->param, state->total_param,
8745 &state->data, state->total_data,
8746 state->max_data_return);
8747 END_PROFILE(Trans2_findfirst);
8751 case TRANSACT2_FINDNEXT:
8753 START_PROFILE(Trans2_findnext);
8754 call_trans2findnext(conn, req,
8755 &state->param, state->total_param,
8756 &state->data, state->total_data,
8757 state->max_data_return);
8758 END_PROFILE(Trans2_findnext);
8762 case TRANSACT2_QFSINFO:
8764 START_PROFILE(Trans2_qfsinfo);
8765 call_trans2qfsinfo(conn, req,
8766 &state->param, state->total_param,
8767 &state->data, state->total_data,
8768 state->max_data_return);
8769 END_PROFILE(Trans2_qfsinfo);
8773 case TRANSACT2_SETFSINFO:
8775 START_PROFILE(Trans2_setfsinfo);
8776 call_trans2setfsinfo(conn, req,
8777 &state->param, state->total_param,
8778 &state->data, state->total_data,
8779 state->max_data_return);
8780 END_PROFILE(Trans2_setfsinfo);
8784 case TRANSACT2_QPATHINFO:
8785 case TRANSACT2_QFILEINFO:
8787 START_PROFILE(Trans2_qpathinfo);
8788 call_trans2qfilepathinfo(conn, req, state->call,
8789 &state->param, state->total_param,
8790 &state->data, state->total_data,
8791 state->max_data_return);
8792 END_PROFILE(Trans2_qpathinfo);
8796 case TRANSACT2_SETPATHINFO:
8797 case TRANSACT2_SETFILEINFO:
8799 START_PROFILE(Trans2_setpathinfo);
8800 call_trans2setfilepathinfo(conn, req, state->call,
8801 &state->param, state->total_param,
8802 &state->data, state->total_data,
8803 state->max_data_return);
8804 END_PROFILE(Trans2_setpathinfo);
8808 case TRANSACT2_FINDNOTIFYFIRST:
8810 START_PROFILE(Trans2_findnotifyfirst);
8811 call_trans2findnotifyfirst(conn, req,
8812 &state->param, state->total_param,
8813 &state->data, state->total_data,
8814 state->max_data_return);
8815 END_PROFILE(Trans2_findnotifyfirst);
8819 case TRANSACT2_FINDNOTIFYNEXT:
8821 START_PROFILE(Trans2_findnotifynext);
8822 call_trans2findnotifynext(conn, req,
8823 &state->param, state->total_param,
8824 &state->data, state->total_data,
8825 state->max_data_return);
8826 END_PROFILE(Trans2_findnotifynext);
8830 case TRANSACT2_MKDIR:
8832 START_PROFILE(Trans2_mkdir);
8833 call_trans2mkdir(conn, req,
8834 &state->param, state->total_param,
8835 &state->data, state->total_data,
8836 state->max_data_return);
8837 END_PROFILE(Trans2_mkdir);
8841 case TRANSACT2_GET_DFS_REFERRAL:
8843 START_PROFILE(Trans2_get_dfs_referral);
8844 call_trans2getdfsreferral(conn, req,
8845 &state->param, state->total_param,
8846 &state->data, state->total_data,
8847 state->max_data_return);
8848 END_PROFILE(Trans2_get_dfs_referral);
8852 case TRANSACT2_IOCTL:
8854 START_PROFILE(Trans2_ioctl);
8855 call_trans2ioctl(conn, req,
8856 &state->param, state->total_param,
8857 &state->data, state->total_data,
8858 state->max_data_return);
8859 END_PROFILE(Trans2_ioctl);
8864 /* Error in request */
8865 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8866 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8870 /****************************************************************************
8871 Reply to a SMBtrans2.
8872 ****************************************************************************/
8874 void reply_trans2(struct smb_request *req)
8876 connection_struct *conn = req->conn;
8881 unsigned int tran_call;
8882 struct trans_state *state;
8885 START_PROFILE(SMBtrans2);
8887 if (req->wct < 14) {
8888 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8889 END_PROFILE(SMBtrans2);
8893 dsoff = SVAL(req->vwv+12, 0);
8894 dscnt = SVAL(req->vwv+11, 0);
8895 psoff = SVAL(req->vwv+10, 0);
8896 pscnt = SVAL(req->vwv+9, 0);
8897 tran_call = SVAL(req->vwv+14, 0);
8899 result = allow_new_trans(conn->pending_trans, req->mid);
8900 if (!NT_STATUS_IS_OK(result)) {
8901 DEBUG(2, ("Got invalid trans2 request: %s\n",
8902 nt_errstr(result)));
8903 reply_nterror(req, result);
8904 END_PROFILE(SMBtrans2);
8909 switch (tran_call) {
8910 /* List the allowed trans2 calls on IPC$ */
8911 case TRANSACT2_OPEN:
8912 case TRANSACT2_GET_DFS_REFERRAL:
8913 case TRANSACT2_QFILEINFO:
8914 case TRANSACT2_QFSINFO:
8915 case TRANSACT2_SETFSINFO:
8918 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8919 END_PROFILE(SMBtrans2);
8924 if ((state = talloc(conn, struct trans_state)) == NULL) {
8925 DEBUG(0, ("talloc failed\n"));
8926 reply_nterror(req, NT_STATUS_NO_MEMORY);
8927 END_PROFILE(SMBtrans2);
8931 state->cmd = SMBtrans2;
8933 state->mid = req->mid;
8934 state->vuid = req->vuid;
8935 state->setup_count = SVAL(req->vwv+13, 0);
8936 state->setup = NULL;
8937 state->total_param = SVAL(req->vwv+0, 0);
8938 state->param = NULL;
8939 state->total_data = SVAL(req->vwv+1, 0);
8941 state->max_param_return = SVAL(req->vwv+2, 0);
8942 state->max_data_return = SVAL(req->vwv+3, 0);
8943 state->max_setup_return = SVAL(req->vwv+4, 0);
8944 state->close_on_completion = BITSETW(req->vwv+5, 0);
8945 state->one_way = BITSETW(req->vwv+5, 1);
8947 state->call = tran_call;
8949 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8950 is so as a sanity check */
8951 if (state->setup_count != 1) {
8953 * Need to have rc=0 for ioctl to get job id for OS/2.
8954 * Network printing will fail if function is not successful.
8955 * Similar function in reply.c will be used if protocol
8956 * is LANMAN1.0 instead of LM1.2X002.
8957 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8958 * outbuf doesn't have to be set(only job id is used).
8960 if ( (state->setup_count == 4)
8961 && (tran_call == TRANSACT2_IOCTL)
8962 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8963 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8964 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8966 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8967 DEBUG(2,("Transaction is %d\n",tran_call));
8969 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8970 END_PROFILE(SMBtrans2);
8975 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8978 if (state->total_data) {
8980 if (trans_oob(state->total_data, 0, dscnt)
8981 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8985 /* Can't use talloc here, the core routines do realloc on the
8986 * params and data. */
8987 state->data = (char *)SMB_MALLOC(state->total_data);
8988 if (state->data == NULL) {
8989 DEBUG(0,("reply_trans2: data malloc fail for %u "
8990 "bytes !\n", (unsigned int)state->total_data));
8992 reply_nterror(req, NT_STATUS_NO_MEMORY);
8993 END_PROFILE(SMBtrans2);
8997 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9000 if (state->total_param) {
9002 if (trans_oob(state->total_param, 0, pscnt)
9003 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9007 /* Can't use talloc here, the core routines do realloc on the
9008 * params and data. */
9009 state->param = (char *)SMB_MALLOC(state->total_param);
9010 if (state->param == NULL) {
9011 DEBUG(0,("reply_trans: param malloc fail for %u "
9012 "bytes !\n", (unsigned int)state->total_param));
9013 SAFE_FREE(state->data);
9015 reply_nterror(req, NT_STATUS_NO_MEMORY);
9016 END_PROFILE(SMBtrans2);
9020 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9023 state->received_data = dscnt;
9024 state->received_param = pscnt;
9026 if ((state->received_param == state->total_param) &&
9027 (state->received_data == state->total_data)) {
9029 handle_trans2(conn, req, state);
9031 SAFE_FREE(state->data);
9032 SAFE_FREE(state->param);
9034 END_PROFILE(SMBtrans2);
9038 DLIST_ADD(conn->pending_trans, state);
9040 /* We need to send an interim response then receive the rest
9041 of the parameter/data bytes */
9042 reply_outbuf(req, 0, 0);
9043 show_msg((char *)req->outbuf);
9044 END_PROFILE(SMBtrans2);
9049 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9050 SAFE_FREE(state->data);
9051 SAFE_FREE(state->param);
9053 END_PROFILE(SMBtrans2);
9054 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9058 /****************************************************************************
9059 Reply to a SMBtranss2
9060 ****************************************************************************/
9062 void reply_transs2(struct smb_request *req)
9064 connection_struct *conn = req->conn;
9065 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9066 struct trans_state *state;
9068 START_PROFILE(SMBtranss2);
9070 show_msg((const char *)req->inbuf);
9072 /* Windows clients expect all replies to
9073 a transact secondary (SMBtranss2 0x33)
9074 to have a command code of transact
9075 (SMBtrans2 0x32). See bug #8989
9076 and also [MS-CIFS] section 2.2.4.47.2
9079 req->cmd = SMBtrans2;
9082 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9083 END_PROFILE(SMBtranss2);
9087 for (state = conn->pending_trans; state != NULL;
9088 state = state->next) {
9089 if (state->mid == req->mid) {
9094 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9096 END_PROFILE(SMBtranss2);
9100 /* Revise state->total_param and state->total_data in case they have
9101 changed downwards */
9103 if (SVAL(req->vwv+0, 0) < state->total_param)
9104 state->total_param = SVAL(req->vwv+0, 0);
9105 if (SVAL(req->vwv+1, 0) < state->total_data)
9106 state->total_data = SVAL(req->vwv+1, 0);
9108 pcnt = SVAL(req->vwv+2, 0);
9109 poff = SVAL(req->vwv+3, 0);
9110 pdisp = SVAL(req->vwv+4, 0);
9112 dcnt = SVAL(req->vwv+5, 0);
9113 doff = SVAL(req->vwv+6, 0);
9114 ddisp = SVAL(req->vwv+7, 0);
9116 state->received_param += pcnt;
9117 state->received_data += dcnt;
9119 if ((state->received_data > state->total_data) ||
9120 (state->received_param > state->total_param))
9124 if (trans_oob(state->total_param, pdisp, pcnt)
9125 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9128 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9132 if (trans_oob(state->total_data, ddisp, dcnt)
9133 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9136 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9139 if ((state->received_param < state->total_param) ||
9140 (state->received_data < state->total_data)) {
9141 END_PROFILE(SMBtranss2);
9145 handle_trans2(conn, req, state);
9147 DLIST_REMOVE(conn->pending_trans, state);
9148 SAFE_FREE(state->data);
9149 SAFE_FREE(state->param);
9152 END_PROFILE(SMBtranss2);
9157 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9158 DLIST_REMOVE(conn->pending_trans, state);
9159 SAFE_FREE(state->data);
9160 SAFE_FREE(state->param);
9162 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9163 END_PROFILE(SMBtranss2);