2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS check_access(connection_struct *conn,
60 const struct smb_filename *smb_fname,
64 if (!(fsp->access_mask & access_mask)) {
65 return NT_STATUS_ACCESS_DENIED;
68 NTSTATUS status = smbd_check_access_rights(conn,
71 if (!NT_STATUS_IS_OK(status)) {
78 /********************************************************************
79 Roundup a value to the nearest allocation roundup size boundary.
80 Only do this for Windows clients.
81 ********************************************************************/
83 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
85 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
87 /* Only roundup for Windows clients. */
88 enum remote_arch_types ra_type = get_remote_arch();
89 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
90 val = SMB_ROUNDUP(val,rval);
95 /********************************************************************
96 Create a 64 bit FileIndex. If the file is on the same device as
97 the root of the share, just return the 64-bit inode. If it isn't,
98 mangle as we used to do.
99 ********************************************************************/
101 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
104 if (conn->base_share_dev == psbuf->st_ex_dev) {
105 return (uint64_t)psbuf->st_ex_ino;
107 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
108 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
112 /****************************************************************************
113 Utility functions for dealing with extended attributes.
114 ****************************************************************************/
116 /****************************************************************************
117 Refuse to allow clients to overwrite our private xattrs.
118 ****************************************************************************/
120 static bool samba_private_attr_name(const char *unix_ea_name)
122 static const char * const prohibited_ea_names[] = {
123 SAMBA_POSIX_INHERITANCE_EA_NAME,
124 SAMBA_XATTR_DOS_ATTRIB,
132 for (i = 0; prohibited_ea_names[i]; i++) {
133 if (strequal( prohibited_ea_names[i], unix_ea_name))
136 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
137 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
143 /****************************************************************************
144 Get one EA value. Fill in a struct ea_struct.
145 ****************************************************************************/
147 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
148 files_struct *fsp, const char *fname,
149 const char *ea_name, struct ea_struct *pea)
151 /* Get the value of this xattr. Max size is 64k. */
152 size_t attr_size = 256;
158 val = talloc_realloc(mem_ctx, val, char, attr_size);
160 return NT_STATUS_NO_MEMORY;
163 if (fsp && fsp->fh->fd != -1) {
164 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
166 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
169 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
175 return map_nt_error_from_unix(errno);
178 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
179 dump_data(10, (uint8 *)val, sizeret);
182 if (strnequal(ea_name, "user.", 5)) {
183 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
185 pea->name = talloc_strdup(mem_ctx, ea_name);
187 if (pea->name == NULL) {
189 return NT_STATUS_NO_MEMORY;
191 pea->value.data = (unsigned char *)val;
192 pea->value.length = (size_t)sizeret;
196 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
197 files_struct *fsp, const char *fname,
198 char ***pnames, size_t *pnum_names)
200 /* Get a list of all xattrs. Max namesize is 64k. */
201 size_t ea_namelist_size = 1024;
202 char *ea_namelist = NULL;
207 ssize_t sizeret = -1;
209 if (!lp_ea_support(SNUM(conn))) {
218 * TALLOC the result early to get the talloc hierarchy right.
221 names = talloc_array(mem_ctx, char *, 1);
223 DEBUG(0, ("talloc failed\n"));
224 return NT_STATUS_NO_MEMORY;
227 while (ea_namelist_size <= 65536) {
229 ea_namelist = talloc_realloc(
230 names, ea_namelist, char, ea_namelist_size);
231 if (ea_namelist == NULL) {
232 DEBUG(0, ("talloc failed\n"));
234 return NT_STATUS_NO_MEMORY;
237 if (fsp && fsp->fh->fd != -1) {
238 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
241 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
245 if ((sizeret == -1) && (errno == ERANGE)) {
246 ea_namelist_size *= 2;
255 return map_nt_error_from_unix(errno);
258 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
259 (unsigned int)sizeret));
271 * Ensure the result is 0-terminated
274 if (ea_namelist[sizeret-1] != '\0') {
276 return NT_STATUS_INTERNAL_ERROR;
284 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
288 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
290 DEBUG(0, ("talloc failed\n"));
292 return NT_STATUS_NO_MEMORY;
298 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
299 names[num_names++] = p;
307 *pnum_names = num_names;
311 /****************************************************************************
312 Return a linked list of the total EA's. Plus the total size
313 ****************************************************************************/
315 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
316 const char *fname, size_t *pea_total_len)
318 /* Get a list of all xattrs. Max namesize is 64k. */
321 struct ea_list *ea_list_head = NULL;
326 if (!lp_ea_support(SNUM(conn))) {
330 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
333 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
337 for (i=0; i<num_names; i++) {
338 struct ea_list *listp;
341 if (strnequal(names[i], "system.", 7)
342 || samba_private_attr_name(names[i]))
345 listp = talloc(mem_ctx, struct ea_list);
350 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
356 push_ascii_fstring(dos_ea_name, listp->ea.name);
359 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
361 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
362 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
363 (unsigned int)listp->ea.value.length));
365 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
369 /* Add on 4 for total length. */
370 if (*pea_total_len) {
374 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
375 (unsigned int)*pea_total_len));
380 /****************************************************************************
381 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
383 ****************************************************************************/
385 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
386 connection_struct *conn, struct ea_list *ea_list)
388 unsigned int ret_data_size = 4;
391 SMB_ASSERT(total_data_size >= 4);
393 if (!lp_ea_support(SNUM(conn))) {
398 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
401 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
402 dos_namelen = strlen(dos_ea_name);
403 if (dos_namelen > 255 || dos_namelen == 0) {
406 if (ea_list->ea.value.length > 65535) {
409 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
413 /* We know we have room. */
414 SCVAL(p,0,ea_list->ea.flags);
415 SCVAL(p,1,dos_namelen);
416 SSVAL(p,2,ea_list->ea.value.length);
417 strlcpy(p+4, dos_ea_name, dos_namelen+1);
418 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
420 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
421 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
424 ret_data_size = PTR_DIFF(p, pdata);
425 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
426 SIVAL(pdata,0,ret_data_size);
427 return ret_data_size;
430 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
432 unsigned int total_data_size,
433 unsigned int *ret_data_size,
434 connection_struct *conn,
435 struct ea_list *ea_list)
437 uint8_t *p = (uint8_t *)pdata;
438 uint8_t *last_start = NULL;
442 if (!lp_ea_support(SNUM(conn))) {
443 return NT_STATUS_NO_EAS_ON_FILE;
446 for (; ea_list; ea_list = ea_list->next) {
452 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
456 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
457 dos_namelen = strlen(dos_ea_name);
458 if (dos_namelen > 255 || dos_namelen == 0) {
459 return NT_STATUS_INTERNAL_ERROR;
461 if (ea_list->ea.value.length > 65535) {
462 return NT_STATUS_INTERNAL_ERROR;
465 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
468 size_t pad = 4 - (this_size % 4);
472 if (this_size > total_data_size) {
473 return NT_STATUS_INFO_LENGTH_MISMATCH;
476 /* We know we have room. */
477 SIVAL(p, 0x00, 0); /* next offset */
478 SCVAL(p, 0x04, ea_list->ea.flags);
479 SCVAL(p, 0x05, dos_namelen);
480 SSVAL(p, 0x06, ea_list->ea.value.length);
481 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
482 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
484 total_data_size -= this_size;
488 *ret_data_size = PTR_DIFF(p, pdata);
489 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
493 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
495 size_t total_ea_len = 0;
500 if (!lp_ea_support(SNUM(conn))) {
503 mem_ctx = talloc_stackframe();
504 status = get_full_smb_filename(mem_ctx, smb_fname, &fname);
505 if (!NT_STATUS_IS_OK(status)) {
506 TALLOC_FREE(mem_ctx);
509 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
510 TALLOC_FREE(mem_ctx);
514 /****************************************************************************
515 Ensure the EA name is case insensitive by matching any existing EA name.
516 ****************************************************************************/
518 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
521 TALLOC_CTX *mem_ctx = talloc_tos();
522 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
524 for (; ea_list; ea_list = ea_list->next) {
525 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
526 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
527 &unix_ea_name[5], ea_list->ea.name));
528 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
534 /****************************************************************************
535 Set or delete an extended attribute.
536 ****************************************************************************/
538 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
539 const struct smb_filename *smb_fname, struct ea_list *ea_list)
544 if (!lp_ea_support(SNUM(conn))) {
545 return NT_STATUS_EAS_NOT_SUPPORTED;
548 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
549 if (!NT_STATUS_IS_OK(status)) {
553 /* For now setting EAs on streams isn't supported. */
554 fname = smb_fname->base_name;
556 for (;ea_list; ea_list = ea_list->next) {
558 fstring unix_ea_name;
560 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
561 fstrcat(unix_ea_name, ea_list->ea.name);
563 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
565 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
567 if (samba_private_attr_name(unix_ea_name)) {
568 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
569 return NT_STATUS_ACCESS_DENIED;
572 if (ea_list->ea.value.length == 0) {
573 /* Remove the attribute. */
574 if (fsp && (fsp->fh->fd != -1)) {
575 DEBUG(10,("set_ea: deleting ea name %s on "
576 "file %s by file descriptor.\n",
577 unix_ea_name, fsp_str_dbg(fsp)));
578 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
580 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
581 unix_ea_name, fname));
582 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
585 /* Removing a non existent attribute always succeeds. */
586 if (ret == -1 && errno == ENOATTR) {
587 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
593 if (fsp && (fsp->fh->fd != -1)) {
594 DEBUG(10,("set_ea: setting ea name %s on file "
595 "%s by file descriptor.\n",
596 unix_ea_name, fsp_str_dbg(fsp)));
597 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
598 ea_list->ea.value.data, ea_list->ea.value.length, 0);
600 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
601 unix_ea_name, fname));
602 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
603 ea_list->ea.value.data, ea_list->ea.value.length, 0);
609 if (errno == ENOTSUP) {
610 return NT_STATUS_EAS_NOT_SUPPORTED;
613 return map_nt_error_from_unix(errno);
619 /****************************************************************************
620 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
621 ****************************************************************************/
623 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
625 struct ea_list *ea_list_head = NULL;
626 size_t converted_size, offset = 0;
628 while (offset + 2 < data_size) {
629 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
630 unsigned int namelen = CVAL(pdata,offset);
632 offset++; /* Go past the namelen byte. */
634 /* integer wrap paranioa. */
635 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
636 (offset > data_size) || (namelen > data_size) ||
637 (offset + namelen >= data_size)) {
640 /* Ensure the name is null terminated. */
641 if (pdata[offset + namelen] != '\0') {
644 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
646 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
647 "failed: %s", strerror(errno)));
653 offset += (namelen + 1); /* Go past the name + terminating zero. */
654 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
655 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
661 /****************************************************************************
662 Read one EA list entry from the buffer.
663 ****************************************************************************/
665 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
667 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
669 unsigned int namelen;
670 size_t converted_size;
680 eal->ea.flags = CVAL(pdata,0);
681 namelen = CVAL(pdata,1);
682 val_len = SVAL(pdata,2);
684 if (4 + namelen + 1 + val_len > data_size) {
688 /* Ensure the name is null terminated. */
689 if (pdata[namelen + 4] != '\0') {
692 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
693 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
700 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
701 if (!eal->ea.value.data) {
705 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
707 /* Ensure we're null terminated just in case we print the value. */
708 eal->ea.value.data[val_len] = '\0';
709 /* But don't count the null. */
710 eal->ea.value.length--;
713 *pbytes_used = 4 + namelen + 1 + val_len;
716 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
717 dump_data(10, eal->ea.value.data, eal->ea.value.length);
722 /****************************************************************************
723 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
724 ****************************************************************************/
726 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
728 struct ea_list *ea_list_head = NULL;
730 size_t bytes_used = 0;
732 while (offset < data_size) {
733 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
739 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
740 offset += bytes_used;
746 /****************************************************************************
747 Count the total EA size needed.
748 ****************************************************************************/
750 static size_t ea_list_size(struct ea_list *ealist)
753 struct ea_list *listp;
756 for (listp = ealist; listp; listp = listp->next) {
757 push_ascii_fstring(dos_ea_name, listp->ea.name);
758 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
760 /* Add on 4 for total length. */
768 /****************************************************************************
769 Return a union of EA's from a file list and a list of names.
770 The TALLOC context for the two lists *MUST* be identical as we steal
771 memory from one list to add to another. JRA.
772 ****************************************************************************/
774 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
776 struct ea_list *nlistp, *flistp;
778 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
779 for (flistp = file_list; flistp; flistp = flistp->next) {
780 if (strequal(nlistp->ea.name, flistp->ea.name)) {
786 /* Copy the data from this entry. */
787 nlistp->ea.flags = flistp->ea.flags;
788 nlistp->ea.value = flistp->ea.value;
791 nlistp->ea.flags = 0;
792 ZERO_STRUCT(nlistp->ea.value);
796 *total_ea_len = ea_list_size(name_list);
800 /****************************************************************************
801 Send the required number of replies back.
802 We assume all fields other than the data fields are
803 set correctly for the type of call.
804 HACK ! Always assumes smb_setup field is zero.
805 ****************************************************************************/
807 void send_trans2_replies(connection_struct *conn,
808 struct smb_request *req,
815 /* As we are using a protocol > LANMAN1 then the max_send
816 variable must have been set in the sessetupX call.
817 This takes precedence over the max_xmit field in the
818 global struct. These different max_xmit variables should
819 be merged as this is now too confusing */
821 int data_to_send = datasize;
822 int params_to_send = paramsize;
824 const char *pp = params;
825 const char *pd = pdata;
826 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
827 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
828 int data_alignment_offset = 0;
829 bool overflow = False;
830 struct smbd_server_connection *sconn = req->sconn;
831 int max_send = sconn->smb1.sessions.max_send;
833 /* Modify the data_to_send and datasize and set the error if
834 we're trying to send more than max_data_bytes. We still send
835 the part of the packet(s) that fit. Strange, but needed
838 if (max_data_bytes > 0 && datasize > max_data_bytes) {
839 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
840 max_data_bytes, datasize ));
841 datasize = data_to_send = max_data_bytes;
845 /* If there genuinely are no parameters or data to send just send the empty packet */
847 if(params_to_send == 0 && data_to_send == 0) {
848 reply_outbuf(req, 10, 0);
849 show_msg((char *)req->outbuf);
850 if (!srv_send_smb(sconn,
853 IS_CONN_ENCRYPTED(conn),
855 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
857 TALLOC_FREE(req->outbuf);
861 /* When sending params and data ensure that both are nicely aligned */
862 /* Only do this alignment when there is also data to send - else
863 can cause NT redirector problems. */
865 if (((params_to_send % 4) != 0) && (data_to_send != 0))
866 data_alignment_offset = 4 - (params_to_send % 4);
868 /* Space is bufsize minus Netbios over TCP header minus SMB header */
869 /* The alignment_offset is to align the param bytes on an even byte
870 boundary. NT 4.0 Beta needs this to work correctly. */
872 useable_space = max_send - (smb_size
875 + data_alignment_offset);
877 if (useable_space < 0) {
878 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
879 "= %d!!!", useable_space));
880 exit_server_cleanly("send_trans2_replies: Not enough space");
883 while (params_to_send || data_to_send) {
884 /* Calculate whether we will totally or partially fill this packet */
886 total_sent_thistime = params_to_send + data_to_send;
888 /* We can never send more than useable_space */
890 * Note that 'useable_space' does not include the alignment offsets,
891 * but we must include the alignment offsets in the calculation of
892 * the length of the data we send over the wire, as the alignment offsets
893 * are sent here. Fix from Marc_Jacobsen@hp.com.
896 total_sent_thistime = MIN(total_sent_thistime, useable_space);
898 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
899 + data_alignment_offset);
901 /* Set total params and data to be sent */
902 SSVAL(req->outbuf,smb_tprcnt,paramsize);
903 SSVAL(req->outbuf,smb_tdrcnt,datasize);
905 /* Calculate how many parameters and data we can fit into
906 * this packet. Parameters get precedence
909 params_sent_thistime = MIN(params_to_send,useable_space);
910 data_sent_thistime = useable_space - params_sent_thistime;
911 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
913 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
915 /* smb_proff is the offset from the start of the SMB header to the
916 parameter bytes, however the first 4 bytes of outbuf are
917 the Netbios over TCP header. Thus use smb_base() to subtract
918 them from the calculation */
920 SSVAL(req->outbuf,smb_proff,
921 ((smb_buf(req->outbuf)+alignment_offset)
922 - smb_base(req->outbuf)));
924 if(params_sent_thistime == 0)
925 SSVAL(req->outbuf,smb_prdisp,0);
927 /* Absolute displacement of param bytes sent in this packet */
928 SSVAL(req->outbuf,smb_prdisp,pp - params);
930 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
931 if(data_sent_thistime == 0) {
932 SSVAL(req->outbuf,smb_droff,0);
933 SSVAL(req->outbuf,smb_drdisp, 0);
935 /* The offset of the data bytes is the offset of the
936 parameter bytes plus the number of parameters being sent this time */
937 SSVAL(req->outbuf, smb_droff,
938 ((smb_buf(req->outbuf)+alignment_offset)
939 - smb_base(req->outbuf))
940 + params_sent_thistime + data_alignment_offset);
941 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
944 /* Initialize the padding for alignment */
946 if (alignment_offset != 0) {
947 memset(smb_buf(req->outbuf), 0, alignment_offset);
950 /* Copy the param bytes into the packet */
952 if(params_sent_thistime) {
953 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
954 params_sent_thistime);
957 /* Copy in the data bytes */
958 if(data_sent_thistime) {
959 if (data_alignment_offset != 0) {
960 memset((smb_buf(req->outbuf)+alignment_offset+
961 params_sent_thistime), 0,
962 data_alignment_offset);
964 memcpy(smb_buf(req->outbuf)+alignment_offset
965 +params_sent_thistime+data_alignment_offset,
966 pd,data_sent_thistime);
969 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
970 params_sent_thistime, data_sent_thistime, useable_space));
971 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
972 params_to_send, data_to_send, paramsize, datasize));
975 error_packet_set((char *)req->outbuf,
976 ERRDOS,ERRbufferoverflow,
977 STATUS_BUFFER_OVERFLOW,
981 /* Send the packet */
982 show_msg((char *)req->outbuf);
983 if (!srv_send_smb(sconn,
986 IS_CONN_ENCRYPTED(conn),
988 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
990 TALLOC_FREE(req->outbuf);
992 pp += params_sent_thistime;
993 pd += data_sent_thistime;
995 params_to_send -= params_sent_thistime;
996 data_to_send -= data_sent_thistime;
999 if(params_to_send < 0 || data_to_send < 0) {
1000 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1001 params_to_send, data_to_send));
1009 /****************************************************************************
1010 Reply to a TRANSACT2_OPEN.
1011 ****************************************************************************/
1013 static void call_trans2open(connection_struct *conn,
1014 struct smb_request *req,
1015 char **pparams, int total_params,
1016 char **ppdata, int total_data,
1017 unsigned int max_data_bytes)
1019 struct smb_filename *smb_fname = NULL;
1020 char *params = *pparams;
1021 char *pdata = *ppdata;
1024 bool oplock_request;
1026 bool return_additional_info;
1035 int fattr=0,mtime=0;
1036 SMB_INO_T inode = 0;
1039 struct ea_list *ea_list = NULL;
1044 uint32 create_disposition;
1045 uint32 create_options = 0;
1046 uint32_t private_flags = 0;
1047 TALLOC_CTX *ctx = talloc_tos();
1050 * Ensure we have enough parameters to perform the operation.
1053 if (total_params < 29) {
1054 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1058 flags = SVAL(params, 0);
1059 deny_mode = SVAL(params, 2);
1060 open_attr = SVAL(params,6);
1061 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1062 if (oplock_request) {
1063 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1067 return_additional_info = BITSETW(params,0);
1068 open_sattr = SVAL(params, 4);
1069 open_time = make_unix_date3(params+8);
1071 open_ofun = SVAL(params,12);
1072 open_size = IVAL(params,14);
1073 pname = ¶ms[28];
1076 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1080 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1081 total_params - 28, STR_TERMINATE,
1083 if (!NT_STATUS_IS_OK(status)) {
1084 reply_nterror(req, status);
1088 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1089 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1090 (unsigned int)open_ofun, open_size));
1092 status = filename_convert(ctx,
1094 req->flags2 & FLAGS2_DFS_PATHNAMES,
1099 if (!NT_STATUS_IS_OK(status)) {
1100 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1101 reply_botherror(req,
1102 NT_STATUS_PATH_NOT_COVERED,
1103 ERRSRV, ERRbadpath);
1106 reply_nterror(req, status);
1110 if (open_ofun == 0) {
1111 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1115 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1117 &access_mask, &share_mode,
1118 &create_disposition,
1121 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1125 /* Any data in this call is an EA list. */
1126 if (total_data && (total_data != 4)) {
1127 if (total_data < 10) {
1128 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1132 if (IVAL(pdata,0) > total_data) {
1133 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1134 IVAL(pdata,0), (unsigned int)total_data));
1135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1139 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1142 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1146 if (!lp_ea_support(SNUM(conn))) {
1147 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1152 status = SMB_VFS_CREATE_FILE(
1155 0, /* root_dir_fid */
1156 smb_fname, /* fname */
1157 access_mask, /* access_mask */
1158 share_mode, /* share_access */
1159 create_disposition, /* create_disposition*/
1160 create_options, /* create_options */
1161 open_attr, /* file_attributes */
1162 oplock_request, /* oplock_request */
1163 open_size, /* allocation_size */
1166 ea_list, /* ea_list */
1168 &smb_action); /* psbuf */
1170 if (!NT_STATUS_IS_OK(status)) {
1171 if (open_was_deferred(req->sconn, req->mid)) {
1172 /* We have re-scheduled this call. */
1175 reply_openerror(req, status);
1179 size = get_file_size_stat(&smb_fname->st);
1180 fattr = dos_mode(conn, smb_fname);
1181 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1182 inode = smb_fname->st.st_ex_ino;
1183 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1184 close_file(req, fsp, ERROR_CLOSE);
1185 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1189 /* Realloc the size of parameters and data we will return */
1190 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1191 if(*pparams == NULL ) {
1192 reply_nterror(req, NT_STATUS_NO_MEMORY);
1197 SSVAL(params,0,fsp->fnum);
1198 SSVAL(params,2,fattr);
1199 srv_put_dos_date2(params,4, mtime);
1200 SIVAL(params,8, (uint32)size);
1201 SSVAL(params,12,deny_mode);
1202 SSVAL(params,14,0); /* open_type - file or directory. */
1203 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1205 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1206 smb_action |= EXTENDED_OPLOCK_GRANTED;
1209 SSVAL(params,18,smb_action);
1212 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1214 SIVAL(params,20,inode);
1215 SSVAL(params,24,0); /* Padding. */
1217 uint32 ea_size = estimate_ea_size(conn, fsp,
1219 SIVAL(params, 26, ea_size);
1221 SIVAL(params, 26, 0);
1224 /* Send the required number of replies */
1225 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1227 TALLOC_FREE(smb_fname);
1230 /*********************************************************
1231 Routine to check if a given string matches exactly.
1232 as a special case a mask of "." does NOT match. That
1233 is required for correct wildcard semantics
1234 Case can be significant or not.
1235 **********************************************************/
1237 static bool exact_match(bool has_wild,
1238 bool case_sensitive,
1242 if (mask[0] == '.' && mask[1] == 0) {
1250 if (case_sensitive) {
1251 return strcmp(str,mask)==0;
1253 return strcasecmp_m(str,mask) == 0;
1257 /****************************************************************************
1258 Return the filetype for UNIX extensions.
1259 ****************************************************************************/
1261 static uint32 unix_filetype(mode_t mode)
1264 return UNIX_TYPE_FILE;
1265 else if(S_ISDIR(mode))
1266 return UNIX_TYPE_DIR;
1268 else if(S_ISLNK(mode))
1269 return UNIX_TYPE_SYMLINK;
1272 else if(S_ISCHR(mode))
1273 return UNIX_TYPE_CHARDEV;
1276 else if(S_ISBLK(mode))
1277 return UNIX_TYPE_BLKDEV;
1280 else if(S_ISFIFO(mode))
1281 return UNIX_TYPE_FIFO;
1284 else if(S_ISSOCK(mode))
1285 return UNIX_TYPE_SOCKET;
1288 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1289 return UNIX_TYPE_UNKNOWN;
1292 /****************************************************************************
1293 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1294 ****************************************************************************/
1296 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1298 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1299 const SMB_STRUCT_STAT *psbuf,
1301 enum perm_type ptype,
1306 if (perms == SMB_MODE_NO_CHANGE) {
1307 if (!VALID_STAT(*psbuf)) {
1308 return NT_STATUS_INVALID_PARAMETER;
1310 *ret_perms = psbuf->st_ex_mode;
1311 return NT_STATUS_OK;
1315 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1316 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1317 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1318 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1319 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1320 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1321 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1322 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1323 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1325 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1328 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1331 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1336 /* Apply mode mask */
1337 ret &= lp_create_mask(SNUM(conn));
1338 /* Add in force bits */
1339 ret |= lp_force_create_mode(SNUM(conn));
1342 ret &= lp_dir_mask(SNUM(conn));
1343 /* Add in force bits */
1344 ret |= lp_force_dir_mode(SNUM(conn));
1346 case PERM_EXISTING_FILE:
1347 /* Apply mode mask */
1348 ret &= lp_security_mask(SNUM(conn));
1349 /* Add in force bits */
1350 ret |= lp_force_security_mode(SNUM(conn));
1352 case PERM_EXISTING_DIR:
1353 /* Apply mode mask */
1354 ret &= lp_dir_security_mask(SNUM(conn));
1355 /* Add in force bits */
1356 ret |= lp_force_dir_security_mode(SNUM(conn));
1361 return NT_STATUS_OK;
1364 /****************************************************************************
1365 Needed to show the msdfs symlinks as directories. Modifies psbuf
1366 to be a directory if it's a msdfs link.
1367 ****************************************************************************/
1369 static bool check_msdfs_link(connection_struct *conn,
1370 const char *pathname,
1371 SMB_STRUCT_STAT *psbuf)
1373 int saved_errno = errno;
1374 if(lp_host_msdfs() &&
1375 lp_msdfs_root(SNUM(conn)) &&
1376 is_msdfs_link(conn, pathname, psbuf)) {
1378 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1381 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1382 errno = saved_errno;
1385 errno = saved_errno;
1390 /****************************************************************************
1391 Get a level dependent lanman2 dir entry.
1392 ****************************************************************************/
1394 struct smbd_dirptr_lanman2_state {
1395 connection_struct *conn;
1396 uint32_t info_level;
1397 bool check_mangled_names;
1399 bool got_exact_match;
1402 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1408 struct smbd_dirptr_lanman2_state *state =
1409 (struct smbd_dirptr_lanman2_state *)private_data;
1411 char mangled_name[13]; /* mangled 8.3 name. */
1415 /* Mangle fname if it's an illegal name. */
1416 if (mangle_must_mangle(dname, state->conn->params)) {
1417 ok = name_to_8_3(dname, mangled_name,
1418 true, state->conn->params);
1422 fname = mangled_name;
1427 got_match = exact_match(state->has_wild,
1428 state->conn->case_sensitive,
1430 state->got_exact_match = got_match;
1432 got_match = mask_match(fname, mask,
1433 state->conn->case_sensitive);
1436 if(!got_match && state->check_mangled_names &&
1437 !mangle_is_8_3(fname, false, state->conn->params)) {
1439 * It turns out that NT matches wildcards against
1440 * both long *and* short names. This may explain some
1441 * of the wildcard wierdness from old DOS clients
1442 * that some people have been seeing.... JRA.
1444 /* Force the mangling into 8.3. */
1445 ok = name_to_8_3(fname, mangled_name,
1446 false, state->conn->params);
1451 got_match = exact_match(state->has_wild,
1452 state->conn->case_sensitive,
1453 mangled_name, mask);
1454 state->got_exact_match = got_match;
1456 got_match = mask_match(mangled_name, mask,
1457 state->conn->case_sensitive);
1465 *_fname = talloc_strdup(ctx, fname);
1466 if (*_fname == NULL) {
1473 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1475 struct smb_filename *smb_fname,
1478 struct smbd_dirptr_lanman2_state *state =
1479 (struct smbd_dirptr_lanman2_state *)private_data;
1480 bool ms_dfs_link = false;
1483 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1484 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1485 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1486 "Couldn't lstat [%s] (%s)\n",
1487 smb_fname_str_dbg(smb_fname),
1491 } else if (!VALID_STAT(smb_fname->st) &&
1492 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1493 /* Needed to show the msdfs symlinks as
1496 ms_dfs_link = check_msdfs_link(state->conn,
1497 smb_fname->base_name,
1500 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1501 "Couldn't stat [%s] (%s)\n",
1502 smb_fname_str_dbg(smb_fname),
1509 mode = dos_mode_msdfs(state->conn, smb_fname);
1511 mode = dos_mode(state->conn, smb_fname);
1518 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1519 connection_struct *conn,
1521 uint32_t info_level,
1522 struct ea_list *name_list,
1523 bool check_mangled_names,
1524 bool requires_resume_key,
1527 const struct smb_filename *smb_fname,
1528 int space_remaining,
1535 uint64_t *last_entry_off)
1537 char *p, *q, *pdata = *ppdata;
1539 uint64_t file_size = 0;
1540 uint64_t allocation_size = 0;
1541 uint64_t file_index = 0;
1543 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1544 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1546 char *last_entry_ptr;
1551 *out_of_space = false;
1553 ZERO_STRUCT(mdate_ts);
1554 ZERO_STRUCT(adate_ts);
1555 ZERO_STRUCT(create_date_ts);
1556 ZERO_STRUCT(cdate_ts);
1558 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1559 file_size = get_file_size_stat(&smb_fname->st);
1561 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1563 file_index = get_FileIndex(conn, &smb_fname->st);
1565 mdate_ts = smb_fname->st.st_ex_mtime;
1566 adate_ts = smb_fname->st.st_ex_atime;
1567 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1568 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1570 if (lp_dos_filetime_resolution(SNUM(conn))) {
1571 dos_filetime_timespec(&create_date_ts);
1572 dos_filetime_timespec(&mdate_ts);
1573 dos_filetime_timespec(&adate_ts);
1574 dos_filetime_timespec(&cdate_ts);
1577 create_date = convert_timespec_to_time_t(create_date_ts);
1578 mdate = convert_timespec_to_time_t(mdate_ts);
1579 adate = convert_timespec_to_time_t(adate_ts);
1581 /* align the record */
1582 SMB_ASSERT(align >= 1);
1584 off = (int)PTR_DIFF(pdata, base_data);
1585 pad = (off + (align-1)) & ~(align-1);
1588 if (pad && pad > space_remaining) {
1589 *out_of_space = true;
1590 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1591 "for padding (wanted %u, had %d)\n",
1594 return false; /* Not finished - just out of space */
1598 /* initialize padding to 0 */
1600 memset(pdata, 0, pad);
1602 space_remaining -= pad;
1604 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1614 switch (info_level) {
1615 case SMB_FIND_INFO_STANDARD:
1616 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1617 if(requires_resume_key) {
1621 srv_put_dos_date2(p,0,create_date);
1622 srv_put_dos_date2(p,4,adate);
1623 srv_put_dos_date2(p,8,mdate);
1624 SIVAL(p,12,(uint32)file_size);
1625 SIVAL(p,16,(uint32)allocation_size);
1629 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1630 p += ucs2_align(base_data, p, 0);
1632 len = srvstr_push(base_data, flags2, p,
1633 fname, PTR_DIFF(end_data, p),
1635 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1637 SCVAL(nameptr, -1, len - 2);
1639 SCVAL(nameptr, -1, 0);
1643 SCVAL(nameptr, -1, len - 1);
1645 SCVAL(nameptr, -1, 0);
1651 case SMB_FIND_EA_SIZE:
1652 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1653 if (requires_resume_key) {
1657 srv_put_dos_date2(p,0,create_date);
1658 srv_put_dos_date2(p,4,adate);
1659 srv_put_dos_date2(p,8,mdate);
1660 SIVAL(p,12,(uint32)file_size);
1661 SIVAL(p,16,(uint32)allocation_size);
1664 unsigned int ea_size = estimate_ea_size(conn, NULL,
1666 SIVAL(p,22,ea_size); /* Extended attributes */
1670 len = srvstr_push(base_data, flags2,
1671 p, fname, PTR_DIFF(end_data, p),
1672 STR_TERMINATE | STR_NOALIGN);
1673 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1686 SCVAL(nameptr,0,len);
1688 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1691 case SMB_FIND_EA_LIST:
1693 struct ea_list *file_list = NULL;
1696 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1700 if (requires_resume_key) {
1704 srv_put_dos_date2(p,0,create_date);
1705 srv_put_dos_date2(p,4,adate);
1706 srv_put_dos_date2(p,8,mdate);
1707 SIVAL(p,12,(uint32)file_size);
1708 SIVAL(p,16,(uint32)allocation_size);
1710 p += 22; /* p now points to the EA area. */
1712 file_list = get_ea_list_from_file(ctx, conn, NULL,
1713 smb_fname->base_name,
1715 name_list = ea_list_union(name_list, file_list, &ea_len);
1717 /* We need to determine if this entry will fit in the space available. */
1718 /* Max string size is 255 bytes. */
1719 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1720 *out_of_space = true;
1721 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1722 "(wanted %u, had %d)\n",
1723 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1725 return False; /* Not finished - just out of space */
1728 /* Push the ea_data followed by the name. */
1729 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1731 len = srvstr_push(base_data, flags2,
1732 p + 1, fname, PTR_DIFF(end_data, p+1),
1733 STR_TERMINATE | STR_NOALIGN);
1734 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1747 SCVAL(nameptr,0,len);
1749 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1753 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1754 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1755 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1757 SIVAL(p,0,reskey); p += 4;
1758 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1759 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1760 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1761 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1762 SOFF_T(p,0,file_size); p += 8;
1763 SOFF_T(p,0,allocation_size); p += 8;
1764 SIVAL(p,0,mode); p += 4;
1765 q = p; p += 4; /* q is placeholder for name length. */
1767 unsigned int ea_size = estimate_ea_size(conn, NULL,
1769 SIVAL(p,0,ea_size); /* Extended attributes */
1772 /* Clear the short name buffer. This is
1773 * IMPORTANT as not doing so will trigger
1774 * a Win2k client bug. JRA.
1776 if (!was_8_3 && check_mangled_names) {
1777 char mangled_name[13]; /* mangled 8.3 name. */
1778 if (!name_to_8_3(fname,mangled_name,True,
1780 /* Error - mangle failed ! */
1781 memset(mangled_name,'\0',12);
1783 mangled_name[12] = 0;
1784 len = srvstr_push(base_data, flags2,
1785 p+2, mangled_name, 24,
1786 STR_UPPER|STR_UNICODE);
1788 memset(p + 2 + len,'\0',24 - len);
1795 len = srvstr_push(base_data, flags2, p,
1796 fname, PTR_DIFF(end_data, p),
1797 STR_TERMINATE_ASCII);
1801 len = PTR_DIFF(p, pdata);
1802 pad = (len + (align-1)) & ~(align-1);
1804 * offset to the next entry, the caller
1805 * will overwrite it for the last entry
1806 * that's why we always include the padding
1810 * set padding to zero
1813 memset(p, 0, pad - len);
1820 case SMB_FIND_FILE_DIRECTORY_INFO:
1821 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1823 SIVAL(p,0,reskey); p += 4;
1824 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1825 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1826 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1827 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1828 SOFF_T(p,0,file_size); p += 8;
1829 SOFF_T(p,0,allocation_size); p += 8;
1830 SIVAL(p,0,mode); p += 4;
1831 len = srvstr_push(base_data, flags2,
1832 p + 4, fname, PTR_DIFF(end_data, p+4),
1833 STR_TERMINATE_ASCII);
1837 len = PTR_DIFF(p, pdata);
1838 pad = (len + (align-1)) & ~(align-1);
1840 * offset to the next entry, the caller
1841 * will overwrite it for the last entry
1842 * that's why we always include the padding
1846 * set padding to zero
1849 memset(p, 0, pad - len);
1856 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1857 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1859 SIVAL(p,0,reskey); p += 4;
1860 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1862 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1863 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1864 SOFF_T(p,0,file_size); p += 8;
1865 SOFF_T(p,0,allocation_size); p += 8;
1866 SIVAL(p,0,mode); p += 4;
1867 q = p; p += 4; /* q is placeholder for name length. */
1869 unsigned int ea_size = estimate_ea_size(conn, NULL,
1871 SIVAL(p,0,ea_size); /* Extended attributes */
1874 len = srvstr_push(base_data, flags2, p,
1875 fname, PTR_DIFF(end_data, p),
1876 STR_TERMINATE_ASCII);
1880 len = PTR_DIFF(p, pdata);
1881 pad = (len + (align-1)) & ~(align-1);
1883 * offset to the next entry, the caller
1884 * will overwrite it for the last entry
1885 * that's why we always include the padding
1889 * set padding to zero
1892 memset(p, 0, pad - len);
1899 case SMB_FIND_FILE_NAMES_INFO:
1900 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1902 SIVAL(p,0,reskey); p += 4;
1904 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1905 acl on a dir (tridge) */
1906 len = srvstr_push(base_data, flags2, p,
1907 fname, PTR_DIFF(end_data, p),
1908 STR_TERMINATE_ASCII);
1912 len = PTR_DIFF(p, pdata);
1913 pad = (len + (align-1)) & ~(align-1);
1915 * offset to the next entry, the caller
1916 * will overwrite it for the last entry
1917 * that's why we always include the padding
1921 * set padding to zero
1924 memset(p, 0, pad - len);
1931 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1932 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1934 SIVAL(p,0,reskey); p += 4;
1935 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1936 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1937 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1938 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1939 SOFF_T(p,0,file_size); p += 8;
1940 SOFF_T(p,0,allocation_size); p += 8;
1941 SIVAL(p,0,mode); p += 4;
1942 q = p; p += 4; /* q is placeholder for name length. */
1944 unsigned int ea_size = estimate_ea_size(conn, NULL,
1946 SIVAL(p,0,ea_size); /* Extended attributes */
1949 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1950 SBVAL(p,0,file_index); p += 8;
1951 len = srvstr_push(base_data, flags2, p,
1952 fname, PTR_DIFF(end_data, p),
1953 STR_TERMINATE_ASCII);
1957 len = PTR_DIFF(p, pdata);
1958 pad = (len + (align-1)) & ~(align-1);
1960 * offset to the next entry, the caller
1961 * will overwrite it for the last entry
1962 * that's why we always include the padding
1966 * set padding to zero
1969 memset(p, 0, pad - len);
1976 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1977 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1978 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1980 SIVAL(p,0,reskey); p += 4;
1981 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1982 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1983 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1984 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1985 SOFF_T(p,0,file_size); p += 8;
1986 SOFF_T(p,0,allocation_size); p += 8;
1987 SIVAL(p,0,mode); p += 4;
1988 q = p; p += 4; /* q is placeholder for name length */
1990 unsigned int ea_size = estimate_ea_size(conn, NULL,
1992 SIVAL(p,0,ea_size); /* Extended attributes */
1995 /* Clear the short name buffer. This is
1996 * IMPORTANT as not doing so will trigger
1997 * a Win2k client bug. JRA.
1999 if (!was_8_3 && check_mangled_names) {
2000 char mangled_name[13]; /* mangled 8.3 name. */
2001 if (!name_to_8_3(fname,mangled_name,True,
2003 /* Error - mangle failed ! */
2004 memset(mangled_name,'\0',12);
2006 mangled_name[12] = 0;
2007 len = srvstr_push(base_data, flags2,
2008 p+2, mangled_name, 24,
2009 STR_UPPER|STR_UNICODE);
2012 memset(p + 2 + len,'\0',24 - len);
2019 SSVAL(p,0,0); p += 2; /* Reserved ? */
2020 SBVAL(p,0,file_index); p += 8;
2021 len = srvstr_push(base_data, flags2, p,
2022 fname, PTR_DIFF(end_data, p),
2023 STR_TERMINATE_ASCII);
2027 len = PTR_DIFF(p, pdata);
2028 pad = (len + (align-1)) & ~(align-1);
2030 * offset to the next entry, the caller
2031 * will overwrite it for the last entry
2032 * that's why we always include the padding
2036 * set padding to zero
2039 memset(p, 0, pad - len);
2046 /* CIFS UNIX Extension. */
2048 case SMB_FIND_FILE_UNIX:
2049 case SMB_FIND_FILE_UNIX_INFO2:
2051 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2053 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2055 if (info_level == SMB_FIND_FILE_UNIX) {
2056 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2057 p = store_file_unix_basic(conn, p,
2058 NULL, &smb_fname->st);
2059 len = srvstr_push(base_data, flags2, p,
2060 fname, PTR_DIFF(end_data, p),
2063 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2064 p = store_file_unix_basic_info2(conn, p,
2065 NULL, &smb_fname->st);
2068 len = srvstr_push(base_data, flags2, p, fname,
2069 PTR_DIFF(end_data, p), 0);
2070 SIVAL(nameptr, 0, len);
2075 len = PTR_DIFF(p, pdata);
2076 pad = (len + (align-1)) & ~(align-1);
2078 * offset to the next entry, the caller
2079 * will overwrite it for the last entry
2080 * that's why we always include the padding
2084 * set padding to zero
2087 memset(p, 0, pad - len);
2092 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2100 if (PTR_DIFF(p,pdata) > space_remaining) {
2101 *out_of_space = true;
2102 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2103 "(wanted %u, had %d)\n",
2104 (unsigned int)PTR_DIFF(p,pdata),
2106 return false; /* Not finished - just out of space */
2109 /* Setup the last entry pointer, as an offset from base_data */
2110 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2111 /* Advance the data pointer to the next slot */
2117 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2118 connection_struct *conn,
2119 struct dptr_struct *dirptr,
2121 const char *path_mask,
2124 int requires_resume_key,
2132 int space_remaining,
2134 bool *got_exact_match,
2135 int *_last_entry_off,
2136 struct ea_list *name_list)
2139 const char *mask = NULL;
2140 long prev_dirpos = 0;
2143 struct smb_filename *smb_fname = NULL;
2144 struct smbd_dirptr_lanman2_state state;
2146 uint64_t last_entry_off = 0;
2150 state.info_level = info_level;
2151 state.check_mangled_names = lp_manglednames(conn->params);
2152 state.has_wild = dptr_has_wild(dirptr);
2153 state.got_exact_match = false;
2155 *out_of_space = false;
2156 *got_exact_match = false;
2158 p = strrchr_m(path_mask,'/');
2169 ok = smbd_dirptr_get_entry(ctx,
2175 smbd_dirptr_lanman2_match_fn,
2176 smbd_dirptr_lanman2_mode_fn,
2186 *got_exact_match = state.got_exact_match;
2188 ok = smbd_marshall_dir_entry(ctx,
2193 state.check_mangled_names,
2194 requires_resume_key,
2207 TALLOC_FREE(smb_fname);
2208 if (*out_of_space) {
2209 dptr_SeekDir(dirptr, prev_dirpos);
2216 *_last_entry_off = last_entry_off;
2220 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2221 connection_struct *conn,
2222 struct dptr_struct *dirptr,
2224 const char *path_mask,
2227 bool requires_resume_key,
2233 int space_remaining,
2235 bool *got_exact_match,
2236 int *last_entry_off,
2237 struct ea_list *name_list)
2240 const bool do_pad = true;
2242 if (info_level >= 1 && info_level <= 3) {
2243 /* No alignment on earlier info levels. */
2247 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2248 path_mask, dirtype, info_level,
2249 requires_resume_key, dont_descend, ask_sharemode,
2251 ppdata, base_data, end_data,
2253 out_of_space, got_exact_match,
2254 last_entry_off, name_list);
2257 /****************************************************************************
2258 Reply to a TRANS2_FINDFIRST.
2259 ****************************************************************************/
2261 static void call_trans2findfirst(connection_struct *conn,
2262 struct smb_request *req,
2263 char **pparams, int total_params,
2264 char **ppdata, int total_data,
2265 unsigned int max_data_bytes)
2267 /* We must be careful here that we don't return more than the
2268 allowed number of data bytes. If this means returning fewer than
2269 maxentries then so be it. We assume that the redirector has
2270 enough room for the fixed number of parameter bytes it has
2272 struct smb_filename *smb_dname = NULL;
2273 char *params = *pparams;
2274 char *pdata = *ppdata;
2278 uint16 findfirst_flags;
2279 bool close_after_first;
2281 bool requires_resume_key;
2283 char *directory = NULL;
2286 int last_entry_off=0;
2290 bool finished = False;
2291 bool dont_descend = False;
2292 bool out_of_space = False;
2293 int space_remaining;
2294 bool mask_contains_wcard = False;
2295 struct ea_list *ea_list = NULL;
2296 NTSTATUS ntstatus = NT_STATUS_OK;
2297 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2298 TALLOC_CTX *ctx = talloc_tos();
2299 struct dptr_struct *dirptr = NULL;
2300 struct smbd_server_connection *sconn = req->sconn;
2301 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2302 bool backup_priv = false;
2304 if (total_params < 13) {
2305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2309 dirtype = SVAL(params,0);
2310 maxentries = SVAL(params,2);
2311 findfirst_flags = SVAL(params,4);
2312 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2313 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2314 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2315 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2316 security_token_has_privilege(get_current_nttok(conn),
2319 info_level = SVAL(params,6);
2321 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2322 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2323 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2325 info_level, max_data_bytes));
2328 /* W2K3 seems to treat zero as 1. */
2332 switch (info_level) {
2333 case SMB_FIND_INFO_STANDARD:
2334 case SMB_FIND_EA_SIZE:
2335 case SMB_FIND_EA_LIST:
2336 case SMB_FIND_FILE_DIRECTORY_INFO:
2337 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2338 case SMB_FIND_FILE_NAMES_INFO:
2339 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2340 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2341 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2343 case SMB_FIND_FILE_UNIX:
2344 case SMB_FIND_FILE_UNIX_INFO2:
2345 /* Always use filesystem for UNIX mtime query. */
2346 ask_sharemode = false;
2347 if (!lp_unix_extensions()) {
2348 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2351 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2354 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2358 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2359 params+12, total_params - 12,
2360 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2361 if (!NT_STATUS_IS_OK(ntstatus)) {
2362 reply_nterror(req, ntstatus);
2368 ntstatus = filename_convert_with_privilege(ctx,
2373 &mask_contains_wcard,
2376 ntstatus = filename_convert(ctx, conn,
2377 req->flags2 & FLAGS2_DFS_PATHNAMES,
2380 &mask_contains_wcard,
2384 if (!NT_STATUS_IS_OK(ntstatus)) {
2385 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2386 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2387 ERRSRV, ERRbadpath);
2390 reply_nterror(req, ntstatus);
2394 mask = smb_dname->original_lcomp;
2396 directory = smb_dname->base_name;
2398 p = strrchr_m(directory,'/');
2400 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2401 if((directory[0] == '.') && (directory[1] == '\0')) {
2402 mask = talloc_strdup(ctx,"*");
2404 reply_nterror(req, NT_STATUS_NO_MEMORY);
2407 mask_contains_wcard = True;
2413 if (p == NULL || p == directory) {
2414 /* Ensure we don't have a directory name of "". */
2415 directory = talloc_strdup(talloc_tos(), ".");
2417 reply_nterror(req, NT_STATUS_NO_MEMORY);
2422 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2424 if (info_level == SMB_FIND_EA_LIST) {
2427 if (total_data < 4) {
2428 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2432 ea_size = IVAL(pdata,0);
2433 if (ea_size != total_data) {
2434 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2435 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2440 if (!lp_ea_support(SNUM(conn))) {
2441 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2445 /* Pull out the list of names. */
2446 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2448 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2453 *ppdata = (char *)SMB_REALLOC(
2454 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2455 if(*ppdata == NULL ) {
2456 reply_nterror(req, NT_STATUS_NO_MEMORY);
2460 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2462 /* Realloc the params space */
2463 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2464 if (*pparams == NULL) {
2465 reply_nterror(req, NT_STATUS_NO_MEMORY);
2470 /* Save the wildcard match and attribs we are using on this directory -
2471 needed as lanman2 assumes these are being saved between calls */
2473 ntstatus = dptr_create(conn,
2481 mask_contains_wcard,
2485 if (!NT_STATUS_IS_OK(ntstatus)) {
2486 reply_nterror(req, ntstatus);
2491 /* Remember this in case we have
2492 to do a findnext. */
2493 dptr_set_priv(dirptr);
2496 dptr_num = dptr_dnum(dirptr);
2497 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2499 /* Initialize per TRANS2_FIND_FIRST operation data */
2500 dptr_init_search_op(dirptr);
2502 /* We don't need to check for VOL here as this is returned by
2503 a different TRANS2 call. */
2505 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2506 directory,lp_dontdescend(ctx, SNUM(conn))));
2507 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2508 dont_descend = True;
2511 space_remaining = max_data_bytes;
2512 out_of_space = False;
2514 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2515 bool got_exact_match = False;
2517 /* this is a heuristic to avoid seeking the dirptr except when
2518 absolutely necessary. It allows for a filename of about 40 chars */
2519 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2520 out_of_space = True;
2523 finished = !get_lanman2_dir_entry(ctx,
2527 mask,dirtype,info_level,
2528 requires_resume_key,dont_descend,
2531 space_remaining, &out_of_space,
2533 &last_entry_off, ea_list);
2536 if (finished && out_of_space)
2539 if (!finished && !out_of_space)
2543 * As an optimisation if we know we aren't looking
2544 * for a wildcard name (ie. the name matches the wildcard exactly)
2545 * then we can finish on any (first) match.
2546 * This speeds up large directory searches. JRA.
2552 /* Ensure space_remaining never goes -ve. */
2553 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2554 space_remaining = 0;
2555 out_of_space = true;
2557 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2561 /* Check if we can close the dirptr */
2562 if(close_after_first || (finished && close_if_end)) {
2563 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2564 dptr_close(sconn, &dptr_num);
2568 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2569 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2570 * the protocol level is less than NT1. Tested with smbclient. JRA.
2571 * This should fix the OS/2 client bug #2335.
2574 if(numentries == 0) {
2575 dptr_close(sconn, &dptr_num);
2576 if (get_Protocol() < PROTOCOL_NT1) {
2577 reply_force_doserror(req, ERRDOS, ERRnofiles);
2580 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2581 ERRDOS, ERRbadfile);
2586 /* At this point pdata points to numentries directory entries. */
2588 /* Set up the return parameter block */
2589 SSVAL(params,0,dptr_num);
2590 SSVAL(params,2,numentries);
2591 SSVAL(params,4,finished);
2592 SSVAL(params,6,0); /* Never an EA error */
2593 SSVAL(params,8,last_entry_off);
2595 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2598 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2599 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2601 reply_nterror(req, NT_STATUS_NO_MEMORY);
2605 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2606 smb_fn_name(req->cmd),
2607 mask, directory, dirtype, numentries ) );
2610 * Force a name mangle here to ensure that the
2611 * mask as an 8.3 name is top of the mangled cache.
2612 * The reasons for this are subtle. Don't remove
2613 * this code unless you know what you are doing
2614 * (see PR#13758). JRA.
2617 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2618 char mangled_name[13];
2619 name_to_8_3(mask, mangled_name, True, conn->params);
2627 TALLOC_FREE(smb_dname);
2631 /****************************************************************************
2632 Reply to a TRANS2_FINDNEXT.
2633 ****************************************************************************/
2635 static void call_trans2findnext(connection_struct *conn,
2636 struct smb_request *req,
2637 char **pparams, int total_params,
2638 char **ppdata, int total_data,
2639 unsigned int max_data_bytes)
2641 /* We must be careful here that we don't return more than the
2642 allowed number of data bytes. If this means returning fewer than
2643 maxentries then so be it. We assume that the redirector has
2644 enough room for the fixed number of parameter bytes it has
2646 char *params = *pparams;
2647 char *pdata = *ppdata;
2653 uint16 findnext_flags;
2654 bool close_after_request;
2656 bool requires_resume_key;
2658 bool mask_contains_wcard = False;
2659 char *resume_name = NULL;
2660 const char *mask = NULL;
2661 const char *directory = NULL;
2665 int i, last_entry_off=0;
2666 bool finished = False;
2667 bool dont_descend = False;
2668 bool out_of_space = False;
2669 int space_remaining;
2670 struct ea_list *ea_list = NULL;
2671 NTSTATUS ntstatus = NT_STATUS_OK;
2672 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2673 TALLOC_CTX *ctx = talloc_tos();
2674 struct dptr_struct *dirptr;
2675 struct smbd_server_connection *sconn = req->sconn;
2676 bool backup_priv = false;
2678 if (total_params < 13) {
2679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2683 dptr_num = SVAL(params,0);
2684 maxentries = SVAL(params,2);
2685 info_level = SVAL(params,4);
2686 resume_key = IVAL(params,6);
2687 findnext_flags = SVAL(params,10);
2688 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2689 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2690 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2691 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2693 if (!continue_bit) {
2694 /* We only need resume_name if continue_bit is zero. */
2695 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2697 total_params - 12, STR_TERMINATE, &ntstatus,
2698 &mask_contains_wcard);
2699 if (!NT_STATUS_IS_OK(ntstatus)) {
2700 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2701 complain (it thinks we're asking for the directory above the shared
2702 path or an invalid name). Catch this as the resume name is only compared, never used in
2703 a file access. JRA. */
2704 srvstr_pull_talloc(ctx, params, req->flags2,
2705 &resume_name, params+12,
2709 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2710 reply_nterror(req, ntstatus);
2716 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2717 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2718 resume_key = %d resume name = %s continue=%d level = %d\n",
2719 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2720 requires_resume_key, resume_key,
2721 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2724 /* W2K3 seems to treat zero as 1. */
2728 switch (info_level) {
2729 case SMB_FIND_INFO_STANDARD:
2730 case SMB_FIND_EA_SIZE:
2731 case SMB_FIND_EA_LIST:
2732 case SMB_FIND_FILE_DIRECTORY_INFO:
2733 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2734 case SMB_FIND_FILE_NAMES_INFO:
2735 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2736 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2737 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2739 case SMB_FIND_FILE_UNIX:
2740 case SMB_FIND_FILE_UNIX_INFO2:
2741 /* Always use filesystem for UNIX mtime query. */
2742 ask_sharemode = false;
2743 if (!lp_unix_extensions()) {
2744 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2749 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2753 if (info_level == SMB_FIND_EA_LIST) {
2756 if (total_data < 4) {
2757 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2761 ea_size = IVAL(pdata,0);
2762 if (ea_size != total_data) {
2763 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2764 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2765 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2769 if (!lp_ea_support(SNUM(conn))) {
2770 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2774 /* Pull out the list of names. */
2775 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2777 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2782 *ppdata = (char *)SMB_REALLOC(
2783 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2784 if(*ppdata == NULL) {
2785 reply_nterror(req, NT_STATUS_NO_MEMORY);
2790 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2792 /* Realloc the params space */
2793 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2794 if(*pparams == NULL ) {
2795 reply_nterror(req, NT_STATUS_NO_MEMORY);
2801 /* Check that the dptr is valid */
2802 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2803 reply_nterror(req, STATUS_NO_MORE_FILES);
2807 directory = dptr_path(sconn, dptr_num);
2809 /* Get the wildcard mask from the dptr */
2810 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2811 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2812 reply_nterror(req, STATUS_NO_MORE_FILES);
2816 /* Get the attr mask from the dptr */
2817 dirtype = dptr_attr(sconn, dptr_num);
2819 backup_priv = dptr_get_priv(dirptr);
2821 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2822 "backup_priv = %d\n",
2823 dptr_num, mask, dirtype,
2825 dptr_TellDir(dirptr),
2828 /* Initialize per TRANS2_FIND_NEXT operation data */
2829 dptr_init_search_op(dirptr);
2831 /* We don't need to check for VOL here as this is returned by
2832 a different TRANS2 call. */
2834 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2835 directory,lp_dontdescend(ctx, SNUM(conn))));
2836 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2837 dont_descend = True;
2840 space_remaining = max_data_bytes;
2841 out_of_space = False;
2848 * Seek to the correct position. We no longer use the resume key but
2849 * depend on the last file name instead.
2852 if(!continue_bit && resume_name && *resume_name) {
2855 long current_pos = 0;
2857 * Remember, name_to_8_3 is called by
2858 * get_lanman2_dir_entry(), so the resume name
2859 * could be mangled. Ensure we check the unmangled name.
2862 if (mangle_is_mangled(resume_name, conn->params)) {
2863 char *new_resume_name = NULL;
2864 mangle_lookup_name_from_8_3(ctx,
2868 if (new_resume_name) {
2869 resume_name = new_resume_name;
2874 * Fix for NT redirector problem triggered by resume key indexes
2875 * changing between directory scans. We now return a resume key of 0
2876 * and instead look for the filename to continue from (also given
2877 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2878 * findfirst/findnext (as is usual) then the directory pointer
2879 * should already be at the correct place.
2882 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2883 } /* end if resume_name && !continue_bit */
2885 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2886 bool got_exact_match = False;
2888 /* this is a heuristic to avoid seeking the dirptr except when
2889 absolutely necessary. It allows for a filename of about 40 chars */
2890 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2891 out_of_space = True;
2894 finished = !get_lanman2_dir_entry(ctx,
2898 mask,dirtype,info_level,
2899 requires_resume_key,dont_descend,
2902 space_remaining, &out_of_space,
2904 &last_entry_off, ea_list);
2907 if (finished && out_of_space)
2910 if (!finished && !out_of_space)
2914 * As an optimisation if we know we aren't looking
2915 * for a wildcard name (ie. the name matches the wildcard exactly)
2916 * then we can finish on any (first) match.
2917 * This speeds up large directory searches. JRA.
2923 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2926 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2927 smb_fn_name(req->cmd),
2928 mask, directory, dirtype, numentries ) );
2930 /* Check if we can close the dirptr */
2931 if(close_after_request || (finished && close_if_end)) {
2932 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2933 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2940 /* Set up the return parameter block */
2941 SSVAL(params,0,numentries);
2942 SSVAL(params,2,finished);
2943 SSVAL(params,4,0); /* Never an EA error */
2944 SSVAL(params,6,last_entry_off);
2946 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2952 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2954 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
2958 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2960 SMB_ASSERT(extended_info != NULL);
2962 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2963 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2964 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2965 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2966 #ifdef SAMBA_VERSION_REVISION
2967 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2969 extended_info->samba_subversion = 0;
2970 #ifdef SAMBA_VERSION_RC_RELEASE
2971 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2973 #ifdef SAMBA_VERSION_PRE_RELEASE
2974 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2977 #ifdef SAMBA_VERSION_VENDOR_PATCH
2978 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2980 extended_info->samba_gitcommitdate = 0;
2981 #ifdef SAMBA_VERSION_COMMIT_TIME
2982 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2985 memset(extended_info->samba_version_string, 0,
2986 sizeof(extended_info->samba_version_string));
2988 snprintf (extended_info->samba_version_string,
2989 sizeof(extended_info->samba_version_string),
2990 "%s", samba_version_string());
2993 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2994 TALLOC_CTX *mem_ctx,
2995 uint16_t info_level,
2997 unsigned int max_data_bytes,
3001 char *pdata, *end_data;
3002 int data_len = 0, len;
3003 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3004 int snum = SNUM(conn);
3005 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3006 uint32 additional_flags = 0;
3007 struct smb_filename smb_fname_dot;
3011 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3012 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3013 "info level (0x%x) on IPC$.\n",
3014 (unsigned int)info_level));
3015 return NT_STATUS_ACCESS_DENIED;
3019 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3021 ZERO_STRUCT(smb_fname_dot);
3022 smb_fname_dot.base_name = discard_const_p(char, ".");
3024 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
3025 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3026 return map_nt_error_from_unix(errno);
3029 st = smb_fname_dot.st;
3031 *ppdata = (char *)SMB_REALLOC(
3032 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3033 if (*ppdata == NULL) {
3034 return NT_STATUS_NO_MEMORY;
3038 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3039 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3041 switch (info_level) {
3042 case SMB_INFO_ALLOCATION:
3044 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3046 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3047 return map_nt_error_from_unix(errno);
3050 block_size = lp_block_size(snum);
3051 if (bsize < block_size) {
3052 uint64_t factor = block_size/bsize;
3057 if (bsize > block_size) {
3058 uint64_t factor = bsize/block_size;
3063 bytes_per_sector = 512;
3064 sectors_per_unit = bsize/bytes_per_sector;
3066 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3067 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3068 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3070 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3071 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3072 SIVAL(pdata,l1_cUnit,dsize);
3073 SIVAL(pdata,l1_cUnitAvail,dfree);
3074 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3078 case SMB_INFO_VOLUME:
3079 /* Return volume name */
3081 * Add volume serial number - hash of a combination of
3082 * the called hostname and the service name.
3084 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3086 * Win2k3 and previous mess this up by sending a name length
3087 * one byte short. I believe only older clients (OS/2 Win9x) use
3088 * this call so try fixing this by adding a terminating null to
3089 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3093 pdata+l2_vol_szVolLabel, vname,
3094 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3095 STR_NOALIGN|STR_TERMINATE);
3096 SCVAL(pdata,l2_vol_cch,len);
3097 data_len = l2_vol_szVolLabel + len;
3098 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3099 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3103 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3104 case SMB_FS_ATTRIBUTE_INFORMATION:
3106 additional_flags = 0;
3107 #if defined(HAVE_SYS_QUOTAS)
3108 additional_flags |= FILE_VOLUME_QUOTAS;
3111 if(lp_nt_acl_support(SNUM(conn))) {
3112 additional_flags |= FILE_PERSISTENT_ACLS;
3115 /* Capabilities are filled in at connection time through STATVFS call */
3116 additional_flags |= conn->fs_capabilities;
3117 additional_flags |= lp_parm_int(conn->params->service,
3118 "share", "fake_fscaps",
3121 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3122 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3123 additional_flags); /* FS ATTRIBUTES */
3125 SIVAL(pdata,4,255); /* Max filename component length */
3126 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3127 and will think we can't do long filenames */
3128 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3129 PTR_DIFF(end_data, pdata+12),
3132 data_len = 12 + len;
3135 case SMB_QUERY_FS_LABEL_INFO:
3136 case SMB_FS_LABEL_INFORMATION:
3137 len = srvstr_push(pdata, flags2, pdata+4, vname,
3138 PTR_DIFF(end_data, pdata+4), 0);
3143 case SMB_QUERY_FS_VOLUME_INFO:
3144 case SMB_FS_VOLUME_INFORMATION:
3147 * Add volume serial number - hash of a combination of
3148 * the called hostname and the service name.
3150 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3151 (str_checksum(get_local_machine_name())<<16));
3153 /* Max label len is 32 characters. */
3154 len = srvstr_push(pdata, flags2, pdata+18, vname,
3155 PTR_DIFF(end_data, pdata+18),
3157 SIVAL(pdata,12,len);
3160 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3161 (int)strlen(vname),vname,
3162 lp_servicename(talloc_tos(), snum)));
3165 case SMB_QUERY_FS_SIZE_INFO:
3166 case SMB_FS_SIZE_INFORMATION:
3168 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3170 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3171 return map_nt_error_from_unix(errno);
3173 block_size = lp_block_size(snum);
3174 if (bsize < block_size) {
3175 uint64_t factor = block_size/bsize;
3180 if (bsize > block_size) {
3181 uint64_t factor = bsize/block_size;
3186 bytes_per_sector = 512;
3187 sectors_per_unit = bsize/bytes_per_sector;
3188 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3189 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3190 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3191 SBIG_UINT(pdata,0,dsize);
3192 SBIG_UINT(pdata,8,dfree);
3193 SIVAL(pdata,16,sectors_per_unit);
3194 SIVAL(pdata,20,bytes_per_sector);
3198 case SMB_FS_FULL_SIZE_INFORMATION:
3200 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3202 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3203 return map_nt_error_from_unix(errno);
3205 block_size = lp_block_size(snum);
3206 if (bsize < block_size) {
3207 uint64_t factor = block_size/bsize;
3212 if (bsize > block_size) {
3213 uint64_t factor = bsize/block_size;
3218 bytes_per_sector = 512;
3219 sectors_per_unit = bsize/bytes_per_sector;
3220 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3221 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3222 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3223 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3224 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3225 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3226 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3227 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3231 case SMB_QUERY_FS_DEVICE_INFO:
3232 case SMB_FS_DEVICE_INFORMATION:
3234 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3236 if (!CAN_WRITE(conn)) {
3237 characteristics |= FILE_READ_ONLY_DEVICE;
3240 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3241 SIVAL(pdata,4,characteristics);
3245 #ifdef HAVE_SYS_QUOTAS
3246 case SMB_FS_QUOTA_INFORMATION:
3248 * what we have to send --metze:
3250 * Unknown1: 24 NULL bytes
3251 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3252 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3253 * Quota Flags: 2 byte :
3254 * Unknown3: 6 NULL bytes
3258 * details for Quota Flags:
3260 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3261 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3262 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3263 * 0x0001 Enable Quotas: enable quota for this fs
3267 /* we need to fake up a fsp here,
3268 * because its not send in this call
3271 SMB_NTQUOTA_STRUCT quotas;
3274 ZERO_STRUCT(quotas);
3277 fsp.fnum = FNUM_FIELD_INVALID;
3280 if (get_current_uid(conn) != 0) {
3281 DEBUG(0,("set_user_quota: access_denied "
3282 "service [%s] user [%s]\n",
3283 lp_servicename(talloc_tos(), SNUM(conn)),
3284 conn->session_info->unix_info->unix_name));
3285 return NT_STATUS_ACCESS_DENIED;
3288 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3289 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3290 return map_nt_error_from_unix(errno);
3295 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3296 lp_servicename(talloc_tos(), SNUM(conn))));
3298 /* Unknown1 24 NULL bytes*/
3299 SBIG_UINT(pdata,0,(uint64_t)0);
3300 SBIG_UINT(pdata,8,(uint64_t)0);
3301 SBIG_UINT(pdata,16,(uint64_t)0);
3303 /* Default Soft Quota 8 bytes */
3304 SBIG_UINT(pdata,24,quotas.softlim);
3306 /* Default Hard Quota 8 bytes */
3307 SBIG_UINT(pdata,32,quotas.hardlim);
3309 /* Quota flag 2 bytes */
3310 SSVAL(pdata,40,quotas.qflags);
3312 /* Unknown3 6 NULL bytes */
3318 #endif /* HAVE_SYS_QUOTAS */
3319 case SMB_FS_OBJECTID_INFORMATION:
3321 unsigned char objid[16];
3322 struct smb_extended_info extended_info;
3323 memcpy(pdata,create_volume_objectid(conn, objid),16);
3324 samba_extended_info_version (&extended_info);
3325 SIVAL(pdata,16,extended_info.samba_magic);
3326 SIVAL(pdata,20,extended_info.samba_version);
3327 SIVAL(pdata,24,extended_info.samba_subversion);
3328 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3329 memcpy(pdata+36,extended_info.samba_version_string,28);
3335 * Query the version and capabilities of the CIFS UNIX extensions
3339 case SMB_QUERY_CIFS_UNIX_INFO:
3341 bool large_write = lp_min_receive_file_size() &&
3342 !srv_is_signing_active(conn->sconn);
3343 bool large_read = !srv_is_signing_active(conn->sconn);
3344 int encrypt_caps = 0;
3346 if (!lp_unix_extensions()) {
3347 return NT_STATUS_INVALID_LEVEL;
3350 switch (conn->encrypt_level) {
3351 case SMB_SIGNING_OFF:
3354 case SMB_SIGNING_IF_REQUIRED:
3355 case SMB_SIGNING_DEFAULT:
3356 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3358 case SMB_SIGNING_REQUIRED:
3359 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3360 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3361 large_write = false;
3367 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3368 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3370 /* We have POSIX ACLs, pathname, encryption,
3371 * large read/write, and locking capability. */
3373 SBIG_UINT(pdata,4,((uint64_t)(
3374 CIFS_UNIX_POSIX_ACLS_CAP|
3375 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3376 CIFS_UNIX_FCNTL_LOCKS_CAP|
3377 CIFS_UNIX_EXTATTR_CAP|
3378 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3380 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3382 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3386 case SMB_QUERY_POSIX_FS_INFO:
3389 vfs_statvfs_struct svfs;
3391 if (!lp_unix_extensions()) {
3392 return NT_STATUS_INVALID_LEVEL;
3395 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3399 SIVAL(pdata,0,svfs.OptimalTransferSize);
3400 SIVAL(pdata,4,svfs.BlockSize);
3401 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3402 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3403 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3404 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3405 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3406 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3407 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3409 } else if (rc == EOPNOTSUPP) {
3410 return NT_STATUS_INVALID_LEVEL;
3411 #endif /* EOPNOTSUPP */
3413 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3414 return NT_STATUS_DOS(ERRSRV, ERRerror);
3419 case SMB_QUERY_POSIX_WHOAMI:
3425 if (!lp_unix_extensions()) {
3426 return NT_STATUS_INVALID_LEVEL;
3429 if (max_data_bytes < 40) {
3430 return NT_STATUS_BUFFER_TOO_SMALL;
3433 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3434 flags |= SMB_WHOAMI_GUEST;
3437 /* NOTE: 8 bytes for UID/GID, irrespective of native
3438 * platform size. This matches
3439 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3441 data_len = 4 /* flags */
3448 + 4 /* pad/reserved */
3449 + (conn->session_info->unix_token->ngroups * 8)
3451 + (conn->session_info->security_token->num_sids *
3455 SIVAL(pdata, 0, flags);
3456 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3458 (uint64_t)conn->session_info->unix_token->uid);
3459 SBIG_UINT(pdata, 16,
3460 (uint64_t)conn->session_info->unix_token->gid);
3463 if (data_len >= max_data_bytes) {
3464 /* Potential overflow, skip the GIDs and SIDs. */
3466 SIVAL(pdata, 24, 0); /* num_groups */
3467 SIVAL(pdata, 28, 0); /* num_sids */
3468 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3469 SIVAL(pdata, 36, 0); /* reserved */
3475 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3476 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3478 /* We walk the SID list twice, but this call is fairly
3479 * infrequent, and I don't expect that it's performance
3480 * sensitive -- jpeach
3482 for (i = 0, sid_bytes = 0;
3483 i < conn->session_info->security_token->num_sids; ++i) {
3484 sid_bytes += ndr_size_dom_sid(
3485 &conn->session_info->security_token->sids[i],
3489 /* SID list byte count */
3490 SIVAL(pdata, 32, sid_bytes);
3492 /* 4 bytes pad/reserved - must be zero */
3493 SIVAL(pdata, 36, 0);
3497 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3498 SBIG_UINT(pdata, data_len,
3499 (uint64_t)conn->session_info->unix_token->groups[i]);
3505 i < conn->session_info->security_token->num_sids; ++i) {
3506 int sid_len = ndr_size_dom_sid(
3507 &conn->session_info->security_token->sids[i],
3510 sid_linearize(pdata + data_len, sid_len,
3511 &conn->session_info->security_token->sids[i]);
3512 data_len += sid_len;
3518 case SMB_MAC_QUERY_FS_INFO:
3520 * Thursby MAC extension... ONLY on NTFS filesystems
3521 * once we do streams then we don't need this
3523 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3525 SIVAL(pdata,84,0x100); /* Don't support mac... */
3530 return NT_STATUS_INVALID_LEVEL;
3533 *ret_data_len = data_len;
3534 return NT_STATUS_OK;
3537 /****************************************************************************
3538 Reply to a TRANS2_QFSINFO (query filesystem info).
3539 ****************************************************************************/
3541 static void call_trans2qfsinfo(connection_struct *conn,
3542 struct smb_request *req,
3543 char **pparams, int total_params,
3544 char **ppdata, int total_data,
3545 unsigned int max_data_bytes)
3547 char *params = *pparams;
3548 uint16_t info_level;
3552 if (total_params < 2) {
3553 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3557 info_level = SVAL(params,0);
3559 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3560 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3561 DEBUG(0,("call_trans2qfsinfo: encryption required "
3562 "and info level 0x%x sent.\n",
3563 (unsigned int)info_level));
3564 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3569 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3571 status = smbd_do_qfsinfo(conn, req,
3576 if (!NT_STATUS_IS_OK(status)) {
3577 reply_nterror(req, status);
3581 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3584 DEBUG( 4, ( "%s info_level = %d\n",
3585 smb_fn_name(req->cmd), info_level) );
3590 /****************************************************************************
3591 Reply to a TRANS2_SETFSINFO (set filesystem info).
3592 ****************************************************************************/
3594 static void call_trans2setfsinfo(connection_struct *conn,
3595 struct smb_request *req,
3596 char **pparams, int total_params,
3597 char **ppdata, int total_data,
3598 unsigned int max_data_bytes)
3600 struct smbd_server_connection *sconn = req->sconn;
3601 char *pdata = *ppdata;
3602 char *params = *pparams;
3605 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3606 lp_servicename(talloc_tos(), SNUM(conn))));
3609 if (total_params < 4) {
3610 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3616 info_level = SVAL(params,2);
3619 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3620 info_level != SMB_SET_CIFS_UNIX_INFO) {
3621 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3622 "info level (0x%x) on IPC$.\n",
3623 (unsigned int)info_level));
3624 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3629 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3630 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3631 DEBUG(0,("call_trans2setfsinfo: encryption required "
3632 "and info level 0x%x sent.\n",
3633 (unsigned int)info_level));
3634 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3639 switch(info_level) {
3640 case SMB_SET_CIFS_UNIX_INFO:
3641 if (!lp_unix_extensions()) {
3642 DEBUG(2,("call_trans2setfsinfo: "
3643 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3644 "unix extensions off\n"));
3646 NT_STATUS_INVALID_LEVEL);
3650 /* There should be 12 bytes of capabilities set. */
3651 if (total_data < 12) {
3654 NT_STATUS_INVALID_PARAMETER);
3657 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3658 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3659 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3660 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3661 /* Just print these values for now. */
3662 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3663 "major = %u, minor = %u cap_low = 0x%x, "
3665 (unsigned int)sconn->
3666 smb1.unix_info.client_major,
3667 (unsigned int)sconn->
3668 smb1.unix_info.client_minor,
3669 (unsigned int)sconn->
3670 smb1.unix_info.client_cap_low,
3671 (unsigned int)sconn->
3672 smb1.unix_info.client_cap_high));
3674 /* Here is where we must switch to posix pathname processing... */
3675 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3676 lp_set_posix_pathnames();
3677 mangle_change_to_posix();
3680 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3681 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3682 /* Client that knows how to do posix locks,
3683 * but not posix open/mkdir operations. Set a
3684 * default type for read/write checks. */
3686 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3691 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3694 size_t param_len = 0;
3695 size_t data_len = total_data;
3697 if (!lp_unix_extensions()) {
3700 NT_STATUS_INVALID_LEVEL);
3704 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3707 NT_STATUS_NOT_SUPPORTED);
3711 if (req->sconn->smb1.echo_handler.trusted_fde) {
3712 DEBUG( 2,("call_trans2setfsinfo: "
3713 "request transport encryption disabled"
3714 "with 'fork echo handler = yes'\n"));
3717 NT_STATUS_NOT_SUPPORTED);
3721 DEBUG( 4,("call_trans2setfsinfo: "
3722 "request transport encryption.\n"));
3724 status = srv_request_encryption_setup(conn,
3725 (unsigned char **)ppdata,
3727 (unsigned char **)pparams,
3730 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3731 !NT_STATUS_IS_OK(status)) {
3732 reply_nterror(req, status);
3736 send_trans2_replies(conn, req,
3743 if (NT_STATUS_IS_OK(status)) {
3744 /* Server-side transport
3745 * encryption is now *on*. */
3746 status = srv_encryption_start(conn);
3747 if (!NT_STATUS_IS_OK(status)) {
3748 char *reason = talloc_asprintf(talloc_tos(),
3749 "Failure in setting "
3750 "up encrypted transport: %s",
3752 exit_server_cleanly(reason);
3758 case SMB_FS_QUOTA_INFORMATION:
3760 files_struct *fsp = NULL;
3761 SMB_NTQUOTA_STRUCT quotas;
3763 ZERO_STRUCT(quotas);
3766 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3767 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3768 lp_servicename(talloc_tos(), SNUM(conn)),
3769 conn->session_info->unix_info->unix_name));
3770 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3774 /* note: normaly there're 48 bytes,
3775 * but we didn't use the last 6 bytes for now
3778 fsp = file_fsp(req, SVAL(params,0));
3780 if (!check_fsp_ntquota_handle(conn, req,
3782 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3784 req, NT_STATUS_INVALID_HANDLE);
3788 if (total_data < 42) {
3789 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3793 NT_STATUS_INVALID_PARAMETER);
3797 /* unknown_1 24 NULL bytes in pdata*/
3799 /* the soft quotas 8 bytes (uint64_t)*/
3800 quotas.softlim = BVAL(pdata,24);
3802 /* the hard quotas 8 bytes (uint64_t)*/
3803 quotas.hardlim = BVAL(pdata,32);
3805 /* quota_flags 2 bytes **/
3806 quotas.qflags = SVAL(pdata,40);
3808 /* unknown_2 6 NULL bytes follow*/
3810 /* now set the quotas */
3811 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3812 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3813 reply_nterror(req, map_nt_error_from_unix(errno));
3820 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3822 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3828 * sending this reply works fine,
3829 * but I'm not sure it's the same
3830 * like windows do...
3833 reply_outbuf(req, 10, 0);
3836 #if defined(HAVE_POSIX_ACLS)
3837 /****************************************************************************
3838 Utility function to count the number of entries in a POSIX acl.
3839 ****************************************************************************/
3841 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3843 unsigned int ace_count = 0;
3844 int entry_id = SMB_ACL_FIRST_ENTRY;
3845 SMB_ACL_ENTRY_T entry;
3847 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3849 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3850 entry_id = SMB_ACL_NEXT_ENTRY;
3857 /****************************************************************************
3858 Utility function to marshall a POSIX acl into wire format.
3859 ****************************************************************************/
3861 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3863 int entry_id = SMB_ACL_FIRST_ENTRY;
3864 SMB_ACL_ENTRY_T entry;
3866 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3867 SMB_ACL_TAG_T tagtype;
3868 SMB_ACL_PERMSET_T permset;
3869 unsigned char perms = 0;
3870 unsigned int own_grp;
3873 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3874 entry_id = SMB_ACL_NEXT_ENTRY;
3877 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3878 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3882 if (sys_acl_get_permset(entry, &permset) == -1) {
3883 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3887 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3888 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3889 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3891 SCVAL(pdata,1,perms);
3894 case SMB_ACL_USER_OBJ:
3895 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3896 own_grp = (unsigned int)pst->st_ex_uid;
3897 SIVAL(pdata,2,own_grp);
3902 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3904 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3907 own_grp = (unsigned int)*puid;
3908 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3909 SIVAL(pdata,2,own_grp);
3913 case SMB_ACL_GROUP_OBJ:
3914 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3915 own_grp = (unsigned int)pst->st_ex_gid;
3916 SIVAL(pdata,2,own_grp);
3921 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3923 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3926 own_grp = (unsigned int)*pgid;
3927 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3928 SIVAL(pdata,2,own_grp);
3933 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3934 SIVAL(pdata,2,0xFFFFFFFF);
3935 SIVAL(pdata,6,0xFFFFFFFF);
3938 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3939 SIVAL(pdata,2,0xFFFFFFFF);
3940 SIVAL(pdata,6,0xFFFFFFFF);
3943 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3946 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3953 /****************************************************************************
3954 Store the FILE_UNIX_BASIC info.
3955 ****************************************************************************/
3957 static char *store_file_unix_basic(connection_struct *conn,
3960 const SMB_STRUCT_STAT *psbuf)
3962 uint64_t file_index = get_FileIndex(conn, psbuf);
3965 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3966 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3968 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3971 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3974 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3975 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3976 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3979 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3983 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3987 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3990 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
3991 devno = psbuf->st_ex_rdev;
3993 devno = psbuf->st_ex_dev;
3996 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4000 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4004 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4007 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4011 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4018 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4019 * the chflags(2) (or equivalent) flags.
4021 * XXX: this really should be behind the VFS interface. To do this, we would
4022 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4023 * Each VFS module could then implement its own mapping as appropriate for the
4024 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4026 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4030 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4034 { UF_IMMUTABLE, EXT_IMMUTABLE },
4038 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4042 { UF_HIDDEN, EXT_HIDDEN },
4045 /* Do not remove. We need to guarantee that this array has at least one
4046 * entry to build on HP-UX.
4052 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4053 uint32 *smb_fflags, uint32 *smb_fmask)
4057 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4058 *smb_fmask |= info2_flags_map[i].smb_fflag;
4059 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4060 *smb_fflags |= info2_flags_map[i].smb_fflag;
4065 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4066 const uint32 smb_fflags,
4067 const uint32 smb_fmask,
4070 uint32 max_fmask = 0;
4073 *stat_fflags = psbuf->st_ex_flags;
4075 /* For each flags requested in smb_fmask, check the state of the
4076 * corresponding flag in smb_fflags and set or clear the matching
4080 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4081 max_fmask |= info2_flags_map[i].smb_fflag;
4082 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4083 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4084 *stat_fflags |= info2_flags_map[i].stat_fflag;
4086 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4091 /* If smb_fmask is asking to set any bits that are not supported by
4092 * our flag mappings, we should fail.
4094 if ((smb_fmask & max_fmask) != smb_fmask) {
4102 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4103 * of file flags and birth (create) time.
4105 static char *store_file_unix_basic_info2(connection_struct *conn,
4108 const SMB_STRUCT_STAT *psbuf)
4110 uint32 file_flags = 0;
4111 uint32 flags_mask = 0;
4113 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4115 /* Create (birth) time 64 bit */
4116 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4119 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4120 SIVAL(pdata, 0, file_flags); /* flags */
4121 SIVAL(pdata, 4, flags_mask); /* mask */
4127 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4128 const struct stream_struct *streams,
4130 unsigned int max_data_bytes,
4131 unsigned int *data_size)
4134 unsigned int ofs = 0;
4136 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4137 unsigned int next_offset;
4139 smb_ucs2_t *namebuf;
4141 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4142 streams[i].name, &namelen) ||
4145 return NT_STATUS_INVALID_PARAMETER;
4149 * name_buf is now null-terminated, we need to marshall as not
4155 SIVAL(data, ofs+4, namelen);
4156 SOFF_T(data, ofs+8, streams[i].size);
4157 SOFF_T(data, ofs+16, streams[i].alloc_size);
4158 memcpy(data+ofs+24, namebuf, namelen);
4159 TALLOC_FREE(namebuf);
4161 next_offset = ofs + 24 + namelen;
4163 if (i == num_streams-1) {
4164 SIVAL(data, ofs, 0);
4167 unsigned int align = ndr_align_size(next_offset, 8);
4169 memset(data+next_offset, 0, align);
4170 next_offset += align;
4172 SIVAL(data, ofs, next_offset - ofs);
4181 return NT_STATUS_OK;
4184 /****************************************************************************
4185 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4186 ****************************************************************************/
4188 static void call_trans2qpipeinfo(connection_struct *conn,
4189 struct smb_request *req,
4190 unsigned int tran_call,
4191 char **pparams, int total_params,
4192 char **ppdata, int total_data,
4193 unsigned int max_data_bytes)
4195 char *params = *pparams;
4196 char *pdata = *ppdata;
4197 unsigned int data_size = 0;
4198 unsigned int param_size = 2;
4203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4207 if (total_params < 4) {
4208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4212 fsp = file_fsp(req, SVAL(params,0));
4213 if (!fsp_is_np(fsp)) {
4214 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4218 info_level = SVAL(params,2);
4220 *pparams = (char *)SMB_REALLOC(*pparams,2);
4221 if (*pparams == NULL) {
4222 reply_nterror(req, NT_STATUS_NO_MEMORY);
4227 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4228 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4229 if (*ppdata == NULL ) {
4230 reply_nterror(req, NT_STATUS_NO_MEMORY);
4235 switch (info_level) {
4236 case SMB_FILE_STANDARD_INFORMATION:
4238 SOFF_T(pdata,0,4096LL);
4245 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4249 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4255 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4256 TALLOC_CTX *mem_ctx,
4257 uint16_t info_level,
4259 struct smb_filename *smb_fname,
4260 bool delete_pending,
4261 struct timespec write_time_ts,
4262 struct ea_list *ea_list,
4263 int lock_data_count,
4266 unsigned int max_data_bytes,
4268 unsigned int *pdata_size)
4270 char *pdata = *ppdata;
4271 char *dstart, *dend;
4272 unsigned int data_size;
4273 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4274 time_t create_time, mtime, atime, c_time;
4275 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4282 uint64_t file_size = 0;
4284 uint64_t allocation_size = 0;
4285 uint64_t file_index = 0;
4286 uint32_t access_mask = 0;
4288 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4289 return NT_STATUS_INVALID_LEVEL;
4292 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4293 smb_fname_str_dbg(smb_fname),
4295 info_level, max_data_bytes));
4297 mode = dos_mode(conn, smb_fname);
4298 nlink = psbuf->st_ex_nlink;
4300 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4304 if ((nlink > 0) && delete_pending) {
4308 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4309 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4310 if (*ppdata == NULL) {
4311 return NT_STATUS_NO_MEMORY;
4315 dend = dstart + data_size - 1;
4317 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4318 update_stat_ex_mtime(psbuf, write_time_ts);
4321 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4322 mtime_ts = psbuf->st_ex_mtime;
4323 atime_ts = psbuf->st_ex_atime;
4324 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4326 if (lp_dos_filetime_resolution(SNUM(conn))) {
4327 dos_filetime_timespec(&create_time_ts);
4328 dos_filetime_timespec(&mtime_ts);
4329 dos_filetime_timespec(&atime_ts);
4330 dos_filetime_timespec(&ctime_ts);
4333 create_time = convert_timespec_to_time_t(create_time_ts);
4334 mtime = convert_timespec_to_time_t(mtime_ts);
4335 atime = convert_timespec_to_time_t(atime_ts);
4336 c_time = convert_timespec_to_time_t(ctime_ts);
4338 p = strrchr_m(smb_fname->base_name,'/');
4340 base_name = smb_fname->base_name;
4344 /* NT expects the name to be in an exact form of the *full*
4345 filename. See the trans2 torture test */
4346 if (ISDOT(base_name)) {
4347 dos_fname = talloc_strdup(mem_ctx, "\\");
4349 return NT_STATUS_NO_MEMORY;
4352 dos_fname = talloc_asprintf(mem_ctx,
4354 smb_fname->base_name);
4356 return NT_STATUS_NO_MEMORY;
4358 if (is_ntfs_stream_smb_fname(smb_fname)) {
4359 dos_fname = talloc_asprintf(dos_fname, "%s",
4360 smb_fname->stream_name);
4362 return NT_STATUS_NO_MEMORY;
4366 string_replace(dos_fname, '/', '\\');
4369 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4372 /* Do we have this path open ? */
4374 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4375 fsp1 = file_find_di_first(conn->sconn, fileid);
4376 if (fsp1 && fsp1->initial_allocation_size) {
4377 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4381 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4382 file_size = get_file_size_stat(psbuf);
4386 pos = fsp->fh->position_information;
4390 access_mask = fsp->access_mask;
4392 /* GENERIC_EXECUTE mapping from Windows */
4393 access_mask = 0x12019F;
4396 /* This should be an index number - looks like
4399 I think this causes us to fail the IFSKIT
4400 BasicFileInformationTest. -tpot */
4401 file_index = get_FileIndex(conn, psbuf);
4403 switch (info_level) {
4404 case SMB_INFO_STANDARD:
4405 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4407 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4408 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4409 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4410 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4411 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4412 SSVAL(pdata,l1_attrFile,mode);
4415 case SMB_INFO_QUERY_EA_SIZE:
4417 unsigned int ea_size =
4418 estimate_ea_size(conn, fsp,
4420 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4422 srv_put_dos_date2(pdata,0,create_time);
4423 srv_put_dos_date2(pdata,4,atime);
4424 srv_put_dos_date2(pdata,8,mtime); /* write time */
4425 SIVAL(pdata,12,(uint32)file_size);
4426 SIVAL(pdata,16,(uint32)allocation_size);
4427 SSVAL(pdata,20,mode);
4428 SIVAL(pdata,22,ea_size);
4432 case SMB_INFO_IS_NAME_VALID:
4433 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4435 /* os/2 needs this ? really ?*/
4436 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4438 /* This is only reached for qpathinfo */
4442 case SMB_INFO_QUERY_EAS_FROM_LIST:
4444 size_t total_ea_len = 0;
4445 struct ea_list *ea_file_list = NULL;
4447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4450 get_ea_list_from_file(mem_ctx, conn, fsp,
4451 smb_fname->base_name,
4453 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4455 if (!ea_list || (total_ea_len > data_size)) {
4457 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4461 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4465 case SMB_INFO_QUERY_ALL_EAS:
4467 /* We have data_size bytes to put EA's into. */
4468 size_t total_ea_len = 0;
4470 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4472 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4473 smb_fname->base_name,
4475 if (!ea_list || (total_ea_len > data_size)) {
4477 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4481 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4485 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4487 /* This is FileFullEaInformation - 0xF which maps to
4488 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4490 /* We have data_size bytes to put EA's into. */
4491 size_t total_ea_len = 0;
4492 struct ea_list *ea_file_list = NULL;
4494 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4496 /*TODO: add filtering and index handling */
4499 get_ea_list_from_file(mem_ctx, conn, fsp,
4500 smb_fname->base_name,
4502 if (!ea_file_list) {
4503 return NT_STATUS_NO_EAS_ON_FILE;
4506 status = fill_ea_chained_buffer(mem_ctx,
4510 conn, ea_file_list);
4511 if (!NT_STATUS_IS_OK(status)) {
4517 case SMB_FILE_BASIC_INFORMATION:
4518 case SMB_QUERY_FILE_BASIC_INFO:
4520 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4521 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4522 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4524 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4528 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4529 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4530 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4531 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4532 SIVAL(pdata,32,mode);
4534 DEBUG(5,("SMB_QFBI - "));
4535 DEBUG(5,("create: %s ", ctime(&create_time)));
4536 DEBUG(5,("access: %s ", ctime(&atime)));
4537 DEBUG(5,("write: %s ", ctime(&mtime)));
4538 DEBUG(5,("change: %s ", ctime(&c_time)));
4539 DEBUG(5,("mode: %x\n", mode));
4542 case SMB_FILE_STANDARD_INFORMATION:
4543 case SMB_QUERY_FILE_STANDARD_INFO:
4545 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4547 SOFF_T(pdata,0,allocation_size);
4548 SOFF_T(pdata,8,file_size);
4549 SIVAL(pdata,16,nlink);
4550 SCVAL(pdata,20,delete_pending?1:0);
4551 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4552 SSVAL(pdata,22,0); /* Padding. */
4555 case SMB_FILE_EA_INFORMATION:
4556 case SMB_QUERY_FILE_EA_INFO:
4558 unsigned int ea_size =
4559 estimate_ea_size(conn, fsp, smb_fname);
4560 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4562 SIVAL(pdata,0,ea_size);
4566 /* Get the 8.3 name - used if NT SMB was negotiated. */
4567 case SMB_QUERY_FILE_ALT_NAME_INFO:
4568 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4571 char mangled_name[13];
4572 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4573 if (!name_to_8_3(base_name,mangled_name,
4574 True,conn->params)) {
4575 return NT_STATUS_NO_MEMORY;
4577 len = srvstr_push(dstart, flags2,
4578 pdata+4, mangled_name,
4579 PTR_DIFF(dend, pdata+4),
4581 data_size = 4 + len;
4586 case SMB_QUERY_FILE_NAME_INFO:
4590 this must be *exactly* right for ACLs on mapped drives to work
4592 len = srvstr_push(dstart, flags2,
4594 PTR_DIFF(dend, pdata+4),
4596 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4597 data_size = 4 + len;
4602 case SMB_FILE_ALLOCATION_INFORMATION:
4603 case SMB_QUERY_FILE_ALLOCATION_INFO:
4604 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4606 SOFF_T(pdata,0,allocation_size);
4609 case SMB_FILE_END_OF_FILE_INFORMATION:
4610 case SMB_QUERY_FILE_END_OF_FILEINFO:
4611 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4613 SOFF_T(pdata,0,file_size);
4616 case SMB_QUERY_FILE_ALL_INFO:
4617 case SMB_FILE_ALL_INFORMATION:
4620 unsigned int ea_size =
4621 estimate_ea_size(conn, fsp, smb_fname);
4622 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4623 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4624 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4625 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4626 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4627 SIVAL(pdata,32,mode);
4628 SIVAL(pdata,36,0); /* padding. */
4630 SOFF_T(pdata,0,allocation_size);
4631 SOFF_T(pdata,8,file_size);
4632 SIVAL(pdata,16,nlink);
4633 SCVAL(pdata,20,delete_pending);
4634 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4637 SIVAL(pdata,0,ea_size);
4638 pdata += 4; /* EA info */
4639 len = srvstr_push(dstart, flags2,
4641 PTR_DIFF(dend, pdata+4),
4645 data_size = PTR_DIFF(pdata,(*ppdata));
4649 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4652 unsigned int ea_size =
4653 estimate_ea_size(conn, fsp, smb_fname->base_name);
4654 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4655 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4656 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4657 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4658 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4659 SIVAL(pdata, 0x20, mode);
4660 SIVAL(pdata, 0x24, 0); /* padding. */
4661 SBVAL(pdata, 0x28, allocation_size);
4662 SBVAL(pdata, 0x30, file_size);
4663 SIVAL(pdata, 0x38, nlink);
4664 SCVAL(pdata, 0x3C, delete_pending);
4665 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4666 SSVAL(pdata, 0x3E, 0); /* padding */
4667 SBVAL(pdata, 0x40, file_index);
4668 SIVAL(pdata, 0x48, ea_size);
4669 SIVAL(pdata, 0x4C, access_mask);
4670 SBVAL(pdata, 0x50, pos);
4671 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4672 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4676 len = srvstr_push(dstart, flags2,
4678 PTR_DIFF(dend, pdata+4),
4682 data_size = PTR_DIFF(pdata,(*ppdata));
4685 case SMB_FILE_INTERNAL_INFORMATION:
4687 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4688 SBVAL(pdata, 0, file_index);
4692 case SMB_FILE_ACCESS_INFORMATION:
4693 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4694 SIVAL(pdata, 0, access_mask);
4698 case SMB_FILE_NAME_INFORMATION:
4699 /* Pathname with leading '\'. */
4702 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4703 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4704 SIVAL(pdata,0,byte_len);
4705 data_size = 4 + byte_len;
4709 case SMB_FILE_DISPOSITION_INFORMATION:
4710 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4712 SCVAL(pdata,0,delete_pending);
4715 case SMB_FILE_POSITION_INFORMATION:
4716 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4718 SOFF_T(pdata,0,pos);
4721 case SMB_FILE_MODE_INFORMATION:
4722 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4723 SIVAL(pdata,0,mode);
4727 case SMB_FILE_ALIGNMENT_INFORMATION:
4728 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4729 SIVAL(pdata,0,0); /* No alignment needed. */
4734 * NT4 server just returns "invalid query" to this - if we try
4735 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4738 /* The first statement above is false - verified using Thursby
4739 * client against NT4 -- gcolley.
4741 case SMB_QUERY_FILE_STREAM_INFO:
4742 case SMB_FILE_STREAM_INFORMATION: {
4743 unsigned int num_streams = 0;
4744 struct stream_struct *streams = NULL;
4746 DEBUG(10,("smbd_do_qfilepathinfo: "
4747 "SMB_FILE_STREAM_INFORMATION\n"));
4749 if (is_ntfs_stream_smb_fname(smb_fname)) {
4750 return NT_STATUS_INVALID_PARAMETER;
4753 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4754 talloc_tos(), &num_streams, &streams);
4756 if (!NT_STATUS_IS_OK(status)) {
4757 DEBUG(10, ("could not get stream info: %s\n",
4758 nt_errstr(status)));
4762 status = marshall_stream_info(num_streams, streams,
4763 pdata, max_data_bytes,
4766 if (!NT_STATUS_IS_OK(status)) {
4767 DEBUG(10, ("marshall_stream_info failed: %s\n",
4768 nt_errstr(status)));
4772 TALLOC_FREE(streams);
4776 case SMB_QUERY_COMPRESSION_INFO:
4777 case SMB_FILE_COMPRESSION_INFORMATION:
4778 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4779 SOFF_T(pdata,0,file_size);
4780 SIVAL(pdata,8,0); /* ??? */
4781 SIVAL(pdata,12,0); /* ??? */
4785 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4786 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4787 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4788 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4789 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4790 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4791 SOFF_T(pdata,32,allocation_size);
4792 SOFF_T(pdata,40,file_size);
4793 SIVAL(pdata,48,mode);
4794 SIVAL(pdata,52,0); /* ??? */
4798 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4799 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4800 SIVAL(pdata,0,mode);
4806 * CIFS UNIX Extensions.
4809 case SMB_QUERY_FILE_UNIX_BASIC:
4811 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4812 data_size = PTR_DIFF(pdata,(*ppdata));
4814 DEBUG(4,("smbd_do_qfilepathinfo: "
4815 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4816 dump_data(4, (uint8_t *)(*ppdata), data_size);
4820 case SMB_QUERY_FILE_UNIX_INFO2:
4822 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4823 data_size = PTR_DIFF(pdata,(*ppdata));
4827 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4829 for (i=0; i<100; i++)
4830 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4836 case SMB_QUERY_FILE_UNIX_LINK:
4839 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4842 return NT_STATUS_NO_MEMORY;
4845 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4847 if(!S_ISLNK(psbuf->st_ex_mode)) {
4848 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4851 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4853 len = SMB_VFS_READLINK(conn,
4854 smb_fname->base_name,
4857 return map_nt_error_from_unix(errno);
4860 len = srvstr_push(dstart, flags2,
4862 PTR_DIFF(dend, pdata),
4865 data_size = PTR_DIFF(pdata,(*ppdata));
4870 #if defined(HAVE_POSIX_ACLS)
4871 case SMB_QUERY_POSIX_ACL:
4873 SMB_ACL_T file_acl = NULL;
4874 SMB_ACL_T def_acl = NULL;
4875 uint16 num_file_acls = 0;
4876 uint16 num_def_acls = 0;
4878 if (fsp && fsp->fh->fd != -1) {
4879 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4882 SMB_VFS_SYS_ACL_GET_FILE(conn,
4883 smb_fname->base_name,
4884 SMB_ACL_TYPE_ACCESS);
4887 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4888 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4889 "not implemented on "
4890 "filesystem containing %s\n",
4891 smb_fname->base_name));
4892 return NT_STATUS_NOT_IMPLEMENTED;
4895 if (S_ISDIR(psbuf->st_ex_mode)) {
4896 if (fsp && fsp->is_directory) {
4898 SMB_VFS_SYS_ACL_GET_FILE(
4900 fsp->fsp_name->base_name,
4901 SMB_ACL_TYPE_DEFAULT);
4904 SMB_VFS_SYS_ACL_GET_FILE(
4906 smb_fname->base_name,
4907 SMB_ACL_TYPE_DEFAULT);
4909 def_acl = free_empty_sys_acl(conn, def_acl);
4912 num_file_acls = count_acl_entries(conn, file_acl);
4913 num_def_acls = count_acl_entries(conn, def_acl);
4915 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4916 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4918 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4919 SMB_POSIX_ACL_HEADER_SIZE) ));
4921 TALLOC_FREE(file_acl);
4924 TALLOC_FREE(def_acl);
4926 return NT_STATUS_BUFFER_TOO_SMALL;
4929 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4930 SSVAL(pdata,2,num_file_acls);
4931 SSVAL(pdata,4,num_def_acls);
4932 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4934 TALLOC_FREE(file_acl);
4937 TALLOC_FREE(def_acl);
4939 return NT_STATUS_INTERNAL_ERROR;
4941 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4943 TALLOC_FREE(file_acl);
4946 TALLOC_FREE(def_acl);
4948 return NT_STATUS_INTERNAL_ERROR;
4952 TALLOC_FREE(file_acl);
4955 TALLOC_FREE(def_acl);
4957 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4963 case SMB_QUERY_POSIX_LOCK:
4968 enum brl_type lock_type;
4970 /* We need an open file with a real fd for this. */
4971 if (!fsp || fsp->fh->fd == -1) {
4972 return NT_STATUS_INVALID_LEVEL;
4975 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4976 return NT_STATUS_INVALID_PARAMETER;
4979 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4980 case POSIX_LOCK_TYPE_READ:
4981 lock_type = READ_LOCK;
4983 case POSIX_LOCK_TYPE_WRITE:
4984 lock_type = WRITE_LOCK;
4986 case POSIX_LOCK_TYPE_UNLOCK:
4988 /* There's no point in asking for an unlock... */
4989 return NT_STATUS_INVALID_PARAMETER;
4992 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4993 #if defined(HAVE_LONGLONG)
4994 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4995 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4996 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4997 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4998 #else /* HAVE_LONGLONG */
4999 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5000 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5001 #endif /* HAVE_LONGLONG */
5003 status = query_lock(fsp,
5010 if (ERROR_WAS_LOCK_DENIED(status)) {
5011 /* Here we need to report who has it locked... */
5012 data_size = POSIX_LOCK_DATA_SIZE;
5014 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5015 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5016 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5017 #if defined(HAVE_LONGLONG)
5018 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5019 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5020 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5021 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5022 #else /* HAVE_LONGLONG */
5023 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5024 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5025 #endif /* HAVE_LONGLONG */
5027 } else if (NT_STATUS_IS_OK(status)) {
5028 /* For success we just return a copy of what we sent
5029 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5030 data_size = POSIX_LOCK_DATA_SIZE;
5031 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5032 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5040 return NT_STATUS_INVALID_LEVEL;
5043 *pdata_size = data_size;
5044 return NT_STATUS_OK;
5047 /****************************************************************************
5048 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5049 file name or file id).
5050 ****************************************************************************/
5052 static void call_trans2qfilepathinfo(connection_struct *conn,
5053 struct smb_request *req,
5054 unsigned int tran_call,
5055 char **pparams, int total_params,
5056 char **ppdata, int total_data,
5057 unsigned int max_data_bytes)
5059 char *params = *pparams;
5060 char *pdata = *ppdata;
5062 unsigned int data_size = 0;
5063 unsigned int param_size = 2;
5064 struct smb_filename *smb_fname = NULL;
5065 bool delete_pending = False;
5066 struct timespec write_time_ts;
5067 files_struct *fsp = NULL;
5068 struct file_id fileid;
5069 struct ea_list *ea_list = NULL;
5070 int lock_data_count = 0;
5071 char *lock_data = NULL;
5072 NTSTATUS status = NT_STATUS_OK;
5075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5079 ZERO_STRUCT(write_time_ts);
5081 if (tran_call == TRANSACT2_QFILEINFO) {
5082 if (total_params < 4) {
5083 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5088 call_trans2qpipeinfo(conn, req, tran_call,
5089 pparams, total_params,
5095 fsp = file_fsp(req, SVAL(params,0));
5096 info_level = SVAL(params,2);
5098 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5100 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5101 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5105 /* Initial check for valid fsp ptr. */
5106 if (!check_fsp_open(conn, req, fsp)) {
5110 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5112 if (!NT_STATUS_IS_OK(status)) {
5113 reply_nterror(req, status);
5117 if(fsp->fake_file_handle) {
5119 * This is actually for the QUOTA_FAKE_FILE --metze
5122 /* We know this name is ok, it's already passed the checks. */
5124 } else if(fsp->fh->fd == -1) {
5126 * This is actually a QFILEINFO on a directory
5127 * handle (returned from an NT SMB). NT5.0 seems
5128 * to do this call. JRA.
5131 if (INFO_LEVEL_IS_UNIX(info_level)) {
5132 /* Always do lstat for UNIX calls. */
5133 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5134 DEBUG(3,("call_trans2qfilepathinfo: "
5135 "SMB_VFS_LSTAT of %s failed "
5137 smb_fname_str_dbg(smb_fname),
5140 map_nt_error_from_unix(errno));
5143 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5144 DEBUG(3,("call_trans2qfilepathinfo: "
5145 "SMB_VFS_STAT of %s failed (%s)\n",
5146 smb_fname_str_dbg(smb_fname),
5149 map_nt_error_from_unix(errno));
5153 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5154 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5157 * Original code - this is an open file.
5159 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5160 DEBUG(3, ("fstat of %s failed (%s)\n",
5161 fsp_fnum_dbg(fsp), strerror(errno)));
5163 map_nt_error_from_unix(errno));
5166 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5167 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5173 uint32_t ucf_flags = 0;
5176 if (total_params < 7) {
5177 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5181 info_level = SVAL(params,0);
5183 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5185 if (INFO_LEVEL_IS_UNIX(info_level)) {
5186 if (!lp_unix_extensions()) {
5187 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5190 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5191 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5192 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5193 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5197 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5199 STR_TERMINATE, &status);
5200 if (!NT_STATUS_IS_OK(status)) {
5201 reply_nterror(req, status);
5205 status = filename_convert(req,
5207 req->flags2 & FLAGS2_DFS_PATHNAMES,
5212 if (!NT_STATUS_IS_OK(status)) {
5213 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5214 reply_botherror(req,
5215 NT_STATUS_PATH_NOT_COVERED,
5216 ERRSRV, ERRbadpath);
5219 reply_nterror(req, status);
5223 /* If this is a stream, check if there is a delete_pending. */
5224 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5225 && is_ntfs_stream_smb_fname(smb_fname)) {
5226 struct smb_filename *smb_fname_base = NULL;
5228 /* Create an smb_filename with stream_name == NULL. */
5230 create_synthetic_smb_fname(talloc_tos(),
5231 smb_fname->base_name,
5234 if (!NT_STATUS_IS_OK(status)) {
5235 reply_nterror(req, status);
5239 if (INFO_LEVEL_IS_UNIX(info_level)) {
5240 /* Always do lstat for UNIX calls. */
5241 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5242 DEBUG(3,("call_trans2qfilepathinfo: "
5243 "SMB_VFS_LSTAT of %s failed "
5245 smb_fname_str_dbg(smb_fname_base),
5247 TALLOC_FREE(smb_fname_base);
5249 map_nt_error_from_unix(errno));
5253 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5254 DEBUG(3,("call_trans2qfilepathinfo: "
5255 "fileinfo of %s failed "
5257 smb_fname_str_dbg(smb_fname_base),
5259 TALLOC_FREE(smb_fname_base);
5261 map_nt_error_from_unix(errno));
5266 status = file_name_hash(conn,
5267 smb_fname_str_dbg(smb_fname_base),
5269 if (!NT_STATUS_IS_OK(status)) {
5270 TALLOC_FREE(smb_fname_base);
5271 reply_nterror(req, status);
5275 fileid = vfs_file_id_from_sbuf(conn,
5276 &smb_fname_base->st);
5277 TALLOC_FREE(smb_fname_base);
5278 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5279 if (delete_pending) {
5280 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5285 if (INFO_LEVEL_IS_UNIX(info_level)) {
5286 /* Always do lstat for UNIX calls. */
5287 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5288 DEBUG(3,("call_trans2qfilepathinfo: "
5289 "SMB_VFS_LSTAT of %s failed (%s)\n",
5290 smb_fname_str_dbg(smb_fname),
5293 map_nt_error_from_unix(errno));
5298 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5299 DEBUG(3,("call_trans2qfilepathinfo: "
5300 "SMB_VFS_STAT of %s failed (%s)\n",
5301 smb_fname_str_dbg(smb_fname),
5304 map_nt_error_from_unix(errno));
5309 status = file_name_hash(conn,
5310 smb_fname_str_dbg(smb_fname),
5312 if (!NT_STATUS_IS_OK(status)) {
5313 reply_nterror(req, status);
5317 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5318 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5319 if (delete_pending) {
5320 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5325 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5326 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5328 info_level,tran_call,total_data));
5330 /* Pull out any data sent here before we realloc. */
5331 switch (info_level) {
5332 case SMB_INFO_QUERY_EAS_FROM_LIST:
5334 /* Pull any EA list from the data portion. */
5337 if (total_data < 4) {
5339 req, NT_STATUS_INVALID_PARAMETER);
5342 ea_size = IVAL(pdata,0);
5344 if (total_data > 0 && ea_size != total_data) {
5345 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5346 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5348 req, NT_STATUS_INVALID_PARAMETER);
5352 if (!lp_ea_support(SNUM(conn))) {
5353 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5357 /* Pull out the list of names. */
5358 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5361 req, NT_STATUS_INVALID_PARAMETER);
5367 case SMB_QUERY_POSIX_LOCK:
5369 if (fsp == NULL || fsp->fh->fd == -1) {
5370 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5374 if (total_data != POSIX_LOCK_DATA_SIZE) {
5376 req, NT_STATUS_INVALID_PARAMETER);
5380 /* Copy the lock range data. */
5381 lock_data = (char *)talloc_memdup(
5382 req, pdata, total_data);
5384 reply_nterror(req, NT_STATUS_NO_MEMORY);
5387 lock_data_count = total_data;
5393 *pparams = (char *)SMB_REALLOC(*pparams,2);
5394 if (*pparams == NULL) {
5395 reply_nterror(req, NT_STATUS_NO_MEMORY);
5402 * draft-leach-cifs-v1-spec-02.txt
5403 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5406 * The requested information is placed in the Data portion of the
5407 * transaction response. For the information levels greater than 0x100,
5408 * the transaction response has 1 parameter word which should be
5409 * ignored by the client.
5411 * However Windows only follows this rule for the IS_NAME_VALID call.
5413 switch (info_level) {
5414 case SMB_INFO_IS_NAME_VALID:
5419 if ((info_level & 0xFF00) == 0xFF00) {
5421 * We use levels that start with 0xFF00
5422 * internally to represent SMB2 specific levels
5424 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5428 status = smbd_do_qfilepathinfo(conn, req, info_level,
5430 delete_pending, write_time_ts,
5432 lock_data_count, lock_data,
5433 req->flags2, max_data_bytes,
5434 ppdata, &data_size);
5435 if (!NT_STATUS_IS_OK(status)) {
5436 reply_nterror(req, status);
5440 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5446 /****************************************************************************
5447 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5449 ****************************************************************************/
5451 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5452 connection_struct *conn,
5453 struct smb_request *req,
5454 bool overwrite_if_exists,
5455 const struct smb_filename *smb_fname_old,
5456 struct smb_filename *smb_fname_new)
5458 NTSTATUS status = NT_STATUS_OK;
5460 /* source must already exist. */
5461 if (!VALID_STAT(smb_fname_old->st)) {
5462 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5465 if (VALID_STAT(smb_fname_new->st)) {
5466 if (overwrite_if_exists) {
5467 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5468 return NT_STATUS_FILE_IS_A_DIRECTORY;
5470 status = unlink_internals(conn,
5472 FILE_ATTRIBUTE_NORMAL,
5475 if (!NT_STATUS_IS_OK(status)) {
5479 /* Disallow if newname already exists. */
5480 return NT_STATUS_OBJECT_NAME_COLLISION;
5484 /* No links from a directory. */
5485 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5486 return NT_STATUS_FILE_IS_A_DIRECTORY;
5489 /* Setting a hardlink to/from a stream isn't currently supported. */
5490 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5491 is_ntfs_stream_smb_fname(smb_fname_new)) {
5492 return NT_STATUS_INVALID_PARAMETER;
5495 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5496 smb_fname_old->base_name, smb_fname_new->base_name));
5498 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5499 smb_fname_new->base_name) != 0) {
5500 status = map_nt_error_from_unix(errno);
5501 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5502 nt_errstr(status), smb_fname_old->base_name,
5503 smb_fname_new->base_name));
5508 /****************************************************************************
5509 Deal with setting the time from any of the setfilepathinfo functions.
5510 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5511 calling this function.
5512 ****************************************************************************/
5514 NTSTATUS smb_set_file_time(connection_struct *conn,
5516 const struct smb_filename *smb_fname,
5517 struct smb_file_time *ft,
5518 bool setting_write_time)
5520 struct smb_filename smb_fname_base;
5522 FILE_NOTIFY_CHANGE_LAST_ACCESS
5523 |FILE_NOTIFY_CHANGE_LAST_WRITE
5524 |FILE_NOTIFY_CHANGE_CREATION;
5526 if (!VALID_STAT(smb_fname->st)) {
5527 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5530 /* get some defaults (no modifications) if any info is zero or -1. */
5531 if (null_timespec(ft->create_time)) {
5532 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5535 if (null_timespec(ft->atime)) {
5536 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5539 if (null_timespec(ft->mtime)) {
5540 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5543 if (!setting_write_time) {
5544 /* ft->mtime comes from change time, not write time. */
5545 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5548 /* Ensure the resolution is the correct for
5549 * what we can store on this filesystem. */
5551 round_timespec(conn->ts_res, &ft->create_time);
5552 round_timespec(conn->ts_res, &ft->ctime);
5553 round_timespec(conn->ts_res, &ft->atime);
5554 round_timespec(conn->ts_res, &ft->mtime);
5556 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5557 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5558 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5559 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5560 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5561 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5562 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5563 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5565 if (setting_write_time) {
5567 * This was a Windows setfileinfo on an open file.
5568 * NT does this a lot. We also need to
5569 * set the time here, as it can be read by
5570 * FindFirst/FindNext and with the patch for bug #2045
5571 * in smbd/fileio.c it ensures that this timestamp is
5572 * kept sticky even after a write. We save the request
5573 * away and will set it on file close and after a write. JRA.
5576 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5577 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5580 if (fsp->base_fsp) {
5581 set_sticky_write_time_fsp(fsp->base_fsp,
5584 set_sticky_write_time_fsp(fsp, ft->mtime);
5587 set_sticky_write_time_path(
5588 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5593 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5595 /* Always call ntimes on the base, even if a stream was passed in. */
5596 smb_fname_base = *smb_fname;
5597 smb_fname_base.stream_name = NULL;
5599 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5600 return map_nt_error_from_unix(errno);
5603 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5604 smb_fname->base_name);
5605 return NT_STATUS_OK;
5608 /****************************************************************************
5609 Deal with setting the dosmode from any of the setfilepathinfo functions.
5610 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5611 done before calling this function.
5612 ****************************************************************************/
5614 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5615 const struct smb_filename *smb_fname,
5618 struct smb_filename *smb_fname_base = NULL;
5621 if (!VALID_STAT(smb_fname->st)) {
5622 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5625 /* Always operate on the base_name, even if a stream was passed in. */
5626 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5627 NULL, &smb_fname->st,
5629 if (!NT_STATUS_IS_OK(status)) {
5634 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5635 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5637 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5641 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5643 /* check the mode isn't different, before changing it */
5644 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5645 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5646 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5647 (unsigned int)dosmode));
5649 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5651 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5653 smb_fname_str_dbg(smb_fname_base),
5655 status = map_nt_error_from_unix(errno);
5659 status = NT_STATUS_OK;
5661 TALLOC_FREE(smb_fname_base);
5665 /****************************************************************************
5666 Deal with setting the size from any of the setfilepathinfo functions.
5667 ****************************************************************************/
5669 static NTSTATUS smb_set_file_size(connection_struct *conn,
5670 struct smb_request *req,
5672 const struct smb_filename *smb_fname,
5673 const SMB_STRUCT_STAT *psbuf,
5675 bool fail_after_createfile)
5677 NTSTATUS status = NT_STATUS_OK;
5678 struct smb_filename *smb_fname_tmp = NULL;
5679 files_struct *new_fsp = NULL;
5681 if (!VALID_STAT(*psbuf)) {
5682 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5685 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5687 if (size == get_file_size_stat(psbuf)) {
5688 return NT_STATUS_OK;
5691 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5692 smb_fname_str_dbg(smb_fname), (double)size));
5694 if (fsp && fsp->fh->fd != -1) {
5695 /* Handle based call. */
5696 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5697 return NT_STATUS_ACCESS_DENIED;
5700 if (vfs_set_filelen(fsp, size) == -1) {
5701 return map_nt_error_from_unix(errno);
5703 trigger_write_time_update_immediate(fsp);
5704 return NT_STATUS_OK;
5707 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5708 if (!NT_STATUS_IS_OK(status)) {
5712 smb_fname_tmp->st = *psbuf;
5714 status = SMB_VFS_CREATE_FILE(
5717 0, /* root_dir_fid */
5718 smb_fname_tmp, /* fname */
5719 FILE_WRITE_DATA, /* access_mask */
5720 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5722 FILE_OPEN, /* create_disposition*/
5723 0, /* create_options */
5724 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5725 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5726 0, /* allocation_size */
5727 0, /* private_flags */
5730 &new_fsp, /* result */
5733 TALLOC_FREE(smb_fname_tmp);
5735 if (!NT_STATUS_IS_OK(status)) {
5736 /* NB. We check for open_was_deferred in the caller. */
5740 /* See RAW-SFILEINFO-END-OF-FILE */
5741 if (fail_after_createfile) {
5742 close_file(req, new_fsp,NORMAL_CLOSE);
5743 return NT_STATUS_INVALID_LEVEL;
5746 if (vfs_set_filelen(new_fsp, size) == -1) {
5747 status = map_nt_error_from_unix(errno);
5748 close_file(req, new_fsp,NORMAL_CLOSE);
5752 trigger_write_time_update_immediate(new_fsp);
5753 close_file(req, new_fsp,NORMAL_CLOSE);
5754 return NT_STATUS_OK;
5757 /****************************************************************************
5758 Deal with SMB_INFO_SET_EA.
5759 ****************************************************************************/
5761 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5765 const struct smb_filename *smb_fname)
5767 struct ea_list *ea_list = NULL;
5768 TALLOC_CTX *ctx = NULL;
5769 NTSTATUS status = NT_STATUS_OK;
5771 if (total_data < 10) {
5773 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5774 length. They seem to have no effect. Bug #3212. JRA */
5776 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5777 /* We're done. We only get EA info in this call. */
5778 return NT_STATUS_OK;
5781 return NT_STATUS_INVALID_PARAMETER;
5784 if (IVAL(pdata,0) > total_data) {
5785 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5786 IVAL(pdata,0), (unsigned int)total_data));
5787 return NT_STATUS_INVALID_PARAMETER;
5791 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5793 return NT_STATUS_INVALID_PARAMETER;
5796 status = set_ea(conn, fsp, smb_fname, ea_list);
5801 /****************************************************************************
5802 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5803 ****************************************************************************/
5805 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5810 struct ea_list *ea_list = NULL;
5814 return NT_STATUS_INVALID_HANDLE;
5817 if (!lp_ea_support(SNUM(conn))) {
5818 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5819 "EA's not supported.\n",
5820 (unsigned int)total_data));
5821 return NT_STATUS_EAS_NOT_SUPPORTED;
5824 if (total_data < 10) {
5825 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5827 (unsigned int)total_data));
5828 return NT_STATUS_INVALID_PARAMETER;
5831 ea_list = read_nttrans_ea_list(talloc_tos(),
5836 return NT_STATUS_INVALID_PARAMETER;
5839 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5841 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5842 smb_fname_str_dbg(fsp->fsp_name),
5843 nt_errstr(status) ));
5849 /****************************************************************************
5850 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5851 ****************************************************************************/
5853 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5857 struct smb_filename *smb_fname)
5859 NTSTATUS status = NT_STATUS_OK;
5860 bool delete_on_close;
5863 if (total_data < 1) {
5864 return NT_STATUS_INVALID_PARAMETER;
5868 return NT_STATUS_INVALID_HANDLE;
5871 delete_on_close = (CVAL(pdata,0) ? True : False);
5872 dosmode = dos_mode(conn, smb_fname);
5874 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5875 "delete_on_close = %u\n",
5876 smb_fname_str_dbg(smb_fname),
5877 (unsigned int)dosmode,
5878 (unsigned int)delete_on_close ));
5880 if (delete_on_close) {
5881 status = can_set_delete_on_close(fsp, dosmode);
5882 if (!NT_STATUS_IS_OK(status)) {
5887 /* The set is across all open files on this dev/inode pair. */
5888 if (!set_delete_on_close(fsp, delete_on_close,
5889 conn->session_info->security_token,
5890 conn->session_info->unix_token)) {
5891 return NT_STATUS_ACCESS_DENIED;
5893 return NT_STATUS_OK;
5896 /****************************************************************************
5897 Deal with SMB_FILE_POSITION_INFORMATION.
5898 ****************************************************************************/
5900 static NTSTATUS smb_file_position_information(connection_struct *conn,
5905 uint64_t position_information;
5907 if (total_data < 8) {
5908 return NT_STATUS_INVALID_PARAMETER;
5912 /* Ignore on pathname based set. */
5913 return NT_STATUS_OK;
5916 position_information = (uint64_t)IVAL(pdata,0);
5917 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5919 DEBUG(10,("smb_file_position_information: Set file position "
5920 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5921 (double)position_information));
5922 fsp->fh->position_information = position_information;
5923 return NT_STATUS_OK;
5926 /****************************************************************************
5927 Deal with SMB_FILE_MODE_INFORMATION.
5928 ****************************************************************************/
5930 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5936 if (total_data < 4) {
5937 return NT_STATUS_INVALID_PARAMETER;
5939 mode = IVAL(pdata,0);
5940 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5941 return NT_STATUS_INVALID_PARAMETER;
5943 return NT_STATUS_OK;
5946 /****************************************************************************
5947 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5948 ****************************************************************************/
5950 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5951 struct smb_request *req,
5954 const struct smb_filename *smb_fname)
5956 char *link_target = NULL;
5957 const char *newname = smb_fname->base_name;
5958 TALLOC_CTX *ctx = talloc_tos();
5960 /* Set a symbolic link. */
5961 /* Don't allow this if follow links is false. */
5963 if (total_data == 0) {
5964 return NT_STATUS_INVALID_PARAMETER;
5967 if (!lp_symlinks(SNUM(conn))) {
5968 return NT_STATUS_ACCESS_DENIED;
5971 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5972 total_data, STR_TERMINATE);
5975 return NT_STATUS_INVALID_PARAMETER;
5978 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5979 newname, link_target ));
5981 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5982 return map_nt_error_from_unix(errno);
5985 return NT_STATUS_OK;
5988 /****************************************************************************
5989 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5990 ****************************************************************************/
5992 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5993 struct smb_request *req,
5994 const char *pdata, int total_data,
5995 struct smb_filename *smb_fname_new)
5997 char *oldname = NULL;
5998 struct smb_filename *smb_fname_old = NULL;
5999 TALLOC_CTX *ctx = talloc_tos();
6000 NTSTATUS status = NT_STATUS_OK;
6002 /* Set a hard link. */
6003 if (total_data == 0) {
6004 return NT_STATUS_INVALID_PARAMETER;
6007 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6008 total_data, STR_TERMINATE, &status);
6009 if (!NT_STATUS_IS_OK(status)) {
6013 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6014 smb_fname_str_dbg(smb_fname_new), oldname));
6016 status = filename_convert(ctx,
6018 req->flags2 & FLAGS2_DFS_PATHNAMES,
6023 if (!NT_STATUS_IS_OK(status)) {
6027 return hardlink_internals(ctx, conn, req, false,
6028 smb_fname_old, smb_fname_new);
6031 /****************************************************************************
6032 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6033 ****************************************************************************/
6035 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6036 struct smb_request *req,
6040 struct smb_filename *smb_fname_src)
6044 char *newname = NULL;
6045 struct smb_filename *smb_fname_dst = NULL;
6046 NTSTATUS status = NT_STATUS_OK;
6047 TALLOC_CTX *ctx = talloc_tos();
6050 return NT_STATUS_INVALID_HANDLE;
6053 if (total_data < 20) {
6054 return NT_STATUS_INVALID_PARAMETER;
6057 overwrite = (CVAL(pdata,0) ? True : False);
6058 len = IVAL(pdata,16);
6060 if (len > (total_data - 20) || (len == 0)) {
6061 return NT_STATUS_INVALID_PARAMETER;
6064 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6065 &pdata[20], len, STR_TERMINATE,
6067 if (!NT_STATUS_IS_OK(status)) {
6071 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6074 status = filename_convert(ctx,
6076 req->flags2 & FLAGS2_DFS_PATHNAMES,
6081 if (!NT_STATUS_IS_OK(status)) {
6085 if (fsp->base_fsp) {
6086 /* newname must be a stream name. */
6087 if (newname[0] != ':') {
6088 return NT_STATUS_NOT_SUPPORTED;
6091 /* Create an smb_fname to call rename_internals_fsp() with. */
6092 status = create_synthetic_smb_fname(talloc_tos(),
6093 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6095 if (!NT_STATUS_IS_OK(status)) {
6100 * Set the original last component, since
6101 * rename_internals_fsp() requires it.
6103 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6105 if (smb_fname_dst->original_lcomp == NULL) {
6106 status = NT_STATUS_NO_MEMORY;
6112 DEBUG(10,("smb2_file_rename_information: "
6113 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6114 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6115 smb_fname_str_dbg(smb_fname_dst)));
6116 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6117 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6121 TALLOC_FREE(smb_fname_dst);
6125 static NTSTATUS smb_file_link_information(connection_struct *conn,
6126 struct smb_request *req,
6130 struct smb_filename *smb_fname_src)
6134 char *newname = NULL;
6135 struct smb_filename *smb_fname_dst = NULL;
6136 NTSTATUS status = NT_STATUS_OK;
6137 TALLOC_CTX *ctx = talloc_tos();
6140 return NT_STATUS_INVALID_HANDLE;
6143 if (total_data < 20) {
6144 return NT_STATUS_INVALID_PARAMETER;
6147 overwrite = (CVAL(pdata,0) ? true : false);
6148 len = IVAL(pdata,16);
6150 if (len > (total_data - 20) || (len == 0)) {
6151 return NT_STATUS_INVALID_PARAMETER;
6154 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6155 &pdata[20], len, STR_TERMINATE,
6157 if (!NT_STATUS_IS_OK(status)) {
6161 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6164 status = filename_convert(ctx,
6166 req->flags2 & FLAGS2_DFS_PATHNAMES,
6171 if (!NT_STATUS_IS_OK(status)) {
6175 if (fsp->base_fsp) {
6176 /* No stream names. */
6177 return NT_STATUS_NOT_SUPPORTED;
6180 DEBUG(10,("smb_file_link_information: "
6181 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6182 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6183 smb_fname_str_dbg(smb_fname_dst)));
6184 status = hardlink_internals(ctx,
6191 TALLOC_FREE(smb_fname_dst);
6195 /****************************************************************************
6196 Deal with SMB_FILE_RENAME_INFORMATION.
6197 ****************************************************************************/
6199 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6200 struct smb_request *req,
6204 struct smb_filename *smb_fname_src)
6209 char *newname = NULL;
6210 struct smb_filename *smb_fname_dst = NULL;
6211 bool dest_has_wcard = False;
6212 NTSTATUS status = NT_STATUS_OK;
6214 TALLOC_CTX *ctx = talloc_tos();
6216 if (total_data < 13) {
6217 return NT_STATUS_INVALID_PARAMETER;
6220 overwrite = (CVAL(pdata,0) ? True : False);
6221 root_fid = IVAL(pdata,4);
6222 len = IVAL(pdata,8);
6224 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6225 return NT_STATUS_INVALID_PARAMETER;
6228 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6231 if (!NT_STATUS_IS_OK(status)) {
6235 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6238 status = resolve_dfspath_wcard(ctx, conn,
6239 req->flags2 & FLAGS2_DFS_PATHNAMES,
6242 !conn->sconn->using_smb2,
6245 if (!NT_STATUS_IS_OK(status)) {
6249 /* Check the new name has no '/' characters. */
6250 if (strchr_m(newname, '/')) {
6251 return NT_STATUS_NOT_SUPPORTED;
6254 if (fsp && fsp->base_fsp) {
6255 /* newname must be a stream name. */
6256 if (newname[0] != ':') {
6257 return NT_STATUS_NOT_SUPPORTED;
6260 /* Create an smb_fname to call rename_internals_fsp() with. */
6261 status = create_synthetic_smb_fname(talloc_tos(),
6262 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6264 if (!NT_STATUS_IS_OK(status)) {
6269 * Set the original last component, since
6270 * rename_internals_fsp() requires it.
6272 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6274 if (smb_fname_dst->original_lcomp == NULL) {
6275 status = NT_STATUS_NO_MEMORY;
6281 * Build up an smb_fname_dst based on the filename passed in.
6282 * We basically just strip off the last component, and put on
6283 * the newname instead.
6285 char *base_name = NULL;
6287 /* newname must *not* be a stream name. */
6288 if (newname[0] == ':') {
6289 return NT_STATUS_NOT_SUPPORTED;
6293 * Strip off the last component (filename) of the path passed
6296 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6298 return NT_STATUS_NO_MEMORY;
6300 p = strrchr_m(base_name, '/');
6304 base_name = talloc_strdup(ctx, "");
6306 return NT_STATUS_NO_MEMORY;
6309 /* Append the new name. */
6310 base_name = talloc_asprintf_append(base_name,
6314 return NT_STATUS_NO_MEMORY;
6317 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6320 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6323 /* If an error we expect this to be
6324 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6326 if (!NT_STATUS_IS_OK(status)) {
6327 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6331 /* Create an smb_fname to call rename_internals_fsp() */
6332 status = create_synthetic_smb_fname(ctx,
6336 if (!NT_STATUS_IS_OK(status)) {
6343 DEBUG(10,("smb_file_rename_information: "
6344 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6345 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6346 smb_fname_str_dbg(smb_fname_dst)));
6347 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6350 DEBUG(10,("smb_file_rename_information: "
6351 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6352 smb_fname_str_dbg(smb_fname_src),
6353 smb_fname_str_dbg(smb_fname_dst)));
6354 status = rename_internals(ctx, conn, req, smb_fname_src,
6355 smb_fname_dst, 0, overwrite, false,
6357 FILE_WRITE_ATTRIBUTES);
6360 TALLOC_FREE(smb_fname_dst);
6364 /****************************************************************************
6365 Deal with SMB_SET_POSIX_ACL.
6366 ****************************************************************************/
6368 #if defined(HAVE_POSIX_ACLS)
6369 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6373 const struct smb_filename *smb_fname)
6375 uint16 posix_acl_version;
6376 uint16 num_file_acls;
6377 uint16 num_def_acls;
6378 bool valid_file_acls = True;
6379 bool valid_def_acls = True;
6381 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6382 return NT_STATUS_INVALID_PARAMETER;
6384 posix_acl_version = SVAL(pdata,0);
6385 num_file_acls = SVAL(pdata,2);
6386 num_def_acls = SVAL(pdata,4);
6388 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6389 valid_file_acls = False;
6393 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6394 valid_def_acls = False;
6398 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6399 return NT_STATUS_INVALID_PARAMETER;
6402 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6403 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6404 return NT_STATUS_INVALID_PARAMETER;
6407 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6408 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6409 (unsigned int)num_file_acls,
6410 (unsigned int)num_def_acls));
6412 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6413 smb_fname->base_name, num_file_acls,
6414 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6415 return map_nt_error_from_unix(errno);
6418 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6419 smb_fname->base_name, &smb_fname->st, num_def_acls,
6420 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6421 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6422 return map_nt_error_from_unix(errno);
6424 return NT_STATUS_OK;
6428 /****************************************************************************
6429 Deal with SMB_SET_POSIX_LOCK.
6430 ****************************************************************************/
6432 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6433 struct smb_request *req,
6441 bool blocking_lock = False;
6442 enum brl_type lock_type;
6444 NTSTATUS status = NT_STATUS_OK;
6446 if (fsp == NULL || fsp->fh->fd == -1) {
6447 return NT_STATUS_INVALID_HANDLE;
6450 if (total_data != POSIX_LOCK_DATA_SIZE) {
6451 return NT_STATUS_INVALID_PARAMETER;
6454 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6455 case POSIX_LOCK_TYPE_READ:
6456 lock_type = READ_LOCK;
6458 case POSIX_LOCK_TYPE_WRITE:
6459 /* Return the right POSIX-mappable error code for files opened read-only. */
6460 if (!fsp->can_write) {
6461 return NT_STATUS_INVALID_HANDLE;
6463 lock_type = WRITE_LOCK;
6465 case POSIX_LOCK_TYPE_UNLOCK:
6466 lock_type = UNLOCK_LOCK;
6469 return NT_STATUS_INVALID_PARAMETER;
6472 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6473 blocking_lock = False;
6474 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6475 blocking_lock = True;
6477 return NT_STATUS_INVALID_PARAMETER;
6480 if (!lp_blocking_locks(SNUM(conn))) {
6481 blocking_lock = False;
6484 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6485 #if defined(HAVE_LONGLONG)
6486 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6487 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6488 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6489 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6490 #else /* HAVE_LONGLONG */
6491 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6492 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6493 #endif /* HAVE_LONGLONG */
6495 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6496 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6498 (unsigned int)lock_type,
6499 (unsigned long long)smblctx,
6503 if (lock_type == UNLOCK_LOCK) {
6504 status = do_unlock(req->sconn->msg_ctx,
6511 uint64_t block_smblctx;
6513 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6525 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6527 * A blocking lock was requested. Package up
6528 * this smb into a queued request and push it
6529 * onto the blocking lock queue.
6531 if(push_blocking_lock_request(br_lck,
6534 -1, /* infinite timeout. */
6542 TALLOC_FREE(br_lck);
6546 TALLOC_FREE(br_lck);
6552 /****************************************************************************
6553 Deal with SMB_SET_FILE_BASIC_INFO.
6554 ****************************************************************************/
6556 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6560 const struct smb_filename *smb_fname)
6562 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6563 struct smb_file_time ft;
6565 NTSTATUS status = NT_STATUS_OK;
6569 if (total_data < 36) {
6570 return NT_STATUS_INVALID_PARAMETER;
6573 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6574 if (!NT_STATUS_IS_OK(status)) {
6578 /* Set the attributes */
6579 dosmode = IVAL(pdata,32);
6580 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6581 if (!NT_STATUS_IS_OK(status)) {
6586 ft.create_time = interpret_long_date(pdata);
6589 ft.atime = interpret_long_date(pdata+8);
6592 ft.mtime = interpret_long_date(pdata+16);
6595 ft.ctime = interpret_long_date(pdata+24);
6597 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6598 smb_fname_str_dbg(smb_fname)));
6600 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6604 /****************************************************************************
6605 Deal with SMB_INFO_STANDARD.
6606 ****************************************************************************/
6608 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6612 const struct smb_filename *smb_fname)
6615 struct smb_file_time ft;
6619 if (total_data < 12) {
6620 return NT_STATUS_INVALID_PARAMETER;
6624 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6626 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6628 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6630 DEBUG(10,("smb_set_info_standard: file %s\n",
6631 smb_fname_str_dbg(smb_fname)));
6633 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6634 if (!NT_STATUS_IS_OK(status)) {
6638 return smb_set_file_time(conn,
6645 /****************************************************************************
6646 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6647 ****************************************************************************/
6649 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6650 struct smb_request *req,
6654 struct smb_filename *smb_fname)
6656 uint64_t allocation_size = 0;
6657 NTSTATUS status = NT_STATUS_OK;
6658 files_struct *new_fsp = NULL;
6660 if (!VALID_STAT(smb_fname->st)) {
6661 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6664 if (total_data < 8) {
6665 return NT_STATUS_INVALID_PARAMETER;
6668 allocation_size = (uint64_t)IVAL(pdata,0);
6669 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6670 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6671 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6672 (double)allocation_size));
6674 if (allocation_size) {
6675 allocation_size = smb_roundup(conn, allocation_size);
6678 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6679 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6680 (double)allocation_size));
6682 if (fsp && fsp->fh->fd != -1) {
6683 /* Open file handle. */
6684 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6685 return NT_STATUS_ACCESS_DENIED;
6688 /* Only change if needed. */
6689 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6690 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6691 return map_nt_error_from_unix(errno);
6694 /* But always update the time. */
6696 * This is equivalent to a write. Ensure it's seen immediately
6697 * if there are no pending writes.
6699 trigger_write_time_update_immediate(fsp);
6700 return NT_STATUS_OK;
6703 /* Pathname or stat or directory file. */
6704 status = SMB_VFS_CREATE_FILE(
6707 0, /* root_dir_fid */
6708 smb_fname, /* fname */
6709 FILE_WRITE_DATA, /* access_mask */
6710 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6712 FILE_OPEN, /* create_disposition*/
6713 0, /* create_options */
6714 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6715 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6716 0, /* allocation_size */
6717 0, /* private_flags */
6720 &new_fsp, /* result */
6723 if (!NT_STATUS_IS_OK(status)) {
6724 /* NB. We check for open_was_deferred in the caller. */
6728 /* Only change if needed. */
6729 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6730 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6731 status = map_nt_error_from_unix(errno);
6732 close_file(req, new_fsp, NORMAL_CLOSE);
6737 /* Changing the allocation size should set the last mod time. */
6739 * This is equivalent to a write. Ensure it's seen immediately
6740 * if there are no pending writes.
6742 trigger_write_time_update_immediate(new_fsp);
6744 close_file(req, new_fsp, NORMAL_CLOSE);
6745 return NT_STATUS_OK;
6748 /****************************************************************************
6749 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6750 ****************************************************************************/
6752 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6753 struct smb_request *req,
6757 const struct smb_filename *smb_fname,
6758 bool fail_after_createfile)
6762 if (total_data < 8) {
6763 return NT_STATUS_INVALID_PARAMETER;
6766 size = IVAL(pdata,0);
6767 size |= (((off_t)IVAL(pdata,4)) << 32);
6768 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6769 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6772 return smb_set_file_size(conn, req,
6777 fail_after_createfile);
6780 /****************************************************************************
6781 Allow a UNIX info mknod.
6782 ****************************************************************************/
6784 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6787 const struct smb_filename *smb_fname)
6789 uint32 file_type = IVAL(pdata,56);
6790 #if defined(HAVE_MAKEDEV)
6791 uint32 dev_major = IVAL(pdata,60);
6792 uint32 dev_minor = IVAL(pdata,68);
6794 SMB_DEV_T dev = (SMB_DEV_T)0;
6795 uint32 raw_unixmode = IVAL(pdata,84);
6799 if (total_data < 100) {
6800 return NT_STATUS_INVALID_PARAMETER;
6803 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6804 PERM_NEW_FILE, &unixmode);
6805 if (!NT_STATUS_IS_OK(status)) {
6809 #if defined(HAVE_MAKEDEV)
6810 dev = makedev(dev_major, dev_minor);
6813 switch (file_type) {
6814 #if defined(S_IFIFO)
6815 case UNIX_TYPE_FIFO:
6816 unixmode |= S_IFIFO;
6819 #if defined(S_IFSOCK)
6820 case UNIX_TYPE_SOCKET:
6821 unixmode |= S_IFSOCK;
6824 #if defined(S_IFCHR)
6825 case UNIX_TYPE_CHARDEV:
6826 unixmode |= S_IFCHR;
6829 #if defined(S_IFBLK)
6830 case UNIX_TYPE_BLKDEV:
6831 unixmode |= S_IFBLK;
6835 return NT_STATUS_INVALID_PARAMETER;
6838 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6839 "%.0f mode 0%o for file %s\n", (double)dev,
6840 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6842 /* Ok - do the mknod. */
6843 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6844 return map_nt_error_from_unix(errno);
6847 /* If any of the other "set" calls fail we
6848 * don't want to end up with a half-constructed mknod.
6851 if (lp_inherit_perms(SNUM(conn))) {
6853 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6855 return NT_STATUS_NO_MEMORY;
6857 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6859 TALLOC_FREE(parent);
6862 return NT_STATUS_OK;
6865 /****************************************************************************
6866 Deal with SMB_SET_FILE_UNIX_BASIC.
6867 ****************************************************************************/
6869 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6870 struct smb_request *req,
6874 const struct smb_filename *smb_fname)
6876 struct smb_file_time ft;
6877 uint32 raw_unixmode;
6880 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6881 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6882 NTSTATUS status = NT_STATUS_OK;
6883 bool delete_on_fail = False;
6884 enum perm_type ptype;
6885 files_struct *all_fsps = NULL;
6886 bool modify_mtime = true;
6888 struct smb_filename *smb_fname_tmp = NULL;
6889 SMB_STRUCT_STAT sbuf;
6893 if (total_data < 100) {
6894 return NT_STATUS_INVALID_PARAMETER;
6897 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6898 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6899 size=IVAL(pdata,0); /* first 8 Bytes are size */
6900 size |= (((off_t)IVAL(pdata,4)) << 32);
6903 ft.atime = interpret_long_date(pdata+24); /* access_time */
6904 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6905 set_owner = (uid_t)IVAL(pdata,40);
6906 set_grp = (gid_t)IVAL(pdata,48);
6907 raw_unixmode = IVAL(pdata,84);
6909 if (VALID_STAT(smb_fname->st)) {
6910 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6911 ptype = PERM_EXISTING_DIR;
6913 ptype = PERM_EXISTING_FILE;
6916 ptype = PERM_NEW_FILE;
6919 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6921 if (!NT_STATUS_IS_OK(status)) {
6925 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6926 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6927 smb_fname_str_dbg(smb_fname), (double)size,
6928 (unsigned int)set_owner, (unsigned int)set_grp,
6929 (int)raw_unixmode));
6931 sbuf = smb_fname->st;
6933 if (!VALID_STAT(sbuf)) {
6935 * The only valid use of this is to create character and block
6936 * devices, and named pipes. This is deprecated (IMHO) and
6937 * a new info level should be used for mknod. JRA.
6940 status = smb_unix_mknod(conn,
6944 if (!NT_STATUS_IS_OK(status)) {
6948 status = copy_smb_filename(talloc_tos(), smb_fname,
6950 if (!NT_STATUS_IS_OK(status)) {
6954 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6955 status = map_nt_error_from_unix(errno);
6956 TALLOC_FREE(smb_fname_tmp);
6957 SMB_VFS_UNLINK(conn, smb_fname);
6961 sbuf = smb_fname_tmp->st;
6962 smb_fname = smb_fname_tmp;
6964 /* Ensure we don't try and change anything else. */
6965 raw_unixmode = SMB_MODE_NO_CHANGE;
6966 size = get_file_size_stat(&sbuf);
6967 ft.atime = sbuf.st_ex_atime;
6968 ft.mtime = sbuf.st_ex_mtime;
6970 * We continue here as we might want to change the
6973 delete_on_fail = True;
6977 /* Horrible backwards compatibility hack as an old server bug
6978 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6982 size = get_file_size_stat(&sbuf);
6987 * Deal with the UNIX specific mode set.
6990 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6991 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6992 "setting mode 0%o for file %s\n",
6993 (unsigned int)unixmode,
6994 smb_fname_str_dbg(smb_fname)));
6995 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6996 return map_nt_error_from_unix(errno);
7001 * Deal with the UNIX specific uid set.
7004 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7005 (sbuf.st_ex_uid != set_owner)) {
7008 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7009 "changing owner %u for path %s\n",
7010 (unsigned int)set_owner,
7011 smb_fname_str_dbg(smb_fname)));
7013 if (S_ISLNK(sbuf.st_ex_mode)) {
7014 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7015 set_owner, (gid_t)-1);
7017 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7018 set_owner, (gid_t)-1);
7022 status = map_nt_error_from_unix(errno);
7023 if (delete_on_fail) {
7024 SMB_VFS_UNLINK(conn, smb_fname);
7031 * Deal with the UNIX specific gid set.
7034 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7035 (sbuf.st_ex_gid != set_grp)) {
7036 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7037 "changing group %u for file %s\n",
7038 (unsigned int)set_owner,
7039 smb_fname_str_dbg(smb_fname)));
7040 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7042 status = map_nt_error_from_unix(errno);
7043 if (delete_on_fail) {
7044 SMB_VFS_UNLINK(conn, smb_fname);
7050 /* Deal with any size changes. */
7052 status = smb_set_file_size(conn, req,
7058 if (!NT_STATUS_IS_OK(status)) {
7062 /* Deal with any time changes. */
7063 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7064 /* No change, don't cancel anything. */
7068 id = vfs_file_id_from_sbuf(conn, &sbuf);
7069 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7070 all_fsps = file_find_di_next(all_fsps)) {
7072 * We're setting the time explicitly for UNIX.
7073 * Cancel any pending changes over all handles.
7075 all_fsps->update_write_time_on_close = false;
7076 TALLOC_FREE(all_fsps->update_write_time_event);
7080 * Override the "setting_write_time"
7081 * parameter here as it almost does what
7082 * we need. Just remember if we modified
7083 * mtime and send the notify ourselves.
7085 if (null_timespec(ft.mtime)) {
7086 modify_mtime = false;
7089 status = smb_set_file_time(conn,
7095 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7096 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7101 /****************************************************************************
7102 Deal with SMB_SET_FILE_UNIX_INFO2.
7103 ****************************************************************************/
7105 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7106 struct smb_request *req,
7110 const struct smb_filename *smb_fname)
7116 if (total_data < 116) {
7117 return NT_STATUS_INVALID_PARAMETER;
7120 /* Start by setting all the fields that are common between UNIX_BASIC
7123 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7125 if (!NT_STATUS_IS_OK(status)) {
7129 smb_fflags = IVAL(pdata, 108);
7130 smb_fmask = IVAL(pdata, 112);
7132 /* NB: We should only attempt to alter the file flags if the client
7133 * sends a non-zero mask.
7135 if (smb_fmask != 0) {
7136 int stat_fflags = 0;
7138 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7139 smb_fmask, &stat_fflags)) {
7140 /* Client asked to alter a flag we don't understand. */
7141 return NT_STATUS_INVALID_PARAMETER;
7144 if (fsp && fsp->fh->fd != -1) {
7145 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7146 return NT_STATUS_NOT_SUPPORTED;
7148 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7149 stat_fflags) != 0) {
7150 return map_nt_error_from_unix(errno);
7155 /* XXX: need to add support for changing the create_time here. You
7156 * can do this for paths on Darwin with setattrlist(2). The right way
7157 * to hook this up is probably by extending the VFS utimes interface.
7160 return NT_STATUS_OK;
7163 /****************************************************************************
7164 Create a directory with POSIX semantics.
7165 ****************************************************************************/
7167 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7168 struct smb_request *req,
7171 struct smb_filename *smb_fname,
7172 int *pdata_return_size)
7174 NTSTATUS status = NT_STATUS_OK;
7175 uint32 raw_unixmode = 0;
7176 uint32 mod_unixmode = 0;
7177 mode_t unixmode = (mode_t)0;
7178 files_struct *fsp = NULL;
7179 uint16 info_level_return = 0;
7181 char *pdata = *ppdata;
7183 if (total_data < 18) {
7184 return NT_STATUS_INVALID_PARAMETER;
7187 raw_unixmode = IVAL(pdata,8);
7188 /* Next 4 bytes are not yet defined. */
7190 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7191 PERM_NEW_DIR, &unixmode);
7192 if (!NT_STATUS_IS_OK(status)) {
7196 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7198 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7199 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7201 status = SMB_VFS_CREATE_FILE(
7204 0, /* root_dir_fid */
7205 smb_fname, /* fname */
7206 FILE_READ_ATTRIBUTES, /* access_mask */
7207 FILE_SHARE_NONE, /* share_access */
7208 FILE_CREATE, /* create_disposition*/
7209 FILE_DIRECTORY_FILE, /* create_options */
7210 mod_unixmode, /* file_attributes */
7211 0, /* oplock_request */
7212 0, /* allocation_size */
7213 0, /* private_flags */
7219 if (NT_STATUS_IS_OK(status)) {
7220 close_file(req, fsp, NORMAL_CLOSE);
7223 info_level_return = SVAL(pdata,16);
7225 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7226 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7227 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7228 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7230 *pdata_return_size = 12;
7233 /* Realloc the data size */
7234 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7235 if (*ppdata == NULL) {
7236 *pdata_return_size = 0;
7237 return NT_STATUS_NO_MEMORY;
7241 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7242 SSVAL(pdata,2,0); /* No fnum. */
7243 SIVAL(pdata,4,info); /* Was directory created. */
7245 switch (info_level_return) {
7246 case SMB_QUERY_FILE_UNIX_BASIC:
7247 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7248 SSVAL(pdata,10,0); /* Padding. */
7249 store_file_unix_basic(conn, pdata + 12, fsp,
7252 case SMB_QUERY_FILE_UNIX_INFO2:
7253 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7254 SSVAL(pdata,10,0); /* Padding. */
7255 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7259 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7260 SSVAL(pdata,10,0); /* Padding. */
7267 /****************************************************************************
7268 Open/Create a file with POSIX semantics.
7269 ****************************************************************************/
7271 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7272 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7274 static NTSTATUS smb_posix_open(connection_struct *conn,
7275 struct smb_request *req,
7278 struct smb_filename *smb_fname,
7279 int *pdata_return_size)
7281 bool extended_oplock_granted = False;
7282 char *pdata = *ppdata;
7284 uint32 wire_open_mode = 0;
7285 uint32 raw_unixmode = 0;
7286 uint32 mod_unixmode = 0;
7287 uint32 create_disp = 0;
7288 uint32 access_mask = 0;
7289 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7290 NTSTATUS status = NT_STATUS_OK;
7291 mode_t unixmode = (mode_t)0;
7292 files_struct *fsp = NULL;
7293 int oplock_request = 0;
7295 uint16 info_level_return = 0;
7297 if (total_data < 18) {
7298 return NT_STATUS_INVALID_PARAMETER;
7301 flags = IVAL(pdata,0);
7302 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7303 if (oplock_request) {
7304 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7307 wire_open_mode = IVAL(pdata,4);
7309 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7310 return smb_posix_mkdir(conn, req,
7317 switch (wire_open_mode & SMB_ACCMODE) {
7319 access_mask = SMB_O_RDONLY_MAPPING;
7322 access_mask = SMB_O_WRONLY_MAPPING;
7325 access_mask = (SMB_O_RDONLY_MAPPING|
7326 SMB_O_WRONLY_MAPPING);
7329 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7330 (unsigned int)wire_open_mode ));
7331 return NT_STATUS_INVALID_PARAMETER;
7334 wire_open_mode &= ~SMB_ACCMODE;
7336 /* First take care of O_CREAT|O_EXCL interactions. */
7337 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7338 case (SMB_O_CREAT | SMB_O_EXCL):
7339 /* File exists fail. File not exist create. */
7340 create_disp = FILE_CREATE;
7343 /* File exists open. File not exist create. */
7344 create_disp = FILE_OPEN_IF;
7347 /* File exists open. File not exist fail. */
7348 create_disp = FILE_OPEN;
7351 /* O_EXCL on its own without O_CREAT is undefined. */
7353 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7354 (unsigned int)wire_open_mode ));
7355 return NT_STATUS_INVALID_PARAMETER;
7358 /* Next factor in the effects of O_TRUNC. */
7359 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7361 if (wire_open_mode & SMB_O_TRUNC) {
7362 switch (create_disp) {
7364 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7365 /* Leave create_disp alone as
7366 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7368 /* File exists fail. File not exist create. */
7371 /* SMB_O_CREAT | SMB_O_TRUNC */
7372 /* File exists overwrite. File not exist create. */
7373 create_disp = FILE_OVERWRITE_IF;
7377 /* File exists overwrite. File not exist fail. */
7378 create_disp = FILE_OVERWRITE;
7381 /* Cannot get here. */
7382 smb_panic("smb_posix_open: logic error");
7383 return NT_STATUS_INVALID_PARAMETER;
7387 raw_unixmode = IVAL(pdata,8);
7388 /* Next 4 bytes are not yet defined. */
7390 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7391 (VALID_STAT(smb_fname->st) ?
7392 PERM_EXISTING_FILE : PERM_NEW_FILE),
7395 if (!NT_STATUS_IS_OK(status)) {
7399 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7401 if (wire_open_mode & SMB_O_SYNC) {
7402 create_options |= FILE_WRITE_THROUGH;
7404 if (wire_open_mode & SMB_O_APPEND) {
7405 access_mask |= FILE_APPEND_DATA;
7407 if (wire_open_mode & SMB_O_DIRECT) {
7408 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7411 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7412 VALID_STAT_OF_DIR(smb_fname->st)) {
7413 if (access_mask != SMB_O_RDONLY_MAPPING) {
7414 return NT_STATUS_FILE_IS_A_DIRECTORY;
7416 create_options &= ~FILE_NON_DIRECTORY_FILE;
7417 create_options |= FILE_DIRECTORY_FILE;
7420 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7421 smb_fname_str_dbg(smb_fname),
7422 (unsigned int)wire_open_mode,
7423 (unsigned int)unixmode ));
7425 status = SMB_VFS_CREATE_FILE(
7428 0, /* root_dir_fid */
7429 smb_fname, /* fname */
7430 access_mask, /* access_mask */
7431 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7433 create_disp, /* create_disposition*/
7434 create_options, /* create_options */
7435 mod_unixmode, /* file_attributes */
7436 oplock_request, /* oplock_request */
7437 0, /* allocation_size */
7438 0, /* private_flags */
7444 if (!NT_STATUS_IS_OK(status)) {
7448 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7449 extended_oplock_granted = True;
7452 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7453 extended_oplock_granted = True;
7456 info_level_return = SVAL(pdata,16);
7458 /* Allocate the correct return size. */
7460 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7461 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7462 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7463 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7465 *pdata_return_size = 12;
7468 /* Realloc the data size */
7469 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7470 if (*ppdata == NULL) {
7471 close_file(req, fsp, ERROR_CLOSE);
7472 *pdata_return_size = 0;
7473 return NT_STATUS_NO_MEMORY;
7477 if (extended_oplock_granted) {
7478 if (flags & REQUEST_BATCH_OPLOCK) {
7479 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7481 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7483 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7484 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7486 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7489 SSVAL(pdata,2,fsp->fnum);
7490 SIVAL(pdata,4,info); /* Was file created etc. */
7492 switch (info_level_return) {
7493 case SMB_QUERY_FILE_UNIX_BASIC:
7494 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7495 SSVAL(pdata,10,0); /* padding. */
7496 store_file_unix_basic(conn, pdata + 12, fsp,
7499 case SMB_QUERY_FILE_UNIX_INFO2:
7500 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7501 SSVAL(pdata,10,0); /* padding. */
7502 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7506 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7507 SSVAL(pdata,10,0); /* padding. */
7510 return NT_STATUS_OK;
7513 /****************************************************************************
7514 Delete a file with POSIX semantics.
7515 ****************************************************************************/
7517 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7518 struct smb_request *req,
7521 struct smb_filename *smb_fname)
7523 NTSTATUS status = NT_STATUS_OK;
7524 files_struct *fsp = NULL;
7528 int create_options = 0;
7530 struct share_mode_lock *lck = NULL;
7532 if (total_data < 2) {
7533 return NT_STATUS_INVALID_PARAMETER;
7536 flags = SVAL(pdata,0);
7538 if (!VALID_STAT(smb_fname->st)) {
7539 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7542 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7543 !VALID_STAT_OF_DIR(smb_fname->st)) {
7544 return NT_STATUS_NOT_A_DIRECTORY;
7547 DEBUG(10,("smb_posix_unlink: %s %s\n",
7548 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7549 smb_fname_str_dbg(smb_fname)));
7551 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7552 create_options |= FILE_DIRECTORY_FILE;
7555 status = SMB_VFS_CREATE_FILE(
7558 0, /* root_dir_fid */
7559 smb_fname, /* fname */
7560 DELETE_ACCESS, /* access_mask */
7561 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7563 FILE_OPEN, /* create_disposition*/
7564 create_options, /* create_options */
7565 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7566 0, /* oplock_request */
7567 0, /* allocation_size */
7568 0, /* private_flags */
7574 if (!NT_STATUS_IS_OK(status)) {
7579 * Don't lie to client. If we can't really delete due to
7580 * non-POSIX opens return SHARING_VIOLATION.
7583 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7585 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7586 "lock for file %s\n", fsp_str_dbg(fsp)));
7587 close_file(req, fsp, NORMAL_CLOSE);
7588 return NT_STATUS_INVALID_PARAMETER;
7592 * See if others still have the file open. If this is the case, then
7593 * don't delete. If all opens are POSIX delete we can set the delete
7594 * on close disposition.
7596 for (i=0; i<lck->data->num_share_modes; i++) {
7597 struct share_mode_entry *e = &lck->data->share_modes[i];
7598 if (is_valid_share_mode_entry(e)) {
7599 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7602 if (share_mode_stale_pid(lck->data, i)) {
7605 /* Fail with sharing violation. */
7606 close_file(req, fsp, NORMAL_CLOSE);
7608 return NT_STATUS_SHARING_VIOLATION;
7613 * Set the delete on close.
7615 status = smb_set_file_disposition_info(conn,
7621 if (!NT_STATUS_IS_OK(status)) {
7622 close_file(req, fsp, NORMAL_CLOSE);
7627 return close_file(req, fsp, NORMAL_CLOSE);
7630 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7631 struct smb_request *req,
7632 TALLOC_CTX *mem_ctx,
7633 uint16_t info_level,
7635 struct smb_filename *smb_fname,
7636 char **ppdata, int total_data,
7639 char *pdata = *ppdata;
7640 NTSTATUS status = NT_STATUS_OK;
7641 int data_return_size = 0;
7645 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7646 return NT_STATUS_INVALID_LEVEL;
7649 if (!CAN_WRITE(conn)) {
7650 /* Allow POSIX opens. The open path will deny
7651 * any non-readonly opens. */
7652 if (info_level != SMB_POSIX_PATH_OPEN) {
7653 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7657 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7658 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7660 info_level, total_data));
7662 switch (info_level) {
7664 case SMB_INFO_STANDARD:
7666 status = smb_set_info_standard(conn,
7674 case SMB_INFO_SET_EA:
7676 status = smb_info_set_ea(conn,
7684 case SMB_SET_FILE_BASIC_INFO:
7685 case SMB_FILE_BASIC_INFORMATION:
7687 status = smb_set_file_basic_info(conn,
7695 case SMB_FILE_ALLOCATION_INFORMATION:
7696 case SMB_SET_FILE_ALLOCATION_INFO:
7698 status = smb_set_file_allocation_info(conn, req,
7706 case SMB_FILE_END_OF_FILE_INFORMATION:
7707 case SMB_SET_FILE_END_OF_FILE_INFO:
7710 * XP/Win7 both fail after the createfile with
7711 * SMB_SET_FILE_END_OF_FILE_INFO but not
7712 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7713 * The level is known here, so pass it down
7717 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7719 status = smb_set_file_end_of_file_info(conn, req,
7728 case SMB_FILE_DISPOSITION_INFORMATION:
7729 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7732 /* JRA - We used to just ignore this on a path ?
7733 * Shouldn't this be invalid level on a pathname
7736 if (tran_call != TRANSACT2_SETFILEINFO) {
7737 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7740 status = smb_set_file_disposition_info(conn,
7748 case SMB_FILE_POSITION_INFORMATION:
7750 status = smb_file_position_information(conn,
7757 case SMB_FILE_FULL_EA_INFORMATION:
7759 status = smb_set_file_full_ea_info(conn,
7766 /* From tridge Samba4 :
7767 * MODE_INFORMATION in setfileinfo (I have no
7768 * idea what "mode information" on a file is - it takes a value of 0,
7769 * 2, 4 or 6. What could it be?).
7772 case SMB_FILE_MODE_INFORMATION:
7774 status = smb_file_mode_information(conn,
7781 * CIFS UNIX extensions.
7784 case SMB_SET_FILE_UNIX_BASIC:
7786 status = smb_set_file_unix_basic(conn, req,
7794 case SMB_SET_FILE_UNIX_INFO2:
7796 status = smb_set_file_unix_info2(conn, req,
7804 case SMB_SET_FILE_UNIX_LINK:
7807 /* We must have a pathname for this. */
7808 return NT_STATUS_INVALID_LEVEL;
7810 status = smb_set_file_unix_link(conn, req, pdata,
7811 total_data, smb_fname);
7815 case SMB_SET_FILE_UNIX_HLINK:
7818 /* We must have a pathname for this. */
7819 return NT_STATUS_INVALID_LEVEL;
7821 status = smb_set_file_unix_hlink(conn, req,
7827 case SMB_FILE_RENAME_INFORMATION:
7829 status = smb_file_rename_information(conn, req,
7835 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7837 /* SMB2 rename information. */
7838 status = smb2_file_rename_information(conn, req,
7844 case SMB_FILE_LINK_INFORMATION:
7846 status = smb_file_link_information(conn, req,
7852 #if defined(HAVE_POSIX_ACLS)
7853 case SMB_SET_POSIX_ACL:
7855 status = smb_set_posix_acl(conn,
7864 case SMB_SET_POSIX_LOCK:
7867 return NT_STATUS_INVALID_LEVEL;
7869 status = smb_set_posix_lock(conn, req,
7870 pdata, total_data, fsp);
7874 case SMB_POSIX_PATH_OPEN:
7877 /* We must have a pathname for this. */
7878 return NT_STATUS_INVALID_LEVEL;
7881 status = smb_posix_open(conn, req,
7889 case SMB_POSIX_PATH_UNLINK:
7892 /* We must have a pathname for this. */
7893 return NT_STATUS_INVALID_LEVEL;
7896 status = smb_posix_unlink(conn, req,
7904 return NT_STATUS_INVALID_LEVEL;
7907 if (!NT_STATUS_IS_OK(status)) {
7911 *ret_data_size = data_return_size;
7912 return NT_STATUS_OK;
7915 /****************************************************************************
7916 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7917 ****************************************************************************/
7919 static void call_trans2setfilepathinfo(connection_struct *conn,
7920 struct smb_request *req,
7921 unsigned int tran_call,
7922 char **pparams, int total_params,
7923 char **ppdata, int total_data,
7924 unsigned int max_data_bytes)
7926 char *params = *pparams;
7927 char *pdata = *ppdata;
7929 struct smb_filename *smb_fname = NULL;
7930 files_struct *fsp = NULL;
7931 NTSTATUS status = NT_STATUS_OK;
7932 int data_return_size = 0;
7935 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7939 if (tran_call == TRANSACT2_SETFILEINFO) {
7940 if (total_params < 4) {
7941 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7945 fsp = file_fsp(req, SVAL(params,0));
7946 /* Basic check for non-null fsp. */
7947 if (!check_fsp_open(conn, req, fsp)) {
7950 info_level = SVAL(params,2);
7952 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7954 if (!NT_STATUS_IS_OK(status)) {
7955 reply_nterror(req, status);
7959 if(fsp->fh->fd == -1) {
7961 * This is actually a SETFILEINFO on a directory
7962 * handle (returned from an NT SMB). NT5.0 seems
7963 * to do this call. JRA.
7965 if (INFO_LEVEL_IS_UNIX(info_level)) {
7966 /* Always do lstat for UNIX calls. */
7967 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7968 DEBUG(3,("call_trans2setfilepathinfo: "
7969 "SMB_VFS_LSTAT of %s failed "
7971 smb_fname_str_dbg(smb_fname),
7973 reply_nterror(req, map_nt_error_from_unix(errno));
7977 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7978 DEBUG(3,("call_trans2setfilepathinfo: "
7979 "fileinfo of %s failed (%s)\n",
7980 smb_fname_str_dbg(smb_fname),
7982 reply_nterror(req, map_nt_error_from_unix(errno));
7986 } else if (fsp->print_file) {
7988 * Doing a DELETE_ON_CLOSE should cancel a print job.
7990 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7991 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7993 DEBUG(3,("call_trans2setfilepathinfo: "
7994 "Cancelling print job (%s)\n",
7998 send_trans2_replies(conn, req, params, 2,
8004 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8009 * Original code - this is an open file.
8011 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8012 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8013 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8015 reply_nterror(req, map_nt_error_from_unix(errno));
8021 uint32_t ucf_flags = 0;
8024 if (total_params < 7) {
8025 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8029 info_level = SVAL(params,0);
8030 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8031 total_params - 6, STR_TERMINATE,
8033 if (!NT_STATUS_IS_OK(status)) {
8034 reply_nterror(req, status);
8038 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8039 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8040 info_level == SMB_FILE_RENAME_INFORMATION ||
8041 info_level == SMB_POSIX_PATH_UNLINK) {
8042 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8045 status = filename_convert(req, conn,
8046 req->flags2 & FLAGS2_DFS_PATHNAMES,
8051 if (!NT_STATUS_IS_OK(status)) {
8052 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8053 reply_botherror(req,
8054 NT_STATUS_PATH_NOT_COVERED,
8055 ERRSRV, ERRbadpath);
8058 reply_nterror(req, status);
8062 if (INFO_LEVEL_IS_UNIX(info_level)) {
8064 * For CIFS UNIX extensions the target name may not exist.
8067 /* Always do lstat for UNIX calls. */
8068 SMB_VFS_LSTAT(conn, smb_fname);
8070 } else if (!VALID_STAT(smb_fname->st) &&
8071 SMB_VFS_STAT(conn, smb_fname)) {
8072 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8074 smb_fname_str_dbg(smb_fname),
8076 reply_nterror(req, map_nt_error_from_unix(errno));
8081 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8082 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8084 info_level,total_data));
8086 /* Realloc the parameter size */
8087 *pparams = (char *)SMB_REALLOC(*pparams,2);
8088 if (*pparams == NULL) {
8089 reply_nterror(req, NT_STATUS_NO_MEMORY);
8096 status = smbd_do_setfilepathinfo(conn, req, req,
8102 if (!NT_STATUS_IS_OK(status)) {
8103 if (open_was_deferred(req->sconn, req->mid)) {
8104 /* We have re-scheduled this call. */
8107 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8108 /* We have re-scheduled this call. */
8111 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8112 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8113 ERRSRV, ERRbadpath);
8116 if (info_level == SMB_POSIX_PATH_OPEN) {
8117 reply_openerror(req, status);
8121 reply_nterror(req, status);
8125 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8131 /****************************************************************************
8132 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8133 ****************************************************************************/
8135 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8136 char **pparams, int total_params,
8137 char **ppdata, int total_data,
8138 unsigned int max_data_bytes)
8140 struct smb_filename *smb_dname = NULL;
8141 char *params = *pparams;
8142 char *pdata = *ppdata;
8143 char *directory = NULL;
8144 NTSTATUS status = NT_STATUS_OK;
8145 struct ea_list *ea_list = NULL;
8146 TALLOC_CTX *ctx = talloc_tos();
8148 if (!CAN_WRITE(conn)) {
8149 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8153 if (total_params < 5) {
8154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8158 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8159 total_params - 4, STR_TERMINATE,
8161 if (!NT_STATUS_IS_OK(status)) {
8162 reply_nterror(req, status);
8166 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8168 status = filename_convert(ctx,
8170 req->flags2 & FLAGS2_DFS_PATHNAMES,
8176 if (!NT_STATUS_IS_OK(status)) {
8177 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8178 reply_botherror(req,
8179 NT_STATUS_PATH_NOT_COVERED,
8180 ERRSRV, ERRbadpath);
8183 reply_nterror(req, status);
8188 * OS/2 workplace shell seems to send SET_EA requests of "null"
8189 * length (4 bytes containing IVAL 4).
8190 * They seem to have no effect. Bug #3212. JRA.
8193 if (total_data && (total_data != 4)) {
8194 /* Any data in this call is an EA list. */
8195 if (total_data < 10) {
8196 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8200 if (IVAL(pdata,0) > total_data) {
8201 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8202 IVAL(pdata,0), (unsigned int)total_data));
8203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8207 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8210 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8214 if (!lp_ea_support(SNUM(conn))) {
8215 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8219 /* If total_data == 4 Windows doesn't care what values
8220 * are placed in that field, it just ignores them.
8221 * The System i QNTC IBM SMB client puts bad values here,
8222 * so ignore them. */
8224 status = create_directory(conn, req, smb_dname);
8226 if (!NT_STATUS_IS_OK(status)) {
8227 reply_nterror(req, status);
8231 /* Try and set any given EA. */
8233 status = set_ea(conn, NULL, smb_dname, ea_list);
8234 if (!NT_STATUS_IS_OK(status)) {
8235 reply_nterror(req, status);
8240 /* Realloc the parameter and data sizes */
8241 *pparams = (char *)SMB_REALLOC(*pparams,2);
8242 if(*pparams == NULL) {
8243 reply_nterror(req, NT_STATUS_NO_MEMORY);
8250 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8253 TALLOC_FREE(smb_dname);
8257 /****************************************************************************
8258 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8259 We don't actually do this - we just send a null response.
8260 ****************************************************************************/
8262 static void call_trans2findnotifyfirst(connection_struct *conn,
8263 struct smb_request *req,
8264 char **pparams, int total_params,
8265 char **ppdata, int total_data,
8266 unsigned int max_data_bytes)
8268 char *params = *pparams;
8271 if (total_params < 6) {
8272 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8276 info_level = SVAL(params,4);
8277 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8279 switch (info_level) {
8284 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8288 /* Realloc the parameter and data sizes */
8289 *pparams = (char *)SMB_REALLOC(*pparams,6);
8290 if (*pparams == NULL) {
8291 reply_nterror(req, NT_STATUS_NO_MEMORY);
8296 SSVAL(params,0,fnf_handle);
8297 SSVAL(params,2,0); /* No changes */
8298 SSVAL(params,4,0); /* No EA errors */
8305 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8310 /****************************************************************************
8311 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8312 changes). Currently this does nothing.
8313 ****************************************************************************/
8315 static void call_trans2findnotifynext(connection_struct *conn,
8316 struct smb_request *req,
8317 char **pparams, int total_params,
8318 char **ppdata, int total_data,
8319 unsigned int max_data_bytes)
8321 char *params = *pparams;
8323 DEBUG(3,("call_trans2findnotifynext\n"));
8325 /* Realloc the parameter and data sizes */
8326 *pparams = (char *)SMB_REALLOC(*pparams,4);
8327 if (*pparams == NULL) {
8328 reply_nterror(req, NT_STATUS_NO_MEMORY);
8333 SSVAL(params,0,0); /* No changes */
8334 SSVAL(params,2,0); /* No EA errors */
8336 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8341 /****************************************************************************
8342 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8343 ****************************************************************************/
8345 static void call_trans2getdfsreferral(connection_struct *conn,
8346 struct smb_request *req,
8347 char **pparams, int total_params,
8348 char **ppdata, int total_data,
8349 unsigned int max_data_bytes)
8351 char *params = *pparams;
8352 char *pathname = NULL;
8354 int max_referral_level;
8355 NTSTATUS status = NT_STATUS_OK;
8356 TALLOC_CTX *ctx = talloc_tos();
8358 DEBUG(10,("call_trans2getdfsreferral\n"));
8360 if (total_params < 3) {
8361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8365 max_referral_level = SVAL(params,0);
8367 if(!lp_host_msdfs()) {
8368 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8372 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8373 total_params - 2, STR_TERMINATE);
8375 reply_nterror(req, NT_STATUS_NOT_FOUND);
8378 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8379 ppdata,&status)) < 0) {
8380 reply_nterror(req, status);
8384 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8385 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8386 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8391 #define LMCAT_SPL 0x53
8392 #define LMFUNC_GETJOBID 0x60
8394 /****************************************************************************
8395 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8396 ****************************************************************************/
8398 static void call_trans2ioctl(connection_struct *conn,
8399 struct smb_request *req,
8400 char **pparams, int total_params,
8401 char **ppdata, int total_data,
8402 unsigned int max_data_bytes)
8404 char *pdata = *ppdata;
8405 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8407 /* check for an invalid fid before proceeding */
8410 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8414 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8415 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8416 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8417 if (*ppdata == NULL) {
8418 reply_nterror(req, NT_STATUS_NO_MEMORY);
8423 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8424 CAN ACCEPT THIS IN UNICODE. JRA. */
8427 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8429 srvstr_push(pdata, req->flags2, pdata + 2,
8430 lp_netbios_name(), 15,
8431 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8432 srvstr_push(pdata, req->flags2, pdata+18,
8433 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8434 STR_ASCII|STR_TERMINATE); /* Service name */
8435 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8440 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8441 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8444 /****************************************************************************
8445 Reply to a SMBfindclose (stop trans2 directory search).
8446 ****************************************************************************/
8448 void reply_findclose(struct smb_request *req)
8451 struct smbd_server_connection *sconn = req->sconn;
8453 START_PROFILE(SMBfindclose);
8456 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8457 END_PROFILE(SMBfindclose);
8461 dptr_num = SVALS(req->vwv+0, 0);
8463 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8465 dptr_close(sconn, &dptr_num);
8467 reply_outbuf(req, 0, 0);
8469 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8471 END_PROFILE(SMBfindclose);
8475 /****************************************************************************
8476 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8477 ****************************************************************************/
8479 void reply_findnclose(struct smb_request *req)
8483 START_PROFILE(SMBfindnclose);
8486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8487 END_PROFILE(SMBfindnclose);
8491 dptr_num = SVAL(req->vwv+0, 0);
8493 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8495 /* We never give out valid handles for a
8496 findnotifyfirst - so any dptr_num is ok here.
8499 reply_outbuf(req, 0, 0);
8501 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8503 END_PROFILE(SMBfindnclose);
8507 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8508 struct trans_state *state)
8510 if (get_Protocol() >= PROTOCOL_NT1) {
8511 req->flags2 |= 0x40; /* IS_LONG_NAME */
8512 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8515 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8516 if (state->call != TRANSACT2_QFSINFO &&
8517 state->call != TRANSACT2_SETFSINFO) {
8518 DEBUG(0,("handle_trans2: encryption required "
8520 (unsigned int)state->call));
8521 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8526 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8528 /* Now we must call the relevant TRANS2 function */
8529 switch(state->call) {
8530 case TRANSACT2_OPEN:
8532 START_PROFILE(Trans2_open);
8533 call_trans2open(conn, req,
8534 &state->param, state->total_param,
8535 &state->data, state->total_data,
8536 state->max_data_return);
8537 END_PROFILE(Trans2_open);
8541 case TRANSACT2_FINDFIRST:
8543 START_PROFILE(Trans2_findfirst);
8544 call_trans2findfirst(conn, req,
8545 &state->param, state->total_param,
8546 &state->data, state->total_data,
8547 state->max_data_return);
8548 END_PROFILE(Trans2_findfirst);
8552 case TRANSACT2_FINDNEXT:
8554 START_PROFILE(Trans2_findnext);
8555 call_trans2findnext(conn, req,
8556 &state->param, state->total_param,
8557 &state->data, state->total_data,
8558 state->max_data_return);
8559 END_PROFILE(Trans2_findnext);
8563 case TRANSACT2_QFSINFO:
8565 START_PROFILE(Trans2_qfsinfo);
8566 call_trans2qfsinfo(conn, req,
8567 &state->param, state->total_param,
8568 &state->data, state->total_data,
8569 state->max_data_return);
8570 END_PROFILE(Trans2_qfsinfo);
8574 case TRANSACT2_SETFSINFO:
8576 START_PROFILE(Trans2_setfsinfo);
8577 call_trans2setfsinfo(conn, req,
8578 &state->param, state->total_param,
8579 &state->data, state->total_data,
8580 state->max_data_return);
8581 END_PROFILE(Trans2_setfsinfo);
8585 case TRANSACT2_QPATHINFO:
8586 case TRANSACT2_QFILEINFO:
8588 START_PROFILE(Trans2_qpathinfo);
8589 call_trans2qfilepathinfo(conn, req, state->call,
8590 &state->param, state->total_param,
8591 &state->data, state->total_data,
8592 state->max_data_return);
8593 END_PROFILE(Trans2_qpathinfo);
8597 case TRANSACT2_SETPATHINFO:
8598 case TRANSACT2_SETFILEINFO:
8600 START_PROFILE(Trans2_setpathinfo);
8601 call_trans2setfilepathinfo(conn, req, state->call,
8602 &state->param, state->total_param,
8603 &state->data, state->total_data,
8604 state->max_data_return);
8605 END_PROFILE(Trans2_setpathinfo);
8609 case TRANSACT2_FINDNOTIFYFIRST:
8611 START_PROFILE(Trans2_findnotifyfirst);
8612 call_trans2findnotifyfirst(conn, req,
8613 &state->param, state->total_param,
8614 &state->data, state->total_data,
8615 state->max_data_return);
8616 END_PROFILE(Trans2_findnotifyfirst);
8620 case TRANSACT2_FINDNOTIFYNEXT:
8622 START_PROFILE(Trans2_findnotifynext);
8623 call_trans2findnotifynext(conn, req,
8624 &state->param, state->total_param,
8625 &state->data, state->total_data,
8626 state->max_data_return);
8627 END_PROFILE(Trans2_findnotifynext);
8631 case TRANSACT2_MKDIR:
8633 START_PROFILE(Trans2_mkdir);
8634 call_trans2mkdir(conn, req,
8635 &state->param, state->total_param,
8636 &state->data, state->total_data,
8637 state->max_data_return);
8638 END_PROFILE(Trans2_mkdir);
8642 case TRANSACT2_GET_DFS_REFERRAL:
8644 START_PROFILE(Trans2_get_dfs_referral);
8645 call_trans2getdfsreferral(conn, req,
8646 &state->param, state->total_param,
8647 &state->data, state->total_data,
8648 state->max_data_return);
8649 END_PROFILE(Trans2_get_dfs_referral);
8653 case TRANSACT2_IOCTL:
8655 START_PROFILE(Trans2_ioctl);
8656 call_trans2ioctl(conn, req,
8657 &state->param, state->total_param,
8658 &state->data, state->total_data,
8659 state->max_data_return);
8660 END_PROFILE(Trans2_ioctl);
8665 /* Error in request */
8666 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8667 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8671 /****************************************************************************
8672 Reply to a SMBtrans2.
8673 ****************************************************************************/
8675 void reply_trans2(struct smb_request *req)
8677 connection_struct *conn = req->conn;
8682 unsigned int tran_call;
8683 struct trans_state *state;
8686 START_PROFILE(SMBtrans2);
8688 if (req->wct < 14) {
8689 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8690 END_PROFILE(SMBtrans2);
8694 dsoff = SVAL(req->vwv+12, 0);
8695 dscnt = SVAL(req->vwv+11, 0);
8696 psoff = SVAL(req->vwv+10, 0);
8697 pscnt = SVAL(req->vwv+9, 0);
8698 tran_call = SVAL(req->vwv+14, 0);
8700 result = allow_new_trans(conn->pending_trans, req->mid);
8701 if (!NT_STATUS_IS_OK(result)) {
8702 DEBUG(2, ("Got invalid trans2 request: %s\n",
8703 nt_errstr(result)));
8704 reply_nterror(req, result);
8705 END_PROFILE(SMBtrans2);
8710 switch (tran_call) {
8711 /* List the allowed trans2 calls on IPC$ */
8712 case TRANSACT2_OPEN:
8713 case TRANSACT2_GET_DFS_REFERRAL:
8714 case TRANSACT2_QFILEINFO:
8715 case TRANSACT2_QFSINFO:
8716 case TRANSACT2_SETFSINFO:
8719 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8720 END_PROFILE(SMBtrans2);
8725 if ((state = talloc(conn, struct trans_state)) == NULL) {
8726 DEBUG(0, ("talloc failed\n"));
8727 reply_nterror(req, NT_STATUS_NO_MEMORY);
8728 END_PROFILE(SMBtrans2);
8732 state->cmd = SMBtrans2;
8734 state->mid = req->mid;
8735 state->vuid = req->vuid;
8736 state->setup_count = SVAL(req->vwv+13, 0);
8737 state->setup = NULL;
8738 state->total_param = SVAL(req->vwv+0, 0);
8739 state->param = NULL;
8740 state->total_data = SVAL(req->vwv+1, 0);
8742 state->max_param_return = SVAL(req->vwv+2, 0);
8743 state->max_data_return = SVAL(req->vwv+3, 0);
8744 state->max_setup_return = SVAL(req->vwv+4, 0);
8745 state->close_on_completion = BITSETW(req->vwv+5, 0);
8746 state->one_way = BITSETW(req->vwv+5, 1);
8748 state->call = tran_call;
8750 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8751 is so as a sanity check */
8752 if (state->setup_count != 1) {
8754 * Need to have rc=0 for ioctl to get job id for OS/2.
8755 * Network printing will fail if function is not successful.
8756 * Similar function in reply.c will be used if protocol
8757 * is LANMAN1.0 instead of LM1.2X002.
8758 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8759 * outbuf doesn't have to be set(only job id is used).
8761 if ( (state->setup_count == 4)
8762 && (tran_call == TRANSACT2_IOCTL)
8763 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8764 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8765 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8767 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8768 DEBUG(2,("Transaction is %d\n",tran_call));
8770 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8771 END_PROFILE(SMBtrans2);
8776 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8779 if (state->total_data) {
8781 if (trans_oob(state->total_data, 0, dscnt)
8782 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8786 /* Can't use talloc here, the core routines do realloc on the
8787 * params and data. */
8788 state->data = (char *)SMB_MALLOC(state->total_data);
8789 if (state->data == NULL) {
8790 DEBUG(0,("reply_trans2: data malloc fail for %u "
8791 "bytes !\n", (unsigned int)state->total_data));
8793 reply_nterror(req, NT_STATUS_NO_MEMORY);
8794 END_PROFILE(SMBtrans2);
8798 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8801 if (state->total_param) {
8803 if (trans_oob(state->total_param, 0, pscnt)
8804 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8808 /* Can't use talloc here, the core routines do realloc on the
8809 * params and data. */
8810 state->param = (char *)SMB_MALLOC(state->total_param);
8811 if (state->param == NULL) {
8812 DEBUG(0,("reply_trans: param malloc fail for %u "
8813 "bytes !\n", (unsigned int)state->total_param));
8814 SAFE_FREE(state->data);
8816 reply_nterror(req, NT_STATUS_NO_MEMORY);
8817 END_PROFILE(SMBtrans2);
8821 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8824 state->received_data = dscnt;
8825 state->received_param = pscnt;
8827 if ((state->received_param == state->total_param) &&
8828 (state->received_data == state->total_data)) {
8830 handle_trans2(conn, req, state);
8832 SAFE_FREE(state->data);
8833 SAFE_FREE(state->param);
8835 END_PROFILE(SMBtrans2);
8839 DLIST_ADD(conn->pending_trans, state);
8841 /* We need to send an interim response then receive the rest
8842 of the parameter/data bytes */
8843 reply_outbuf(req, 0, 0);
8844 show_msg((char *)req->outbuf);
8845 END_PROFILE(SMBtrans2);
8850 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8851 SAFE_FREE(state->data);
8852 SAFE_FREE(state->param);
8854 END_PROFILE(SMBtrans2);
8855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8859 /****************************************************************************
8860 Reply to a SMBtranss2
8861 ****************************************************************************/
8863 void reply_transs2(struct smb_request *req)
8865 connection_struct *conn = req->conn;
8866 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8867 struct trans_state *state;
8869 START_PROFILE(SMBtranss2);
8871 show_msg((const char *)req->inbuf);
8873 /* Windows clients expect all replies to
8874 a transact secondary (SMBtranss2 0x33)
8875 to have a command code of transact
8876 (SMBtrans2 0x32). See bug #8989
8877 and also [MS-CIFS] section 2.2.4.47.2
8880 req->cmd = SMBtrans2;
8883 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8884 END_PROFILE(SMBtranss2);
8888 for (state = conn->pending_trans; state != NULL;
8889 state = state->next) {
8890 if (state->mid == req->mid) {
8895 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8896 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8897 END_PROFILE(SMBtranss2);
8901 /* Revise state->total_param and state->total_data in case they have
8902 changed downwards */
8904 if (SVAL(req->vwv+0, 0) < state->total_param)
8905 state->total_param = SVAL(req->vwv+0, 0);
8906 if (SVAL(req->vwv+1, 0) < state->total_data)
8907 state->total_data = SVAL(req->vwv+1, 0);
8909 pcnt = SVAL(req->vwv+2, 0);
8910 poff = SVAL(req->vwv+3, 0);
8911 pdisp = SVAL(req->vwv+4, 0);
8913 dcnt = SVAL(req->vwv+5, 0);
8914 doff = SVAL(req->vwv+6, 0);
8915 ddisp = SVAL(req->vwv+7, 0);
8917 state->received_param += pcnt;
8918 state->received_data += dcnt;
8920 if ((state->received_data > state->total_data) ||
8921 (state->received_param > state->total_param))
8925 if (trans_oob(state->total_param, pdisp, pcnt)
8926 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8929 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8933 if (trans_oob(state->total_data, ddisp, dcnt)
8934 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8937 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8940 if ((state->received_param < state->total_param) ||
8941 (state->received_data < state->total_data)) {
8942 END_PROFILE(SMBtranss2);
8946 handle_trans2(conn, req, state);
8948 DLIST_REMOVE(conn->pending_trans, state);
8949 SAFE_FREE(state->data);
8950 SAFE_FREE(state->param);
8953 END_PROFILE(SMBtranss2);
8958 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8959 DLIST_REMOVE(conn->pending_trans, state);
8960 SAFE_FREE(state->data);
8961 SAFE_FREE(state->param);
8963 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8964 END_PROFILE(SMBtranss2);