2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "system/filesys.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
55 const SMB_STRUCT_STAT *psbuf);
57 /********************************************************************
58 The canonical "check access" based on object handle or path function.
59 ********************************************************************/
61 NTSTATUS check_access(connection_struct *conn,
63 const struct smb_filename *smb_fname,
67 if (!(fsp->access_mask & access_mask)) {
68 return NT_STATUS_ACCESS_DENIED;
71 NTSTATUS status = smbd_check_access_rights(conn,
75 if (!NT_STATUS_IS_OK(status)) {
82 /********************************************************************
83 Roundup a value to the nearest allocation roundup size boundary.
84 Only do this for Windows clients.
85 ********************************************************************/
87 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
89 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
91 /* Only roundup for Windows clients. */
92 enum remote_arch_types ra_type = get_remote_arch();
93 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
94 val = SMB_ROUNDUP(val,rval);
99 /********************************************************************
100 Create a 64 bit FileIndex. If the file is on the same device as
101 the root of the share, just return the 64-bit inode. If it isn't,
102 mangle as we used to do.
103 ********************************************************************/
105 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
108 if (conn->base_share_dev == psbuf->st_ex_dev) {
109 return (uint64_t)psbuf->st_ex_ino;
111 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
112 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
116 /****************************************************************************
117 Utility functions for dealing with extended attributes.
118 ****************************************************************************/
120 /****************************************************************************
121 Refuse to allow clients to overwrite our private xattrs.
122 ****************************************************************************/
124 bool samba_private_attr_name(const char *unix_ea_name)
126 static const char * const prohibited_ea_names[] = {
127 SAMBA_POSIX_INHERITANCE_EA_NAME,
128 SAMBA_XATTR_DOS_ATTRIB,
136 for (i = 0; prohibited_ea_names[i]; i++) {
137 if (strequal( prohibited_ea_names[i], unix_ea_name))
140 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
141 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
147 /****************************************************************************
148 Get one EA value. Fill in a struct ea_struct.
149 ****************************************************************************/
151 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
152 files_struct *fsp, const char *fname,
153 const char *ea_name, struct ea_struct *pea)
155 /* Get the value of this xattr. Max size is 64k. */
156 size_t attr_size = 256;
162 val = talloc_realloc(mem_ctx, val, char, attr_size);
164 return NT_STATUS_NO_MEMORY;
167 if (fsp && fsp->fh->fd != -1) {
168 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
170 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
173 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
179 return map_nt_error_from_unix(errno);
182 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
183 dump_data(10, (uint8 *)val, sizeret);
186 if (strnequal(ea_name, "user.", 5)) {
187 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
189 pea->name = talloc_strdup(mem_ctx, ea_name);
191 if (pea->name == NULL) {
193 return NT_STATUS_NO_MEMORY;
195 pea->value.data = (unsigned char *)val;
196 pea->value.length = (size_t)sizeret;
200 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
201 files_struct *fsp, const char *fname,
202 char ***pnames, size_t *pnum_names)
204 /* Get a list of all xattrs. Max namesize is 64k. */
205 size_t ea_namelist_size = 1024;
206 char *ea_namelist = NULL;
211 ssize_t sizeret = -1;
213 if (!lp_ea_support(SNUM(conn))) {
222 * TALLOC the result early to get the talloc hierarchy right.
225 names = talloc_array(mem_ctx, char *, 1);
227 DEBUG(0, ("talloc failed\n"));
228 return NT_STATUS_NO_MEMORY;
231 while (ea_namelist_size <= 65536) {
233 ea_namelist = talloc_realloc(
234 names, ea_namelist, char, ea_namelist_size);
235 if (ea_namelist == NULL) {
236 DEBUG(0, ("talloc failed\n"));
238 return NT_STATUS_NO_MEMORY;
241 if (fsp && fsp->fh->fd != -1) {
242 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
245 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
249 if ((sizeret == -1) && (errno == ERANGE)) {
250 ea_namelist_size *= 2;
259 return map_nt_error_from_unix(errno);
262 DEBUG(10, ("%s: ea_namelist size = %u\n",
263 __func__, (unsigned int)sizeret));
275 * Ensure the result is 0-terminated
278 if (ea_namelist[sizeret-1] != '\0') {
280 return NT_STATUS_INTERNAL_ERROR;
288 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
292 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
294 DEBUG(0, ("talloc failed\n"));
296 return NT_STATUS_NO_MEMORY;
302 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
303 names[num_names++] = p;
311 *pnum_names = num_names;
315 /****************************************************************************
316 Return a linked list of the total EA's. Plus the total size
317 ****************************************************************************/
319 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
320 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
322 /* Get a list of all xattrs. Max namesize is 64k. */
325 struct ea_list *ea_list_head = NULL;
331 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
334 if (!NT_STATUS_IS_OK(status)) {
338 if (num_names == 0) {
343 for (i=0; i<num_names; i++) {
344 struct ea_list *listp;
347 if (strnequal(names[i], "system.", 7)
348 || samba_private_attr_name(names[i]))
352 * Filter out any underlying POSIX EA names
353 * that a Windows client can't handle.
355 if (!lp_posix_pathnames() &&
356 is_invalid_windows_ea_name(names[i])) {
360 listp = talloc(mem_ctx, struct ea_list);
362 return NT_STATUS_NO_MEMORY;
365 status = get_ea_value(listp, conn, fsp,
369 if (!NT_STATUS_IS_OK(status)) {
374 if (listp->ea.value.length == 0) {
376 * We can never return a zero length EA.
377 * Windows reports the EA's as corrupted.
383 push_ascii_fstring(dos_ea_name, listp->ea.name);
386 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
388 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
389 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
390 (unsigned int)listp->ea.value.length));
392 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
396 /* Add on 4 for total length. */
397 if (*pea_total_len) {
401 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
402 (unsigned int)*pea_total_len));
404 *ea_list = ea_list_head;
408 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
409 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
414 if (!lp_ea_support(SNUM(conn))) {
418 if (is_ntfs_stream_smb_fname(smb_fname)) {
419 return NT_STATUS_INVALID_PARAMETER;
422 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
425 /****************************************************************************
426 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
428 ****************************************************************************/
430 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
431 connection_struct *conn, struct ea_list *ea_list)
433 unsigned int ret_data_size = 4;
436 SMB_ASSERT(total_data_size >= 4);
438 if (!lp_ea_support(SNUM(conn))) {
443 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
446 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
447 dos_namelen = strlen(dos_ea_name);
448 if (dos_namelen > 255 || dos_namelen == 0) {
451 if (ea_list->ea.value.length > 65535) {
454 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
458 /* We know we have room. */
459 SCVAL(p,0,ea_list->ea.flags);
460 SCVAL(p,1,dos_namelen);
461 SSVAL(p,2,ea_list->ea.value.length);
462 strlcpy(p+4, dos_ea_name, dos_namelen+1);
463 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
465 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
466 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
469 ret_data_size = PTR_DIFF(p, pdata);
470 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
471 SIVAL(pdata,0,ret_data_size);
472 return ret_data_size;
475 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
477 unsigned int total_data_size,
478 unsigned int *ret_data_size,
479 connection_struct *conn,
480 struct ea_list *ea_list)
482 uint8_t *p = (uint8_t *)pdata;
483 uint8_t *last_start = NULL;
484 bool do_store_data = (pdata != NULL);
488 if (!lp_ea_support(SNUM(conn))) {
489 return NT_STATUS_NO_EAS_ON_FILE;
492 for (; ea_list; ea_list = ea_list->next) {
498 if (last_start != NULL && do_store_data) {
499 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
503 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
504 dos_namelen = strlen(dos_ea_name);
505 if (dos_namelen > 255 || dos_namelen == 0) {
506 return NT_STATUS_INTERNAL_ERROR;
508 if (ea_list->ea.value.length > 65535) {
509 return NT_STATUS_INTERNAL_ERROR;
512 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
515 pad = (4 - (this_size % 4)) % 4;
520 if (this_size > total_data_size) {
521 return NT_STATUS_INFO_LENGTH_MISMATCH;
524 /* We know we have room. */
525 SIVAL(p, 0x00, 0); /* next offset */
526 SCVAL(p, 0x04, ea_list->ea.flags);
527 SCVAL(p, 0x05, dos_namelen);
528 SSVAL(p, 0x06, ea_list->ea.value.length);
529 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
530 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
532 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
536 total_data_size -= this_size;
542 *ret_data_size = PTR_DIFF(p, pdata);
543 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
547 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
549 size_t total_ea_len = 0;
551 struct ea_list *ea_list = NULL;
553 if (!lp_ea_support(SNUM(conn))) {
556 mem_ctx = talloc_stackframe();
558 /* If this is a stream fsp, then we need to instead find the
559 * estimated ea len from the main file, not the stream
560 * (streams cannot have EAs), but the estimate isn't just 0 in
562 if (is_ntfs_stream_smb_fname(smb_fname)) {
565 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
566 if(conn->sconn->using_smb2) {
568 unsigned int ret_data_size;
570 * We're going to be using fill_ea_chained_buffer() to
571 * marshall EA's - this size is significantly larger
572 * than the SMB1 buffer. Re-calculate the size without
575 status = fill_ea_chained_buffer(mem_ctx,
581 if (!NT_STATUS_IS_OK(status)) {
584 total_ea_len = ret_data_size;
586 TALLOC_FREE(mem_ctx);
590 /****************************************************************************
591 Ensure the EA name is case insensitive by matching any existing EA name.
592 ****************************************************************************/
594 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
597 TALLOC_CTX *mem_ctx = talloc_tos();
598 struct ea_list *ea_list;
599 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
600 if (!NT_STATUS_IS_OK(status)) {
604 for (; ea_list; ea_list = ea_list->next) {
605 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
606 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
607 &unix_ea_name[5], ea_list->ea.name));
608 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
614 /****************************************************************************
615 Set or delete an extended attribute.
616 ****************************************************************************/
618 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
619 const struct smb_filename *smb_fname, struct ea_list *ea_list)
624 if (!lp_ea_support(SNUM(conn))) {
625 return NT_STATUS_EAS_NOT_SUPPORTED;
628 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
629 if (!NT_STATUS_IS_OK(status)) {
633 /* Setting EAs on streams isn't supported. */
634 if (is_ntfs_stream_smb_fname(smb_fname)) {
635 return NT_STATUS_INVALID_PARAMETER;
639 * Filter out invalid Windows EA names - before
640 * we set *any* of them.
643 if (ea_list_has_invalid_name(ea_list)) {
644 return STATUS_INVALID_EA_NAME;
647 fname = smb_fname->base_name;
649 for (;ea_list; ea_list = ea_list->next) {
651 fstring unix_ea_name;
653 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
654 fstrcat(unix_ea_name, ea_list->ea.name);
656 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
658 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
660 if (samba_private_attr_name(unix_ea_name)) {
661 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
662 return NT_STATUS_ACCESS_DENIED;
665 if (ea_list->ea.value.length == 0) {
666 /* Remove the attribute. */
667 if (fsp && (fsp->fh->fd != -1)) {
668 DEBUG(10,("set_ea: deleting ea name %s on "
669 "file %s by file descriptor.\n",
670 unix_ea_name, fsp_str_dbg(fsp)));
671 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
673 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
674 unix_ea_name, fname));
675 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
678 /* Removing a non existent attribute always succeeds. */
679 if (ret == -1 && errno == ENOATTR) {
680 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
686 if (fsp && (fsp->fh->fd != -1)) {
687 DEBUG(10,("set_ea: setting ea name %s on file "
688 "%s by file descriptor.\n",
689 unix_ea_name, fsp_str_dbg(fsp)));
690 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
691 ea_list->ea.value.data, ea_list->ea.value.length, 0);
693 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
694 unix_ea_name, fname));
695 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
696 ea_list->ea.value.data, ea_list->ea.value.length, 0);
702 if (errno == ENOTSUP) {
703 return NT_STATUS_EAS_NOT_SUPPORTED;
706 return map_nt_error_from_unix(errno);
712 /****************************************************************************
713 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
714 ****************************************************************************/
716 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
718 struct ea_list *ea_list_head = NULL;
719 size_t converted_size, offset = 0;
721 while (offset + 2 < data_size) {
722 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
723 unsigned int namelen = CVAL(pdata,offset);
725 offset++; /* Go past the namelen byte. */
727 /* integer wrap paranioa. */
728 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
729 (offset > data_size) || (namelen > data_size) ||
730 (offset + namelen >= data_size)) {
733 /* Ensure the name is null terminated. */
734 if (pdata[offset + namelen] != '\0') {
737 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
739 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
740 "failed: %s", strerror(errno)));
746 offset += (namelen + 1); /* Go past the name + terminating zero. */
747 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
748 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
754 /****************************************************************************
755 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
756 ****************************************************************************/
758 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
760 struct ea_list *ea_list_head = NULL;
762 size_t bytes_used = 0;
764 while (offset < data_size) {
765 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
771 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
772 offset += bytes_used;
778 /****************************************************************************
779 Count the total EA size needed.
780 ****************************************************************************/
782 static size_t ea_list_size(struct ea_list *ealist)
785 struct ea_list *listp;
788 for (listp = ealist; listp; listp = listp->next) {
789 push_ascii_fstring(dos_ea_name, listp->ea.name);
790 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
792 /* Add on 4 for total length. */
800 /****************************************************************************
801 Return a union of EA's from a file list and a list of names.
802 The TALLOC context for the two lists *MUST* be identical as we steal
803 memory from one list to add to another. JRA.
804 ****************************************************************************/
806 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
808 struct ea_list *nlistp, *flistp;
810 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
811 for (flistp = file_list; flistp; flistp = flistp->next) {
812 if (strequal(nlistp->ea.name, flistp->ea.name)) {
818 /* Copy the data from this entry. */
819 nlistp->ea.flags = flistp->ea.flags;
820 nlistp->ea.value = flistp->ea.value;
823 nlistp->ea.flags = 0;
824 ZERO_STRUCT(nlistp->ea.value);
828 *total_ea_len = ea_list_size(name_list);
832 /****************************************************************************
833 Send the required number of replies back.
834 We assume all fields other than the data fields are
835 set correctly for the type of call.
836 HACK ! Always assumes smb_setup field is zero.
837 ****************************************************************************/
839 void send_trans2_replies(connection_struct *conn,
840 struct smb_request *req,
848 /* As we are using a protocol > LANMAN1 then the max_send
849 variable must have been set in the sessetupX call.
850 This takes precedence over the max_xmit field in the
851 global struct. These different max_xmit variables should
852 be merged as this is now too confusing */
854 int data_to_send = datasize;
855 int params_to_send = paramsize;
857 const char *pp = params;
858 const char *pd = pdata;
859 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
860 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
861 int data_alignment_offset = 0;
862 bool overflow = False;
863 struct smbXsrv_connection *xconn = req->xconn;
864 int max_send = xconn->smb1.sessions.max_send;
866 /* Modify the data_to_send and datasize and set the error if
867 we're trying to send more than max_data_bytes. We still send
868 the part of the packet(s) that fit. Strange, but needed
871 if (max_data_bytes > 0 && datasize > max_data_bytes) {
872 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
873 max_data_bytes, datasize ));
874 datasize = data_to_send = max_data_bytes;
878 /* If there genuinely are no parameters or data to send just send the empty packet */
880 if(params_to_send == 0 && data_to_send == 0) {
881 reply_outbuf(req, 10, 0);
882 if (NT_STATUS_V(status)) {
885 ntstatus_to_dos(status, &eclass, &ecode);
886 error_packet_set((char *)req->outbuf,
887 eclass, ecode, status,
890 show_msg((char *)req->outbuf);
891 if (!srv_send_smb(xconn,
894 IS_CONN_ENCRYPTED(conn),
896 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
898 TALLOC_FREE(req->outbuf);
902 /* When sending params and data ensure that both are nicely aligned */
903 /* Only do this alignment when there is also data to send - else
904 can cause NT redirector problems. */
906 if (((params_to_send % 4) != 0) && (data_to_send != 0))
907 data_alignment_offset = 4 - (params_to_send % 4);
909 /* Space is bufsize minus Netbios over TCP header minus SMB header */
910 /* The alignment_offset is to align the param bytes on an even byte
911 boundary. NT 4.0 Beta needs this to work correctly. */
913 useable_space = max_send - (smb_size
916 + data_alignment_offset);
918 if (useable_space < 0) {
919 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
920 "= %d!!!", useable_space));
921 exit_server_cleanly("send_trans2_replies: Not enough space");
924 while (params_to_send || data_to_send) {
925 /* Calculate whether we will totally or partially fill this packet */
927 total_sent_thistime = params_to_send + data_to_send;
929 /* We can never send more than useable_space */
931 * Note that 'useable_space' does not include the alignment offsets,
932 * but we must include the alignment offsets in the calculation of
933 * the length of the data we send over the wire, as the alignment offsets
934 * are sent here. Fix from Marc_Jacobsen@hp.com.
937 total_sent_thistime = MIN(total_sent_thistime, useable_space);
939 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
940 + data_alignment_offset);
942 /* Set total params and data to be sent */
943 SSVAL(req->outbuf,smb_tprcnt,paramsize);
944 SSVAL(req->outbuf,smb_tdrcnt,datasize);
946 /* Calculate how many parameters and data we can fit into
947 * this packet. Parameters get precedence
950 params_sent_thistime = MIN(params_to_send,useable_space);
951 data_sent_thistime = useable_space - params_sent_thistime;
952 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
954 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
956 /* smb_proff is the offset from the start of the SMB header to the
957 parameter bytes, however the first 4 bytes of outbuf are
958 the Netbios over TCP header. Thus use smb_base() to subtract
959 them from the calculation */
961 SSVAL(req->outbuf,smb_proff,
962 ((smb_buf(req->outbuf)+alignment_offset)
963 - smb_base(req->outbuf)));
965 if(params_sent_thistime == 0)
966 SSVAL(req->outbuf,smb_prdisp,0);
968 /* Absolute displacement of param bytes sent in this packet */
969 SSVAL(req->outbuf,smb_prdisp,pp - params);
971 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
972 if(data_sent_thistime == 0) {
973 SSVAL(req->outbuf,smb_droff,0);
974 SSVAL(req->outbuf,smb_drdisp, 0);
976 /* The offset of the data bytes is the offset of the
977 parameter bytes plus the number of parameters being sent this time */
978 SSVAL(req->outbuf, smb_droff,
979 ((smb_buf(req->outbuf)+alignment_offset)
980 - smb_base(req->outbuf))
981 + params_sent_thistime + data_alignment_offset);
982 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
985 /* Initialize the padding for alignment */
987 if (alignment_offset != 0) {
988 memset(smb_buf(req->outbuf), 0, alignment_offset);
991 /* Copy the param bytes into the packet */
993 if(params_sent_thistime) {
994 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
995 params_sent_thistime);
998 /* Copy in the data bytes */
999 if(data_sent_thistime) {
1000 if (data_alignment_offset != 0) {
1001 memset((smb_buf(req->outbuf)+alignment_offset+
1002 params_sent_thistime), 0,
1003 data_alignment_offset);
1005 memcpy(smb_buf(req->outbuf)+alignment_offset
1006 +params_sent_thistime+data_alignment_offset,
1007 pd,data_sent_thistime);
1010 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1011 params_sent_thistime, data_sent_thistime, useable_space));
1012 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1013 params_to_send, data_to_send, paramsize, datasize));
1016 error_packet_set((char *)req->outbuf,
1017 ERRDOS,ERRbufferoverflow,
1018 STATUS_BUFFER_OVERFLOW,
1020 } else if (NT_STATUS_V(status)) {
1023 ntstatus_to_dos(status, &eclass, &ecode);
1024 error_packet_set((char *)req->outbuf,
1025 eclass, ecode, status,
1029 /* Send the packet */
1030 show_msg((char *)req->outbuf);
1031 if (!srv_send_smb(xconn,
1032 (char *)req->outbuf,
1033 true, req->seqnum+1,
1034 IS_CONN_ENCRYPTED(conn),
1036 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1038 TALLOC_FREE(req->outbuf);
1040 pp += params_sent_thistime;
1041 pd += data_sent_thistime;
1043 params_to_send -= params_sent_thistime;
1044 data_to_send -= data_sent_thistime;
1047 if(params_to_send < 0 || data_to_send < 0) {
1048 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1049 params_to_send, data_to_send));
1057 /****************************************************************************
1058 Reply to a TRANSACT2_OPEN.
1059 ****************************************************************************/
1061 static void call_trans2open(connection_struct *conn,
1062 struct smb_request *req,
1063 char **pparams, int total_params,
1064 char **ppdata, int total_data,
1065 unsigned int max_data_bytes)
1067 struct smb_filename *smb_fname = NULL;
1068 char *params = *pparams;
1069 char *pdata = *ppdata;
1072 bool oplock_request;
1074 bool return_additional_info;
1083 int fattr=0,mtime=0;
1084 SMB_INO_T inode = 0;
1087 struct ea_list *ea_list = NULL;
1092 uint32 create_disposition;
1093 uint32 create_options = 0;
1094 uint32_t private_flags = 0;
1095 TALLOC_CTX *ctx = talloc_tos();
1098 * Ensure we have enough parameters to perform the operation.
1101 if (total_params < 29) {
1102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1106 flags = SVAL(params, 0);
1107 deny_mode = SVAL(params, 2);
1108 open_attr = SVAL(params,6);
1109 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1110 if (oplock_request) {
1111 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1115 return_additional_info = BITSETW(params,0);
1116 open_sattr = SVAL(params, 4);
1117 open_time = make_unix_date3(params+8);
1119 open_ofun = SVAL(params,12);
1120 open_size = IVAL(params,14);
1121 pname = ¶ms[28];
1124 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1128 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1129 total_params - 28, STR_TERMINATE,
1131 if (!NT_STATUS_IS_OK(status)) {
1132 reply_nterror(req, status);
1136 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1137 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1138 (unsigned int)open_ofun, open_size));
1140 status = filename_convert(ctx,
1142 req->flags2 & FLAGS2_DFS_PATHNAMES,
1147 if (!NT_STATUS_IS_OK(status)) {
1148 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1149 reply_botherror(req,
1150 NT_STATUS_PATH_NOT_COVERED,
1151 ERRSRV, ERRbadpath);
1154 reply_nterror(req, status);
1158 if (open_ofun == 0) {
1159 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1163 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1165 &access_mask, &share_mode,
1166 &create_disposition,
1169 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1173 /* Any data in this call is an EA list. */
1174 if (total_data && (total_data != 4)) {
1175 if (total_data < 10) {
1176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1180 if (IVAL(pdata,0) > total_data) {
1181 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1182 IVAL(pdata,0), (unsigned int)total_data));
1183 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1187 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1190 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1194 if (!lp_ea_support(SNUM(conn))) {
1195 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1199 if (ea_list_has_invalid_name(ea_list)) {
1201 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1202 if(*pparams == NULL ) {
1203 reply_nterror(req, NT_STATUS_NO_MEMORY);
1207 memset(params, '\0', param_len);
1208 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1209 params, param_len, NULL, 0, max_data_bytes);
1214 status = SMB_VFS_CREATE_FILE(
1217 0, /* root_dir_fid */
1218 smb_fname, /* fname */
1219 access_mask, /* access_mask */
1220 share_mode, /* share_access */
1221 create_disposition, /* create_disposition*/
1222 create_options, /* create_options */
1223 open_attr, /* file_attributes */
1224 oplock_request, /* oplock_request */
1226 open_size, /* allocation_size */
1229 ea_list, /* ea_list */
1231 &smb_action, /* psbuf */
1232 NULL, NULL); /* create context */
1234 if (!NT_STATUS_IS_OK(status)) {
1235 if (open_was_deferred(req->xconn, req->mid)) {
1236 /* We have re-scheduled this call. */
1239 reply_openerror(req, status);
1243 size = get_file_size_stat(&smb_fname->st);
1244 fattr = dos_mode(conn, smb_fname);
1245 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1246 inode = smb_fname->st.st_ex_ino;
1247 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1248 close_file(req, fsp, ERROR_CLOSE);
1249 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1253 /* Realloc the size of parameters and data we will return */
1254 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1255 if(*pparams == NULL ) {
1256 reply_nterror(req, NT_STATUS_NO_MEMORY);
1261 SSVAL(params,0,fsp->fnum);
1262 SSVAL(params,2,fattr);
1263 srv_put_dos_date2(params,4, mtime);
1264 SIVAL(params,8, (uint32)size);
1265 SSVAL(params,12,deny_mode);
1266 SSVAL(params,14,0); /* open_type - file or directory. */
1267 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1269 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1270 smb_action |= EXTENDED_OPLOCK_GRANTED;
1273 SSVAL(params,18,smb_action);
1276 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1278 SIVAL(params,20,inode);
1279 SSVAL(params,24,0); /* Padding. */
1281 uint32 ea_size = estimate_ea_size(conn, fsp,
1283 SIVAL(params, 26, ea_size);
1285 SIVAL(params, 26, 0);
1288 /* Send the required number of replies */
1289 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1291 TALLOC_FREE(smb_fname);
1294 /*********************************************************
1295 Routine to check if a given string matches exactly.
1296 as a special case a mask of "." does NOT match. That
1297 is required for correct wildcard semantics
1298 Case can be significant or not.
1299 **********************************************************/
1301 static bool exact_match(bool has_wild,
1302 bool case_sensitive,
1306 if (mask[0] == '.' && mask[1] == 0) {
1314 if (case_sensitive) {
1315 return strcmp(str,mask)==0;
1317 return strcasecmp_m(str,mask) == 0;
1321 /****************************************************************************
1322 Return the filetype for UNIX extensions.
1323 ****************************************************************************/
1325 static uint32 unix_filetype(mode_t mode)
1328 return UNIX_TYPE_FILE;
1329 else if(S_ISDIR(mode))
1330 return UNIX_TYPE_DIR;
1332 else if(S_ISLNK(mode))
1333 return UNIX_TYPE_SYMLINK;
1336 else if(S_ISCHR(mode))
1337 return UNIX_TYPE_CHARDEV;
1340 else if(S_ISBLK(mode))
1341 return UNIX_TYPE_BLKDEV;
1344 else if(S_ISFIFO(mode))
1345 return UNIX_TYPE_FIFO;
1348 else if(S_ISSOCK(mode))
1349 return UNIX_TYPE_SOCKET;
1352 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1353 return UNIX_TYPE_UNKNOWN;
1356 /****************************************************************************
1357 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1358 ****************************************************************************/
1360 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1362 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1363 const SMB_STRUCT_STAT *psbuf,
1365 enum perm_type ptype,
1370 if (perms == SMB_MODE_NO_CHANGE) {
1371 if (!VALID_STAT(*psbuf)) {
1372 return NT_STATUS_INVALID_PARAMETER;
1374 *ret_perms = psbuf->st_ex_mode;
1375 return NT_STATUS_OK;
1379 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1380 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1381 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1382 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1383 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1384 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1385 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1386 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1387 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1389 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1392 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1395 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1398 if (ptype == PERM_NEW_FILE) {
1400 * "create mask"/"force create mode" are
1401 * only applied to new files, not existing ones.
1403 ret &= lp_create_mask(SNUM(conn));
1404 /* Add in force bits */
1405 ret |= lp_force_create_mode(SNUM(conn));
1406 } else if (ptype == PERM_NEW_DIR) {
1408 * "directory mask"/"force directory mode" are
1409 * only applied to new directories, not existing ones.
1411 ret &= lp_directory_mask(SNUM(conn));
1412 /* Add in force bits */
1413 ret |= lp_force_directory_mode(SNUM(conn));
1417 return NT_STATUS_OK;
1420 /****************************************************************************
1421 Needed to show the msdfs symlinks as directories. Modifies psbuf
1422 to be a directory if it's a msdfs link.
1423 ****************************************************************************/
1425 static bool check_msdfs_link(connection_struct *conn,
1426 const char *pathname,
1427 SMB_STRUCT_STAT *psbuf)
1429 int saved_errno = errno;
1430 if(lp_host_msdfs() &&
1431 lp_msdfs_root(SNUM(conn)) &&
1432 is_msdfs_link(conn, pathname, psbuf)) {
1434 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1437 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1438 errno = saved_errno;
1441 errno = saved_errno;
1446 /****************************************************************************
1447 Get a level dependent lanman2 dir entry.
1448 ****************************************************************************/
1450 struct smbd_dirptr_lanman2_state {
1451 connection_struct *conn;
1452 uint32_t info_level;
1453 bool check_mangled_names;
1455 bool got_exact_match;
1458 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1464 struct smbd_dirptr_lanman2_state *state =
1465 (struct smbd_dirptr_lanman2_state *)private_data;
1467 char mangled_name[13]; /* mangled 8.3 name. */
1471 /* Mangle fname if it's an illegal name. */
1472 if (mangle_must_mangle(dname, state->conn->params)) {
1474 * Slow path - ensure we can push the original name as UCS2. If
1475 * not, then just don't return this name.
1479 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1480 uint8_t *tmp = talloc_array(talloc_tos(),
1484 status = srvstr_push(NULL,
1485 FLAGS2_UNICODE_STRINGS,
1494 if (!NT_STATUS_IS_OK(status)) {
1498 ok = name_to_8_3(dname, mangled_name,
1499 true, state->conn->params);
1503 fname = mangled_name;
1508 got_match = exact_match(state->has_wild,
1509 state->conn->case_sensitive,
1511 state->got_exact_match = got_match;
1513 got_match = mask_match(fname, mask,
1514 state->conn->case_sensitive);
1517 if(!got_match && state->check_mangled_names &&
1518 !mangle_is_8_3(fname, false, state->conn->params)) {
1520 * It turns out that NT matches wildcards against
1521 * both long *and* short names. This may explain some
1522 * of the wildcard wierdness from old DOS clients
1523 * that some people have been seeing.... JRA.
1525 /* Force the mangling into 8.3. */
1526 ok = name_to_8_3(fname, mangled_name,
1527 false, state->conn->params);
1532 got_match = exact_match(state->has_wild,
1533 state->conn->case_sensitive,
1534 mangled_name, mask);
1535 state->got_exact_match = got_match;
1537 got_match = mask_match(mangled_name, mask,
1538 state->conn->case_sensitive);
1546 *_fname = talloc_strdup(ctx, fname);
1547 if (*_fname == NULL) {
1554 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1556 struct smb_filename *smb_fname,
1559 struct smbd_dirptr_lanman2_state *state =
1560 (struct smbd_dirptr_lanman2_state *)private_data;
1561 bool ms_dfs_link = false;
1564 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1565 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1566 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1567 "Couldn't lstat [%s] (%s)\n",
1568 smb_fname_str_dbg(smb_fname),
1572 } else if (!VALID_STAT(smb_fname->st) &&
1573 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1574 /* Needed to show the msdfs symlinks as
1577 ms_dfs_link = check_msdfs_link(state->conn,
1578 smb_fname->base_name,
1581 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1582 "Couldn't stat [%s] (%s)\n",
1583 smb_fname_str_dbg(smb_fname),
1590 mode = dos_mode_msdfs(state->conn, smb_fname);
1592 mode = dos_mode(state->conn, smb_fname);
1599 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1600 connection_struct *conn,
1602 uint32_t info_level,
1603 struct ea_list *name_list,
1604 bool check_mangled_names,
1605 bool requires_resume_key,
1608 const struct smb_filename *smb_fname,
1609 int space_remaining,
1615 uint64_t *last_entry_off)
1617 char *p, *q, *pdata = *ppdata;
1619 uint64_t file_size = 0;
1620 uint64_t allocation_size = 0;
1621 uint64_t file_index = 0;
1623 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1624 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1626 char *last_entry_ptr;
1631 struct readdir_attr_data *readdir_attr_data = NULL;
1633 ZERO_STRUCT(mdate_ts);
1634 ZERO_STRUCT(adate_ts);
1635 ZERO_STRUCT(create_date_ts);
1636 ZERO_STRUCT(cdate_ts);
1638 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1639 file_size = get_file_size_stat(&smb_fname->st);
1641 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1643 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1644 if (!NT_STATUS_IS_OK(status)) {
1645 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1650 file_index = get_FileIndex(conn, &smb_fname->st);
1652 mdate_ts = smb_fname->st.st_ex_mtime;
1653 adate_ts = smb_fname->st.st_ex_atime;
1654 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1655 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1657 if (lp_dos_filetime_resolution(SNUM(conn))) {
1658 dos_filetime_timespec(&create_date_ts);
1659 dos_filetime_timespec(&mdate_ts);
1660 dos_filetime_timespec(&adate_ts);
1661 dos_filetime_timespec(&cdate_ts);
1664 create_date = convert_timespec_to_time_t(create_date_ts);
1665 mdate = convert_timespec_to_time_t(mdate_ts);
1666 adate = convert_timespec_to_time_t(adate_ts);
1668 /* align the record */
1669 SMB_ASSERT(align >= 1);
1671 off = (int)PTR_DIFF(pdata, base_data);
1672 pad = (off + (align-1)) & ~(align-1);
1675 if (pad && pad > space_remaining) {
1676 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1677 "for padding (wanted %u, had %d)\n",
1680 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1684 /* initialize padding to 0 */
1686 memset(pdata, 0, pad);
1688 space_remaining -= pad;
1690 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1700 switch (info_level) {
1701 case SMB_FIND_INFO_STANDARD:
1702 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1703 if(requires_resume_key) {
1707 srv_put_dos_date2(p,0,create_date);
1708 srv_put_dos_date2(p,4,adate);
1709 srv_put_dos_date2(p,8,mdate);
1710 SIVAL(p,12,(uint32)file_size);
1711 SIVAL(p,16,(uint32)allocation_size);
1715 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1716 p += ucs2_align(base_data, p, 0);
1718 status = srvstr_push(base_data, flags2, p,
1719 fname, PTR_DIFF(end_data, p),
1720 STR_TERMINATE, &len);
1721 if (!NT_STATUS_IS_OK(status)) {
1724 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1726 SCVAL(nameptr, -1, len - 2);
1728 SCVAL(nameptr, -1, 0);
1732 SCVAL(nameptr, -1, len - 1);
1734 SCVAL(nameptr, -1, 0);
1740 case SMB_FIND_EA_SIZE:
1741 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1742 if (requires_resume_key) {
1746 srv_put_dos_date2(p,0,create_date);
1747 srv_put_dos_date2(p,4,adate);
1748 srv_put_dos_date2(p,8,mdate);
1749 SIVAL(p,12,(uint32)file_size);
1750 SIVAL(p,16,(uint32)allocation_size);
1753 unsigned int ea_size = estimate_ea_size(conn, NULL,
1755 SIVAL(p,22,ea_size); /* Extended attributes */
1759 status = srvstr_push(base_data, flags2,
1760 p, fname, PTR_DIFF(end_data, p),
1761 STR_TERMINATE | STR_NOALIGN, &len);
1762 if (!NT_STATUS_IS_OK(status)) {
1765 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1778 SCVAL(nameptr,0,len);
1780 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1783 case SMB_FIND_EA_LIST:
1785 struct ea_list *file_list = NULL;
1788 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1790 return NT_STATUS_INVALID_PARAMETER;
1792 if (requires_resume_key) {
1796 srv_put_dos_date2(p,0,create_date);
1797 srv_put_dos_date2(p,4,adate);
1798 srv_put_dos_date2(p,8,mdate);
1799 SIVAL(p,12,(uint32)file_size);
1800 SIVAL(p,16,(uint32)allocation_size);
1802 p += 22; /* p now points to the EA area. */
1804 status = get_ea_list_from_file(ctx, conn, NULL,
1806 &ea_len, &file_list);
1807 if (!NT_STATUS_IS_OK(status)) {
1810 name_list = ea_list_union(name_list, file_list, &ea_len);
1812 /* We need to determine if this entry will fit in the space available. */
1813 /* Max string size is 255 bytes. */
1814 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1815 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1816 "(wanted %u, had %d)\n",
1817 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1819 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1822 /* Push the ea_data followed by the name. */
1823 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1825 status = srvstr_push(base_data, flags2,
1826 p + 1, fname, PTR_DIFF(end_data, p+1),
1827 STR_TERMINATE | STR_NOALIGN, &len);
1828 if (!NT_STATUS_IS_OK(status)) {
1831 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1844 SCVAL(nameptr,0,len);
1846 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1850 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1851 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1852 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1854 SIVAL(p,0,reskey); p += 4;
1855 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1856 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1857 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1858 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1859 SOFF_T(p,0,file_size); p += 8;
1860 SOFF_T(p,0,allocation_size); p += 8;
1861 SIVAL(p,0,mode); p += 4;
1862 q = p; p += 4; /* q is placeholder for name length. */
1863 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1864 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1866 unsigned int ea_size = estimate_ea_size(conn, NULL,
1868 SIVAL(p,0,ea_size); /* Extended attributes */
1871 /* Clear the short name buffer. This is
1872 * IMPORTANT as not doing so will trigger
1873 * a Win2k client bug. JRA.
1875 if (!was_8_3 && check_mangled_names) {
1876 char mangled_name[13]; /* mangled 8.3 name. */
1877 if (!name_to_8_3(fname,mangled_name,True,
1879 /* Error - mangle failed ! */
1880 memset(mangled_name,'\0',12);
1882 mangled_name[12] = 0;
1883 status = srvstr_push(base_data, flags2,
1884 p+2, mangled_name, 24,
1885 STR_UPPER|STR_UNICODE, &len);
1886 if (!NT_STATUS_IS_OK(status)) {
1890 memset(p + 2 + len,'\0',24 - len);
1897 status = srvstr_push(base_data, flags2, p,
1898 fname, PTR_DIFF(end_data, p),
1899 STR_TERMINATE_ASCII, &len);
1900 if (!NT_STATUS_IS_OK(status)) {
1906 len = PTR_DIFF(p, pdata);
1907 pad = (len + (align-1)) & ~(align-1);
1909 * offset to the next entry, the caller
1910 * will overwrite it for the last entry
1911 * that's why we always include the padding
1915 * set padding to zero
1918 memset(p, 0, pad - len);
1925 case SMB_FIND_FILE_DIRECTORY_INFO:
1926 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1928 SIVAL(p,0,reskey); p += 4;
1929 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1930 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1931 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1932 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1933 SOFF_T(p,0,file_size); p += 8;
1934 SOFF_T(p,0,allocation_size); p += 8;
1935 SIVAL(p,0,mode); p += 4;
1936 status = srvstr_push(base_data, flags2,
1937 p + 4, fname, PTR_DIFF(end_data, p+4),
1938 STR_TERMINATE_ASCII, &len);
1939 if (!NT_STATUS_IS_OK(status)) {
1945 len = PTR_DIFF(p, pdata);
1946 pad = (len + (align-1)) & ~(align-1);
1948 * offset to the next entry, the caller
1949 * will overwrite it for the last entry
1950 * that's why we always include the padding
1954 * set padding to zero
1957 memset(p, 0, pad - len);
1964 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1965 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1967 SIVAL(p,0,reskey); p += 4;
1968 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1969 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1970 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1971 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1972 SOFF_T(p,0,file_size); p += 8;
1973 SOFF_T(p,0,allocation_size); p += 8;
1974 SIVAL(p,0,mode); p += 4;
1975 q = p; p += 4; /* q is placeholder for name length. */
1977 unsigned int ea_size = estimate_ea_size(conn, NULL,
1979 SIVAL(p,0,ea_size); /* Extended attributes */
1982 status = srvstr_push(base_data, flags2, p,
1983 fname, PTR_DIFF(end_data, p),
1984 STR_TERMINATE_ASCII, &len);
1985 if (!NT_STATUS_IS_OK(status)) {
1991 len = PTR_DIFF(p, pdata);
1992 pad = (len + (align-1)) & ~(align-1);
1994 * offset to the next entry, the caller
1995 * will overwrite it for the last entry
1996 * that's why we always include the padding
2000 * set padding to zero
2003 memset(p, 0, pad - len);
2010 case SMB_FIND_FILE_NAMES_INFO:
2011 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2013 SIVAL(p,0,reskey); p += 4;
2015 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2016 acl on a dir (tridge) */
2017 status = srvstr_push(base_data, flags2, p,
2018 fname, PTR_DIFF(end_data, p),
2019 STR_TERMINATE_ASCII, &len);
2020 if (!NT_STATUS_IS_OK(status)) {
2026 len = PTR_DIFF(p, pdata);
2027 pad = (len + (align-1)) & ~(align-1);
2029 * offset to the next entry, the caller
2030 * will overwrite it for the last entry
2031 * that's why we always include the padding
2035 * set padding to zero
2038 memset(p, 0, pad - len);
2045 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2046 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2048 SIVAL(p,0,reskey); p += 4;
2049 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2050 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2051 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2052 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2053 SOFF_T(p,0,file_size); p += 8;
2054 SOFF_T(p,0,allocation_size); p += 8;
2055 SIVAL(p,0,mode); p += 4;
2056 q = p; p += 4; /* q is placeholder for name length. */
2057 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2058 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2060 unsigned int ea_size = estimate_ea_size(conn, NULL,
2062 SIVAL(p,0,ea_size); /* Extended attributes */
2065 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2066 SBVAL(p,0,file_index); p += 8;
2067 status = srvstr_push(base_data, flags2, p,
2068 fname, PTR_DIFF(end_data, p),
2069 STR_TERMINATE_ASCII, &len);
2070 if (!NT_STATUS_IS_OK(status)) {
2076 len = PTR_DIFF(p, pdata);
2077 pad = (len + (align-1)) & ~(align-1);
2079 * offset to the next entry, the caller
2080 * will overwrite it for the last entry
2081 * that's why we always include the padding
2085 * set padding to zero
2088 memset(p, 0, pad - len);
2095 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2096 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2097 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2099 SIVAL(p,0,reskey); p += 4;
2100 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2101 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2102 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2103 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2104 SOFF_T(p,0,file_size); p += 8;
2105 SOFF_T(p,0,allocation_size); p += 8;
2106 SIVAL(p,0,mode); p += 4;
2107 q = p; p += 4; /* q is placeholder for name length */
2108 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2109 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2110 } else if (readdir_attr_data &&
2111 readdir_attr_data->type == RDATTR_AAPL) {
2113 * OS X specific SMB2 extension negotiated via
2114 * AAPL create context: return max_access in
2117 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2119 unsigned int ea_size = estimate_ea_size(conn, NULL,
2121 SIVAL(p,0,ea_size); /* Extended attributes */
2125 if (readdir_attr_data &&
2126 readdir_attr_data->type == RDATTR_AAPL) {
2128 * OS X specific SMB2 extension negotiated via
2129 * AAPL create context: return resource fork
2130 * length and compressed FinderInfo in
2133 * According to documentation short_name_len
2134 * should be 0, but on the wire behaviour
2135 * shows its set to 24 by clients.
2139 /* Resourefork length */
2140 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2142 /* Compressed FinderInfo */
2143 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2144 } else if (!was_8_3 && check_mangled_names) {
2145 char mangled_name[13]; /* mangled 8.3 name. */
2146 if (!name_to_8_3(fname,mangled_name,True,
2148 /* Error - mangle failed ! */
2149 memset(mangled_name,'\0',12);
2151 mangled_name[12] = 0;
2152 status = srvstr_push(base_data, flags2,
2153 p+2, mangled_name, 24,
2154 STR_UPPER|STR_UNICODE, &len);
2155 if (!NT_STATUS_IS_OK(status)) {
2160 memset(p + 2 + len,'\0',24 - len);
2164 /* Clear the short name buffer. This is
2165 * IMPORTANT as not doing so will trigger
2166 * a Win2k client bug. JRA.
2173 if (readdir_attr_data &&
2174 readdir_attr_data->type == RDATTR_AAPL) {
2176 * OS X specific SMB2 extension negotiated via
2177 * AAPL create context: return UNIX mode in
2180 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2181 SSVAL(p, 0, aapl_mode);
2187 SBVAL(p,0,file_index); p += 8;
2188 status = srvstr_push(base_data, flags2, p,
2189 fname, PTR_DIFF(end_data, p),
2190 STR_TERMINATE_ASCII, &len);
2191 if (!NT_STATUS_IS_OK(status)) {
2197 len = PTR_DIFF(p, pdata);
2198 pad = (len + (align-1)) & ~(align-1);
2200 * offset to the next entry, the caller
2201 * will overwrite it for the last entry
2202 * that's why we always include the padding
2206 * set padding to zero
2209 memset(p, 0, pad - len);
2216 /* CIFS UNIX Extension. */
2218 case SMB_FIND_FILE_UNIX:
2219 case SMB_FIND_FILE_UNIX_INFO2:
2221 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2223 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2225 if (info_level == SMB_FIND_FILE_UNIX) {
2226 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2227 p = store_file_unix_basic(conn, p,
2228 NULL, &smb_fname->st);
2229 status = srvstr_push(base_data, flags2, p,
2230 fname, PTR_DIFF(end_data, p),
2231 STR_TERMINATE, &len);
2232 if (!NT_STATUS_IS_OK(status)) {
2236 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2237 p = store_file_unix_basic_info2(conn, p,
2238 NULL, &smb_fname->st);
2241 status = srvstr_push(base_data, flags2, p, fname,
2242 PTR_DIFF(end_data, p), 0, &len);
2243 if (!NT_STATUS_IS_OK(status)) {
2246 SIVAL(nameptr, 0, len);
2251 len = PTR_DIFF(p, pdata);
2252 pad = (len + (align-1)) & ~(align-1);
2254 * offset to the next entry, the caller
2255 * will overwrite it for the last entry
2256 * that's why we always include the padding
2260 * set padding to zero
2263 memset(p, 0, pad - len);
2268 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2273 return NT_STATUS_INVALID_LEVEL;
2276 if (PTR_DIFF(p,pdata) > space_remaining) {
2277 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2278 "(wanted %u, had %d)\n",
2279 (unsigned int)PTR_DIFF(p,pdata),
2281 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2284 /* Setup the last entry pointer, as an offset from base_data */
2285 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2286 /* Advance the data pointer to the next slot */
2289 return NT_STATUS_OK;
2292 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2293 connection_struct *conn,
2294 struct dptr_struct *dirptr,
2296 const char *path_mask,
2299 int requires_resume_key,
2307 int space_remaining,
2308 bool *got_exact_match,
2309 int *_last_entry_off,
2310 struct ea_list *name_list)
2313 const char *mask = NULL;
2314 long prev_dirpos = 0;
2317 struct smb_filename *smb_fname = NULL;
2318 struct smbd_dirptr_lanman2_state state;
2320 uint64_t last_entry_off = 0;
2325 state.info_level = info_level;
2326 state.check_mangled_names = lp_mangled_names(conn->params);
2327 state.has_wild = dptr_has_wild(dirptr);
2328 state.got_exact_match = false;
2330 *got_exact_match = false;
2332 p = strrchr_m(path_mask,'/');
2343 ok = smbd_dirptr_get_entry(ctx,
2349 smbd_dirptr_lanman2_match_fn,
2350 smbd_dirptr_lanman2_mode_fn,
2357 return NT_STATUS_END_OF_FILE;
2360 *got_exact_match = state.got_exact_match;
2362 status = smbd_marshall_dir_entry(ctx,
2367 state.check_mangled_names,
2368 requires_resume_key,
2380 TALLOC_FREE(smb_fname);
2381 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2382 dptr_SeekDir(dirptr, prev_dirpos);
2385 if (!NT_STATUS_IS_OK(status)) {
2389 *_last_entry_off = last_entry_off;
2390 return NT_STATUS_OK;
2393 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2394 connection_struct *conn,
2395 struct dptr_struct *dirptr,
2397 const char *path_mask,
2400 bool requires_resume_key,
2406 int space_remaining,
2407 bool *got_exact_match,
2408 int *last_entry_off,
2409 struct ea_list *name_list)
2412 const bool do_pad = true;
2414 if (info_level >= 1 && info_level <= 3) {
2415 /* No alignment on earlier info levels. */
2419 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2420 path_mask, dirtype, info_level,
2421 requires_resume_key, dont_descend, ask_sharemode,
2423 ppdata, base_data, end_data,
2426 last_entry_off, name_list);
2429 /****************************************************************************
2430 Reply to a TRANS2_FINDFIRST.
2431 ****************************************************************************/
2433 static void call_trans2findfirst(connection_struct *conn,
2434 struct smb_request *req,
2435 char **pparams, int total_params,
2436 char **ppdata, int total_data,
2437 unsigned int max_data_bytes)
2439 /* We must be careful here that we don't return more than the
2440 allowed number of data bytes. If this means returning fewer than
2441 maxentries then so be it. We assume that the redirector has
2442 enough room for the fixed number of parameter bytes it has
2444 struct smb_filename *smb_dname = NULL;
2445 char *params = *pparams;
2446 char *pdata = *ppdata;
2450 uint16 findfirst_flags;
2451 bool close_after_first;
2453 bool requires_resume_key;
2455 char *directory = NULL;
2458 int last_entry_off=0;
2462 bool finished = False;
2463 bool dont_descend = False;
2464 bool out_of_space = False;
2465 int space_remaining;
2466 bool mask_contains_wcard = False;
2467 struct ea_list *ea_list = NULL;
2468 NTSTATUS ntstatus = NT_STATUS_OK;
2469 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2470 TALLOC_CTX *ctx = talloc_tos();
2471 struct dptr_struct *dirptr = NULL;
2472 struct smbd_server_connection *sconn = req->sconn;
2473 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2474 bool backup_priv = false;
2476 if (total_params < 13) {
2477 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2481 dirtype = SVAL(params,0);
2482 maxentries = SVAL(params,2);
2483 findfirst_flags = SVAL(params,4);
2484 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2485 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2486 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2487 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2488 security_token_has_privilege(get_current_nttok(conn),
2491 info_level = SVAL(params,6);
2493 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2494 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2495 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2497 info_level, max_data_bytes));
2500 /* W2K3 seems to treat zero as 1. */
2504 switch (info_level) {
2505 case SMB_FIND_INFO_STANDARD:
2506 case SMB_FIND_EA_SIZE:
2507 case SMB_FIND_EA_LIST:
2508 case SMB_FIND_FILE_DIRECTORY_INFO:
2509 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2510 case SMB_FIND_FILE_NAMES_INFO:
2511 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2512 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2513 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2515 case SMB_FIND_FILE_UNIX:
2516 case SMB_FIND_FILE_UNIX_INFO2:
2517 /* Always use filesystem for UNIX mtime query. */
2518 ask_sharemode = false;
2519 if (!lp_unix_extensions()) {
2520 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2523 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2526 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2530 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2531 params+12, total_params - 12,
2532 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2533 if (!NT_STATUS_IS_OK(ntstatus)) {
2534 reply_nterror(req, ntstatus);
2540 ntstatus = filename_convert_with_privilege(ctx,
2545 &mask_contains_wcard,
2548 ntstatus = filename_convert(ctx, conn,
2549 req->flags2 & FLAGS2_DFS_PATHNAMES,
2552 &mask_contains_wcard,
2556 if (!NT_STATUS_IS_OK(ntstatus)) {
2557 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2558 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2559 ERRSRV, ERRbadpath);
2562 reply_nterror(req, ntstatus);
2566 mask = smb_dname->original_lcomp;
2568 directory = smb_dname->base_name;
2570 p = strrchr_m(directory,'/');
2572 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2573 if((directory[0] == '.') && (directory[1] == '\0')) {
2574 mask = talloc_strdup(ctx,"*");
2576 reply_nterror(req, NT_STATUS_NO_MEMORY);
2579 mask_contains_wcard = True;
2585 if (p == NULL || p == directory) {
2586 /* Ensure we don't have a directory name of "". */
2587 directory = talloc_strdup(talloc_tos(), ".");
2589 reply_nterror(req, NT_STATUS_NO_MEMORY);
2594 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2596 if (info_level == SMB_FIND_EA_LIST) {
2599 if (total_data < 4) {
2600 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2604 ea_size = IVAL(pdata,0);
2605 if (ea_size != total_data) {
2606 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2607 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2612 if (!lp_ea_support(SNUM(conn))) {
2613 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2617 /* Pull out the list of names. */
2618 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2620 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2625 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2626 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2630 *ppdata = (char *)SMB_REALLOC(
2631 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2632 if(*ppdata == NULL ) {
2633 reply_nterror(req, NT_STATUS_NO_MEMORY);
2637 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2639 /* Realloc the params space */
2640 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2641 if (*pparams == NULL) {
2642 reply_nterror(req, NT_STATUS_NO_MEMORY);
2647 /* Save the wildcard match and attribs we are using on this directory -
2648 needed as lanman2 assumes these are being saved between calls */
2650 ntstatus = dptr_create(conn,
2658 mask_contains_wcard,
2662 if (!NT_STATUS_IS_OK(ntstatus)) {
2663 reply_nterror(req, ntstatus);
2668 /* Remember this in case we have
2669 to do a findnext. */
2670 dptr_set_priv(dirptr);
2673 dptr_num = dptr_dnum(dirptr);
2674 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2676 /* Initialize per TRANS2_FIND_FIRST operation data */
2677 dptr_init_search_op(dirptr);
2679 /* We don't need to check for VOL here as this is returned by
2680 a different TRANS2 call. */
2682 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2683 directory,lp_dont_descend(ctx, SNUM(conn))));
2684 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2685 dont_descend = True;
2688 space_remaining = max_data_bytes;
2689 out_of_space = False;
2691 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2692 bool got_exact_match = False;
2694 /* this is a heuristic to avoid seeking the dirptr except when
2695 absolutely necessary. It allows for a filename of about 40 chars */
2696 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2697 out_of_space = True;
2700 ntstatus = get_lanman2_dir_entry(ctx,
2704 mask,dirtype,info_level,
2705 requires_resume_key,dont_descend,
2710 &last_entry_off, ea_list);
2711 if (NT_STATUS_EQUAL(ntstatus,
2712 NT_STATUS_ILLEGAL_CHARACTER)) {
2714 * Bad character conversion on name. Ignore this
2719 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2720 out_of_space = true;
2722 finished = !NT_STATUS_IS_OK(ntstatus);
2726 if (!finished && !out_of_space)
2730 * As an optimisation if we know we aren't looking
2731 * for a wildcard name (ie. the name matches the wildcard exactly)
2732 * then we can finish on any (first) match.
2733 * This speeds up large directory searches. JRA.
2739 /* Ensure space_remaining never goes -ve. */
2740 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2741 space_remaining = 0;
2742 out_of_space = true;
2744 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2748 /* Check if we can close the dirptr */
2749 if(close_after_first || (finished && close_if_end)) {
2750 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2751 dptr_close(sconn, &dptr_num);
2755 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2756 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2757 * the protocol level is less than NT1. Tested with smbclient. JRA.
2758 * This should fix the OS/2 client bug #2335.
2761 if(numentries == 0) {
2762 dptr_close(sconn, &dptr_num);
2763 if (get_Protocol() < PROTOCOL_NT1) {
2764 reply_force_doserror(req, ERRDOS, ERRnofiles);
2767 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2768 ERRDOS, ERRbadfile);
2773 /* At this point pdata points to numentries directory entries. */
2775 /* Set up the return parameter block */
2776 SSVAL(params,0,dptr_num);
2777 SSVAL(params,2,numentries);
2778 SSVAL(params,4,finished);
2779 SSVAL(params,6,0); /* Never an EA error */
2780 SSVAL(params,8,last_entry_off);
2782 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2785 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2786 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2788 reply_nterror(req, NT_STATUS_NO_MEMORY);
2792 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2793 smb_fn_name(req->cmd),
2794 mask, directory, dirtype, numentries ) );
2797 * Force a name mangle here to ensure that the
2798 * mask as an 8.3 name is top of the mangled cache.
2799 * The reasons for this are subtle. Don't remove
2800 * this code unless you know what you are doing
2801 * (see PR#13758). JRA.
2804 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2805 char mangled_name[13];
2806 name_to_8_3(mask, mangled_name, True, conn->params);
2814 TALLOC_FREE(smb_dname);
2818 /****************************************************************************
2819 Reply to a TRANS2_FINDNEXT.
2820 ****************************************************************************/
2822 static void call_trans2findnext(connection_struct *conn,
2823 struct smb_request *req,
2824 char **pparams, int total_params,
2825 char **ppdata, int total_data,
2826 unsigned int max_data_bytes)
2828 /* We must be careful here that we don't return more than the
2829 allowed number of data bytes. If this means returning fewer than
2830 maxentries then so be it. We assume that the redirector has
2831 enough room for the fixed number of parameter bytes it has
2833 char *params = *pparams;
2834 char *pdata = *ppdata;
2840 uint16 findnext_flags;
2841 bool close_after_request;
2843 bool requires_resume_key;
2845 bool mask_contains_wcard = False;
2846 char *resume_name = NULL;
2847 const char *mask = NULL;
2848 const char *directory = NULL;
2852 int i, last_entry_off=0;
2853 bool finished = False;
2854 bool dont_descend = False;
2855 bool out_of_space = False;
2856 int space_remaining;
2857 struct ea_list *ea_list = NULL;
2858 NTSTATUS ntstatus = NT_STATUS_OK;
2859 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2860 TALLOC_CTX *ctx = talloc_tos();
2861 struct dptr_struct *dirptr;
2862 struct smbd_server_connection *sconn = req->sconn;
2863 bool backup_priv = false;
2865 if (total_params < 13) {
2866 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2870 dptr_num = SVAL(params,0);
2871 maxentries = SVAL(params,2);
2872 info_level = SVAL(params,4);
2873 resume_key = IVAL(params,6);
2874 findnext_flags = SVAL(params,10);
2875 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2876 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2877 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2878 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2880 if (!continue_bit) {
2881 /* We only need resume_name if continue_bit is zero. */
2882 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2884 total_params - 12, STR_TERMINATE, &ntstatus,
2885 &mask_contains_wcard);
2886 if (!NT_STATUS_IS_OK(ntstatus)) {
2887 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2888 complain (it thinks we're asking for the directory above the shared
2889 path or an invalid name). Catch this as the resume name is only compared, never used in
2890 a file access. JRA. */
2891 srvstr_pull_talloc(ctx, params, req->flags2,
2892 &resume_name, params+12,
2896 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2897 reply_nterror(req, ntstatus);
2903 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2904 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2905 resume_key = %d resume name = %s continue=%d level = %d\n",
2906 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2907 requires_resume_key, resume_key,
2908 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2911 /* W2K3 seems to treat zero as 1. */
2915 switch (info_level) {
2916 case SMB_FIND_INFO_STANDARD:
2917 case SMB_FIND_EA_SIZE:
2918 case SMB_FIND_EA_LIST:
2919 case SMB_FIND_FILE_DIRECTORY_INFO:
2920 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2921 case SMB_FIND_FILE_NAMES_INFO:
2922 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2923 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2924 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2926 case SMB_FIND_FILE_UNIX:
2927 case SMB_FIND_FILE_UNIX_INFO2:
2928 /* Always use filesystem for UNIX mtime query. */
2929 ask_sharemode = false;
2930 if (!lp_unix_extensions()) {
2931 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2936 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2940 if (info_level == SMB_FIND_EA_LIST) {
2943 if (total_data < 4) {
2944 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2948 ea_size = IVAL(pdata,0);
2949 if (ea_size != total_data) {
2950 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2951 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2952 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2956 if (!lp_ea_support(SNUM(conn))) {
2957 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2961 /* Pull out the list of names. */
2962 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2964 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2969 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2970 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2974 *ppdata = (char *)SMB_REALLOC(
2975 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2976 if(*ppdata == NULL) {
2977 reply_nterror(req, NT_STATUS_NO_MEMORY);
2982 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2984 /* Realloc the params space */
2985 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2986 if(*pparams == NULL ) {
2987 reply_nterror(req, NT_STATUS_NO_MEMORY);
2993 /* Check that the dptr is valid */
2994 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2995 reply_nterror(req, STATUS_NO_MORE_FILES);
2999 directory = dptr_path(sconn, dptr_num);
3001 /* Get the wildcard mask from the dptr */
3002 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3003 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3004 reply_nterror(req, STATUS_NO_MORE_FILES);
3008 /* Get the attr mask from the dptr */
3009 dirtype = dptr_attr(sconn, dptr_num);
3011 backup_priv = dptr_get_priv(dirptr);
3013 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3014 "backup_priv = %d\n",
3015 dptr_num, mask, dirtype,
3017 dptr_TellDir(dirptr),
3020 /* Initialize per TRANS2_FIND_NEXT operation data */
3021 dptr_init_search_op(dirptr);
3023 /* We don't need to check for VOL here as this is returned by
3024 a different TRANS2 call. */
3026 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3027 directory,lp_dont_descend(ctx, SNUM(conn))));
3028 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3029 dont_descend = True;
3032 space_remaining = max_data_bytes;
3033 out_of_space = False;
3040 * Seek to the correct position. We no longer use the resume key but
3041 * depend on the last file name instead.
3044 if(!continue_bit && resume_name && *resume_name) {
3047 long current_pos = 0;
3049 * Remember, name_to_8_3 is called by
3050 * get_lanman2_dir_entry(), so the resume name
3051 * could be mangled. Ensure we check the unmangled name.
3054 if (mangle_is_mangled(resume_name, conn->params)) {
3055 char *new_resume_name = NULL;
3056 mangle_lookup_name_from_8_3(ctx,
3060 if (new_resume_name) {
3061 resume_name = new_resume_name;
3066 * Fix for NT redirector problem triggered by resume key indexes
3067 * changing between directory scans. We now return a resume key of 0
3068 * and instead look for the filename to continue from (also given
3069 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3070 * findfirst/findnext (as is usual) then the directory pointer
3071 * should already be at the correct place.
3074 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3075 } /* end if resume_name && !continue_bit */
3077 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3078 bool got_exact_match = False;
3080 /* this is a heuristic to avoid seeking the dirptr except when
3081 absolutely necessary. It allows for a filename of about 40 chars */
3082 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3083 out_of_space = True;
3086 ntstatus = get_lanman2_dir_entry(ctx,
3090 mask,dirtype,info_level,
3091 requires_resume_key,dont_descend,
3096 &last_entry_off, ea_list);
3097 if (NT_STATUS_EQUAL(ntstatus,
3098 NT_STATUS_ILLEGAL_CHARACTER)) {
3100 * Bad character conversion on name. Ignore this
3105 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3106 out_of_space = true;
3108 finished = !NT_STATUS_IS_OK(ntstatus);
3112 if (!finished && !out_of_space)
3116 * As an optimisation if we know we aren't looking
3117 * for a wildcard name (ie. the name matches the wildcard exactly)
3118 * then we can finish on any (first) match.
3119 * This speeds up large directory searches. JRA.
3125 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3128 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3129 smb_fn_name(req->cmd),
3130 mask, directory, dirtype, numentries ) );
3132 /* Check if we can close the dirptr */
3133 if(close_after_request || (finished && close_if_end)) {
3134 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3135 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3142 /* Set up the return parameter block */
3143 SSVAL(params,0,numentries);
3144 SSVAL(params,2,finished);
3145 SSVAL(params,4,0); /* Never an EA error */
3146 SSVAL(params,6,last_entry_off);
3148 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3154 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3156 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3160 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3162 SMB_ASSERT(extended_info != NULL);
3164 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3165 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3166 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3167 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3168 #ifdef SAMBA_VERSION_REVISION
3169 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3171 extended_info->samba_subversion = 0;
3172 #ifdef SAMBA_VERSION_RC_RELEASE
3173 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3175 #ifdef SAMBA_VERSION_PRE_RELEASE
3176 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3179 #ifdef SAMBA_VERSION_VENDOR_PATCH
3180 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3182 extended_info->samba_gitcommitdate = 0;
3183 #ifdef SAMBA_VERSION_COMMIT_TIME
3184 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3187 memset(extended_info->samba_version_string, 0,
3188 sizeof(extended_info->samba_version_string));
3190 snprintf (extended_info->samba_version_string,
3191 sizeof(extended_info->samba_version_string),
3192 "%s", samba_version_string());
3195 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3196 connection_struct *conn,
3197 TALLOC_CTX *mem_ctx,
3198 uint16_t info_level,
3200 unsigned int max_data_bytes,
3201 size_t *fixed_portion,
3202 struct smb_filename *fname,
3206 char *pdata, *end_data;
3209 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3210 int snum = SNUM(conn);
3211 const char *fstype = lp_fstype(SNUM(conn));
3212 const char *filename = NULL;
3213 uint32 additional_flags = 0;
3214 struct smb_filename smb_fname;
3216 NTSTATUS status = NT_STATUS_OK;
3219 if (fname == NULL || fname->base_name == NULL) {
3222 filename = fname->base_name;
3226 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3227 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3228 "info level (0x%x) on IPC$.\n",
3229 (unsigned int)info_level));
3230 return NT_STATUS_ACCESS_DENIED;
3234 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3236 ZERO_STRUCT(smb_fname);
3237 smb_fname.base_name = discard_const_p(char, filename);
3239 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3240 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3241 return map_nt_error_from_unix(errno);
3246 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3247 return NT_STATUS_INVALID_PARAMETER;
3250 *ppdata = (char *)SMB_REALLOC(
3251 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3252 if (*ppdata == NULL) {
3253 return NT_STATUS_NO_MEMORY;
3257 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3258 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3262 switch (info_level) {
3263 case SMB_INFO_ALLOCATION:
3265 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3267 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3269 if (df_ret == (uint64_t)-1) {
3270 return map_nt_error_from_unix(errno);
3273 block_size = lp_block_size(snum);
3274 if (bsize < block_size) {
3275 uint64_t factor = block_size/bsize;
3280 if (bsize > block_size) {
3281 uint64_t factor = bsize/block_size;
3286 bytes_per_sector = 512;
3287 sectors_per_unit = bsize/bytes_per_sector;
3289 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3290 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3291 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3293 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3294 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3295 SIVAL(pdata,l1_cUnit,dsize);
3296 SIVAL(pdata,l1_cUnitAvail,dfree);
3297 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3301 case SMB_INFO_VOLUME:
3302 /* Return volume name */
3304 * Add volume serial number - hash of a combination of
3305 * the called hostname and the service name.
3307 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3309 * Win2k3 and previous mess this up by sending a name length
3310 * one byte short. I believe only older clients (OS/2 Win9x) use
3311 * this call so try fixing this by adding a terminating null to
3312 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3314 status = srvstr_push(
3316 pdata+l2_vol_szVolLabel, vname,
3317 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3318 STR_NOALIGN|STR_TERMINATE, &len);
3319 if (!NT_STATUS_IS_OK(status)) {
3322 SCVAL(pdata,l2_vol_cch,len);
3323 data_len = l2_vol_szVolLabel + len;
3324 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3325 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3326 (unsigned)len, vname));
3329 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3330 case SMB_FS_ATTRIBUTE_INFORMATION:
3332 additional_flags = 0;
3333 #if defined(HAVE_SYS_QUOTAS)
3334 additional_flags |= FILE_VOLUME_QUOTAS;
3337 if(lp_nt_acl_support(SNUM(conn))) {
3338 additional_flags |= FILE_PERSISTENT_ACLS;
3341 /* Capabilities are filled in at connection time through STATVFS call */
3342 additional_flags |= conn->fs_capabilities;
3343 additional_flags |= lp_parm_int(conn->params->service,
3344 "share", "fake_fscaps",
3347 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3348 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3349 additional_flags); /* FS ATTRIBUTES */
3351 SIVAL(pdata,4,255); /* Max filename component length */
3352 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3353 and will think we can't do long filenames */
3354 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3355 PTR_DIFF(end_data, pdata+12),
3357 if (!NT_STATUS_IS_OK(status)) {
3361 data_len = 12 + len;
3362 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3363 /* the client only requested a portion of the
3365 data_len = max_data_bytes;
3366 status = STATUS_BUFFER_OVERFLOW;
3368 *fixed_portion = 16;
3371 case SMB_QUERY_FS_LABEL_INFO:
3372 case SMB_FS_LABEL_INFORMATION:
3373 status = srvstr_push(pdata, flags2, pdata+4, vname,
3374 PTR_DIFF(end_data, pdata+4), 0, &len);
3375 if (!NT_STATUS_IS_OK(status)) {
3382 case SMB_QUERY_FS_VOLUME_INFO:
3383 case SMB_FS_VOLUME_INFORMATION:
3386 * Add volume serial number - hash of a combination of
3387 * the called hostname and the service name.
3389 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3390 (str_checksum(get_local_machine_name())<<16));
3392 /* Max label len is 32 characters. */
3393 status = srvstr_push(pdata, flags2, pdata+18, vname,
3394 PTR_DIFF(end_data, pdata+18),
3396 if (!NT_STATUS_IS_OK(status)) {
3399 SIVAL(pdata,12,len);
3402 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3403 (int)strlen(vname),vname,
3404 lp_servicename(talloc_tos(), snum)));
3405 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3406 /* the client only requested a portion of the
3408 data_len = max_data_bytes;
3409 status = STATUS_BUFFER_OVERFLOW;
3411 *fixed_portion = 24;
3414 case SMB_QUERY_FS_SIZE_INFO:
3415 case SMB_FS_SIZE_INFORMATION:
3417 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3419 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3421 if (df_ret == (uint64_t)-1) {
3422 return map_nt_error_from_unix(errno);
3424 block_size = lp_block_size(snum);
3425 if (bsize < block_size) {
3426 uint64_t factor = block_size/bsize;
3431 if (bsize > block_size) {
3432 uint64_t factor = bsize/block_size;
3437 bytes_per_sector = 512;
3438 sectors_per_unit = bsize/bytes_per_sector;
3439 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3440 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3441 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3442 SBIG_UINT(pdata,0,dsize);
3443 SBIG_UINT(pdata,8,dfree);
3444 SIVAL(pdata,16,sectors_per_unit);
3445 SIVAL(pdata,20,bytes_per_sector);
3446 *fixed_portion = 24;
3450 case SMB_FS_FULL_SIZE_INFORMATION:
3452 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3454 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3456 if (df_ret == (uint64_t)-1) {
3457 return map_nt_error_from_unix(errno);
3459 block_size = lp_block_size(snum);
3460 if (bsize < block_size) {
3461 uint64_t factor = block_size/bsize;
3466 if (bsize > block_size) {
3467 uint64_t factor = bsize/block_size;
3472 bytes_per_sector = 512;
3473 sectors_per_unit = bsize/bytes_per_sector;
3474 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3475 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3476 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3477 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3478 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3479 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3480 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3481 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3482 *fixed_portion = 32;
3486 case SMB_QUERY_FS_DEVICE_INFO:
3487 case SMB_FS_DEVICE_INFORMATION:
3489 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3491 if (!CAN_WRITE(conn)) {
3492 characteristics |= FILE_READ_ONLY_DEVICE;
3495 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3496 SIVAL(pdata,4,characteristics);
3501 #ifdef HAVE_SYS_QUOTAS
3502 case SMB_FS_QUOTA_INFORMATION:
3504 * what we have to send --metze:
3506 * Unknown1: 24 NULL bytes
3507 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3508 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3509 * Quota Flags: 2 byte :
3510 * Unknown3: 6 NULL bytes
3514 * details for Quota Flags:
3516 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3517 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3518 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3519 * 0x0001 Enable Quotas: enable quota for this fs
3523 /* we need to fake up a fsp here,
3524 * because its not send in this call
3527 SMB_NTQUOTA_STRUCT quotas;
3530 ZERO_STRUCT(quotas);
3533 fsp.fnum = FNUM_FIELD_INVALID;
3536 if (get_current_uid(conn) != 0) {
3537 DEBUG(0,("get_user_quota: access_denied "
3538 "service [%s] user [%s]\n",
3539 lp_servicename(talloc_tos(), SNUM(conn)),
3540 conn->session_info->unix_info->unix_name));
3541 return NT_STATUS_ACCESS_DENIED;
3544 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3545 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3546 return map_nt_error_from_unix(errno);
3551 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3552 lp_servicename(talloc_tos(), SNUM(conn))));
3554 /* Unknown1 24 NULL bytes*/
3555 SBIG_UINT(pdata,0,(uint64_t)0);
3556 SBIG_UINT(pdata,8,(uint64_t)0);
3557 SBIG_UINT(pdata,16,(uint64_t)0);
3559 /* Default Soft Quota 8 bytes */
3560 SBIG_UINT(pdata,24,quotas.softlim);
3562 /* Default Hard Quota 8 bytes */
3563 SBIG_UINT(pdata,32,quotas.hardlim);
3565 /* Quota flag 2 bytes */
3566 SSVAL(pdata,40,quotas.qflags);
3568 /* Unknown3 6 NULL bytes */
3574 #endif /* HAVE_SYS_QUOTAS */
3575 case SMB_FS_OBJECTID_INFORMATION:
3577 unsigned char objid[16];
3578 struct smb_extended_info extended_info;
3579 memcpy(pdata,create_volume_objectid(conn, objid),16);
3580 samba_extended_info_version (&extended_info);
3581 SIVAL(pdata,16,extended_info.samba_magic);
3582 SIVAL(pdata,20,extended_info.samba_version);
3583 SIVAL(pdata,24,extended_info.samba_subversion);
3584 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3585 memcpy(pdata+36,extended_info.samba_version_string,28);
3591 * Query the version and capabilities of the CIFS UNIX extensions
3595 case SMB_QUERY_CIFS_UNIX_INFO:
3597 bool large_write = lp_min_receive_file_size() &&
3598 !srv_is_signing_active(xconn);
3599 bool large_read = !srv_is_signing_active(xconn);
3600 int encrypt_caps = 0;
3602 if (!lp_unix_extensions()) {
3603 return NT_STATUS_INVALID_LEVEL;
3606 switch (conn->encrypt_level) {
3607 case SMB_SIGNING_OFF:
3610 case SMB_SIGNING_IF_REQUIRED:
3611 case SMB_SIGNING_DEFAULT:
3612 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3614 case SMB_SIGNING_REQUIRED:
3615 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3616 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3617 large_write = false;
3623 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3624 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3626 /* We have POSIX ACLs, pathname, encryption,
3627 * large read/write, and locking capability. */
3629 SBIG_UINT(pdata,4,((uint64_t)(
3630 CIFS_UNIX_POSIX_ACLS_CAP|
3631 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3632 CIFS_UNIX_FCNTL_LOCKS_CAP|
3633 CIFS_UNIX_EXTATTR_CAP|
3634 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3636 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3638 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3642 case SMB_QUERY_POSIX_FS_INFO:
3645 vfs_statvfs_struct svfs;
3647 if (!lp_unix_extensions()) {
3648 return NT_STATUS_INVALID_LEVEL;
3651 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3655 SIVAL(pdata,0,svfs.OptimalTransferSize);
3656 SIVAL(pdata,4,svfs.BlockSize);
3657 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3658 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3659 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3660 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3661 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3662 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3663 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3665 } else if (rc == EOPNOTSUPP) {
3666 return NT_STATUS_INVALID_LEVEL;
3667 #endif /* EOPNOTSUPP */
3669 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3670 return NT_STATUS_DOS(ERRSRV, ERRerror);
3675 case SMB_QUERY_POSIX_WHOAMI:
3681 if (!lp_unix_extensions()) {
3682 return NT_STATUS_INVALID_LEVEL;
3685 if (max_data_bytes < 40) {
3686 return NT_STATUS_BUFFER_TOO_SMALL;
3689 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3690 flags |= SMB_WHOAMI_GUEST;
3693 /* NOTE: 8 bytes for UID/GID, irrespective of native
3694 * platform size. This matches
3695 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3697 data_len = 4 /* flags */
3704 + 4 /* pad/reserved */
3705 + (conn->session_info->unix_token->ngroups * 8)
3707 + (conn->session_info->security_token->num_sids *
3711 SIVAL(pdata, 0, flags);
3712 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3714 (uint64_t)conn->session_info->unix_token->uid);
3715 SBIG_UINT(pdata, 16,
3716 (uint64_t)conn->session_info->unix_token->gid);
3719 if (data_len >= max_data_bytes) {
3720 /* Potential overflow, skip the GIDs and SIDs. */
3722 SIVAL(pdata, 24, 0); /* num_groups */
3723 SIVAL(pdata, 28, 0); /* num_sids */
3724 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3725 SIVAL(pdata, 36, 0); /* reserved */
3731 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3732 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3734 /* We walk the SID list twice, but this call is fairly
3735 * infrequent, and I don't expect that it's performance
3736 * sensitive -- jpeach
3738 for (i = 0, sid_bytes = 0;
3739 i < conn->session_info->security_token->num_sids; ++i) {
3740 sid_bytes += ndr_size_dom_sid(
3741 &conn->session_info->security_token->sids[i],
3745 /* SID list byte count */
3746 SIVAL(pdata, 32, sid_bytes);
3748 /* 4 bytes pad/reserved - must be zero */
3749 SIVAL(pdata, 36, 0);
3753 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3754 SBIG_UINT(pdata, data_len,
3755 (uint64_t)conn->session_info->unix_token->groups[i]);
3761 i < conn->session_info->security_token->num_sids; ++i) {
3762 int sid_len = ndr_size_dom_sid(
3763 &conn->session_info->security_token->sids[i],
3766 sid_linearize(pdata + data_len, sid_len,
3767 &conn->session_info->security_token->sids[i]);
3768 data_len += sid_len;
3774 case SMB_MAC_QUERY_FS_INFO:
3776 * Thursby MAC extension... ONLY on NTFS filesystems
3777 * once we do streams then we don't need this
3779 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3781 SIVAL(pdata,84,0x100); /* Don't support mac... */
3786 return NT_STATUS_INVALID_LEVEL;
3789 *ret_data_len = data_len;
3793 /****************************************************************************
3794 Reply to a TRANS2_QFSINFO (query filesystem info).
3795 ****************************************************************************/
3797 static void call_trans2qfsinfo(connection_struct *conn,
3798 struct smb_request *req,
3799 char **pparams, int total_params,
3800 char **ppdata, int total_data,
3801 unsigned int max_data_bytes)
3803 char *params = *pparams;
3804 uint16_t info_level;
3806 size_t fixed_portion;
3809 if (total_params < 2) {
3810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3814 info_level = SVAL(params,0);
3816 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3817 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3818 DEBUG(0,("call_trans2qfsinfo: encryption required "
3819 "and info level 0x%x sent.\n",
3820 (unsigned int)info_level));
3821 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3826 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3828 status = smbd_do_qfsinfo(req->xconn, conn, req,
3835 if (!NT_STATUS_IS_OK(status)) {
3836 reply_nterror(req, status);
3840 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3843 DEBUG( 4, ( "%s info_level = %d\n",
3844 smb_fn_name(req->cmd), info_level) );
3849 /****************************************************************************
3850 Reply to a TRANS2_SETFSINFO (set filesystem info).
3851 ****************************************************************************/
3853 static void call_trans2setfsinfo(connection_struct *conn,
3854 struct smb_request *req,
3855 char **pparams, int total_params,
3856 char **ppdata, int total_data,
3857 unsigned int max_data_bytes)
3859 struct smbXsrv_connection *xconn = req->xconn;
3860 char *pdata = *ppdata;
3861 char *params = *pparams;
3864 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3865 lp_servicename(talloc_tos(), SNUM(conn))));
3868 if (total_params < 4) {
3869 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3871 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3875 info_level = SVAL(params,2);
3878 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3879 info_level != SMB_SET_CIFS_UNIX_INFO) {
3880 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3881 "info level (0x%x) on IPC$.\n",
3882 (unsigned int)info_level));
3883 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3888 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3889 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3890 DEBUG(0,("call_trans2setfsinfo: encryption required "
3891 "and info level 0x%x sent.\n",
3892 (unsigned int)info_level));
3893 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3898 switch(info_level) {
3899 case SMB_SET_CIFS_UNIX_INFO:
3900 if (!lp_unix_extensions()) {
3901 DEBUG(2,("call_trans2setfsinfo: "
3902 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3903 "unix extensions off\n"));
3905 NT_STATUS_INVALID_LEVEL);
3909 /* There should be 12 bytes of capabilities set. */
3910 if (total_data < 12) {
3913 NT_STATUS_INVALID_PARAMETER);
3916 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
3917 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3918 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3919 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3920 /* Just print these values for now. */
3921 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3922 "major = %u, minor = %u cap_low = 0x%x, "
3924 (unsigned int)xconn->
3925 smb1.unix_info.client_major,
3926 (unsigned int)xconn->
3927 smb1.unix_info.client_minor,
3928 (unsigned int)xconn->
3929 smb1.unix_info.client_cap_low,
3930 (unsigned int)xconn->
3931 smb1.unix_info.client_cap_high));
3933 /* Here is where we must switch to posix pathname processing... */
3934 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3935 lp_set_posix_pathnames();
3936 mangle_change_to_posix();
3939 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3940 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3941 /* Client that knows how to do posix locks,
3942 * but not posix open/mkdir operations. Set a
3943 * default type for read/write checks. */
3945 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3950 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3953 size_t param_len = 0;
3954 size_t data_len = total_data;
3956 if (!lp_unix_extensions()) {
3959 NT_STATUS_INVALID_LEVEL);
3963 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3966 NT_STATUS_NOT_SUPPORTED);
3970 if (xconn->smb1.echo_handler.trusted_fde) {
3971 DEBUG( 2,("call_trans2setfsinfo: "
3972 "request transport encryption disabled"
3973 "with 'fork echo handler = yes'\n"));
3976 NT_STATUS_NOT_SUPPORTED);
3980 DEBUG( 4,("call_trans2setfsinfo: "
3981 "request transport encryption.\n"));
3983 status = srv_request_encryption_setup(conn,
3984 (unsigned char **)ppdata,
3986 (unsigned char **)pparams,
3989 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3990 !NT_STATUS_IS_OK(status)) {
3991 reply_nterror(req, status);
3995 send_trans2_replies(conn, req,
4003 if (NT_STATUS_IS_OK(status)) {
4004 /* Server-side transport
4005 * encryption is now *on*. */
4006 status = srv_encryption_start(conn);
4007 if (!NT_STATUS_IS_OK(status)) {
4008 char *reason = talloc_asprintf(talloc_tos(),
4009 "Failure in setting "
4010 "up encrypted transport: %s",
4012 exit_server_cleanly(reason);
4018 case SMB_FS_QUOTA_INFORMATION:
4020 files_struct *fsp = NULL;
4021 SMB_NTQUOTA_STRUCT quotas;
4023 ZERO_STRUCT(quotas);
4026 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4027 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4028 lp_servicename(talloc_tos(), SNUM(conn)),
4029 conn->session_info->unix_info->unix_name));
4030 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4034 /* note: normally there're 48 bytes,
4035 * but we didn't use the last 6 bytes for now
4038 fsp = file_fsp(req, SVAL(params,0));
4040 if (!check_fsp_ntquota_handle(conn, req,
4042 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4044 req, NT_STATUS_INVALID_HANDLE);
4048 if (total_data < 42) {
4049 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4053 NT_STATUS_INVALID_PARAMETER);
4057 /* unknown_1 24 NULL bytes in pdata*/
4059 /* the soft quotas 8 bytes (uint64_t)*/
4060 quotas.softlim = BVAL(pdata,24);
4062 /* the hard quotas 8 bytes (uint64_t)*/
4063 quotas.hardlim = BVAL(pdata,32);
4065 /* quota_flags 2 bytes **/
4066 quotas.qflags = SVAL(pdata,40);
4068 /* unknown_2 6 NULL bytes follow*/
4070 /* now set the quotas */
4071 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4072 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4073 reply_nterror(req, map_nt_error_from_unix(errno));
4080 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4082 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4088 * sending this reply works fine,
4089 * but I'm not sure it's the same
4090 * like windows do...
4093 reply_outbuf(req, 10, 0);
4096 #if defined(HAVE_POSIX_ACLS)
4097 /****************************************************************************
4098 Utility function to count the number of entries in a POSIX acl.
4099 ****************************************************************************/
4101 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4103 unsigned int ace_count = 0;
4104 int entry_id = SMB_ACL_FIRST_ENTRY;
4105 SMB_ACL_ENTRY_T entry;
4107 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4109 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4110 entry_id = SMB_ACL_NEXT_ENTRY;
4117 /****************************************************************************
4118 Utility function to marshall a POSIX acl into wire format.
4119 ****************************************************************************/
4121 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4123 int entry_id = SMB_ACL_FIRST_ENTRY;
4124 SMB_ACL_ENTRY_T entry;
4126 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4127 SMB_ACL_TAG_T tagtype;
4128 SMB_ACL_PERMSET_T permset;
4129 unsigned char perms = 0;
4130 unsigned int own_grp;
4133 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4134 entry_id = SMB_ACL_NEXT_ENTRY;
4137 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4138 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4142 if (sys_acl_get_permset(entry, &permset) == -1) {
4143 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4147 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4148 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4149 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4151 SCVAL(pdata,1,perms);
4154 case SMB_ACL_USER_OBJ:
4155 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4156 own_grp = (unsigned int)pst->st_ex_uid;
4157 SIVAL(pdata,2,own_grp);
4162 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4164 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4167 own_grp = (unsigned int)*puid;
4168 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4169 SIVAL(pdata,2,own_grp);
4173 case SMB_ACL_GROUP_OBJ:
4174 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4175 own_grp = (unsigned int)pst->st_ex_gid;
4176 SIVAL(pdata,2,own_grp);
4181 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4183 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4186 own_grp = (unsigned int)*pgid;
4187 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4188 SIVAL(pdata,2,own_grp);
4193 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4194 SIVAL(pdata,2,0xFFFFFFFF);
4195 SIVAL(pdata,6,0xFFFFFFFF);
4198 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4199 SIVAL(pdata,2,0xFFFFFFFF);
4200 SIVAL(pdata,6,0xFFFFFFFF);
4203 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4206 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4213 /****************************************************************************
4214 Store the FILE_UNIX_BASIC info.
4215 ****************************************************************************/
4217 static char *store_file_unix_basic(connection_struct *conn,
4220 const SMB_STRUCT_STAT *psbuf)
4222 uint64_t file_index = get_FileIndex(conn, psbuf);
4225 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4226 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4228 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4231 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4234 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4235 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4236 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4239 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4243 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4247 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4250 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4251 devno = psbuf->st_ex_rdev;
4253 devno = psbuf->st_ex_dev;
4256 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4260 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4264 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4267 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4271 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4278 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4279 * the chflags(2) (or equivalent) flags.
4281 * XXX: this really should be behind the VFS interface. To do this, we would
4282 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4283 * Each VFS module could then implement its own mapping as appropriate for the
4284 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4286 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4290 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4294 { UF_IMMUTABLE, EXT_IMMUTABLE },
4298 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4302 { UF_HIDDEN, EXT_HIDDEN },
4305 /* Do not remove. We need to guarantee that this array has at least one
4306 * entry to build on HP-UX.
4312 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4313 uint32 *smb_fflags, uint32 *smb_fmask)
4317 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4318 *smb_fmask |= info2_flags_map[i].smb_fflag;
4319 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4320 *smb_fflags |= info2_flags_map[i].smb_fflag;
4325 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4326 const uint32 smb_fflags,
4327 const uint32 smb_fmask,
4330 uint32 max_fmask = 0;
4333 *stat_fflags = psbuf->st_ex_flags;
4335 /* For each flags requested in smb_fmask, check the state of the
4336 * corresponding flag in smb_fflags and set or clear the matching
4340 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4341 max_fmask |= info2_flags_map[i].smb_fflag;
4342 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4343 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4344 *stat_fflags |= info2_flags_map[i].stat_fflag;
4346 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4351 /* If smb_fmask is asking to set any bits that are not supported by
4352 * our flag mappings, we should fail.
4354 if ((smb_fmask & max_fmask) != smb_fmask) {
4362 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4363 * of file flags and birth (create) time.
4365 static char *store_file_unix_basic_info2(connection_struct *conn,
4368 const SMB_STRUCT_STAT *psbuf)
4370 uint32 file_flags = 0;
4371 uint32 flags_mask = 0;
4373 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4375 /* Create (birth) time 64 bit */
4376 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4379 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4380 SIVAL(pdata, 0, file_flags); /* flags */
4381 SIVAL(pdata, 4, flags_mask); /* mask */
4387 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4388 const struct stream_struct *streams,
4390 unsigned int max_data_bytes,
4391 unsigned int *data_size)
4394 unsigned int ofs = 0;
4396 if (max_data_bytes < 32) {
4397 return NT_STATUS_INFO_LENGTH_MISMATCH;
4400 for (i = 0; i < num_streams; i++) {
4401 unsigned int next_offset;
4403 smb_ucs2_t *namebuf;
4405 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4406 streams[i].name, &namelen) ||
4409 return NT_STATUS_INVALID_PARAMETER;
4413 * name_buf is now null-terminated, we need to marshall as not
4420 * We cannot overflow ...
4422 if ((ofs + 24 + namelen) > max_data_bytes) {
4423 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4425 TALLOC_FREE(namebuf);
4426 return STATUS_BUFFER_OVERFLOW;
4429 SIVAL(data, ofs+4, namelen);
4430 SOFF_T(data, ofs+8, streams[i].size);
4431 SOFF_T(data, ofs+16, streams[i].alloc_size);
4432 memcpy(data+ofs+24, namebuf, namelen);
4433 TALLOC_FREE(namebuf);
4435 next_offset = ofs + 24 + namelen;
4437 if (i == num_streams-1) {
4438 SIVAL(data, ofs, 0);
4441 unsigned int align = ndr_align_size(next_offset, 8);
4443 if ((next_offset + align) > max_data_bytes) {
4444 DEBUG(10, ("refusing to overflow align "
4445 "reply at stream %u\n",
4447 TALLOC_FREE(namebuf);
4448 return STATUS_BUFFER_OVERFLOW;
4451 memset(data+next_offset, 0, align);
4452 next_offset += align;
4454 SIVAL(data, ofs, next_offset - ofs);
4461 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4465 return NT_STATUS_OK;
4468 /****************************************************************************
4469 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4470 ****************************************************************************/
4472 static void call_trans2qpipeinfo(connection_struct *conn,
4473 struct smb_request *req,
4474 unsigned int tran_call,
4475 char **pparams, int total_params,
4476 char **ppdata, int total_data,
4477 unsigned int max_data_bytes)
4479 char *params = *pparams;
4480 char *pdata = *ppdata;
4481 unsigned int data_size = 0;
4482 unsigned int param_size = 2;
4487 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4491 if (total_params < 4) {
4492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4496 fsp = file_fsp(req, SVAL(params,0));
4497 if (!fsp_is_np(fsp)) {
4498 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4502 info_level = SVAL(params,2);
4504 *pparams = (char *)SMB_REALLOC(*pparams,2);
4505 if (*pparams == NULL) {
4506 reply_nterror(req, NT_STATUS_NO_MEMORY);
4511 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4512 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4515 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4516 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4517 if (*ppdata == NULL ) {
4518 reply_nterror(req, NT_STATUS_NO_MEMORY);
4523 switch (info_level) {
4524 case SMB_FILE_STANDARD_INFORMATION:
4526 SOFF_T(pdata,0,4096LL);
4533 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4537 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4543 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4544 TALLOC_CTX *mem_ctx,
4545 uint16_t info_level,
4547 struct smb_filename *smb_fname,
4548 bool delete_pending,
4549 struct timespec write_time_ts,
4550 struct ea_list *ea_list,
4551 int lock_data_count,
4554 unsigned int max_data_bytes,
4555 size_t *fixed_portion,
4557 unsigned int *pdata_size)
4559 char *pdata = *ppdata;
4560 char *dstart, *dend;
4561 unsigned int data_size;
4562 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4563 time_t create_time, mtime, atime, c_time;
4564 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4571 uint64_t file_size = 0;
4573 uint64_t allocation_size = 0;
4574 uint64_t file_index = 0;
4575 uint32_t access_mask = 0;
4578 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4579 return NT_STATUS_INVALID_LEVEL;
4582 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4583 smb_fname_str_dbg(smb_fname),
4585 info_level, max_data_bytes));
4587 mode = dos_mode(conn, smb_fname);
4588 nlink = psbuf->st_ex_nlink;
4590 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4594 if ((nlink > 0) && delete_pending) {
4598 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4599 return NT_STATUS_INVALID_PARAMETER;
4602 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4603 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4604 if (*ppdata == NULL) {
4605 return NT_STATUS_NO_MEMORY;
4609 dend = dstart + data_size - 1;
4611 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4612 update_stat_ex_mtime(psbuf, write_time_ts);
4615 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4616 mtime_ts = psbuf->st_ex_mtime;
4617 atime_ts = psbuf->st_ex_atime;
4618 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4620 if (lp_dos_filetime_resolution(SNUM(conn))) {
4621 dos_filetime_timespec(&create_time_ts);
4622 dos_filetime_timespec(&mtime_ts);
4623 dos_filetime_timespec(&atime_ts);
4624 dos_filetime_timespec(&ctime_ts);
4627 create_time = convert_timespec_to_time_t(create_time_ts);
4628 mtime = convert_timespec_to_time_t(mtime_ts);
4629 atime = convert_timespec_to_time_t(atime_ts);
4630 c_time = convert_timespec_to_time_t(ctime_ts);
4632 p = strrchr_m(smb_fname->base_name,'/');
4634 base_name = smb_fname->base_name;
4638 /* NT expects the name to be in an exact form of the *full*
4639 filename. See the trans2 torture test */
4640 if (ISDOT(base_name)) {
4641 dos_fname = talloc_strdup(mem_ctx, "\\");
4643 return NT_STATUS_NO_MEMORY;
4646 dos_fname = talloc_asprintf(mem_ctx,
4648 smb_fname->base_name);
4650 return NT_STATUS_NO_MEMORY;
4652 if (is_ntfs_stream_smb_fname(smb_fname)) {
4653 dos_fname = talloc_asprintf(dos_fname, "%s",
4654 smb_fname->stream_name);
4656 return NT_STATUS_NO_MEMORY;
4660 string_replace(dos_fname, '/', '\\');
4663 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4666 /* Do we have this path open ? */
4668 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4669 fsp1 = file_find_di_first(conn->sconn, fileid);
4670 if (fsp1 && fsp1->initial_allocation_size) {
4671 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4675 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4676 file_size = get_file_size_stat(psbuf);
4680 pos = fsp->fh->position_information;
4684 access_mask = fsp->access_mask;
4686 /* GENERIC_EXECUTE mapping from Windows */
4687 access_mask = 0x12019F;
4690 /* This should be an index number - looks like
4693 I think this causes us to fail the IFSKIT
4694 BasicFileInformationTest. -tpot */
4695 file_index = get_FileIndex(conn, psbuf);
4699 switch (info_level) {
4700 case SMB_INFO_STANDARD:
4701 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4703 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4704 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4705 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4706 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4707 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4708 SSVAL(pdata,l1_attrFile,mode);
4711 case SMB_INFO_QUERY_EA_SIZE:
4713 unsigned int ea_size =
4714 estimate_ea_size(conn, fsp,
4716 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4718 srv_put_dos_date2(pdata,0,create_time);
4719 srv_put_dos_date2(pdata,4,atime);
4720 srv_put_dos_date2(pdata,8,mtime); /* write time */
4721 SIVAL(pdata,12,(uint32)file_size);
4722 SIVAL(pdata,16,(uint32)allocation_size);
4723 SSVAL(pdata,20,mode);
4724 SIVAL(pdata,22,ea_size);
4728 case SMB_INFO_IS_NAME_VALID:
4729 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4731 /* os/2 needs this ? really ?*/
4732 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4734 /* This is only reached for qpathinfo */
4738 case SMB_INFO_QUERY_EAS_FROM_LIST:
4740 size_t total_ea_len = 0;
4741 struct ea_list *ea_file_list = NULL;
4742 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4745 get_ea_list_from_file(mem_ctx, conn, fsp,
4747 &total_ea_len, &ea_file_list);
4748 if (!NT_STATUS_IS_OK(status)) {
4752 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4754 if (!ea_list || (total_ea_len > data_size)) {
4756 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4760 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4764 case SMB_INFO_QUERY_ALL_EAS:
4766 /* We have data_size bytes to put EA's into. */
4767 size_t total_ea_len = 0;
4768 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4770 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4772 &total_ea_len, &ea_list);
4773 if (!NT_STATUS_IS_OK(status)) {
4777 if (!ea_list || (total_ea_len > data_size)) {
4779 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4783 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4787 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4789 /* This is FileFullEaInformation - 0xF which maps to
4790 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4792 /* We have data_size bytes to put EA's into. */
4793 size_t total_ea_len = 0;
4794 struct ea_list *ea_file_list = NULL;
4796 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4798 /*TODO: add filtering and index handling */
4801 get_ea_list_from_file(mem_ctx, conn, fsp,
4803 &total_ea_len, &ea_file_list);
4804 if (!NT_STATUS_IS_OK(status)) {
4807 if (!ea_file_list) {
4808 return NT_STATUS_NO_EAS_ON_FILE;
4811 status = fill_ea_chained_buffer(mem_ctx,
4815 conn, ea_file_list);
4816 if (!NT_STATUS_IS_OK(status)) {
4822 case SMB_FILE_BASIC_INFORMATION:
4823 case SMB_QUERY_FILE_BASIC_INFO:
4825 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4826 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4827 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4829 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4833 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4834 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4835 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4836 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4837 SIVAL(pdata,32,mode);
4839 DEBUG(5,("SMB_QFBI - "));
4840 DEBUG(5,("create: %s ", ctime(&create_time)));
4841 DEBUG(5,("access: %s ", ctime(&atime)));
4842 DEBUG(5,("write: %s ", ctime(&mtime)));
4843 DEBUG(5,("change: %s ", ctime(&c_time)));
4844 DEBUG(5,("mode: %x\n", mode));
4845 *fixed_portion = data_size;
4848 case SMB_FILE_STANDARD_INFORMATION:
4849 case SMB_QUERY_FILE_STANDARD_INFO:
4851 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4853 SOFF_T(pdata,0,allocation_size);
4854 SOFF_T(pdata,8,file_size);
4855 SIVAL(pdata,16,nlink);
4856 SCVAL(pdata,20,delete_pending?1:0);
4857 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4858 SSVAL(pdata,22,0); /* Padding. */
4859 *fixed_portion = 24;
4862 case SMB_FILE_EA_INFORMATION:
4863 case SMB_QUERY_FILE_EA_INFO:
4865 unsigned int ea_size =
4866 estimate_ea_size(conn, fsp, smb_fname);
4867 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4870 SIVAL(pdata,0,ea_size);
4874 /* Get the 8.3 name - used if NT SMB was negotiated. */
4875 case SMB_QUERY_FILE_ALT_NAME_INFO:
4876 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4878 char mangled_name[13];
4879 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4880 if (!name_to_8_3(base_name,mangled_name,
4881 True,conn->params)) {
4882 return NT_STATUS_NO_MEMORY;
4884 status = srvstr_push(dstart, flags2,
4885 pdata+4, mangled_name,
4886 PTR_DIFF(dend, pdata+4),
4888 if (!NT_STATUS_IS_OK(status)) {
4891 data_size = 4 + len;
4897 case SMB_QUERY_FILE_NAME_INFO:
4900 this must be *exactly* right for ACLs on mapped drives to work
4902 status = srvstr_push(dstart, flags2,
4904 PTR_DIFF(dend, pdata+4),
4906 if (!NT_STATUS_IS_OK(status)) {
4909 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4910 data_size = 4 + len;
4915 case SMB_FILE_ALLOCATION_INFORMATION:
4916 case SMB_QUERY_FILE_ALLOCATION_INFO:
4917 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4919 SOFF_T(pdata,0,allocation_size);
4922 case SMB_FILE_END_OF_FILE_INFORMATION:
4923 case SMB_QUERY_FILE_END_OF_FILEINFO:
4924 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4926 SOFF_T(pdata,0,file_size);
4929 case SMB_QUERY_FILE_ALL_INFO:
4930 case SMB_FILE_ALL_INFORMATION:
4932 unsigned int ea_size =
4933 estimate_ea_size(conn, fsp, smb_fname);
4934 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4935 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4936 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4937 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4938 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4939 SIVAL(pdata,32,mode);
4940 SIVAL(pdata,36,0); /* padding. */
4942 SOFF_T(pdata,0,allocation_size);
4943 SOFF_T(pdata,8,file_size);
4944 SIVAL(pdata,16,nlink);
4945 SCVAL(pdata,20,delete_pending);
4946 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4949 SIVAL(pdata,0,ea_size);
4950 pdata += 4; /* EA info */
4951 status = srvstr_push(dstart, flags2,
4953 PTR_DIFF(dend, pdata+4),
4955 if (!NT_STATUS_IS_OK(status)) {
4960 data_size = PTR_DIFF(pdata,(*ppdata));
4961 *fixed_portion = 10;
4965 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4967 unsigned int ea_size =
4968 estimate_ea_size(conn, fsp, smb_fname);
4969 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4970 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4971 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4972 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4973 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4974 SIVAL(pdata, 0x20, mode);
4975 SIVAL(pdata, 0x24, 0); /* padding. */
4976 SBVAL(pdata, 0x28, allocation_size);
4977 SBVAL(pdata, 0x30, file_size);
4978 SIVAL(pdata, 0x38, nlink);
4979 SCVAL(pdata, 0x3C, delete_pending);
4980 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4981 SSVAL(pdata, 0x3E, 0); /* padding */
4982 SBVAL(pdata, 0x40, file_index);
4983 SIVAL(pdata, 0x48, ea_size);
4984 SIVAL(pdata, 0x4C, access_mask);
4985 SBVAL(pdata, 0x50, pos);
4986 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4987 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4991 status = srvstr_push(dstart, flags2,
4993 PTR_DIFF(dend, pdata+4),
4995 if (!NT_STATUS_IS_OK(status)) {
5000 data_size = PTR_DIFF(pdata,(*ppdata));
5001 *fixed_portion = 104;
5004 case SMB_FILE_INTERNAL_INFORMATION:
5006 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5007 SBVAL(pdata, 0, file_index);
5012 case SMB_FILE_ACCESS_INFORMATION:
5013 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5014 SIVAL(pdata, 0, access_mask);
5019 case SMB_FILE_NAME_INFORMATION:
5020 /* Pathname with leading '\'. */
5023 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5024 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5025 SIVAL(pdata,0,byte_len);
5026 data_size = 4 + byte_len;
5030 case SMB_FILE_DISPOSITION_INFORMATION:
5031 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5033 SCVAL(pdata,0,delete_pending);
5037 case SMB_FILE_POSITION_INFORMATION:
5038 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5040 SOFF_T(pdata,0,pos);
5044 case SMB_FILE_MODE_INFORMATION:
5045 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5046 SIVAL(pdata,0,mode);
5051 case SMB_FILE_ALIGNMENT_INFORMATION:
5052 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5053 SIVAL(pdata,0,0); /* No alignment needed. */
5059 * NT4 server just returns "invalid query" to this - if we try
5060 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5063 /* The first statement above is false - verified using Thursby
5064 * client against NT4 -- gcolley.
5066 case SMB_QUERY_FILE_STREAM_INFO:
5067 case SMB_FILE_STREAM_INFORMATION: {
5068 unsigned int num_streams = 0;
5069 struct stream_struct *streams = NULL;
5071 DEBUG(10,("smbd_do_qfilepathinfo: "
5072 "SMB_FILE_STREAM_INFORMATION\n"));
5074 if (is_ntfs_stream_smb_fname(smb_fname)) {
5075 return NT_STATUS_INVALID_PARAMETER;
5078 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
5079 talloc_tos(), &num_streams, &streams);
5081 if (!NT_STATUS_IS_OK(status)) {
5082 DEBUG(10, ("could not get stream info: %s\n",
5083 nt_errstr(status)));
5087 status = marshall_stream_info(num_streams, streams,
5088 pdata, max_data_bytes,
5091 if (!NT_STATUS_IS_OK(status)) {
5092 DEBUG(10, ("marshall_stream_info failed: %s\n",
5093 nt_errstr(status)));
5094 TALLOC_FREE(streams);
5098 TALLOC_FREE(streams);
5100 *fixed_portion = 32;
5104 case SMB_QUERY_COMPRESSION_INFO:
5105 case SMB_FILE_COMPRESSION_INFORMATION:
5106 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5107 SOFF_T(pdata,0,file_size);
5108 SIVAL(pdata,8,0); /* ??? */
5109 SIVAL(pdata,12,0); /* ??? */
5111 *fixed_portion = 16;
5114 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5115 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5116 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5117 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5118 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5119 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5120 SOFF_T(pdata,32,allocation_size);
5121 SOFF_T(pdata,40,file_size);
5122 SIVAL(pdata,48,mode);
5123 SIVAL(pdata,52,0); /* ??? */
5125 *fixed_portion = 56;
5128 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5129 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5130 SIVAL(pdata,0,mode);
5137 * CIFS UNIX Extensions.
5140 case SMB_QUERY_FILE_UNIX_BASIC:
5142 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5143 data_size = PTR_DIFF(pdata,(*ppdata));
5145 DEBUG(4,("smbd_do_qfilepathinfo: "
5146 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5147 dump_data(4, (uint8_t *)(*ppdata), data_size);
5151 case SMB_QUERY_FILE_UNIX_INFO2:
5153 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5154 data_size = PTR_DIFF(pdata,(*ppdata));
5158 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5160 for (i=0; i<100; i++)
5161 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5167 case SMB_QUERY_FILE_UNIX_LINK:
5170 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5173 return NT_STATUS_NO_MEMORY;
5176 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5178 if(!S_ISLNK(psbuf->st_ex_mode)) {
5179 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5182 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5184 link_len = SMB_VFS_READLINK(conn,
5185 smb_fname->base_name,
5187 if (link_len == -1) {
5188 return map_nt_error_from_unix(errno);
5190 buffer[link_len] = 0;
5191 status = srvstr_push(dstart, flags2,
5193 PTR_DIFF(dend, pdata),
5194 STR_TERMINATE, &len);
5195 if (!NT_STATUS_IS_OK(status)) {
5199 data_size = PTR_DIFF(pdata,(*ppdata));
5204 #if defined(HAVE_POSIX_ACLS)
5205 case SMB_QUERY_POSIX_ACL:
5207 SMB_ACL_T file_acl = NULL;
5208 SMB_ACL_T def_acl = NULL;
5209 uint16 num_file_acls = 0;
5210 uint16 num_def_acls = 0;
5212 if (fsp && fsp->fh->fd != -1) {
5213 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5217 SMB_VFS_SYS_ACL_GET_FILE(conn,
5218 smb_fname->base_name,
5219 SMB_ACL_TYPE_ACCESS,
5223 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5224 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5225 "not implemented on "
5226 "filesystem containing %s\n",
5227 smb_fname->base_name));
5228 return NT_STATUS_NOT_IMPLEMENTED;
5231 if (S_ISDIR(psbuf->st_ex_mode)) {
5232 if (fsp && fsp->is_directory) {
5234 SMB_VFS_SYS_ACL_GET_FILE(
5236 fsp->fsp_name->base_name,
5237 SMB_ACL_TYPE_DEFAULT,
5241 SMB_VFS_SYS_ACL_GET_FILE(
5243 smb_fname->base_name,
5244 SMB_ACL_TYPE_DEFAULT,
5247 def_acl = free_empty_sys_acl(conn, def_acl);
5250 num_file_acls = count_acl_entries(conn, file_acl);
5251 num_def_acls = count_acl_entries(conn, def_acl);
5253 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5254 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5256 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5257 SMB_POSIX_ACL_HEADER_SIZE) ));
5259 TALLOC_FREE(file_acl);
5262 TALLOC_FREE(def_acl);
5264 return NT_STATUS_BUFFER_TOO_SMALL;
5267 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5268 SSVAL(pdata,2,num_file_acls);
5269 SSVAL(pdata,4,num_def_acls);
5270 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5272 TALLOC_FREE(file_acl);
5275 TALLOC_FREE(def_acl);
5277 return NT_STATUS_INTERNAL_ERROR;
5279 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5281 TALLOC_FREE(file_acl);
5284 TALLOC_FREE(def_acl);
5286 return NT_STATUS_INTERNAL_ERROR;
5290 TALLOC_FREE(file_acl);
5293 TALLOC_FREE(def_acl);
5295 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5301 case SMB_QUERY_POSIX_LOCK:
5306 enum brl_type lock_type;
5308 /* We need an open file with a real fd for this. */
5309 if (!fsp || fsp->fh->fd == -1) {
5310 return NT_STATUS_INVALID_LEVEL;
5313 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5314 return NT_STATUS_INVALID_PARAMETER;
5317 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5318 case POSIX_LOCK_TYPE_READ:
5319 lock_type = READ_LOCK;
5321 case POSIX_LOCK_TYPE_WRITE:
5322 lock_type = WRITE_LOCK;
5324 case POSIX_LOCK_TYPE_UNLOCK:
5326 /* There's no point in asking for an unlock... */
5327 return NT_STATUS_INVALID_PARAMETER;
5330 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5331 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5332 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5334 status = query_lock(fsp,
5341 if (ERROR_WAS_LOCK_DENIED(status)) {
5342 /* Here we need to report who has it locked... */
5343 data_size = POSIX_LOCK_DATA_SIZE;
5345 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5346 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5347 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5348 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5349 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5351 } else if (NT_STATUS_IS_OK(status)) {
5352 /* For success we just return a copy of what we sent
5353 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5354 data_size = POSIX_LOCK_DATA_SIZE;
5355 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5356 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5364 return NT_STATUS_INVALID_LEVEL;
5367 *pdata_size = data_size;
5368 return NT_STATUS_OK;
5371 /****************************************************************************
5372 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5373 file name or file id).
5374 ****************************************************************************/
5376 static void call_trans2qfilepathinfo(connection_struct *conn,
5377 struct smb_request *req,
5378 unsigned int tran_call,
5379 char **pparams, int total_params,
5380 char **ppdata, int total_data,
5381 unsigned int max_data_bytes)
5383 char *params = *pparams;
5384 char *pdata = *ppdata;
5386 unsigned int data_size = 0;
5387 unsigned int param_size = 2;
5388 struct smb_filename *smb_fname = NULL;
5389 bool delete_pending = False;
5390 struct timespec write_time_ts;
5391 files_struct *fsp = NULL;
5392 struct file_id fileid;
5393 struct ea_list *ea_list = NULL;
5394 int lock_data_count = 0;
5395 char *lock_data = NULL;
5396 size_t fixed_portion;
5397 NTSTATUS status = NT_STATUS_OK;
5400 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5404 ZERO_STRUCT(write_time_ts);
5406 if (tran_call == TRANSACT2_QFILEINFO) {
5407 if (total_params < 4) {
5408 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5413 call_trans2qpipeinfo(conn, req, tran_call,
5414 pparams, total_params,
5420 fsp = file_fsp(req, SVAL(params,0));
5421 info_level = SVAL(params,2);
5423 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5425 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5426 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5430 /* Initial check for valid fsp ptr. */
5431 if (!check_fsp_open(conn, req, fsp)) {
5435 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5436 if (smb_fname == NULL) {
5437 reply_nterror(req, NT_STATUS_NO_MEMORY);
5441 if(fsp->fake_file_handle) {
5443 * This is actually for the QUOTA_FAKE_FILE --metze
5446 /* We know this name is ok, it's already passed the checks. */
5448 } else if(fsp->fh->fd == -1) {
5450 * This is actually a QFILEINFO on a directory
5451 * handle (returned from an NT SMB). NT5.0 seems
5452 * to do this call. JRA.
5455 if (INFO_LEVEL_IS_UNIX(info_level)) {
5456 /* Always do lstat for UNIX calls. */
5457 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5458 DEBUG(3,("call_trans2qfilepathinfo: "
5459 "SMB_VFS_LSTAT of %s failed "
5461 smb_fname_str_dbg(smb_fname),
5464 map_nt_error_from_unix(errno));
5467 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5468 DEBUG(3,("call_trans2qfilepathinfo: "
5469 "SMB_VFS_STAT of %s failed (%s)\n",
5470 smb_fname_str_dbg(smb_fname),
5473 map_nt_error_from_unix(errno));
5477 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5478 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5481 * Original code - this is an open file.
5483 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5484 DEBUG(3, ("fstat of %s failed (%s)\n",
5485 fsp_fnum_dbg(fsp), strerror(errno)));
5487 map_nt_error_from_unix(errno));
5490 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5491 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5497 uint32_t ucf_flags = 0;
5500 if (total_params < 7) {
5501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5505 info_level = SVAL(params,0);
5507 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5509 if (INFO_LEVEL_IS_UNIX(info_level)) {
5510 if (!lp_unix_extensions()) {
5511 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5514 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5515 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5516 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5517 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5521 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5523 STR_TERMINATE, &status);
5524 if (!NT_STATUS_IS_OK(status)) {
5525 reply_nterror(req, status);
5529 status = filename_convert(req,
5531 req->flags2 & FLAGS2_DFS_PATHNAMES,
5536 if (!NT_STATUS_IS_OK(status)) {
5537 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5538 reply_botherror(req,
5539 NT_STATUS_PATH_NOT_COVERED,
5540 ERRSRV, ERRbadpath);
5543 reply_nterror(req, status);
5547 /* If this is a stream, check if there is a delete_pending. */
5548 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5549 && is_ntfs_stream_smb_fname(smb_fname)) {
5550 struct smb_filename *smb_fname_base;
5552 /* Create an smb_filename with stream_name == NULL. */
5553 smb_fname_base = synthetic_smb_fname(
5554 talloc_tos(), smb_fname->base_name,
5556 if (smb_fname_base == NULL) {
5557 reply_nterror(req, NT_STATUS_NO_MEMORY);
5561 if (INFO_LEVEL_IS_UNIX(info_level)) {
5562 /* Always do lstat for UNIX calls. */
5563 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5564 DEBUG(3,("call_trans2qfilepathinfo: "
5565 "SMB_VFS_LSTAT of %s failed "
5567 smb_fname_str_dbg(smb_fname_base),
5569 TALLOC_FREE(smb_fname_base);
5571 map_nt_error_from_unix(errno));
5575 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5576 DEBUG(3,("call_trans2qfilepathinfo: "
5577 "fileinfo of %s failed "
5579 smb_fname_str_dbg(smb_fname_base),
5581 TALLOC_FREE(smb_fname_base);
5583 map_nt_error_from_unix(errno));
5588 status = file_name_hash(conn,
5589 smb_fname_str_dbg(smb_fname_base),
5591 if (!NT_STATUS_IS_OK(status)) {
5592 TALLOC_FREE(smb_fname_base);
5593 reply_nterror(req, status);
5597 fileid = vfs_file_id_from_sbuf(conn,
5598 &smb_fname_base->st);
5599 TALLOC_FREE(smb_fname_base);
5600 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5601 if (delete_pending) {
5602 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5607 if (INFO_LEVEL_IS_UNIX(info_level)) {
5608 /* Always do lstat for UNIX calls. */
5609 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5610 DEBUG(3,("call_trans2qfilepathinfo: "
5611 "SMB_VFS_LSTAT of %s failed (%s)\n",
5612 smb_fname_str_dbg(smb_fname),
5615 map_nt_error_from_unix(errno));
5620 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5621 DEBUG(3,("call_trans2qfilepathinfo: "
5622 "SMB_VFS_STAT of %s failed (%s)\n",
5623 smb_fname_str_dbg(smb_fname),
5626 map_nt_error_from_unix(errno));
5631 status = file_name_hash(conn,
5632 smb_fname_str_dbg(smb_fname),
5634 if (!NT_STATUS_IS_OK(status)) {
5635 reply_nterror(req, status);
5639 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5640 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5641 if (delete_pending) {
5642 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5647 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5648 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5650 info_level,tran_call,total_data));
5652 /* Pull out any data sent here before we realloc. */
5653 switch (info_level) {
5654 case SMB_INFO_QUERY_EAS_FROM_LIST:
5656 /* Pull any EA list from the data portion. */
5659 if (total_data < 4) {
5661 req, NT_STATUS_INVALID_PARAMETER);
5664 ea_size = IVAL(pdata,0);
5666 if (total_data > 0 && ea_size != total_data) {
5667 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5668 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5670 req, NT_STATUS_INVALID_PARAMETER);
5674 if (!lp_ea_support(SNUM(conn))) {
5675 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5679 /* Pull out the list of names. */
5680 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5683 req, NT_STATUS_INVALID_PARAMETER);
5689 case SMB_QUERY_POSIX_LOCK:
5691 if (fsp == NULL || fsp->fh->fd == -1) {
5692 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5696 if (total_data != POSIX_LOCK_DATA_SIZE) {
5698 req, NT_STATUS_INVALID_PARAMETER);
5702 /* Copy the lock range data. */
5703 lock_data = (char *)talloc_memdup(
5704 req, pdata, total_data);
5706 reply_nterror(req, NT_STATUS_NO_MEMORY);
5709 lock_data_count = total_data;
5715 *pparams = (char *)SMB_REALLOC(*pparams,2);
5716 if (*pparams == NULL) {
5717 reply_nterror(req, NT_STATUS_NO_MEMORY);
5724 * draft-leach-cifs-v1-spec-02.txt
5725 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5728 * The requested information is placed in the Data portion of the
5729 * transaction response. For the information levels greater than 0x100,
5730 * the transaction response has 1 parameter word which should be
5731 * ignored by the client.
5733 * However Windows only follows this rule for the IS_NAME_VALID call.
5735 switch (info_level) {
5736 case SMB_INFO_IS_NAME_VALID:
5741 if ((info_level & 0xFF00) == 0xFF00) {
5743 * We use levels that start with 0xFF00
5744 * internally to represent SMB2 specific levels
5746 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5750 status = smbd_do_qfilepathinfo(conn, req, info_level,
5752 delete_pending, write_time_ts,
5754 lock_data_count, lock_data,
5755 req->flags2, max_data_bytes,
5757 ppdata, &data_size);
5758 if (!NT_STATUS_IS_OK(status)) {
5759 reply_nterror(req, status);
5762 if (fixed_portion > max_data_bytes) {
5763 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5767 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5773 /****************************************************************************
5774 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5776 ****************************************************************************/
5778 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5779 connection_struct *conn,
5780 struct smb_request *req,
5781 bool overwrite_if_exists,
5782 const struct smb_filename *smb_fname_old,
5783 struct smb_filename *smb_fname_new)
5785 NTSTATUS status = NT_STATUS_OK;
5787 /* source must already exist. */
5788 if (!VALID_STAT(smb_fname_old->st)) {
5789 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5792 if (VALID_STAT(smb_fname_new->st)) {
5793 if (overwrite_if_exists) {
5794 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5795 return NT_STATUS_FILE_IS_A_DIRECTORY;
5797 status = unlink_internals(conn,
5799 FILE_ATTRIBUTE_NORMAL,
5802 if (!NT_STATUS_IS_OK(status)) {
5806 /* Disallow if newname already exists. */
5807 return NT_STATUS_OBJECT_NAME_COLLISION;
5811 /* No links from a directory. */
5812 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5813 return NT_STATUS_FILE_IS_A_DIRECTORY;
5816 /* Setting a hardlink to/from a stream isn't currently supported. */
5817 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5818 is_ntfs_stream_smb_fname(smb_fname_new)) {
5819 return NT_STATUS_INVALID_PARAMETER;
5822 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5823 smb_fname_old->base_name, smb_fname_new->base_name));
5825 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5826 smb_fname_new->base_name) != 0) {
5827 status = map_nt_error_from_unix(errno);
5828 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5829 nt_errstr(status), smb_fname_old->base_name,
5830 smb_fname_new->base_name));
5835 /****************************************************************************
5836 Deal with setting the time from any of the setfilepathinfo functions.
5837 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5838 calling this function.
5839 ****************************************************************************/
5841 NTSTATUS smb_set_file_time(connection_struct *conn,
5843 const struct smb_filename *smb_fname,
5844 struct smb_file_time *ft,
5845 bool setting_write_time)
5847 struct smb_filename smb_fname_base;
5849 FILE_NOTIFY_CHANGE_LAST_ACCESS
5850 |FILE_NOTIFY_CHANGE_LAST_WRITE
5851 |FILE_NOTIFY_CHANGE_CREATION;
5853 if (!VALID_STAT(smb_fname->st)) {
5854 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5857 /* get some defaults (no modifications) if any info is zero or -1. */
5858 if (null_timespec(ft->create_time)) {
5859 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5862 if (null_timespec(ft->atime)) {
5863 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5866 if (null_timespec(ft->mtime)) {
5867 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5870 if (!setting_write_time) {
5871 /* ft->mtime comes from change time, not write time. */
5872 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5875 /* Ensure the resolution is the correct for
5876 * what we can store on this filesystem. */
5878 round_timespec(conn->ts_res, &ft->create_time);
5879 round_timespec(conn->ts_res, &ft->ctime);
5880 round_timespec(conn->ts_res, &ft->atime);
5881 round_timespec(conn->ts_res, &ft->mtime);
5883 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5884 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5885 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5886 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5887 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5888 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5889 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5890 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5892 if (setting_write_time) {
5894 * This was a Windows setfileinfo on an open file.
5895 * NT does this a lot. We also need to
5896 * set the time here, as it can be read by
5897 * FindFirst/FindNext and with the patch for bug #2045
5898 * in smbd/fileio.c it ensures that this timestamp is
5899 * kept sticky even after a write. We save the request
5900 * away and will set it on file close and after a write. JRA.
5903 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5904 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5907 if (fsp->base_fsp) {
5908 set_sticky_write_time_fsp(fsp->base_fsp,
5911 set_sticky_write_time_fsp(fsp, ft->mtime);
5914 set_sticky_write_time_path(
5915 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5920 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5922 /* Always call ntimes on the base, even if a stream was passed in. */
5923 smb_fname_base = *smb_fname;
5924 smb_fname_base.stream_name = NULL;
5926 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5927 return map_nt_error_from_unix(errno);
5930 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5931 smb_fname->base_name);
5932 return NT_STATUS_OK;
5935 /****************************************************************************
5936 Deal with setting the dosmode from any of the setfilepathinfo functions.
5937 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5938 done before calling this function.
5939 ****************************************************************************/
5941 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5942 const struct smb_filename *smb_fname,
5945 struct smb_filename *smb_fname_base;
5948 if (!VALID_STAT(smb_fname->st)) {
5949 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5952 /* Always operate on the base_name, even if a stream was passed in. */
5953 smb_fname_base = synthetic_smb_fname(
5954 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5955 if (smb_fname_base == NULL) {
5956 return NT_STATUS_NO_MEMORY;
5960 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5961 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5963 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5967 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5969 /* check the mode isn't different, before changing it */
5970 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5971 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5972 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5973 (unsigned int)dosmode));
5975 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5977 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5979 smb_fname_str_dbg(smb_fname_base),
5981 status = map_nt_error_from_unix(errno);
5985 status = NT_STATUS_OK;
5987 TALLOC_FREE(smb_fname_base);
5991 /****************************************************************************
5992 Deal with setting the size from any of the setfilepathinfo functions.
5993 ****************************************************************************/
5995 static NTSTATUS smb_set_file_size(connection_struct *conn,
5996 struct smb_request *req,
5998 const struct smb_filename *smb_fname,
5999 const SMB_STRUCT_STAT *psbuf,
6001 bool fail_after_createfile)
6003 NTSTATUS status = NT_STATUS_OK;
6004 struct smb_filename *smb_fname_tmp = NULL;
6005 files_struct *new_fsp = NULL;
6007 if (!VALID_STAT(*psbuf)) {
6008 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6011 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6013 if (size == get_file_size_stat(psbuf)) {
6014 return NT_STATUS_OK;
6017 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6018 smb_fname_str_dbg(smb_fname), (double)size));
6020 if (fsp && fsp->fh->fd != -1) {
6021 /* Handle based call. */
6022 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6023 return NT_STATUS_ACCESS_DENIED;
6026 if (vfs_set_filelen(fsp, size) == -1) {
6027 return map_nt_error_from_unix(errno);
6029 trigger_write_time_update_immediate(fsp);
6030 return NT_STATUS_OK;
6033 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6034 if (smb_fname_tmp == NULL) {
6035 return NT_STATUS_NO_MEMORY;
6038 smb_fname_tmp->st = *psbuf;
6040 status = SMB_VFS_CREATE_FILE(
6043 0, /* root_dir_fid */
6044 smb_fname_tmp, /* fname */
6045 FILE_WRITE_DATA, /* access_mask */
6046 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6048 FILE_OPEN, /* create_disposition*/
6049 0, /* create_options */
6050 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6051 0, /* oplock_request */
6053 0, /* allocation_size */
6054 0, /* private_flags */
6057 &new_fsp, /* result */
6059 NULL, NULL); /* create context */
6061 TALLOC_FREE(smb_fname_tmp);
6063 if (!NT_STATUS_IS_OK(status)) {
6064 /* NB. We check for open_was_deferred in the caller. */
6068 /* See RAW-SFILEINFO-END-OF-FILE */
6069 if (fail_after_createfile) {
6070 close_file(req, new_fsp,NORMAL_CLOSE);
6071 return NT_STATUS_INVALID_LEVEL;
6074 if (vfs_set_filelen(new_fsp, size) == -1) {
6075 status = map_nt_error_from_unix(errno);
6076 close_file(req, new_fsp,NORMAL_CLOSE);
6080 trigger_write_time_update_immediate(new_fsp);
6081 close_file(req, new_fsp,NORMAL_CLOSE);
6082 return NT_STATUS_OK;
6085 /****************************************************************************
6086 Deal with SMB_INFO_SET_EA.
6087 ****************************************************************************/
6089 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6093 const struct smb_filename *smb_fname)
6095 struct ea_list *ea_list = NULL;
6096 TALLOC_CTX *ctx = NULL;
6097 NTSTATUS status = NT_STATUS_OK;
6099 if (total_data < 10) {
6101 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6102 length. They seem to have no effect. Bug #3212. JRA */
6104 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6105 /* We're done. We only get EA info in this call. */
6106 return NT_STATUS_OK;
6109 return NT_STATUS_INVALID_PARAMETER;
6112 if (IVAL(pdata,0) > total_data) {
6113 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6114 IVAL(pdata,0), (unsigned int)total_data));
6115 return NT_STATUS_INVALID_PARAMETER;
6119 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6121 return NT_STATUS_INVALID_PARAMETER;
6124 status = set_ea(conn, fsp, smb_fname, ea_list);
6129 /****************************************************************************
6130 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6131 ****************************************************************************/
6133 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6138 struct ea_list *ea_list = NULL;
6142 return NT_STATUS_INVALID_HANDLE;
6145 if (!lp_ea_support(SNUM(conn))) {
6146 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6147 "EA's not supported.\n",
6148 (unsigned int)total_data));
6149 return NT_STATUS_EAS_NOT_SUPPORTED;
6152 if (total_data < 10) {
6153 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6155 (unsigned int)total_data));
6156 return NT_STATUS_INVALID_PARAMETER;
6159 ea_list = read_nttrans_ea_list(talloc_tos(),
6164 return NT_STATUS_INVALID_PARAMETER;
6167 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6169 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6170 smb_fname_str_dbg(fsp->fsp_name),
6171 nt_errstr(status) ));
6177 /****************************************************************************
6178 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6179 ****************************************************************************/
6181 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6185 struct smb_filename *smb_fname)
6187 NTSTATUS status = NT_STATUS_OK;
6188 bool delete_on_close;
6191 if (total_data < 1) {
6192 return NT_STATUS_INVALID_PARAMETER;
6196 return NT_STATUS_INVALID_HANDLE;
6199 delete_on_close = (CVAL(pdata,0) ? True : False);
6200 dosmode = dos_mode(conn, smb_fname);
6202 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6203 "delete_on_close = %u\n",
6204 smb_fname_str_dbg(smb_fname),
6205 (unsigned int)dosmode,
6206 (unsigned int)delete_on_close ));
6208 if (delete_on_close) {
6209 status = can_set_delete_on_close(fsp, dosmode);
6210 if (!NT_STATUS_IS_OK(status)) {
6215 /* The set is across all open files on this dev/inode pair. */
6216 if (!set_delete_on_close(fsp, delete_on_close,
6217 conn->session_info->security_token,
6218 conn->session_info->unix_token)) {
6219 return NT_STATUS_ACCESS_DENIED;
6221 return NT_STATUS_OK;
6224 /****************************************************************************
6225 Deal with SMB_FILE_POSITION_INFORMATION.
6226 ****************************************************************************/
6228 static NTSTATUS smb_file_position_information(connection_struct *conn,
6233 uint64_t position_information;
6235 if (total_data < 8) {
6236 return NT_STATUS_INVALID_PARAMETER;
6240 /* Ignore on pathname based set. */
6241 return NT_STATUS_OK;
6244 position_information = (uint64_t)IVAL(pdata,0);
6245 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6247 DEBUG(10,("smb_file_position_information: Set file position "
6248 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6249 (double)position_information));
6250 fsp->fh->position_information = position_information;
6251 return NT_STATUS_OK;
6254 /****************************************************************************
6255 Deal with SMB_FILE_MODE_INFORMATION.
6256 ****************************************************************************/
6258 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6264 if (total_data < 4) {
6265 return NT_STATUS_INVALID_PARAMETER;
6267 mode = IVAL(pdata,0);
6268 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6269 return NT_STATUS_INVALID_PARAMETER;
6271 return NT_STATUS_OK;
6274 /****************************************************************************
6275 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6276 ****************************************************************************/
6278 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6279 struct smb_request *req,
6282 const struct smb_filename *smb_fname)
6284 char *link_target = NULL;
6285 const char *newname = smb_fname->base_name;
6286 TALLOC_CTX *ctx = talloc_tos();
6288 /* Set a symbolic link. */
6289 /* Don't allow this if follow links is false. */
6291 if (total_data == 0) {
6292 return NT_STATUS_INVALID_PARAMETER;
6295 if (!lp_follow_symlinks(SNUM(conn))) {
6296 return NT_STATUS_ACCESS_DENIED;
6299 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6300 total_data, STR_TERMINATE);
6303 return NT_STATUS_INVALID_PARAMETER;
6306 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6307 newname, link_target ));
6309 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6310 return map_nt_error_from_unix(errno);
6313 return NT_STATUS_OK;
6316 /****************************************************************************
6317 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6318 ****************************************************************************/
6320 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6321 struct smb_request *req,
6322 const char *pdata, int total_data,
6323 struct smb_filename *smb_fname_new)
6325 char *oldname = NULL;
6326 struct smb_filename *smb_fname_old = NULL;
6327 TALLOC_CTX *ctx = talloc_tos();
6328 NTSTATUS status = NT_STATUS_OK;
6330 /* Set a hard link. */
6331 if (total_data == 0) {
6332 return NT_STATUS_INVALID_PARAMETER;
6335 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6336 total_data, STR_TERMINATE, &status);
6337 if (!NT_STATUS_IS_OK(status)) {
6341 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6342 smb_fname_str_dbg(smb_fname_new), oldname));
6344 status = filename_convert(ctx,
6346 req->flags2 & FLAGS2_DFS_PATHNAMES,
6351 if (!NT_STATUS_IS_OK(status)) {
6355 return hardlink_internals(ctx, conn, req, false,
6356 smb_fname_old, smb_fname_new);
6359 /****************************************************************************
6360 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6361 ****************************************************************************/
6363 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6364 struct smb_request *req,
6368 struct smb_filename *smb_fname_src)
6372 char *newname = NULL;
6373 struct smb_filename *smb_fname_dst = NULL;
6374 NTSTATUS status = NT_STATUS_OK;
6375 TALLOC_CTX *ctx = talloc_tos();
6378 return NT_STATUS_INVALID_HANDLE;
6381 if (total_data < 20) {
6382 return NT_STATUS_INVALID_PARAMETER;
6385 overwrite = (CVAL(pdata,0) ? True : False);
6386 len = IVAL(pdata,16);
6388 if (len > (total_data - 20) || (len == 0)) {
6389 return NT_STATUS_INVALID_PARAMETER;
6392 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6393 &pdata[20], len, STR_TERMINATE,
6395 if (!NT_STATUS_IS_OK(status)) {
6399 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6402 status = filename_convert(ctx,
6404 req->flags2 & FLAGS2_DFS_PATHNAMES,
6409 if (!NT_STATUS_IS_OK(status)) {
6413 if (fsp->base_fsp) {
6414 /* newname must be a stream name. */
6415 if (newname[0] != ':') {
6416 return NT_STATUS_NOT_SUPPORTED;
6419 /* Create an smb_fname to call rename_internals_fsp() with. */
6420 smb_fname_dst = synthetic_smb_fname(
6421 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6423 if (smb_fname_dst == NULL) {
6424 status = NT_STATUS_NO_MEMORY;
6429 * Set the original last component, since
6430 * rename_internals_fsp() requires it.
6432 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6434 if (smb_fname_dst->original_lcomp == NULL) {
6435 status = NT_STATUS_NO_MEMORY;
6441 DEBUG(10,("smb2_file_rename_information: "
6442 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6443 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6444 smb_fname_str_dbg(smb_fname_dst)));
6445 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6446 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6450 TALLOC_FREE(smb_fname_dst);
6454 static NTSTATUS smb_file_link_information(connection_struct *conn,
6455 struct smb_request *req,
6459 struct smb_filename *smb_fname_src)
6463 char *newname = NULL;
6464 struct smb_filename *smb_fname_dst = NULL;
6465 NTSTATUS status = NT_STATUS_OK;
6466 TALLOC_CTX *ctx = talloc_tos();
6469 return NT_STATUS_INVALID_HANDLE;
6472 if (total_data < 20) {
6473 return NT_STATUS_INVALID_PARAMETER;
6476 overwrite = (CVAL(pdata,0) ? true : false);
6477 len = IVAL(pdata,16);
6479 if (len > (total_data - 20) || (len == 0)) {
6480 return NT_STATUS_INVALID_PARAMETER;
6483 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6484 &pdata[20], len, STR_TERMINATE,
6486 if (!NT_STATUS_IS_OK(status)) {
6490 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6493 status = filename_convert(ctx,
6495 req->flags2 & FLAGS2_DFS_PATHNAMES,
6500 if (!NT_STATUS_IS_OK(status)) {
6504 if (fsp->base_fsp) {
6505 /* No stream names. */
6506 return NT_STATUS_NOT_SUPPORTED;
6509 DEBUG(10,("smb_file_link_information: "
6510 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6511 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6512 smb_fname_str_dbg(smb_fname_dst)));
6513 status = hardlink_internals(ctx,
6520 TALLOC_FREE(smb_fname_dst);
6524 /****************************************************************************
6525 Deal with SMB_FILE_RENAME_INFORMATION.
6526 ****************************************************************************/
6528 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6529 struct smb_request *req,
6533 struct smb_filename *smb_fname_src)
6538 char *newname = NULL;
6539 struct smb_filename *smb_fname_dst = NULL;
6540 bool dest_has_wcard = False;
6541 NTSTATUS status = NT_STATUS_OK;
6543 TALLOC_CTX *ctx = talloc_tos();
6545 if (total_data < 13) {
6546 return NT_STATUS_INVALID_PARAMETER;
6549 overwrite = (CVAL(pdata,0) ? True : False);
6550 root_fid = IVAL(pdata,4);
6551 len = IVAL(pdata,8);
6553 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6554 return NT_STATUS_INVALID_PARAMETER;
6557 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6560 if (!NT_STATUS_IS_OK(status)) {
6564 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6567 status = resolve_dfspath_wcard(ctx, conn,
6568 req->flags2 & FLAGS2_DFS_PATHNAMES,
6571 !conn->sconn->using_smb2,
6574 if (!NT_STATUS_IS_OK(status)) {
6578 /* Check the new name has no '/' characters. */
6579 if (strchr_m(newname, '/')) {
6580 return NT_STATUS_NOT_SUPPORTED;
6583 if (fsp && fsp->base_fsp) {
6584 /* newname must be a stream name. */
6585 if (newname[0] != ':') {
6586 return NT_STATUS_NOT_SUPPORTED;
6589 /* Create an smb_fname to call rename_internals_fsp() with. */
6590 smb_fname_dst = synthetic_smb_fname(
6591 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6593 if (smb_fname_dst == NULL) {
6594 status = NT_STATUS_NO_MEMORY;
6599 * Set the original last component, since
6600 * rename_internals_fsp() requires it.
6602 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6604 if (smb_fname_dst->original_lcomp == NULL) {
6605 status = NT_STATUS_NO_MEMORY;
6611 * Build up an smb_fname_dst based on the filename passed in.
6612 * We basically just strip off the last component, and put on
6613 * the newname instead.
6615 char *base_name = NULL;
6617 /* newname must *not* be a stream name. */
6618 if (newname[0] == ':') {
6619 return NT_STATUS_NOT_SUPPORTED;
6623 * Strip off the last component (filename) of the path passed
6626 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6628 return NT_STATUS_NO_MEMORY;
6630 p = strrchr_m(base_name, '/');
6634 base_name = talloc_strdup(ctx, "");
6636 return NT_STATUS_NO_MEMORY;
6639 /* Append the new name. */
6640 base_name = talloc_asprintf_append(base_name,
6644 return NT_STATUS_NO_MEMORY;
6647 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6650 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6653 /* If an error we expect this to be
6654 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6656 if (!NT_STATUS_IS_OK(status)) {
6657 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6661 /* Create an smb_fname to call rename_internals_fsp() */
6662 smb_fname_dst = synthetic_smb_fname(
6663 ctx, base_name, NULL, NULL);
6664 if (smb_fname_dst == NULL) {
6665 status = NT_STATUS_NO_MEMORY;
6672 DEBUG(10,("smb_file_rename_information: "
6673 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6674 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6675 smb_fname_str_dbg(smb_fname_dst)));
6676 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6679 DEBUG(10,("smb_file_rename_information: "
6680 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6681 smb_fname_str_dbg(smb_fname_src),
6682 smb_fname_str_dbg(smb_fname_dst)));
6683 status = rename_internals(ctx, conn, req, smb_fname_src,
6684 smb_fname_dst, 0, overwrite, false,
6686 FILE_WRITE_ATTRIBUTES);
6689 TALLOC_FREE(smb_fname_dst);
6693 /****************************************************************************
6694 Deal with SMB_SET_POSIX_ACL.
6695 ****************************************************************************/
6697 #if defined(HAVE_POSIX_ACLS)
6698 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6702 const struct smb_filename *smb_fname)
6704 uint16 posix_acl_version;
6705 uint16 num_file_acls;
6706 uint16 num_def_acls;
6707 bool valid_file_acls = True;
6708 bool valid_def_acls = True;
6710 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6711 return NT_STATUS_INVALID_PARAMETER;
6713 posix_acl_version = SVAL(pdata,0);
6714 num_file_acls = SVAL(pdata,2);
6715 num_def_acls = SVAL(pdata,4);
6717 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6718 valid_file_acls = False;
6722 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6723 valid_def_acls = False;
6727 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6728 return NT_STATUS_INVALID_PARAMETER;
6731 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6732 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6733 return NT_STATUS_INVALID_PARAMETER;
6736 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6737 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6738 (unsigned int)num_file_acls,
6739 (unsigned int)num_def_acls));
6741 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6742 smb_fname->base_name, num_file_acls,
6743 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6744 return map_nt_error_from_unix(errno);
6747 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6748 smb_fname->base_name, &smb_fname->st, num_def_acls,
6749 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6750 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6751 return map_nt_error_from_unix(errno);
6753 return NT_STATUS_OK;
6757 /****************************************************************************
6758 Deal with SMB_SET_POSIX_LOCK.
6759 ****************************************************************************/
6761 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6762 struct smb_request *req,
6770 bool blocking_lock = False;
6771 enum brl_type lock_type;
6773 NTSTATUS status = NT_STATUS_OK;
6775 if (fsp == NULL || fsp->fh->fd == -1) {
6776 return NT_STATUS_INVALID_HANDLE;
6779 if (total_data != POSIX_LOCK_DATA_SIZE) {
6780 return NT_STATUS_INVALID_PARAMETER;
6783 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6784 case POSIX_LOCK_TYPE_READ:
6785 lock_type = READ_LOCK;
6787 case POSIX_LOCK_TYPE_WRITE:
6788 /* Return the right POSIX-mappable error code for files opened read-only. */
6789 if (!fsp->can_write) {
6790 return NT_STATUS_INVALID_HANDLE;
6792 lock_type = WRITE_LOCK;
6794 case POSIX_LOCK_TYPE_UNLOCK:
6795 lock_type = UNLOCK_LOCK;
6798 return NT_STATUS_INVALID_PARAMETER;
6801 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6802 blocking_lock = False;
6803 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6804 blocking_lock = True;
6806 return NT_STATUS_INVALID_PARAMETER;
6809 if (!lp_blocking_locks(SNUM(conn))) {
6810 blocking_lock = False;
6813 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6814 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6815 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6816 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6817 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6819 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6820 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6822 (unsigned int)lock_type,
6823 (unsigned long long)smblctx,
6827 if (lock_type == UNLOCK_LOCK) {
6828 status = do_unlock(req->sconn->msg_ctx,
6835 uint64_t block_smblctx;
6837 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6848 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6850 * A blocking lock was requested. Package up
6851 * this smb into a queued request and push it
6852 * onto the blocking lock queue.
6854 if(push_blocking_lock_request(br_lck,
6857 -1, /* infinite timeout. */
6865 TALLOC_FREE(br_lck);
6869 TALLOC_FREE(br_lck);
6875 /****************************************************************************
6876 Deal with SMB_SET_FILE_BASIC_INFO.
6877 ****************************************************************************/
6879 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6883 const struct smb_filename *smb_fname)
6885 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6886 struct smb_file_time ft;
6888 NTSTATUS status = NT_STATUS_OK;
6892 if (total_data < 36) {
6893 return NT_STATUS_INVALID_PARAMETER;
6896 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6897 if (!NT_STATUS_IS_OK(status)) {
6901 /* Set the attributes */
6902 dosmode = IVAL(pdata,32);
6903 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6904 if (!NT_STATUS_IS_OK(status)) {
6909 ft.create_time = interpret_long_date(pdata);
6912 ft.atime = interpret_long_date(pdata+8);
6915 ft.mtime = interpret_long_date(pdata+16);
6918 ft.ctime = interpret_long_date(pdata+24);
6920 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6921 smb_fname_str_dbg(smb_fname)));
6923 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6927 /****************************************************************************
6928 Deal with SMB_INFO_STANDARD.
6929 ****************************************************************************/
6931 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6935 const struct smb_filename *smb_fname)
6938 struct smb_file_time ft;
6942 if (total_data < 12) {
6943 return NT_STATUS_INVALID_PARAMETER;
6947 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6949 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6951 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6953 DEBUG(10,("smb_set_info_standard: file %s\n",
6954 smb_fname_str_dbg(smb_fname)));
6956 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6957 if (!NT_STATUS_IS_OK(status)) {
6961 return smb_set_file_time(conn,
6968 /****************************************************************************
6969 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6970 ****************************************************************************/
6972 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6973 struct smb_request *req,
6977 struct smb_filename *smb_fname)
6979 uint64_t allocation_size = 0;
6980 NTSTATUS status = NT_STATUS_OK;
6981 files_struct *new_fsp = NULL;
6983 if (!VALID_STAT(smb_fname->st)) {
6984 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6987 if (total_data < 8) {
6988 return NT_STATUS_INVALID_PARAMETER;
6991 allocation_size = (uint64_t)IVAL(pdata,0);
6992 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6993 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6994 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6995 (double)allocation_size));
6997 if (allocation_size) {
6998 allocation_size = smb_roundup(conn, allocation_size);
7001 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7002 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7003 (double)allocation_size));
7005 if (fsp && fsp->fh->fd != -1) {
7006 /* Open file handle. */
7007 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7008 return NT_STATUS_ACCESS_DENIED;
7011 /* Only change if needed. */
7012 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7013 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7014 return map_nt_error_from_unix(errno);
7017 /* But always update the time. */
7019 * This is equivalent to a write. Ensure it's seen immediately
7020 * if there are no pending writes.
7022 trigger_write_time_update_immediate(fsp);
7023 return NT_STATUS_OK;
7026 /* Pathname or stat or directory file. */
7027 status = SMB_VFS_CREATE_FILE(
7030 0, /* root_dir_fid */
7031 smb_fname, /* fname */
7032 FILE_WRITE_DATA, /* access_mask */
7033 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7035 FILE_OPEN, /* create_disposition*/
7036 0, /* create_options */
7037 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7038 0, /* oplock_request */
7040 0, /* allocation_size */
7041 0, /* private_flags */
7044 &new_fsp, /* result */
7046 NULL, NULL); /* create context */
7048 if (!NT_STATUS_IS_OK(status)) {
7049 /* NB. We check for open_was_deferred in the caller. */
7053 /* Only change if needed. */
7054 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7055 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7056 status = map_nt_error_from_unix(errno);
7057 close_file(req, new_fsp, NORMAL_CLOSE);
7062 /* Changing the allocation size should set the last mod time. */
7064 * This is equivalent to a write. Ensure it's seen immediately
7065 * if there are no pending writes.
7067 trigger_write_time_update_immediate(new_fsp);
7068 close_file(req, new_fsp, NORMAL_CLOSE);
7069 return NT_STATUS_OK;
7072 /****************************************************************************
7073 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7074 ****************************************************************************/
7076 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7077 struct smb_request *req,
7081 const struct smb_filename *smb_fname,
7082 bool fail_after_createfile)
7086 if (total_data < 8) {
7087 return NT_STATUS_INVALID_PARAMETER;
7090 size = IVAL(pdata,0);
7091 size |= (((off_t)IVAL(pdata,4)) << 32);
7092 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7093 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7096 return smb_set_file_size(conn, req,
7101 fail_after_createfile);
7104 /****************************************************************************
7105 Allow a UNIX info mknod.
7106 ****************************************************************************/
7108 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7111 const struct smb_filename *smb_fname)
7113 uint32 file_type = IVAL(pdata,56);
7114 #if defined(HAVE_MAKEDEV)
7115 uint32 dev_major = IVAL(pdata,60);
7116 uint32 dev_minor = IVAL(pdata,68);
7118 SMB_DEV_T dev = (SMB_DEV_T)0;
7119 uint32 raw_unixmode = IVAL(pdata,84);
7123 if (total_data < 100) {
7124 return NT_STATUS_INVALID_PARAMETER;
7127 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7128 PERM_NEW_FILE, &unixmode);
7129 if (!NT_STATUS_IS_OK(status)) {
7133 #if defined(HAVE_MAKEDEV)
7134 dev = makedev(dev_major, dev_minor);
7137 switch (file_type) {
7138 #if defined(S_IFIFO)
7139 case UNIX_TYPE_FIFO:
7140 unixmode |= S_IFIFO;
7143 #if defined(S_IFSOCK)
7144 case UNIX_TYPE_SOCKET:
7145 unixmode |= S_IFSOCK;
7148 #if defined(S_IFCHR)
7149 case UNIX_TYPE_CHARDEV:
7150 unixmode |= S_IFCHR;
7153 #if defined(S_IFBLK)
7154 case UNIX_TYPE_BLKDEV:
7155 unixmode |= S_IFBLK;
7159 return NT_STATUS_INVALID_PARAMETER;
7162 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7163 "%.0f mode 0%o for file %s\n", (double)dev,
7164 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7166 /* Ok - do the mknod. */
7167 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7168 return map_nt_error_from_unix(errno);
7171 /* If any of the other "set" calls fail we
7172 * don't want to end up with a half-constructed mknod.
7175 if (lp_inherit_permissions(SNUM(conn))) {
7177 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7179 return NT_STATUS_NO_MEMORY;
7181 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7183 TALLOC_FREE(parent);
7186 return NT_STATUS_OK;
7189 /****************************************************************************
7190 Deal with SMB_SET_FILE_UNIX_BASIC.
7191 ****************************************************************************/
7193 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7194 struct smb_request *req,
7198 const struct smb_filename *smb_fname)
7200 struct smb_file_time ft;
7201 uint32 raw_unixmode;
7204 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7205 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7206 NTSTATUS status = NT_STATUS_OK;
7207 bool delete_on_fail = False;
7208 enum perm_type ptype;
7209 files_struct *all_fsps = NULL;
7210 bool modify_mtime = true;
7212 struct smb_filename *smb_fname_tmp = NULL;
7213 SMB_STRUCT_STAT sbuf;
7217 if (total_data < 100) {
7218 return NT_STATUS_INVALID_PARAMETER;
7221 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7222 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7223 size=IVAL(pdata,0); /* first 8 Bytes are size */
7224 size |= (((off_t)IVAL(pdata,4)) << 32);
7227 ft.atime = interpret_long_date(pdata+24); /* access_time */
7228 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7229 set_owner = (uid_t)IVAL(pdata,40);
7230 set_grp = (gid_t)IVAL(pdata,48);
7231 raw_unixmode = IVAL(pdata,84);
7233 if (VALID_STAT(smb_fname->st)) {
7234 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7235 ptype = PERM_EXISTING_DIR;
7237 ptype = PERM_EXISTING_FILE;
7240 ptype = PERM_NEW_FILE;
7243 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7245 if (!NT_STATUS_IS_OK(status)) {
7249 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7250 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7251 smb_fname_str_dbg(smb_fname), (double)size,
7252 (unsigned int)set_owner, (unsigned int)set_grp,
7253 (int)raw_unixmode));
7255 sbuf = smb_fname->st;
7257 if (!VALID_STAT(sbuf)) {
7259 * The only valid use of this is to create character and block
7260 * devices, and named pipes. This is deprecated (IMHO) and
7261 * a new info level should be used for mknod. JRA.
7264 status = smb_unix_mknod(conn,
7268 if (!NT_STATUS_IS_OK(status)) {
7272 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7273 if (smb_fname_tmp == NULL) {
7274 return NT_STATUS_NO_MEMORY;
7277 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7278 status = map_nt_error_from_unix(errno);
7279 TALLOC_FREE(smb_fname_tmp);
7280 SMB_VFS_UNLINK(conn, smb_fname);
7284 sbuf = smb_fname_tmp->st;
7285 smb_fname = smb_fname_tmp;
7287 /* Ensure we don't try and change anything else. */
7288 raw_unixmode = SMB_MODE_NO_CHANGE;
7289 size = get_file_size_stat(&sbuf);
7290 ft.atime = sbuf.st_ex_atime;
7291 ft.mtime = sbuf.st_ex_mtime;
7293 * We continue here as we might want to change the
7296 delete_on_fail = True;
7300 /* Horrible backwards compatibility hack as an old server bug
7301 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7305 size = get_file_size_stat(&sbuf);
7310 * Deal with the UNIX specific mode set.
7313 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7316 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7317 "setting mode 0%o for file %s\n",
7318 (unsigned int)unixmode,
7319 smb_fname_str_dbg(smb_fname)));
7320 if (fsp && fsp->fh->fd != -1) {
7321 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7323 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7326 return map_nt_error_from_unix(errno);
7331 * Deal with the UNIX specific uid set.
7334 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7335 (sbuf.st_ex_uid != set_owner)) {
7338 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7339 "changing owner %u for path %s\n",
7340 (unsigned int)set_owner,
7341 smb_fname_str_dbg(smb_fname)));
7343 if (fsp && fsp->fh->fd != -1) {
7344 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7347 * UNIX extensions calls must always operate
7350 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7351 set_owner, (gid_t)-1);
7355 status = map_nt_error_from_unix(errno);
7356 if (delete_on_fail) {
7357 SMB_VFS_UNLINK(conn, smb_fname);
7364 * Deal with the UNIX specific gid set.
7367 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7368 (sbuf.st_ex_gid != set_grp)) {
7371 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7372 "changing group %u for file %s\n",
7373 (unsigned int)set_owner,
7374 smb_fname_str_dbg(smb_fname)));
7375 if (fsp && fsp->fh->fd != -1) {
7376 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7379 * UNIX extensions calls must always operate
7382 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7386 status = map_nt_error_from_unix(errno);
7387 if (delete_on_fail) {
7388 SMB_VFS_UNLINK(conn, smb_fname);
7394 /* Deal with any size changes. */
7396 status = smb_set_file_size(conn, req,
7402 if (!NT_STATUS_IS_OK(status)) {
7406 /* Deal with any time changes. */
7407 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7408 /* No change, don't cancel anything. */
7412 id = vfs_file_id_from_sbuf(conn, &sbuf);
7413 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7414 all_fsps = file_find_di_next(all_fsps)) {
7416 * We're setting the time explicitly for UNIX.
7417 * Cancel any pending changes over all handles.
7419 all_fsps->update_write_time_on_close = false;
7420 TALLOC_FREE(all_fsps->update_write_time_event);
7424 * Override the "setting_write_time"
7425 * parameter here as it almost does what
7426 * we need. Just remember if we modified
7427 * mtime and send the notify ourselves.
7429 if (null_timespec(ft.mtime)) {
7430 modify_mtime = false;
7433 status = smb_set_file_time(conn,
7439 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7440 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7445 /****************************************************************************
7446 Deal with SMB_SET_FILE_UNIX_INFO2.
7447 ****************************************************************************/
7449 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7450 struct smb_request *req,
7454 const struct smb_filename *smb_fname)
7460 if (total_data < 116) {
7461 return NT_STATUS_INVALID_PARAMETER;
7464 /* Start by setting all the fields that are common between UNIX_BASIC
7467 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7469 if (!NT_STATUS_IS_OK(status)) {
7473 smb_fflags = IVAL(pdata, 108);
7474 smb_fmask = IVAL(pdata, 112);
7476 /* NB: We should only attempt to alter the file flags if the client
7477 * sends a non-zero mask.
7479 if (smb_fmask != 0) {
7480 int stat_fflags = 0;
7482 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7483 smb_fmask, &stat_fflags)) {
7484 /* Client asked to alter a flag we don't understand. */
7485 return NT_STATUS_INVALID_PARAMETER;
7488 if (fsp && fsp->fh->fd != -1) {
7489 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7490 return NT_STATUS_NOT_SUPPORTED;
7492 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7493 stat_fflags) != 0) {
7494 return map_nt_error_from_unix(errno);
7499 /* XXX: need to add support for changing the create_time here. You
7500 * can do this for paths on Darwin with setattrlist(2). The right way
7501 * to hook this up is probably by extending the VFS utimes interface.
7504 return NT_STATUS_OK;
7507 /****************************************************************************
7508 Create a directory with POSIX semantics.
7509 ****************************************************************************/
7511 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7512 struct smb_request *req,
7515 struct smb_filename *smb_fname,
7516 int *pdata_return_size)
7518 NTSTATUS status = NT_STATUS_OK;
7519 uint32 raw_unixmode = 0;
7520 uint32 mod_unixmode = 0;
7521 mode_t unixmode = (mode_t)0;
7522 files_struct *fsp = NULL;
7523 uint16 info_level_return = 0;
7525 char *pdata = *ppdata;
7527 if (total_data < 18) {
7528 return NT_STATUS_INVALID_PARAMETER;
7531 raw_unixmode = IVAL(pdata,8);
7532 /* Next 4 bytes are not yet defined. */
7534 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7535 PERM_NEW_DIR, &unixmode);
7536 if (!NT_STATUS_IS_OK(status)) {
7540 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7542 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7543 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7545 status = SMB_VFS_CREATE_FILE(
7548 0, /* root_dir_fid */
7549 smb_fname, /* fname */
7550 FILE_READ_ATTRIBUTES, /* access_mask */
7551 FILE_SHARE_NONE, /* share_access */
7552 FILE_CREATE, /* create_disposition*/
7553 FILE_DIRECTORY_FILE, /* create_options */
7554 mod_unixmode, /* file_attributes */
7555 0, /* oplock_request */
7557 0, /* allocation_size */
7558 0, /* private_flags */
7563 NULL, NULL); /* create context */
7565 if (NT_STATUS_IS_OK(status)) {
7566 close_file(req, fsp, NORMAL_CLOSE);
7569 info_level_return = SVAL(pdata,16);
7571 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7572 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7573 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7574 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7576 *pdata_return_size = 12;
7579 /* Realloc the data size */
7580 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7581 if (*ppdata == NULL) {
7582 *pdata_return_size = 0;
7583 return NT_STATUS_NO_MEMORY;
7587 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7588 SSVAL(pdata,2,0); /* No fnum. */
7589 SIVAL(pdata,4,info); /* Was directory created. */
7591 switch (info_level_return) {
7592 case SMB_QUERY_FILE_UNIX_BASIC:
7593 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7594 SSVAL(pdata,10,0); /* Padding. */
7595 store_file_unix_basic(conn, pdata + 12, fsp,
7598 case SMB_QUERY_FILE_UNIX_INFO2:
7599 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7600 SSVAL(pdata,10,0); /* Padding. */
7601 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7605 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7606 SSVAL(pdata,10,0); /* Padding. */
7613 /****************************************************************************
7614 Open/Create a file with POSIX semantics.
7615 ****************************************************************************/
7617 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7618 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7620 static NTSTATUS smb_posix_open(connection_struct *conn,
7621 struct smb_request *req,
7624 struct smb_filename *smb_fname,
7625 int *pdata_return_size)
7627 bool extended_oplock_granted = False;
7628 char *pdata = *ppdata;
7630 uint32 wire_open_mode = 0;
7631 uint32 raw_unixmode = 0;
7632 uint32 mod_unixmode = 0;
7633 uint32 create_disp = 0;
7634 uint32 access_mask = 0;
7635 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7636 NTSTATUS status = NT_STATUS_OK;
7637 mode_t unixmode = (mode_t)0;
7638 files_struct *fsp = NULL;
7639 int oplock_request = 0;
7641 uint16 info_level_return = 0;
7643 if (total_data < 18) {
7644 return NT_STATUS_INVALID_PARAMETER;
7647 flags = IVAL(pdata,0);
7648 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7649 if (oplock_request) {
7650 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7653 wire_open_mode = IVAL(pdata,4);
7655 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7656 return smb_posix_mkdir(conn, req,
7663 switch (wire_open_mode & SMB_ACCMODE) {
7665 access_mask = SMB_O_RDONLY_MAPPING;
7668 access_mask = SMB_O_WRONLY_MAPPING;
7671 access_mask = (SMB_O_RDONLY_MAPPING|
7672 SMB_O_WRONLY_MAPPING);
7675 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7676 (unsigned int)wire_open_mode ));
7677 return NT_STATUS_INVALID_PARAMETER;
7680 wire_open_mode &= ~SMB_ACCMODE;
7682 /* First take care of O_CREAT|O_EXCL interactions. */
7683 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7684 case (SMB_O_CREAT | SMB_O_EXCL):
7685 /* File exists fail. File not exist create. */
7686 create_disp = FILE_CREATE;
7689 /* File exists open. File not exist create. */
7690 create_disp = FILE_OPEN_IF;
7693 /* O_EXCL on its own without O_CREAT is undefined.
7694 We deliberately ignore it as some versions of
7695 Linux CIFSFS can send a bare O_EXCL on the
7696 wire which other filesystems in the kernel
7697 ignore. See bug 9519 for details. */
7702 /* File exists open. File not exist fail. */
7703 create_disp = FILE_OPEN;
7706 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7707 (unsigned int)wire_open_mode ));
7708 return NT_STATUS_INVALID_PARAMETER;
7711 /* Next factor in the effects of O_TRUNC. */
7712 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7714 if (wire_open_mode & SMB_O_TRUNC) {
7715 switch (create_disp) {
7717 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7718 /* Leave create_disp alone as
7719 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7721 /* File exists fail. File not exist create. */
7724 /* SMB_O_CREAT | SMB_O_TRUNC */
7725 /* File exists overwrite. File not exist create. */
7726 create_disp = FILE_OVERWRITE_IF;
7730 /* File exists overwrite. File not exist fail. */
7731 create_disp = FILE_OVERWRITE;
7734 /* Cannot get here. */
7735 smb_panic("smb_posix_open: logic error");
7736 return NT_STATUS_INVALID_PARAMETER;
7740 raw_unixmode = IVAL(pdata,8);
7741 /* Next 4 bytes are not yet defined. */
7743 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7744 (VALID_STAT(smb_fname->st) ?
7745 PERM_EXISTING_FILE : PERM_NEW_FILE),
7748 if (!NT_STATUS_IS_OK(status)) {
7752 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7754 if (wire_open_mode & SMB_O_SYNC) {
7755 create_options |= FILE_WRITE_THROUGH;
7757 if (wire_open_mode & SMB_O_APPEND) {
7758 access_mask |= FILE_APPEND_DATA;
7760 if (wire_open_mode & SMB_O_DIRECT) {
7761 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7764 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7765 VALID_STAT_OF_DIR(smb_fname->st)) {
7766 if (access_mask != SMB_O_RDONLY_MAPPING) {
7767 return NT_STATUS_FILE_IS_A_DIRECTORY;
7769 create_options &= ~FILE_NON_DIRECTORY_FILE;
7770 create_options |= FILE_DIRECTORY_FILE;
7773 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7774 smb_fname_str_dbg(smb_fname),
7775 (unsigned int)wire_open_mode,
7776 (unsigned int)unixmode ));
7778 status = SMB_VFS_CREATE_FILE(
7781 0, /* root_dir_fid */
7782 smb_fname, /* fname */
7783 access_mask, /* access_mask */
7784 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7786 create_disp, /* create_disposition*/
7787 create_options, /* create_options */
7788 mod_unixmode, /* file_attributes */
7789 oplock_request, /* oplock_request */
7791 0, /* allocation_size */
7792 0, /* private_flags */
7797 NULL, NULL); /* create context */
7799 if (!NT_STATUS_IS_OK(status)) {
7803 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7804 extended_oplock_granted = True;
7807 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7808 extended_oplock_granted = True;
7811 info_level_return = SVAL(pdata,16);
7813 /* Allocate the correct return size. */
7815 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7816 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7817 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7818 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7820 *pdata_return_size = 12;
7823 /* Realloc the data size */
7824 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7825 if (*ppdata == NULL) {
7826 close_file(req, fsp, ERROR_CLOSE);
7827 *pdata_return_size = 0;
7828 return NT_STATUS_NO_MEMORY;
7832 if (extended_oplock_granted) {
7833 if (flags & REQUEST_BATCH_OPLOCK) {
7834 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7836 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7838 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7839 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7841 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7844 SSVAL(pdata,2,fsp->fnum);
7845 SIVAL(pdata,4,info); /* Was file created etc. */
7847 switch (info_level_return) {
7848 case SMB_QUERY_FILE_UNIX_BASIC:
7849 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7850 SSVAL(pdata,10,0); /* padding. */
7851 store_file_unix_basic(conn, pdata + 12, fsp,
7854 case SMB_QUERY_FILE_UNIX_INFO2:
7855 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7856 SSVAL(pdata,10,0); /* padding. */
7857 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7861 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7862 SSVAL(pdata,10,0); /* padding. */
7865 return NT_STATUS_OK;
7868 /****************************************************************************
7869 Delete a file with POSIX semantics.
7870 ****************************************************************************/
7872 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7873 struct smb_request *req,
7876 struct smb_filename *smb_fname)
7878 NTSTATUS status = NT_STATUS_OK;
7879 files_struct *fsp = NULL;
7883 int create_options = 0;
7885 struct share_mode_lock *lck = NULL;
7887 if (total_data < 2) {
7888 return NT_STATUS_INVALID_PARAMETER;
7891 flags = SVAL(pdata,0);
7893 if (!VALID_STAT(smb_fname->st)) {
7894 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7897 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7898 !VALID_STAT_OF_DIR(smb_fname->st)) {
7899 return NT_STATUS_NOT_A_DIRECTORY;
7902 DEBUG(10,("smb_posix_unlink: %s %s\n",
7903 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7904 smb_fname_str_dbg(smb_fname)));
7906 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7907 create_options |= FILE_DIRECTORY_FILE;
7910 status = SMB_VFS_CREATE_FILE(
7913 0, /* root_dir_fid */
7914 smb_fname, /* fname */
7915 DELETE_ACCESS, /* access_mask */
7916 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7918 FILE_OPEN, /* create_disposition*/
7919 create_options, /* create_options */
7920 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7921 0, /* oplock_request */
7923 0, /* allocation_size */
7924 0, /* private_flags */
7929 NULL, NULL); /* create context */
7931 if (!NT_STATUS_IS_OK(status)) {
7936 * Don't lie to client. If we can't really delete due to
7937 * non-POSIX opens return SHARING_VIOLATION.
7940 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7942 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7943 "lock for file %s\n", fsp_str_dbg(fsp)));
7944 close_file(req, fsp, NORMAL_CLOSE);
7945 return NT_STATUS_INVALID_PARAMETER;
7949 * See if others still have the file open. If this is the case, then
7950 * don't delete. If all opens are POSIX delete we can set the delete
7951 * on close disposition.
7953 for (i=0; i<lck->data->num_share_modes; i++) {
7954 struct share_mode_entry *e = &lck->data->share_modes[i];
7955 if (is_valid_share_mode_entry(e)) {
7956 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7959 if (share_mode_stale_pid(lck->data, i)) {
7962 /* Fail with sharing violation. */
7964 close_file(req, fsp, NORMAL_CLOSE);
7965 return NT_STATUS_SHARING_VIOLATION;
7970 * Set the delete on close.
7972 status = smb_set_file_disposition_info(conn,
7980 if (!NT_STATUS_IS_OK(status)) {
7981 close_file(req, fsp, NORMAL_CLOSE);
7984 return close_file(req, fsp, NORMAL_CLOSE);
7987 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7988 struct smb_request *req,
7989 TALLOC_CTX *mem_ctx,
7990 uint16_t info_level,
7992 struct smb_filename *smb_fname,
7993 char **ppdata, int total_data,
7996 char *pdata = *ppdata;
7997 NTSTATUS status = NT_STATUS_OK;
7998 int data_return_size = 0;
8002 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8003 return NT_STATUS_INVALID_LEVEL;
8006 if (!CAN_WRITE(conn)) {
8007 /* Allow POSIX opens. The open path will deny
8008 * any non-readonly opens. */
8009 if (info_level != SMB_POSIX_PATH_OPEN) {
8010 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8014 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8015 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8017 info_level, total_data));
8019 switch (info_level) {
8021 case SMB_INFO_STANDARD:
8023 status = smb_set_info_standard(conn,
8031 case SMB_INFO_SET_EA:
8033 status = smb_info_set_ea(conn,
8041 case SMB_SET_FILE_BASIC_INFO:
8042 case SMB_FILE_BASIC_INFORMATION:
8044 status = smb_set_file_basic_info(conn,
8052 case SMB_FILE_ALLOCATION_INFORMATION:
8053 case SMB_SET_FILE_ALLOCATION_INFO:
8055 status = smb_set_file_allocation_info(conn, req,
8063 case SMB_FILE_END_OF_FILE_INFORMATION:
8064 case SMB_SET_FILE_END_OF_FILE_INFO:
8067 * XP/Win7 both fail after the createfile with
8068 * SMB_SET_FILE_END_OF_FILE_INFO but not
8069 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8070 * The level is known here, so pass it down
8074 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8076 status = smb_set_file_end_of_file_info(conn, req,
8085 case SMB_FILE_DISPOSITION_INFORMATION:
8086 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8089 /* JRA - We used to just ignore this on a path ?
8090 * Shouldn't this be invalid level on a pathname
8093 if (tran_call != TRANSACT2_SETFILEINFO) {
8094 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8097 status = smb_set_file_disposition_info(conn,
8105 case SMB_FILE_POSITION_INFORMATION:
8107 status = smb_file_position_information(conn,
8114 case SMB_FILE_FULL_EA_INFORMATION:
8116 status = smb_set_file_full_ea_info(conn,
8123 /* From tridge Samba4 :
8124 * MODE_INFORMATION in setfileinfo (I have no
8125 * idea what "mode information" on a file is - it takes a value of 0,
8126 * 2, 4 or 6. What could it be?).
8129 case SMB_FILE_MODE_INFORMATION:
8131 status = smb_file_mode_information(conn,
8138 * CIFS UNIX extensions.
8141 case SMB_SET_FILE_UNIX_BASIC:
8143 status = smb_set_file_unix_basic(conn, req,
8151 case SMB_SET_FILE_UNIX_INFO2:
8153 status = smb_set_file_unix_info2(conn, req,
8161 case SMB_SET_FILE_UNIX_LINK:
8164 /* We must have a pathname for this. */
8165 return NT_STATUS_INVALID_LEVEL;
8167 status = smb_set_file_unix_link(conn, req, pdata,
8168 total_data, smb_fname);
8172 case SMB_SET_FILE_UNIX_HLINK:
8175 /* We must have a pathname for this. */
8176 return NT_STATUS_INVALID_LEVEL;
8178 status = smb_set_file_unix_hlink(conn, req,
8184 case SMB_FILE_RENAME_INFORMATION:
8186 status = smb_file_rename_information(conn, req,
8192 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8194 /* SMB2 rename information. */
8195 status = smb2_file_rename_information(conn, req,
8201 case SMB_FILE_LINK_INFORMATION:
8203 status = smb_file_link_information(conn, req,
8209 #if defined(HAVE_POSIX_ACLS)
8210 case SMB_SET_POSIX_ACL:
8212 status = smb_set_posix_acl(conn,
8221 case SMB_SET_POSIX_LOCK:
8224 return NT_STATUS_INVALID_LEVEL;
8226 status = smb_set_posix_lock(conn, req,
8227 pdata, total_data, fsp);
8231 case SMB_POSIX_PATH_OPEN:
8234 /* We must have a pathname for this. */
8235 return NT_STATUS_INVALID_LEVEL;
8238 status = smb_posix_open(conn, req,
8246 case SMB_POSIX_PATH_UNLINK:
8249 /* We must have a pathname for this. */
8250 return NT_STATUS_INVALID_LEVEL;
8253 status = smb_posix_unlink(conn, req,
8261 return NT_STATUS_INVALID_LEVEL;
8264 if (!NT_STATUS_IS_OK(status)) {
8268 *ret_data_size = data_return_size;
8269 return NT_STATUS_OK;
8272 /****************************************************************************
8273 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8274 ****************************************************************************/
8276 static void call_trans2setfilepathinfo(connection_struct *conn,
8277 struct smb_request *req,
8278 unsigned int tran_call,
8279 char **pparams, int total_params,
8280 char **ppdata, int total_data,
8281 unsigned int max_data_bytes)
8283 char *params = *pparams;
8284 char *pdata = *ppdata;
8286 struct smb_filename *smb_fname = NULL;
8287 files_struct *fsp = NULL;
8288 NTSTATUS status = NT_STATUS_OK;
8289 int data_return_size = 0;
8292 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8296 if (tran_call == TRANSACT2_SETFILEINFO) {
8297 if (total_params < 4) {
8298 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8302 fsp = file_fsp(req, SVAL(params,0));
8303 /* Basic check for non-null fsp. */
8304 if (!check_fsp_open(conn, req, fsp)) {
8307 info_level = SVAL(params,2);
8309 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8310 if (smb_fname == NULL) {
8311 reply_nterror(req, NT_STATUS_NO_MEMORY);
8315 if(fsp->fh->fd == -1) {
8317 * This is actually a SETFILEINFO on a directory
8318 * handle (returned from an NT SMB). NT5.0 seems
8319 * to do this call. JRA.
8321 if (INFO_LEVEL_IS_UNIX(info_level)) {
8322 /* Always do lstat for UNIX calls. */
8323 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8324 DEBUG(3,("call_trans2setfilepathinfo: "
8325 "SMB_VFS_LSTAT of %s failed "
8327 smb_fname_str_dbg(smb_fname),
8329 reply_nterror(req, map_nt_error_from_unix(errno));
8333 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8334 DEBUG(3,("call_trans2setfilepathinfo: "
8335 "fileinfo of %s failed (%s)\n",
8336 smb_fname_str_dbg(smb_fname),
8338 reply_nterror(req, map_nt_error_from_unix(errno));
8342 } else if (fsp->print_file) {
8344 * Doing a DELETE_ON_CLOSE should cancel a print job.
8346 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8347 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8349 DEBUG(3,("call_trans2setfilepathinfo: "
8350 "Cancelling print job (%s)\n",
8354 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8360 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8365 * Original code - this is an open file.
8367 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8368 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8369 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8371 reply_nterror(req, map_nt_error_from_unix(errno));
8377 uint32_t ucf_flags = 0;
8380 if (total_params < 7) {
8381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8385 info_level = SVAL(params,0);
8386 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8387 total_params - 6, STR_TERMINATE,
8389 if (!NT_STATUS_IS_OK(status)) {
8390 reply_nterror(req, status);
8394 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8395 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8396 info_level == SMB_FILE_RENAME_INFORMATION ||
8397 info_level == SMB_POSIX_PATH_UNLINK) {
8398 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8401 status = filename_convert(req, conn,
8402 req->flags2 & FLAGS2_DFS_PATHNAMES,
8407 if (!NT_STATUS_IS_OK(status)) {
8408 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8409 reply_botherror(req,
8410 NT_STATUS_PATH_NOT_COVERED,
8411 ERRSRV, ERRbadpath);
8414 reply_nterror(req, status);
8418 if (INFO_LEVEL_IS_UNIX(info_level)) {
8420 * For CIFS UNIX extensions the target name may not exist.
8423 /* Always do lstat for UNIX calls. */
8424 SMB_VFS_LSTAT(conn, smb_fname);
8426 } else if (!VALID_STAT(smb_fname->st) &&
8427 SMB_VFS_STAT(conn, smb_fname)) {
8428 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8430 smb_fname_str_dbg(smb_fname),
8432 reply_nterror(req, map_nt_error_from_unix(errno));
8437 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8438 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8440 info_level,total_data));
8442 /* Realloc the parameter size */
8443 *pparams = (char *)SMB_REALLOC(*pparams,2);
8444 if (*pparams == NULL) {
8445 reply_nterror(req, NT_STATUS_NO_MEMORY);
8452 status = smbd_do_setfilepathinfo(conn, req, req,
8458 if (!NT_STATUS_IS_OK(status)) {
8459 if (open_was_deferred(req->xconn, req->mid)) {
8460 /* We have re-scheduled this call. */
8463 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8464 /* We have re-scheduled this call. */
8467 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8468 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8469 ERRSRV, ERRbadpath);
8472 if (info_level == SMB_POSIX_PATH_OPEN) {
8473 reply_openerror(req, status);
8478 * Invalid EA name needs to return 2 param bytes,
8479 * not a zero-length error packet.
8481 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8482 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8485 reply_nterror(req, status);
8490 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8496 /****************************************************************************
8497 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8498 ****************************************************************************/
8500 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8501 char **pparams, int total_params,
8502 char **ppdata, int total_data,
8503 unsigned int max_data_bytes)
8505 struct smb_filename *smb_dname = NULL;
8506 char *params = *pparams;
8507 char *pdata = *ppdata;
8508 char *directory = NULL;
8509 NTSTATUS status = NT_STATUS_OK;
8510 struct ea_list *ea_list = NULL;
8511 TALLOC_CTX *ctx = talloc_tos();
8513 if (!CAN_WRITE(conn)) {
8514 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8518 if (total_params < 5) {
8519 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8523 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8524 total_params - 4, STR_TERMINATE,
8526 if (!NT_STATUS_IS_OK(status)) {
8527 reply_nterror(req, status);
8531 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8533 status = filename_convert(ctx,
8535 req->flags2 & FLAGS2_DFS_PATHNAMES,
8541 if (!NT_STATUS_IS_OK(status)) {
8542 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8543 reply_botherror(req,
8544 NT_STATUS_PATH_NOT_COVERED,
8545 ERRSRV, ERRbadpath);
8548 reply_nterror(req, status);
8553 * OS/2 workplace shell seems to send SET_EA requests of "null"
8554 * length (4 bytes containing IVAL 4).
8555 * They seem to have no effect. Bug #3212. JRA.
8558 if (total_data && (total_data != 4)) {
8559 /* Any data in this call is an EA list. */
8560 if (total_data < 10) {
8561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8565 if (IVAL(pdata,0) > total_data) {
8566 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8567 IVAL(pdata,0), (unsigned int)total_data));
8568 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8572 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8575 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8579 if (!lp_ea_support(SNUM(conn))) {
8580 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8584 /* If total_data == 4 Windows doesn't care what values
8585 * are placed in that field, it just ignores them.
8586 * The System i QNTC IBM SMB client puts bad values here,
8587 * so ignore them. */
8589 status = create_directory(conn, req, smb_dname);
8591 if (!NT_STATUS_IS_OK(status)) {
8592 reply_nterror(req, status);
8596 /* Try and set any given EA. */
8598 status = set_ea(conn, NULL, smb_dname, ea_list);
8599 if (!NT_STATUS_IS_OK(status)) {
8600 reply_nterror(req, status);
8605 /* Realloc the parameter and data sizes */
8606 *pparams = (char *)SMB_REALLOC(*pparams,2);
8607 if(*pparams == NULL) {
8608 reply_nterror(req, NT_STATUS_NO_MEMORY);
8615 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8618 TALLOC_FREE(smb_dname);
8622 /****************************************************************************
8623 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8624 We don't actually do this - we just send a null response.
8625 ****************************************************************************/
8627 static void call_trans2findnotifyfirst(connection_struct *conn,
8628 struct smb_request *req,
8629 char **pparams, int total_params,
8630 char **ppdata, int total_data,
8631 unsigned int max_data_bytes)
8633 char *params = *pparams;
8636 if (total_params < 6) {
8637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8641 info_level = SVAL(params,4);
8642 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8644 switch (info_level) {
8649 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8653 /* Realloc the parameter and data sizes */
8654 *pparams = (char *)SMB_REALLOC(*pparams,6);
8655 if (*pparams == NULL) {
8656 reply_nterror(req, NT_STATUS_NO_MEMORY);
8661 SSVAL(params,0,fnf_handle);
8662 SSVAL(params,2,0); /* No changes */
8663 SSVAL(params,4,0); /* No EA errors */
8670 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8675 /****************************************************************************
8676 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8677 changes). Currently this does nothing.
8678 ****************************************************************************/
8680 static void call_trans2findnotifynext(connection_struct *conn,
8681 struct smb_request *req,
8682 char **pparams, int total_params,
8683 char **ppdata, int total_data,
8684 unsigned int max_data_bytes)
8686 char *params = *pparams;
8688 DEBUG(3,("call_trans2findnotifynext\n"));
8690 /* Realloc the parameter and data sizes */
8691 *pparams = (char *)SMB_REALLOC(*pparams,4);
8692 if (*pparams == NULL) {
8693 reply_nterror(req, NT_STATUS_NO_MEMORY);
8698 SSVAL(params,0,0); /* No changes */
8699 SSVAL(params,2,0); /* No EA errors */
8701 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8706 /****************************************************************************
8707 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8708 ****************************************************************************/
8710 static void call_trans2getdfsreferral(connection_struct *conn,
8711 struct smb_request *req,
8712 char **pparams, int total_params,
8713 char **ppdata, int total_data,
8714 unsigned int max_data_bytes)
8716 char *params = *pparams;
8717 char *pathname = NULL;
8719 int max_referral_level;
8720 NTSTATUS status = NT_STATUS_OK;
8721 TALLOC_CTX *ctx = talloc_tos();
8723 DEBUG(10,("call_trans2getdfsreferral\n"));
8725 if (total_params < 3) {
8726 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8730 max_referral_level = SVAL(params,0);
8732 if(!lp_host_msdfs()) {
8733 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8737 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8738 total_params - 2, STR_TERMINATE);
8740 reply_nterror(req, NT_STATUS_NOT_FOUND);
8743 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8744 ppdata,&status)) < 0) {
8745 reply_nterror(req, status);
8749 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8750 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8751 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8756 #define LMCAT_SPL 0x53
8757 #define LMFUNC_GETJOBID 0x60
8759 /****************************************************************************
8760 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8761 ****************************************************************************/
8763 static void call_trans2ioctl(connection_struct *conn,
8764 struct smb_request *req,
8765 char **pparams, int total_params,
8766 char **ppdata, int total_data,
8767 unsigned int max_data_bytes)
8769 char *pdata = *ppdata;
8770 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8774 /* check for an invalid fid before proceeding */
8777 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8781 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8782 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8783 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8784 if (*ppdata == NULL) {
8785 reply_nterror(req, NT_STATUS_NO_MEMORY);
8790 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8791 CAN ACCEPT THIS IN UNICODE. JRA. */
8794 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8796 status = srvstr_push(pdata, req->flags2, pdata + 2,
8797 lp_netbios_name(), 15,
8798 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
8799 if (!NT_STATUS_IS_OK(status)) {
8800 reply_nterror(req, status);
8803 status = srvstr_push(pdata, req->flags2, pdata+18,
8804 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8805 STR_ASCII|STR_TERMINATE, &len); /* Service name */
8806 if (!NT_STATUS_IS_OK(status)) {
8807 reply_nterror(req, status);
8810 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8815 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8816 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8819 /****************************************************************************
8820 Reply to a SMBfindclose (stop trans2 directory search).
8821 ****************************************************************************/
8823 void reply_findclose(struct smb_request *req)
8826 struct smbd_server_connection *sconn = req->sconn;
8828 START_PROFILE(SMBfindclose);
8831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8832 END_PROFILE(SMBfindclose);
8836 dptr_num = SVALS(req->vwv+0, 0);
8838 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8840 dptr_close(sconn, &dptr_num);
8842 reply_outbuf(req, 0, 0);
8844 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8846 END_PROFILE(SMBfindclose);
8850 /****************************************************************************
8851 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8852 ****************************************************************************/
8854 void reply_findnclose(struct smb_request *req)
8858 START_PROFILE(SMBfindnclose);
8861 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8862 END_PROFILE(SMBfindnclose);
8866 dptr_num = SVAL(req->vwv+0, 0);
8868 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8870 /* We never give out valid handles for a
8871 findnotifyfirst - so any dptr_num is ok here.
8874 reply_outbuf(req, 0, 0);
8876 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8878 END_PROFILE(SMBfindnclose);
8882 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8883 struct trans_state *state)
8885 if (get_Protocol() >= PROTOCOL_NT1) {
8886 req->flags2 |= 0x40; /* IS_LONG_NAME */
8887 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8890 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8891 if (state->call != TRANSACT2_QFSINFO &&
8892 state->call != TRANSACT2_SETFSINFO) {
8893 DEBUG(0,("handle_trans2: encryption required "
8895 (unsigned int)state->call));
8896 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8901 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8903 /* Now we must call the relevant TRANS2 function */
8904 switch(state->call) {
8905 case TRANSACT2_OPEN:
8907 START_PROFILE(Trans2_open);
8908 call_trans2open(conn, req,
8909 &state->param, state->total_param,
8910 &state->data, state->total_data,
8911 state->max_data_return);
8912 END_PROFILE(Trans2_open);
8916 case TRANSACT2_FINDFIRST:
8918 START_PROFILE(Trans2_findfirst);
8919 call_trans2findfirst(conn, req,
8920 &state->param, state->total_param,
8921 &state->data, state->total_data,
8922 state->max_data_return);
8923 END_PROFILE(Trans2_findfirst);
8927 case TRANSACT2_FINDNEXT:
8929 START_PROFILE(Trans2_findnext);
8930 call_trans2findnext(conn, req,
8931 &state->param, state->total_param,
8932 &state->data, state->total_data,
8933 state->max_data_return);
8934 END_PROFILE(Trans2_findnext);
8938 case TRANSACT2_QFSINFO:
8940 START_PROFILE(Trans2_qfsinfo);
8941 call_trans2qfsinfo(conn, req,
8942 &state->param, state->total_param,
8943 &state->data, state->total_data,
8944 state->max_data_return);
8945 END_PROFILE(Trans2_qfsinfo);
8949 case TRANSACT2_SETFSINFO:
8951 START_PROFILE(Trans2_setfsinfo);
8952 call_trans2setfsinfo(conn, req,
8953 &state->param, state->total_param,
8954 &state->data, state->total_data,
8955 state->max_data_return);
8956 END_PROFILE(Trans2_setfsinfo);
8960 case TRANSACT2_QPATHINFO:
8961 case TRANSACT2_QFILEINFO:
8963 START_PROFILE(Trans2_qpathinfo);
8964 call_trans2qfilepathinfo(conn, req, state->call,
8965 &state->param, state->total_param,
8966 &state->data, state->total_data,
8967 state->max_data_return);
8968 END_PROFILE(Trans2_qpathinfo);
8972 case TRANSACT2_SETPATHINFO:
8973 case TRANSACT2_SETFILEINFO:
8975 START_PROFILE(Trans2_setpathinfo);
8976 call_trans2setfilepathinfo(conn, req, state->call,
8977 &state->param, state->total_param,
8978 &state->data, state->total_data,
8979 state->max_data_return);
8980 END_PROFILE(Trans2_setpathinfo);
8984 case TRANSACT2_FINDNOTIFYFIRST:
8986 START_PROFILE(Trans2_findnotifyfirst);
8987 call_trans2findnotifyfirst(conn, req,
8988 &state->param, state->total_param,
8989 &state->data, state->total_data,
8990 state->max_data_return);
8991 END_PROFILE(Trans2_findnotifyfirst);
8995 case TRANSACT2_FINDNOTIFYNEXT:
8997 START_PROFILE(Trans2_findnotifynext);
8998 call_trans2findnotifynext(conn, req,
8999 &state->param, state->total_param,
9000 &state->data, state->total_data,
9001 state->max_data_return);
9002 END_PROFILE(Trans2_findnotifynext);
9006 case TRANSACT2_MKDIR:
9008 START_PROFILE(Trans2_mkdir);
9009 call_trans2mkdir(conn, req,
9010 &state->param, state->total_param,
9011 &state->data, state->total_data,
9012 state->max_data_return);
9013 END_PROFILE(Trans2_mkdir);
9017 case TRANSACT2_GET_DFS_REFERRAL:
9019 START_PROFILE(Trans2_get_dfs_referral);
9020 call_trans2getdfsreferral(conn, req,
9021 &state->param, state->total_param,
9022 &state->data, state->total_data,
9023 state->max_data_return);
9024 END_PROFILE(Trans2_get_dfs_referral);
9028 case TRANSACT2_IOCTL:
9030 START_PROFILE(Trans2_ioctl);
9031 call_trans2ioctl(conn, req,
9032 &state->param, state->total_param,
9033 &state->data, state->total_data,
9034 state->max_data_return);
9035 END_PROFILE(Trans2_ioctl);
9040 /* Error in request */
9041 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9042 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9046 /****************************************************************************
9047 Reply to a SMBtrans2.
9048 ****************************************************************************/
9050 void reply_trans2(struct smb_request *req)
9052 connection_struct *conn = req->conn;
9057 unsigned int tran_call;
9058 struct trans_state *state;
9061 START_PROFILE(SMBtrans2);
9063 if (req->wct < 14) {
9064 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9065 END_PROFILE(SMBtrans2);
9069 dsoff = SVAL(req->vwv+12, 0);
9070 dscnt = SVAL(req->vwv+11, 0);
9071 psoff = SVAL(req->vwv+10, 0);
9072 pscnt = SVAL(req->vwv+9, 0);
9073 tran_call = SVAL(req->vwv+14, 0);
9075 result = allow_new_trans(conn->pending_trans, req->mid);
9076 if (!NT_STATUS_IS_OK(result)) {
9077 DEBUG(2, ("Got invalid trans2 request: %s\n",
9078 nt_errstr(result)));
9079 reply_nterror(req, result);
9080 END_PROFILE(SMBtrans2);
9085 switch (tran_call) {
9086 /* List the allowed trans2 calls on IPC$ */
9087 case TRANSACT2_OPEN:
9088 case TRANSACT2_GET_DFS_REFERRAL:
9089 case TRANSACT2_QFILEINFO:
9090 case TRANSACT2_QFSINFO:
9091 case TRANSACT2_SETFSINFO:
9094 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9095 END_PROFILE(SMBtrans2);
9100 if ((state = talloc(conn, struct trans_state)) == NULL) {
9101 DEBUG(0, ("talloc failed\n"));
9102 reply_nterror(req, NT_STATUS_NO_MEMORY);
9103 END_PROFILE(SMBtrans2);
9107 state->cmd = SMBtrans2;
9109 state->mid = req->mid;
9110 state->vuid = req->vuid;
9111 state->setup_count = SVAL(req->vwv+13, 0);
9112 state->setup = NULL;
9113 state->total_param = SVAL(req->vwv+0, 0);
9114 state->param = NULL;
9115 state->total_data = SVAL(req->vwv+1, 0);
9117 state->max_param_return = SVAL(req->vwv+2, 0);
9118 state->max_data_return = SVAL(req->vwv+3, 0);
9119 state->max_setup_return = SVAL(req->vwv+4, 0);
9120 state->close_on_completion = BITSETW(req->vwv+5, 0);
9121 state->one_way = BITSETW(req->vwv+5, 1);
9123 state->call = tran_call;
9125 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9126 is so as a sanity check */
9127 if (state->setup_count != 1) {
9129 * Need to have rc=0 for ioctl to get job id for OS/2.
9130 * Network printing will fail if function is not successful.
9131 * Similar function in reply.c will be used if protocol
9132 * is LANMAN1.0 instead of LM1.2X002.
9133 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9134 * outbuf doesn't have to be set(only job id is used).
9136 if ( (state->setup_count == 4)
9137 && (tran_call == TRANSACT2_IOCTL)
9138 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9139 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9140 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9142 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9143 DEBUG(2,("Transaction is %d\n",tran_call));
9145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9146 END_PROFILE(SMBtrans2);
9151 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9154 if (state->total_data) {
9156 if (trans_oob(state->total_data, 0, dscnt)
9157 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9161 /* Can't use talloc here, the core routines do realloc on the
9162 * params and data. */
9163 state->data = (char *)SMB_MALLOC(state->total_data);
9164 if (state->data == NULL) {
9165 DEBUG(0,("reply_trans2: data malloc fail for %u "
9166 "bytes !\n", (unsigned int)state->total_data));
9168 reply_nterror(req, NT_STATUS_NO_MEMORY);
9169 END_PROFILE(SMBtrans2);
9173 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9176 if (state->total_param) {
9178 if (trans_oob(state->total_param, 0, pscnt)
9179 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9183 /* Can't use talloc here, the core routines do realloc on the
9184 * params and data. */
9185 state->param = (char *)SMB_MALLOC(state->total_param);
9186 if (state->param == NULL) {
9187 DEBUG(0,("reply_trans: param malloc fail for %u "
9188 "bytes !\n", (unsigned int)state->total_param));
9189 SAFE_FREE(state->data);
9191 reply_nterror(req, NT_STATUS_NO_MEMORY);
9192 END_PROFILE(SMBtrans2);
9196 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9199 state->received_data = dscnt;
9200 state->received_param = pscnt;
9202 if ((state->received_param == state->total_param) &&
9203 (state->received_data == state->total_data)) {
9205 handle_trans2(conn, req, state);
9207 SAFE_FREE(state->data);
9208 SAFE_FREE(state->param);
9210 END_PROFILE(SMBtrans2);
9214 DLIST_ADD(conn->pending_trans, state);
9216 /* We need to send an interim response then receive the rest
9217 of the parameter/data bytes */
9218 reply_outbuf(req, 0, 0);
9219 show_msg((char *)req->outbuf);
9220 END_PROFILE(SMBtrans2);
9225 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9226 SAFE_FREE(state->data);
9227 SAFE_FREE(state->param);
9229 END_PROFILE(SMBtrans2);
9230 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9234 /****************************************************************************
9235 Reply to a SMBtranss2
9236 ****************************************************************************/
9238 void reply_transs2(struct smb_request *req)
9240 connection_struct *conn = req->conn;
9241 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9242 struct trans_state *state;
9244 START_PROFILE(SMBtranss2);
9246 show_msg((const char *)req->inbuf);
9248 /* Windows clients expect all replies to
9249 a transact secondary (SMBtranss2 0x33)
9250 to have a command code of transact
9251 (SMBtrans2 0x32). See bug #8989
9252 and also [MS-CIFS] section 2.2.4.47.2
9255 req->cmd = SMBtrans2;
9258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9259 END_PROFILE(SMBtranss2);
9263 for (state = conn->pending_trans; state != NULL;
9264 state = state->next) {
9265 if (state->mid == req->mid) {
9270 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9271 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9272 END_PROFILE(SMBtranss2);
9276 /* Revise state->total_param and state->total_data in case they have
9277 changed downwards */
9279 if (SVAL(req->vwv+0, 0) < state->total_param)
9280 state->total_param = SVAL(req->vwv+0, 0);
9281 if (SVAL(req->vwv+1, 0) < state->total_data)
9282 state->total_data = SVAL(req->vwv+1, 0);
9284 pcnt = SVAL(req->vwv+2, 0);
9285 poff = SVAL(req->vwv+3, 0);
9286 pdisp = SVAL(req->vwv+4, 0);
9288 dcnt = SVAL(req->vwv+5, 0);
9289 doff = SVAL(req->vwv+6, 0);
9290 ddisp = SVAL(req->vwv+7, 0);
9292 state->received_param += pcnt;
9293 state->received_data += dcnt;
9295 if ((state->received_data > state->total_data) ||
9296 (state->received_param > state->total_param))
9300 if (trans_oob(state->total_param, pdisp, pcnt)
9301 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9304 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9308 if (trans_oob(state->total_data, ddisp, dcnt)
9309 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9312 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9315 if ((state->received_param < state->total_param) ||
9316 (state->received_data < state->total_data)) {
9317 END_PROFILE(SMBtranss2);
9321 handle_trans2(conn, req, state);
9323 DLIST_REMOVE(conn->pending_trans, state);
9324 SAFE_FREE(state->data);
9325 SAFE_FREE(state->param);
9328 END_PROFILE(SMBtranss2);
9333 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9334 DLIST_REMOVE(conn->pending_trans, state);
9335 SAFE_FREE(state->data);
9336 SAFE_FREE(state->param);
9338 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9339 END_PROFILE(SMBtranss2);