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_t *)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;
1090 uint32_t access_mask;
1091 uint32_t share_mode;
1092 uint32_t create_disposition;
1093 uint32_t 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_t)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_t 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_t 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 = {0};
1624 struct timespec adate_ts = {0};
1625 struct timespec cdate_ts = {0};
1626 struct timespec create_date_ts = {0};
1627 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1629 char *last_entry_ptr;
1634 struct readdir_attr_data *readdir_attr_data = NULL;
1636 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1637 file_size = get_file_size_stat(&smb_fname->st);
1639 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1641 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1642 if (!NT_STATUS_IS_OK(status)) {
1643 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1648 file_index = get_FileIndex(conn, &smb_fname->st);
1650 mdate_ts = smb_fname->st.st_ex_mtime;
1651 adate_ts = smb_fname->st.st_ex_atime;
1652 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1653 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1655 if (lp_dos_filetime_resolution(SNUM(conn))) {
1656 dos_filetime_timespec(&create_date_ts);
1657 dos_filetime_timespec(&mdate_ts);
1658 dos_filetime_timespec(&adate_ts);
1659 dos_filetime_timespec(&cdate_ts);
1662 create_date = convert_timespec_to_time_t(create_date_ts);
1663 mdate = convert_timespec_to_time_t(mdate_ts);
1664 adate = convert_timespec_to_time_t(adate_ts);
1666 /* align the record */
1667 SMB_ASSERT(align >= 1);
1669 off = (int)PTR_DIFF(pdata, base_data);
1670 pad = (off + (align-1)) & ~(align-1);
1673 if (pad && pad > space_remaining) {
1674 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1675 "for padding (wanted %u, had %d)\n",
1678 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1682 /* initialize padding to 0 */
1684 memset(pdata, 0, pad);
1686 space_remaining -= pad;
1688 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1698 switch (info_level) {
1699 case SMB_FIND_INFO_STANDARD:
1700 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1701 if(requires_resume_key) {
1705 srv_put_dos_date2(p,0,create_date);
1706 srv_put_dos_date2(p,4,adate);
1707 srv_put_dos_date2(p,8,mdate);
1708 SIVAL(p,12,(uint32_t)file_size);
1709 SIVAL(p,16,(uint32_t)allocation_size);
1713 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1714 p += ucs2_align(base_data, p, 0);
1716 status = srvstr_push(base_data, flags2, p,
1717 fname, PTR_DIFF(end_data, p),
1718 STR_TERMINATE, &len);
1719 if (!NT_STATUS_IS_OK(status)) {
1722 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1724 SCVAL(nameptr, -1, len - 2);
1726 SCVAL(nameptr, -1, 0);
1730 SCVAL(nameptr, -1, len - 1);
1732 SCVAL(nameptr, -1, 0);
1738 case SMB_FIND_EA_SIZE:
1739 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1740 if (requires_resume_key) {
1744 srv_put_dos_date2(p,0,create_date);
1745 srv_put_dos_date2(p,4,adate);
1746 srv_put_dos_date2(p,8,mdate);
1747 SIVAL(p,12,(uint32_t)file_size);
1748 SIVAL(p,16,(uint32_t)allocation_size);
1751 unsigned int ea_size = estimate_ea_size(conn, NULL,
1753 SIVAL(p,22,ea_size); /* Extended attributes */
1757 status = srvstr_push(base_data, flags2,
1758 p, fname, PTR_DIFF(end_data, p),
1759 STR_TERMINATE | STR_NOALIGN, &len);
1760 if (!NT_STATUS_IS_OK(status)) {
1763 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1776 SCVAL(nameptr,0,len);
1778 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1781 case SMB_FIND_EA_LIST:
1783 struct ea_list *file_list = NULL;
1786 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1788 return NT_STATUS_INVALID_PARAMETER;
1790 if (requires_resume_key) {
1794 srv_put_dos_date2(p,0,create_date);
1795 srv_put_dos_date2(p,4,adate);
1796 srv_put_dos_date2(p,8,mdate);
1797 SIVAL(p,12,(uint32_t)file_size);
1798 SIVAL(p,16,(uint32_t)allocation_size);
1800 p += 22; /* p now points to the EA area. */
1802 status = get_ea_list_from_file(ctx, conn, NULL,
1804 &ea_len, &file_list);
1805 if (!NT_STATUS_IS_OK(status)) {
1808 name_list = ea_list_union(name_list, file_list, &ea_len);
1810 /* We need to determine if this entry will fit in the space available. */
1811 /* Max string size is 255 bytes. */
1812 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1813 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1814 "(wanted %u, had %d)\n",
1815 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1817 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1820 /* Push the ea_data followed by the name. */
1821 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1823 status = srvstr_push(base_data, flags2,
1824 p + 1, fname, PTR_DIFF(end_data, p+1),
1825 STR_TERMINATE | STR_NOALIGN, &len);
1826 if (!NT_STATUS_IS_OK(status)) {
1829 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1842 SCVAL(nameptr,0,len);
1844 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1848 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1849 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1850 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1852 SIVAL(p,0,reskey); p += 4;
1853 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1854 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1855 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1856 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1857 SOFF_T(p,0,file_size); p += 8;
1858 SOFF_T(p,0,allocation_size); p += 8;
1859 SIVAL(p,0,mode); p += 4;
1860 q = p; p += 4; /* q is placeholder for name length. */
1861 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1862 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1864 unsigned int ea_size = estimate_ea_size(conn, NULL,
1866 SIVAL(p,0,ea_size); /* Extended attributes */
1869 /* Clear the short name buffer. This is
1870 * IMPORTANT as not doing so will trigger
1871 * a Win2k client bug. JRA.
1873 if (!was_8_3 && check_mangled_names) {
1874 char mangled_name[13]; /* mangled 8.3 name. */
1875 if (!name_to_8_3(fname,mangled_name,True,
1877 /* Error - mangle failed ! */
1878 memset(mangled_name,'\0',12);
1880 mangled_name[12] = 0;
1881 status = srvstr_push(base_data, flags2,
1882 p+2, mangled_name, 24,
1883 STR_UPPER|STR_UNICODE, &len);
1884 if (!NT_STATUS_IS_OK(status)) {
1888 memset(p + 2 + len,'\0',24 - len);
1895 status = srvstr_push(base_data, flags2, p,
1896 fname, PTR_DIFF(end_data, p),
1897 STR_TERMINATE_ASCII, &len);
1898 if (!NT_STATUS_IS_OK(status)) {
1904 len = PTR_DIFF(p, pdata);
1905 pad = (len + (align-1)) & ~(align-1);
1907 * offset to the next entry, the caller
1908 * will overwrite it for the last entry
1909 * that's why we always include the padding
1913 * set padding to zero
1916 memset(p, 0, pad - len);
1923 case SMB_FIND_FILE_DIRECTORY_INFO:
1924 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1926 SIVAL(p,0,reskey); p += 4;
1927 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1928 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1929 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1930 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1931 SOFF_T(p,0,file_size); p += 8;
1932 SOFF_T(p,0,allocation_size); p += 8;
1933 SIVAL(p,0,mode); p += 4;
1934 status = srvstr_push(base_data, flags2,
1935 p + 4, fname, PTR_DIFF(end_data, p+4),
1936 STR_TERMINATE_ASCII, &len);
1937 if (!NT_STATUS_IS_OK(status)) {
1943 len = PTR_DIFF(p, pdata);
1944 pad = (len + (align-1)) & ~(align-1);
1946 * offset to the next entry, the caller
1947 * will overwrite it for the last entry
1948 * that's why we always include the padding
1952 * set padding to zero
1955 memset(p, 0, pad - len);
1962 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1963 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1965 SIVAL(p,0,reskey); p += 4;
1966 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1967 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1968 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1969 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1970 SOFF_T(p,0,file_size); p += 8;
1971 SOFF_T(p,0,allocation_size); p += 8;
1972 SIVAL(p,0,mode); p += 4;
1973 q = p; p += 4; /* q is placeholder for name length. */
1975 unsigned int ea_size = estimate_ea_size(conn, NULL,
1977 SIVAL(p,0,ea_size); /* Extended attributes */
1980 status = srvstr_push(base_data, flags2, p,
1981 fname, PTR_DIFF(end_data, p),
1982 STR_TERMINATE_ASCII, &len);
1983 if (!NT_STATUS_IS_OK(status)) {
1989 len = PTR_DIFF(p, pdata);
1990 pad = (len + (align-1)) & ~(align-1);
1992 * offset to the next entry, the caller
1993 * will overwrite it for the last entry
1994 * that's why we always include the padding
1998 * set padding to zero
2001 memset(p, 0, pad - len);
2008 case SMB_FIND_FILE_NAMES_INFO:
2009 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2011 SIVAL(p,0,reskey); p += 4;
2013 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2014 acl on a dir (tridge) */
2015 status = srvstr_push(base_data, flags2, p,
2016 fname, PTR_DIFF(end_data, p),
2017 STR_TERMINATE_ASCII, &len);
2018 if (!NT_STATUS_IS_OK(status)) {
2024 len = PTR_DIFF(p, pdata);
2025 pad = (len + (align-1)) & ~(align-1);
2027 * offset to the next entry, the caller
2028 * will overwrite it for the last entry
2029 * that's why we always include the padding
2033 * set padding to zero
2036 memset(p, 0, pad - len);
2043 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2044 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2046 SIVAL(p,0,reskey); p += 4;
2047 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2048 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2049 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2050 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2051 SOFF_T(p,0,file_size); p += 8;
2052 SOFF_T(p,0,allocation_size); p += 8;
2053 SIVAL(p,0,mode); p += 4;
2054 q = p; p += 4; /* q is placeholder for name length. */
2055 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2056 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2058 unsigned int ea_size = estimate_ea_size(conn, NULL,
2060 SIVAL(p,0,ea_size); /* Extended attributes */
2063 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2064 SBVAL(p,0,file_index); p += 8;
2065 status = srvstr_push(base_data, flags2, p,
2066 fname, PTR_DIFF(end_data, p),
2067 STR_TERMINATE_ASCII, &len);
2068 if (!NT_STATUS_IS_OK(status)) {
2074 len = PTR_DIFF(p, pdata);
2075 pad = (len + (align-1)) & ~(align-1);
2077 * offset to the next entry, the caller
2078 * will overwrite it for the last entry
2079 * that's why we always include the padding
2083 * set padding to zero
2086 memset(p, 0, pad - len);
2093 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2094 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2095 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2097 SIVAL(p,0,reskey); p += 4;
2098 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2099 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2100 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2101 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2102 SOFF_T(p,0,file_size); p += 8;
2103 SOFF_T(p,0,allocation_size); p += 8;
2104 SIVAL(p,0,mode); p += 4;
2105 q = p; p += 4; /* q is placeholder for name length */
2106 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2107 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2108 } else if (readdir_attr_data &&
2109 readdir_attr_data->type == RDATTR_AAPL) {
2111 * OS X specific SMB2 extension negotiated via
2112 * AAPL create context: return max_access in
2115 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2117 unsigned int ea_size = estimate_ea_size(conn, NULL,
2119 SIVAL(p,0,ea_size); /* Extended attributes */
2123 if (readdir_attr_data &&
2124 readdir_attr_data->type == RDATTR_AAPL) {
2126 * OS X specific SMB2 extension negotiated via
2127 * AAPL create context: return resource fork
2128 * length and compressed FinderInfo in
2131 * According to documentation short_name_len
2132 * should be 0, but on the wire behaviour
2133 * shows its set to 24 by clients.
2137 /* Resourefork length */
2138 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2140 /* Compressed FinderInfo */
2141 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2142 } else if (!was_8_3 && check_mangled_names) {
2143 char mangled_name[13]; /* mangled 8.3 name. */
2144 if (!name_to_8_3(fname,mangled_name,True,
2146 /* Error - mangle failed ! */
2147 memset(mangled_name,'\0',12);
2149 mangled_name[12] = 0;
2150 status = srvstr_push(base_data, flags2,
2151 p+2, mangled_name, 24,
2152 STR_UPPER|STR_UNICODE, &len);
2153 if (!NT_STATUS_IS_OK(status)) {
2158 memset(p + 2 + len,'\0',24 - len);
2162 /* Clear the short name buffer. This is
2163 * IMPORTANT as not doing so will trigger
2164 * a Win2k client bug. JRA.
2171 if (readdir_attr_data &&
2172 readdir_attr_data->type == RDATTR_AAPL) {
2174 * OS X specific SMB2 extension negotiated via
2175 * AAPL create context: return UNIX mode in
2178 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2179 SSVAL(p, 0, aapl_mode);
2185 SBVAL(p,0,file_index); p += 8;
2186 status = srvstr_push(base_data, flags2, p,
2187 fname, PTR_DIFF(end_data, p),
2188 STR_TERMINATE_ASCII, &len);
2189 if (!NT_STATUS_IS_OK(status)) {
2195 len = PTR_DIFF(p, pdata);
2196 pad = (len + (align-1)) & ~(align-1);
2198 * offset to the next entry, the caller
2199 * will overwrite it for the last entry
2200 * that's why we always include the padding
2204 * set padding to zero
2207 memset(p, 0, pad - len);
2214 /* CIFS UNIX Extension. */
2216 case SMB_FIND_FILE_UNIX:
2217 case SMB_FIND_FILE_UNIX_INFO2:
2219 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2221 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2223 if (info_level == SMB_FIND_FILE_UNIX) {
2224 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2225 p = store_file_unix_basic(conn, p,
2226 NULL, &smb_fname->st);
2227 status = srvstr_push(base_data, flags2, p,
2228 fname, PTR_DIFF(end_data, p),
2229 STR_TERMINATE, &len);
2230 if (!NT_STATUS_IS_OK(status)) {
2234 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2235 p = store_file_unix_basic_info2(conn, p,
2236 NULL, &smb_fname->st);
2239 status = srvstr_push(base_data, flags2, p, fname,
2240 PTR_DIFF(end_data, p), 0, &len);
2241 if (!NT_STATUS_IS_OK(status)) {
2244 SIVAL(nameptr, 0, len);
2249 len = PTR_DIFF(p, pdata);
2250 pad = (len + (align-1)) & ~(align-1);
2252 * offset to the next entry, the caller
2253 * will overwrite it for the last entry
2254 * that's why we always include the padding
2258 * set padding to zero
2261 memset(p, 0, pad - len);
2266 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2271 return NT_STATUS_INVALID_LEVEL;
2274 if (PTR_DIFF(p,pdata) > space_remaining) {
2275 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2276 "(wanted %u, had %d)\n",
2277 (unsigned int)PTR_DIFF(p,pdata),
2279 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2282 /* Setup the last entry pointer, as an offset from base_data */
2283 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2284 /* Advance the data pointer to the next slot */
2287 return NT_STATUS_OK;
2290 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2291 connection_struct *conn,
2292 struct dptr_struct *dirptr,
2294 const char *path_mask,
2297 int requires_resume_key,
2305 int space_remaining,
2306 bool *got_exact_match,
2307 int *_last_entry_off,
2308 struct ea_list *name_list)
2311 const char *mask = NULL;
2312 long prev_dirpos = 0;
2315 struct smb_filename *smb_fname = NULL;
2316 struct smbd_dirptr_lanman2_state state;
2318 uint64_t last_entry_off = 0;
2323 state.info_level = info_level;
2324 state.check_mangled_names = lp_mangled_names(conn->params);
2325 state.has_wild = dptr_has_wild(dirptr);
2326 state.got_exact_match = false;
2328 *got_exact_match = false;
2330 p = strrchr_m(path_mask,'/');
2341 ok = smbd_dirptr_get_entry(ctx,
2347 smbd_dirptr_lanman2_match_fn,
2348 smbd_dirptr_lanman2_mode_fn,
2355 return NT_STATUS_END_OF_FILE;
2358 *got_exact_match = state.got_exact_match;
2360 status = smbd_marshall_dir_entry(ctx,
2365 state.check_mangled_names,
2366 requires_resume_key,
2377 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2378 DEBUG(1,("Conversion error: illegal character: %s\n",
2379 smb_fname_str_dbg(smb_fname)));
2382 TALLOC_FREE(smb_fname);
2383 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2384 dptr_SeekDir(dirptr, prev_dirpos);
2387 if (!NT_STATUS_IS_OK(status)) {
2391 *_last_entry_off = last_entry_off;
2392 return NT_STATUS_OK;
2395 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2396 connection_struct *conn,
2397 struct dptr_struct *dirptr,
2399 const char *path_mask,
2402 bool requires_resume_key,
2408 int space_remaining,
2409 bool *got_exact_match,
2410 int *last_entry_off,
2411 struct ea_list *name_list)
2414 const bool do_pad = true;
2416 if (info_level >= 1 && info_level <= 3) {
2417 /* No alignment on earlier info levels. */
2421 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2422 path_mask, dirtype, info_level,
2423 requires_resume_key, dont_descend, ask_sharemode,
2425 ppdata, base_data, end_data,
2428 last_entry_off, name_list);
2431 /****************************************************************************
2432 Reply to a TRANS2_FINDFIRST.
2433 ****************************************************************************/
2435 static void call_trans2findfirst(connection_struct *conn,
2436 struct smb_request *req,
2437 char **pparams, int total_params,
2438 char **ppdata, int total_data,
2439 unsigned int max_data_bytes)
2441 /* We must be careful here that we don't return more than the
2442 allowed number of data bytes. If this means returning fewer than
2443 maxentries then so be it. We assume that the redirector has
2444 enough room for the fixed number of parameter bytes it has
2446 struct smb_filename *smb_dname = NULL;
2447 char *params = *pparams;
2448 char *pdata = *ppdata;
2452 uint16_t findfirst_flags;
2453 bool close_after_first;
2455 bool requires_resume_key;
2457 char *directory = NULL;
2460 int last_entry_off=0;
2464 bool finished = False;
2465 bool dont_descend = False;
2466 bool out_of_space = False;
2467 int space_remaining;
2468 bool mask_contains_wcard = False;
2469 struct ea_list *ea_list = NULL;
2470 NTSTATUS ntstatus = NT_STATUS_OK;
2471 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2472 TALLOC_CTX *ctx = talloc_tos();
2473 struct dptr_struct *dirptr = NULL;
2474 struct smbd_server_connection *sconn = req->sconn;
2475 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2476 bool backup_priv = false;
2477 bool as_root = false;
2479 if (total_params < 13) {
2480 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2484 dirtype = SVAL(params,0);
2485 maxentries = SVAL(params,2);
2486 findfirst_flags = SVAL(params,4);
2487 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2488 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2489 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2490 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2491 security_token_has_privilege(get_current_nttok(conn),
2494 info_level = SVAL(params,6);
2496 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2497 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2498 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2500 info_level, max_data_bytes));
2503 /* W2K3 seems to treat zero as 1. */
2507 switch (info_level) {
2508 case SMB_FIND_INFO_STANDARD:
2509 case SMB_FIND_EA_SIZE:
2510 case SMB_FIND_EA_LIST:
2511 case SMB_FIND_FILE_DIRECTORY_INFO:
2512 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2513 case SMB_FIND_FILE_NAMES_INFO:
2514 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2515 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2516 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2518 case SMB_FIND_FILE_UNIX:
2519 case SMB_FIND_FILE_UNIX_INFO2:
2520 /* Always use filesystem for UNIX mtime query. */
2521 ask_sharemode = false;
2522 if (!lp_unix_extensions()) {
2523 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2526 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2529 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2533 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2534 params+12, total_params - 12,
2535 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2536 if (!NT_STATUS_IS_OK(ntstatus)) {
2537 reply_nterror(req, ntstatus);
2544 ntstatus = filename_convert_with_privilege(ctx,
2549 &mask_contains_wcard,
2552 ntstatus = filename_convert(ctx, conn,
2553 req->flags2 & FLAGS2_DFS_PATHNAMES,
2556 &mask_contains_wcard,
2560 if (!NT_STATUS_IS_OK(ntstatus)) {
2561 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2562 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2563 ERRSRV, ERRbadpath);
2566 reply_nterror(req, ntstatus);
2570 mask = smb_dname->original_lcomp;
2572 directory = smb_dname->base_name;
2574 p = strrchr_m(directory,'/');
2576 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2577 if((directory[0] == '.') && (directory[1] == '\0')) {
2578 mask = talloc_strdup(ctx,"*");
2580 reply_nterror(req, NT_STATUS_NO_MEMORY);
2583 mask_contains_wcard = True;
2589 if (p == NULL || p == directory) {
2590 /* Ensure we don't have a directory name of "". */
2591 directory = talloc_strdup(talloc_tos(), ".");
2593 reply_nterror(req, NT_STATUS_NO_MEMORY);
2598 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2600 if (info_level == SMB_FIND_EA_LIST) {
2603 if (total_data < 4) {
2604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2608 ea_size = IVAL(pdata,0);
2609 if (ea_size != total_data) {
2610 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2611 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2612 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2616 if (!lp_ea_support(SNUM(conn))) {
2617 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2621 /* Pull out the list of names. */
2622 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2624 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2629 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2630 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2634 *ppdata = (char *)SMB_REALLOC(
2635 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2636 if(*ppdata == NULL ) {
2637 reply_nterror(req, NT_STATUS_NO_MEMORY);
2641 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2643 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2646 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2647 /* Realloc the params space */
2648 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2649 if (*pparams == NULL) {
2650 reply_nterror(req, NT_STATUS_NO_MEMORY);
2655 /* Save the wildcard match and attribs we are using on this directory -
2656 needed as lanman2 assumes these are being saved between calls */
2658 ntstatus = dptr_create(conn,
2666 mask_contains_wcard,
2670 if (!NT_STATUS_IS_OK(ntstatus)) {
2671 reply_nterror(req, ntstatus);
2676 /* Remember this in case we have
2677 to do a findnext. */
2678 dptr_set_priv(dirptr);
2681 dptr_num = dptr_dnum(dirptr);
2682 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2684 /* Initialize per TRANS2_FIND_FIRST operation data */
2685 dptr_init_search_op(dirptr);
2687 /* We don't need to check for VOL here as this is returned by
2688 a different TRANS2 call. */
2690 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2691 directory,lp_dont_descend(ctx, SNUM(conn))));
2692 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
2693 dont_descend = True;
2696 space_remaining = max_data_bytes;
2697 out_of_space = False;
2699 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2700 bool got_exact_match = False;
2702 /* this is a heuristic to avoid seeking the dirptr except when
2703 absolutely necessary. It allows for a filename of about 40 chars */
2704 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2705 out_of_space = True;
2708 ntstatus = get_lanman2_dir_entry(ctx,
2712 mask,dirtype,info_level,
2713 requires_resume_key,dont_descend,
2718 &last_entry_off, ea_list);
2719 if (NT_STATUS_EQUAL(ntstatus,
2720 NT_STATUS_ILLEGAL_CHARACTER)) {
2722 * Bad character conversion on name. Ignore this
2727 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2728 out_of_space = true;
2730 finished = !NT_STATUS_IS_OK(ntstatus);
2734 if (!finished && !out_of_space)
2738 * As an optimisation if we know we aren't looking
2739 * for a wildcard name (ie. the name matches the wildcard exactly)
2740 * then we can finish on any (first) match.
2741 * This speeds up large directory searches. JRA.
2747 /* Ensure space_remaining never goes -ve. */
2748 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2749 space_remaining = 0;
2750 out_of_space = true;
2752 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2756 /* Check if we can close the dirptr */
2757 if(close_after_first || (finished && close_if_end)) {
2758 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2759 dptr_close(sconn, &dptr_num);
2763 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2764 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2765 * the protocol level is less than NT1. Tested with smbclient. JRA.
2766 * This should fix the OS/2 client bug #2335.
2769 if(numentries == 0) {
2770 dptr_close(sconn, &dptr_num);
2771 if (get_Protocol() < PROTOCOL_NT1) {
2772 reply_force_doserror(req, ERRDOS, ERRnofiles);
2775 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2776 ERRDOS, ERRbadfile);
2781 /* At this point pdata points to numentries directory entries. */
2783 /* Set up the return parameter block */
2784 SSVAL(params,0,dptr_num);
2785 SSVAL(params,2,numentries);
2786 SSVAL(params,4,finished);
2787 SSVAL(params,6,0); /* Never an EA error */
2788 SSVAL(params,8,last_entry_off);
2790 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2793 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2794 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2796 reply_nterror(req, NT_STATUS_NO_MEMORY);
2800 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2801 smb_fn_name(req->cmd),
2802 mask, directory, dirtype, numentries ) );
2805 * Force a name mangle here to ensure that the
2806 * mask as an 8.3 name is top of the mangled cache.
2807 * The reasons for this are subtle. Don't remove
2808 * this code unless you know what you are doing
2809 * (see PR#13758). JRA.
2812 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2813 char mangled_name[13];
2814 name_to_8_3(mask, mangled_name, True, conn->params);
2822 TALLOC_FREE(smb_dname);
2826 /****************************************************************************
2827 Reply to a TRANS2_FINDNEXT.
2828 ****************************************************************************/
2830 static void call_trans2findnext(connection_struct *conn,
2831 struct smb_request *req,
2832 char **pparams, int total_params,
2833 char **ppdata, int total_data,
2834 unsigned int max_data_bytes)
2836 /* We must be careful here that we don't return more than the
2837 allowed number of data bytes. If this means returning fewer than
2838 maxentries then so be it. We assume that the redirector has
2839 enough room for the fixed number of parameter bytes it has
2841 char *params = *pparams;
2842 char *pdata = *ppdata;
2846 uint16_t info_level;
2847 uint32_t resume_key;
2848 uint16_t findnext_flags;
2849 bool close_after_request;
2851 bool requires_resume_key;
2853 bool mask_contains_wcard = False;
2854 char *resume_name = NULL;
2855 const char *mask = NULL;
2856 const char *directory = NULL;
2860 int i, last_entry_off=0;
2861 bool finished = False;
2862 bool dont_descend = False;
2863 bool out_of_space = False;
2864 int space_remaining;
2865 struct ea_list *ea_list = NULL;
2866 NTSTATUS ntstatus = NT_STATUS_OK;
2867 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2868 TALLOC_CTX *ctx = talloc_tos();
2869 struct dptr_struct *dirptr;
2870 struct smbd_server_connection *sconn = req->sconn;
2871 bool backup_priv = false;
2872 bool as_root = false;
2874 if (total_params < 13) {
2875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2879 dptr_num = SVAL(params,0);
2880 maxentries = SVAL(params,2);
2881 info_level = SVAL(params,4);
2882 resume_key = IVAL(params,6);
2883 findnext_flags = SVAL(params,10);
2884 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2885 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2886 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2887 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2889 if (!continue_bit) {
2890 /* We only need resume_name if continue_bit is zero. */
2891 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2893 total_params - 12, STR_TERMINATE, &ntstatus,
2894 &mask_contains_wcard);
2895 if (!NT_STATUS_IS_OK(ntstatus)) {
2896 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2897 complain (it thinks we're asking for the directory above the shared
2898 path or an invalid name). Catch this as the resume name is only compared, never used in
2899 a file access. JRA. */
2900 srvstr_pull_talloc(ctx, params, req->flags2,
2901 &resume_name, params+12,
2905 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2906 reply_nterror(req, ntstatus);
2912 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2913 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2914 resume_key = %d resume name = %s continue=%d level = %d\n",
2915 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2916 requires_resume_key, resume_key,
2917 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2920 /* W2K3 seems to treat zero as 1. */
2924 switch (info_level) {
2925 case SMB_FIND_INFO_STANDARD:
2926 case SMB_FIND_EA_SIZE:
2927 case SMB_FIND_EA_LIST:
2928 case SMB_FIND_FILE_DIRECTORY_INFO:
2929 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2930 case SMB_FIND_FILE_NAMES_INFO:
2931 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2932 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2933 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2935 case SMB_FIND_FILE_UNIX:
2936 case SMB_FIND_FILE_UNIX_INFO2:
2937 /* Always use filesystem for UNIX mtime query. */
2938 ask_sharemode = false;
2939 if (!lp_unix_extensions()) {
2940 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2945 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2949 if (info_level == SMB_FIND_EA_LIST) {
2952 if (total_data < 4) {
2953 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2957 ea_size = IVAL(pdata,0);
2958 if (ea_size != total_data) {
2959 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2960 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2961 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2965 if (!lp_ea_support(SNUM(conn))) {
2966 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2970 /* Pull out the list of names. */
2971 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2973 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2978 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2979 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2983 *ppdata = (char *)SMB_REALLOC(
2984 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2985 if(*ppdata == NULL) {
2986 reply_nterror(req, NT_STATUS_NO_MEMORY);
2991 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2994 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2997 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
2998 /* Realloc the params space */
2999 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3000 if(*pparams == NULL ) {
3001 reply_nterror(req, NT_STATUS_NO_MEMORY);
3007 /* Check that the dptr is valid */
3008 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3009 reply_nterror(req, STATUS_NO_MORE_FILES);
3013 directory = dptr_path(sconn, dptr_num);
3015 /* Get the wildcard mask from the dptr */
3016 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3017 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3018 reply_nterror(req, STATUS_NO_MORE_FILES);
3022 /* Get the attr mask from the dptr */
3023 dirtype = dptr_attr(sconn, dptr_num);
3025 backup_priv = dptr_get_priv(dirptr);
3027 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3028 "backup_priv = %d\n",
3029 dptr_num, mask, dirtype,
3031 dptr_TellDir(dirptr),
3034 /* Initialize per TRANS2_FIND_NEXT operation data */
3035 dptr_init_search_op(dirptr);
3037 /* We don't need to check for VOL here as this is returned by
3038 a different TRANS2 call. */
3040 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3041 directory,lp_dont_descend(ctx, SNUM(conn))));
3042 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3043 dont_descend = True;
3046 space_remaining = max_data_bytes;
3047 out_of_space = False;
3055 * Seek to the correct position. We no longer use the resume key but
3056 * depend on the last file name instead.
3059 if(!continue_bit && resume_name && *resume_name) {
3062 long current_pos = 0;
3064 * Remember, name_to_8_3 is called by
3065 * get_lanman2_dir_entry(), so the resume name
3066 * could be mangled. Ensure we check the unmangled name.
3069 if (mangle_is_mangled(resume_name, conn->params)) {
3070 char *new_resume_name = NULL;
3071 mangle_lookup_name_from_8_3(ctx,
3075 if (new_resume_name) {
3076 resume_name = new_resume_name;
3081 * Fix for NT redirector problem triggered by resume key indexes
3082 * changing between directory scans. We now return a resume key of 0
3083 * and instead look for the filename to continue from (also given
3084 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3085 * findfirst/findnext (as is usual) then the directory pointer
3086 * should already be at the correct place.
3089 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3090 } /* end if resume_name && !continue_bit */
3092 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3093 bool got_exact_match = False;
3095 /* this is a heuristic to avoid seeking the dirptr except when
3096 absolutely necessary. It allows for a filename of about 40 chars */
3097 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3098 out_of_space = True;
3101 ntstatus = get_lanman2_dir_entry(ctx,
3105 mask,dirtype,info_level,
3106 requires_resume_key,dont_descend,
3111 &last_entry_off, ea_list);
3112 if (NT_STATUS_EQUAL(ntstatus,
3113 NT_STATUS_ILLEGAL_CHARACTER)) {
3115 * Bad character conversion on name. Ignore this
3120 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3121 out_of_space = true;
3123 finished = !NT_STATUS_IS_OK(ntstatus);
3127 if (!finished && !out_of_space)
3131 * As an optimisation if we know we aren't looking
3132 * for a wildcard name (ie. the name matches the wildcard exactly)
3133 * then we can finish on any (first) match.
3134 * This speeds up large directory searches. JRA.
3140 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3143 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3144 smb_fn_name(req->cmd),
3145 mask, directory, dirtype, numentries ) );
3147 /* Check if we can close the dirptr */
3148 if(close_after_request || (finished && close_if_end)) {
3149 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3150 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3157 /* Set up the return parameter block */
3158 SSVAL(params,0,numentries);
3159 SSVAL(params,2,finished);
3160 SSVAL(params,4,0); /* Never an EA error */
3161 SSVAL(params,6,last_entry_off);
3163 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3169 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3171 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3175 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3177 SMB_ASSERT(extended_info != NULL);
3179 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3180 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3181 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3182 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3183 #ifdef SAMBA_VERSION_REVISION
3184 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3186 extended_info->samba_subversion = 0;
3187 #ifdef SAMBA_VERSION_RC_RELEASE
3188 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3190 #ifdef SAMBA_VERSION_PRE_RELEASE
3191 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3194 #ifdef SAMBA_VERSION_VENDOR_PATCH
3195 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3197 extended_info->samba_gitcommitdate = 0;
3198 #ifdef SAMBA_VERSION_COMMIT_TIME
3199 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3202 memset(extended_info->samba_version_string, 0,
3203 sizeof(extended_info->samba_version_string));
3205 snprintf (extended_info->samba_version_string,
3206 sizeof(extended_info->samba_version_string),
3207 "%s", samba_version_string());
3210 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3211 connection_struct *conn,
3212 TALLOC_CTX *mem_ctx,
3213 uint16_t info_level,
3215 unsigned int max_data_bytes,
3216 size_t *fixed_portion,
3217 struct smb_filename *fname,
3221 char *pdata, *end_data;
3224 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3225 int snum = SNUM(conn);
3226 const char *fstype = lp_fstype(SNUM(conn));
3227 const char *filename = NULL;
3228 const uint64_t bytes_per_sector = 512;
3229 uint32_t additional_flags = 0;
3230 struct smb_filename smb_fname;
3232 NTSTATUS status = NT_STATUS_OK;
3235 if (fname == NULL || fname->base_name == NULL) {
3238 filename = fname->base_name;
3242 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3243 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3244 "info level (0x%x) on IPC$.\n",
3245 (unsigned int)info_level));
3246 return NT_STATUS_ACCESS_DENIED;
3250 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3252 ZERO_STRUCT(smb_fname);
3253 smb_fname.base_name = discard_const_p(char, filename);
3255 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3256 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3257 return map_nt_error_from_unix(errno);
3262 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3263 return NT_STATUS_INVALID_PARAMETER;
3266 *ppdata = (char *)SMB_REALLOC(
3267 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3268 if (*ppdata == NULL) {
3269 return NT_STATUS_NO_MEMORY;
3273 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3274 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3278 switch (info_level) {
3279 case SMB_INFO_ALLOCATION:
3281 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3283 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3285 if (df_ret == (uint64_t)-1) {
3286 return map_nt_error_from_unix(errno);
3289 block_size = lp_block_size(snum);
3290 if (bsize < block_size) {
3291 uint64_t factor = block_size/bsize;
3296 if (bsize > block_size) {
3297 uint64_t factor = bsize/block_size;
3302 sectors_per_unit = bsize/bytes_per_sector;
3304 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3305 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3306 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3308 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3309 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3310 SIVAL(pdata,l1_cUnit,dsize);
3311 SIVAL(pdata,l1_cUnitAvail,dfree);
3312 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3316 case SMB_INFO_VOLUME:
3317 /* Return volume name */
3319 * Add volume serial number - hash of a combination of
3320 * the called hostname and the service name.
3322 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3324 * Win2k3 and previous mess this up by sending a name length
3325 * one byte short. I believe only older clients (OS/2 Win9x) use
3326 * this call so try fixing this by adding a terminating null to
3327 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3329 status = srvstr_push(
3331 pdata+l2_vol_szVolLabel, vname,
3332 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3333 STR_NOALIGN|STR_TERMINATE, &len);
3334 if (!NT_STATUS_IS_OK(status)) {
3337 SCVAL(pdata,l2_vol_cch,len);
3338 data_len = l2_vol_szVolLabel + len;
3339 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3340 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3341 (unsigned)len, vname));
3344 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3345 case SMB_FS_ATTRIBUTE_INFORMATION:
3347 additional_flags = 0;
3348 #if defined(HAVE_SYS_QUOTAS)
3349 additional_flags |= FILE_VOLUME_QUOTAS;
3352 if(lp_nt_acl_support(SNUM(conn))) {
3353 additional_flags |= FILE_PERSISTENT_ACLS;
3356 /* Capabilities are filled in at connection time through STATVFS call */
3357 additional_flags |= conn->fs_capabilities;
3358 additional_flags |= lp_parm_int(conn->params->service,
3359 "share", "fake_fscaps",
3362 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3363 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3364 additional_flags); /* FS ATTRIBUTES */
3366 SIVAL(pdata,4,255); /* Max filename component length */
3367 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3368 and will think we can't do long filenames */
3369 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3370 PTR_DIFF(end_data, pdata+12),
3372 if (!NT_STATUS_IS_OK(status)) {
3376 data_len = 12 + len;
3377 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3378 /* the client only requested a portion of the
3380 data_len = max_data_bytes;
3381 status = STATUS_BUFFER_OVERFLOW;
3383 *fixed_portion = 16;
3386 case SMB_QUERY_FS_LABEL_INFO:
3387 case SMB_FS_LABEL_INFORMATION:
3388 status = srvstr_push(pdata, flags2, pdata+4, vname,
3389 PTR_DIFF(end_data, pdata+4), 0, &len);
3390 if (!NT_STATUS_IS_OK(status)) {
3397 case SMB_QUERY_FS_VOLUME_INFO:
3398 case SMB_FS_VOLUME_INFORMATION:
3401 * Add volume serial number - hash of a combination of
3402 * the called hostname and the service name.
3404 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3405 (str_checksum(get_local_machine_name())<<16));
3407 /* Max label len is 32 characters. */
3408 status = srvstr_push(pdata, flags2, pdata+18, vname,
3409 PTR_DIFF(end_data, pdata+18),
3411 if (!NT_STATUS_IS_OK(status)) {
3414 SIVAL(pdata,12,len);
3417 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3418 (int)strlen(vname),vname,
3419 lp_servicename(talloc_tos(), snum)));
3420 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3421 /* the client only requested a portion of the
3423 data_len = max_data_bytes;
3424 status = STATUS_BUFFER_OVERFLOW;
3426 *fixed_portion = 24;
3429 case SMB_QUERY_FS_SIZE_INFO:
3430 case SMB_FS_SIZE_INFORMATION:
3432 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3434 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3436 if (df_ret == (uint64_t)-1) {
3437 return map_nt_error_from_unix(errno);
3439 block_size = lp_block_size(snum);
3440 if (bsize < block_size) {
3441 uint64_t factor = block_size/bsize;
3446 if (bsize > block_size) {
3447 uint64_t factor = bsize/block_size;
3452 sectors_per_unit = bsize/bytes_per_sector;
3453 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3454 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3455 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3456 SBIG_UINT(pdata,0,dsize);
3457 SBIG_UINT(pdata,8,dfree);
3458 SIVAL(pdata,16,sectors_per_unit);
3459 SIVAL(pdata,20,bytes_per_sector);
3460 *fixed_portion = 24;
3464 case SMB_FS_FULL_SIZE_INFORMATION:
3466 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3468 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3470 if (df_ret == (uint64_t)-1) {
3471 return map_nt_error_from_unix(errno);
3473 block_size = lp_block_size(snum);
3474 if (bsize < block_size) {
3475 uint64_t factor = block_size/bsize;
3480 if (bsize > block_size) {
3481 uint64_t factor = bsize/block_size;
3486 sectors_per_unit = bsize/bytes_per_sector;
3487 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3488 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3489 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3490 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3491 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3492 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3493 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3494 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3495 *fixed_portion = 32;
3499 case SMB_QUERY_FS_DEVICE_INFO:
3500 case SMB_FS_DEVICE_INFORMATION:
3502 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3504 if (!CAN_WRITE(conn)) {
3505 characteristics |= FILE_READ_ONLY_DEVICE;
3508 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3509 SIVAL(pdata,4,characteristics);
3514 #ifdef HAVE_SYS_QUOTAS
3515 case SMB_FS_QUOTA_INFORMATION:
3517 * what we have to send --metze:
3519 * Unknown1: 24 NULL bytes
3520 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3521 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3522 * Quota Flags: 2 byte :
3523 * Unknown3: 6 NULL bytes
3527 * details for Quota Flags:
3529 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3530 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3531 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3532 * 0x0001 Enable Quotas: enable quota for this fs
3536 /* we need to fake up a fsp here,
3537 * because its not send in this call
3540 SMB_NTQUOTA_STRUCT quotas;
3543 ZERO_STRUCT(quotas);
3546 fsp.fnum = FNUM_FIELD_INVALID;
3549 if (get_current_uid(conn) != 0) {
3550 DEBUG(0,("get_user_quota: access_denied "
3551 "service [%s] user [%s]\n",
3552 lp_servicename(talloc_tos(), SNUM(conn)),
3553 conn->session_info->unix_info->unix_name));
3554 return NT_STATUS_ACCESS_DENIED;
3557 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3558 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3559 return map_nt_error_from_unix(errno);
3564 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3565 lp_servicename(talloc_tos(), SNUM(conn))));
3567 /* Unknown1 24 NULL bytes*/
3568 SBIG_UINT(pdata,0,(uint64_t)0);
3569 SBIG_UINT(pdata,8,(uint64_t)0);
3570 SBIG_UINT(pdata,16,(uint64_t)0);
3572 /* Default Soft Quota 8 bytes */
3573 SBIG_UINT(pdata,24,quotas.softlim);
3575 /* Default Hard Quota 8 bytes */
3576 SBIG_UINT(pdata,32,quotas.hardlim);
3578 /* Quota flag 2 bytes */
3579 SSVAL(pdata,40,quotas.qflags);
3581 /* Unknown3 6 NULL bytes */
3587 #endif /* HAVE_SYS_QUOTAS */
3588 case SMB_FS_OBJECTID_INFORMATION:
3590 unsigned char objid[16];
3591 struct smb_extended_info extended_info;
3592 memcpy(pdata,create_volume_objectid(conn, objid),16);
3593 samba_extended_info_version (&extended_info);
3594 SIVAL(pdata,16,extended_info.samba_magic);
3595 SIVAL(pdata,20,extended_info.samba_version);
3596 SIVAL(pdata,24,extended_info.samba_subversion);
3597 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3598 memcpy(pdata+36,extended_info.samba_version_string,28);
3603 case SMB_FS_SECTOR_SIZE_INFORMATION:
3607 * These values match a physical Windows Server 2012
3608 * share backed by NTFS atop spinning rust.
3610 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3611 /* logical_bytes_per_sector */
3612 SIVAL(pdata, 0, bytes_per_sector);
3613 /* phys_bytes_per_sector_atomic */
3614 SIVAL(pdata, 4, bytes_per_sector);
3615 /* phys_bytes_per_sector_perf */
3616 SIVAL(pdata, 8, bytes_per_sector);
3617 /* fs_effective_phys_bytes_per_sector_atomic */
3618 SIVAL(pdata, 12, bytes_per_sector);
3620 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3621 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3622 /* byte_off_sector_align */
3623 SIVAL(pdata, 20, 0);
3624 /* byte_off_partition_align */
3625 SIVAL(pdata, 24, 0);
3626 *fixed_portion = 28;
3632 * Query the version and capabilities of the CIFS UNIX extensions
3636 case SMB_QUERY_CIFS_UNIX_INFO:
3638 bool large_write = lp_min_receive_file_size() &&
3639 !srv_is_signing_active(xconn);
3640 bool large_read = !srv_is_signing_active(xconn);
3641 int encrypt_caps = 0;
3643 if (!lp_unix_extensions()) {
3644 return NT_STATUS_INVALID_LEVEL;
3647 switch (conn->encrypt_level) {
3648 case SMB_SIGNING_OFF:
3651 case SMB_SIGNING_DESIRED:
3652 case SMB_SIGNING_IF_REQUIRED:
3653 case SMB_SIGNING_DEFAULT:
3654 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3656 case SMB_SIGNING_REQUIRED:
3657 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3658 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3659 large_write = false;
3665 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3666 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3668 /* We have POSIX ACLs, pathname, encryption,
3669 * large read/write, and locking capability. */
3671 SBIG_UINT(pdata,4,((uint64_t)(
3672 CIFS_UNIX_POSIX_ACLS_CAP|
3673 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3674 CIFS_UNIX_FCNTL_LOCKS_CAP|
3675 CIFS_UNIX_EXTATTR_CAP|
3676 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3678 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3680 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3684 case SMB_QUERY_POSIX_FS_INFO:
3687 vfs_statvfs_struct svfs;
3689 if (!lp_unix_extensions()) {
3690 return NT_STATUS_INVALID_LEVEL;
3693 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3697 SIVAL(pdata,0,svfs.OptimalTransferSize);
3698 SIVAL(pdata,4,svfs.BlockSize);
3699 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3700 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3701 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3702 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3703 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3704 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3705 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3707 } else if (rc == EOPNOTSUPP) {
3708 return NT_STATUS_INVALID_LEVEL;
3709 #endif /* EOPNOTSUPP */
3711 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3712 return NT_STATUS_DOS(ERRSRV, ERRerror);
3717 case SMB_QUERY_POSIX_WHOAMI:
3723 if (!lp_unix_extensions()) {
3724 return NT_STATUS_INVALID_LEVEL;
3727 if (max_data_bytes < 40) {
3728 return NT_STATUS_BUFFER_TOO_SMALL;
3731 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3732 flags |= SMB_WHOAMI_GUEST;
3735 /* NOTE: 8 bytes for UID/GID, irrespective of native
3736 * platform size. This matches
3737 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3739 data_len = 4 /* flags */
3746 + 4 /* pad/reserved */
3747 + (conn->session_info->unix_token->ngroups * 8)
3749 + (conn->session_info->security_token->num_sids *
3753 SIVAL(pdata, 0, flags);
3754 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3756 (uint64_t)conn->session_info->unix_token->uid);
3757 SBIG_UINT(pdata, 16,
3758 (uint64_t)conn->session_info->unix_token->gid);
3761 if (data_len >= max_data_bytes) {
3762 /* Potential overflow, skip the GIDs and SIDs. */
3764 SIVAL(pdata, 24, 0); /* num_groups */
3765 SIVAL(pdata, 28, 0); /* num_sids */
3766 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3767 SIVAL(pdata, 36, 0); /* reserved */
3773 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3774 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3776 /* We walk the SID list twice, but this call is fairly
3777 * infrequent, and I don't expect that it's performance
3778 * sensitive -- jpeach
3780 for (i = 0, sid_bytes = 0;
3781 i < conn->session_info->security_token->num_sids; ++i) {
3782 sid_bytes += ndr_size_dom_sid(
3783 &conn->session_info->security_token->sids[i],
3787 /* SID list byte count */
3788 SIVAL(pdata, 32, sid_bytes);
3790 /* 4 bytes pad/reserved - must be zero */
3791 SIVAL(pdata, 36, 0);
3795 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3796 SBIG_UINT(pdata, data_len,
3797 (uint64_t)conn->session_info->unix_token->groups[i]);
3803 i < conn->session_info->security_token->num_sids; ++i) {
3804 int sid_len = ndr_size_dom_sid(
3805 &conn->session_info->security_token->sids[i],
3808 sid_linearize((uint8_t *)(pdata + data_len),
3810 &conn->session_info->security_token->sids[i]);
3811 data_len += sid_len;
3817 case SMB_MAC_QUERY_FS_INFO:
3819 * Thursby MAC extension... ONLY on NTFS filesystems
3820 * once we do streams then we don't need this
3822 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3824 SIVAL(pdata,84,0x100); /* Don't support mac... */
3829 return NT_STATUS_INVALID_LEVEL;
3832 *ret_data_len = data_len;
3836 /****************************************************************************
3837 Reply to a TRANS2_QFSINFO (query filesystem info).
3838 ****************************************************************************/
3840 static void call_trans2qfsinfo(connection_struct *conn,
3841 struct smb_request *req,
3842 char **pparams, int total_params,
3843 char **ppdata, int total_data,
3844 unsigned int max_data_bytes)
3846 char *params = *pparams;
3847 uint16_t info_level;
3849 size_t fixed_portion;
3852 if (total_params < 2) {
3853 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3857 info_level = SVAL(params,0);
3859 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3860 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3861 DEBUG(0,("call_trans2qfsinfo: encryption required "
3862 "and info level 0x%x sent.\n",
3863 (unsigned int)info_level));
3864 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3869 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3871 status = smbd_do_qfsinfo(req->xconn, conn, req,
3878 if (!NT_STATUS_IS_OK(status)) {
3879 reply_nterror(req, status);
3883 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3886 DEBUG( 4, ( "%s info_level = %d\n",
3887 smb_fn_name(req->cmd), info_level) );
3892 /****************************************************************************
3893 Reply to a TRANS2_SETFSINFO (set filesystem info).
3894 ****************************************************************************/
3896 static void call_trans2setfsinfo(connection_struct *conn,
3897 struct smb_request *req,
3898 char **pparams, int total_params,
3899 char **ppdata, int total_data,
3900 unsigned int max_data_bytes)
3902 struct smbXsrv_connection *xconn = req->xconn;
3903 char *pdata = *ppdata;
3904 char *params = *pparams;
3905 uint16_t info_level;
3907 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3908 lp_servicename(talloc_tos(), SNUM(conn))));
3911 if (total_params < 4) {
3912 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3914 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3918 info_level = SVAL(params,2);
3921 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3922 info_level != SMB_SET_CIFS_UNIX_INFO) {
3923 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3924 "info level (0x%x) on IPC$.\n",
3925 (unsigned int)info_level));
3926 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3931 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3932 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3933 DEBUG(0,("call_trans2setfsinfo: encryption required "
3934 "and info level 0x%x sent.\n",
3935 (unsigned int)info_level));
3936 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3941 switch(info_level) {
3942 case SMB_SET_CIFS_UNIX_INFO:
3943 if (!lp_unix_extensions()) {
3944 DEBUG(2,("call_trans2setfsinfo: "
3945 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3946 "unix extensions off\n"));
3948 NT_STATUS_INVALID_LEVEL);
3952 /* There should be 12 bytes of capabilities set. */
3953 if (total_data < 12) {
3956 NT_STATUS_INVALID_PARAMETER);
3959 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
3960 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3961 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3962 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3963 /* Just print these values for now. */
3964 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3965 "major = %u, minor = %u cap_low = 0x%x, "
3967 (unsigned int)xconn->
3968 smb1.unix_info.client_major,
3969 (unsigned int)xconn->
3970 smb1.unix_info.client_minor,
3971 (unsigned int)xconn->
3972 smb1.unix_info.client_cap_low,
3973 (unsigned int)xconn->
3974 smb1.unix_info.client_cap_high));
3976 /* Here is where we must switch to posix pathname processing... */
3977 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3978 lp_set_posix_pathnames();
3979 mangle_change_to_posix();
3982 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3983 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3984 /* Client that knows how to do posix locks,
3985 * but not posix open/mkdir operations. Set a
3986 * default type for read/write checks. */
3988 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3993 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3996 size_t param_len = 0;
3997 size_t data_len = total_data;
3999 if (!lp_unix_extensions()) {
4002 NT_STATUS_INVALID_LEVEL);
4006 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4009 NT_STATUS_NOT_SUPPORTED);
4013 if (xconn->smb1.echo_handler.trusted_fde) {
4014 DEBUG( 2,("call_trans2setfsinfo: "
4015 "request transport encryption disabled"
4016 "with 'fork echo handler = yes'\n"));
4019 NT_STATUS_NOT_SUPPORTED);
4023 DEBUG( 4,("call_trans2setfsinfo: "
4024 "request transport encryption.\n"));
4026 status = srv_request_encryption_setup(conn,
4027 (unsigned char **)ppdata,
4029 (unsigned char **)pparams,
4032 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4033 !NT_STATUS_IS_OK(status)) {
4034 reply_nterror(req, status);
4038 send_trans2_replies(conn, req,
4046 if (NT_STATUS_IS_OK(status)) {
4047 /* Server-side transport
4048 * encryption is now *on*. */
4049 status = srv_encryption_start(conn);
4050 if (!NT_STATUS_IS_OK(status)) {
4051 char *reason = talloc_asprintf(talloc_tos(),
4052 "Failure in setting "
4053 "up encrypted transport: %s",
4055 exit_server_cleanly(reason);
4061 case SMB_FS_QUOTA_INFORMATION:
4063 files_struct *fsp = NULL;
4064 SMB_NTQUOTA_STRUCT quotas;
4066 ZERO_STRUCT(quotas);
4069 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4070 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4071 lp_servicename(talloc_tos(), SNUM(conn)),
4072 conn->session_info->unix_info->unix_name));
4073 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4077 /* note: normally there're 48 bytes,
4078 * but we didn't use the last 6 bytes for now
4081 fsp = file_fsp(req, SVAL(params,0));
4083 if (!check_fsp_ntquota_handle(conn, req,
4085 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4087 req, NT_STATUS_INVALID_HANDLE);
4091 if (total_data < 42) {
4092 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4096 NT_STATUS_INVALID_PARAMETER);
4100 /* unknown_1 24 NULL bytes in pdata*/
4102 /* the soft quotas 8 bytes (uint64_t)*/
4103 quotas.softlim = BVAL(pdata,24);
4105 /* the hard quotas 8 bytes (uint64_t)*/
4106 quotas.hardlim = BVAL(pdata,32);
4108 /* quota_flags 2 bytes **/
4109 quotas.qflags = SVAL(pdata,40);
4111 /* unknown_2 6 NULL bytes follow*/
4113 /* now set the quotas */
4114 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4115 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4116 reply_nterror(req, map_nt_error_from_unix(errno));
4123 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4125 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4131 * sending this reply works fine,
4132 * but I'm not sure it's the same
4133 * like windows do...
4136 reply_outbuf(req, 10, 0);
4139 #if defined(HAVE_POSIX_ACLS)
4140 /****************************************************************************
4141 Utility function to count the number of entries in a POSIX acl.
4142 ****************************************************************************/
4144 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4146 unsigned int ace_count = 0;
4147 int entry_id = SMB_ACL_FIRST_ENTRY;
4148 SMB_ACL_ENTRY_T entry;
4150 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4152 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4153 entry_id = SMB_ACL_NEXT_ENTRY;
4160 /****************************************************************************
4161 Utility function to marshall a POSIX acl into wire format.
4162 ****************************************************************************/
4164 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4166 int entry_id = SMB_ACL_FIRST_ENTRY;
4167 SMB_ACL_ENTRY_T entry;
4169 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4170 SMB_ACL_TAG_T tagtype;
4171 SMB_ACL_PERMSET_T permset;
4172 unsigned char perms = 0;
4173 unsigned int own_grp;
4176 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4177 entry_id = SMB_ACL_NEXT_ENTRY;
4180 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4181 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4185 if (sys_acl_get_permset(entry, &permset) == -1) {
4186 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4190 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4191 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4192 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4194 SCVAL(pdata,1,perms);
4197 case SMB_ACL_USER_OBJ:
4198 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4199 own_grp = (unsigned int)pst->st_ex_uid;
4200 SIVAL(pdata,2,own_grp);
4205 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4207 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4210 own_grp = (unsigned int)*puid;
4211 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4212 SIVAL(pdata,2,own_grp);
4216 case SMB_ACL_GROUP_OBJ:
4217 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4218 own_grp = (unsigned int)pst->st_ex_gid;
4219 SIVAL(pdata,2,own_grp);
4224 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4226 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4229 own_grp = (unsigned int)*pgid;
4230 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4231 SIVAL(pdata,2,own_grp);
4236 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4237 SIVAL(pdata,2,0xFFFFFFFF);
4238 SIVAL(pdata,6,0xFFFFFFFF);
4241 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4242 SIVAL(pdata,2,0xFFFFFFFF);
4243 SIVAL(pdata,6,0xFFFFFFFF);
4246 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4249 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4256 /****************************************************************************
4257 Store the FILE_UNIX_BASIC info.
4258 ****************************************************************************/
4260 static char *store_file_unix_basic(connection_struct *conn,
4263 const SMB_STRUCT_STAT *psbuf)
4265 uint64_t file_index = get_FileIndex(conn, psbuf);
4268 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4269 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4271 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4274 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4277 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4278 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4279 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4282 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4286 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4290 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4293 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4294 devno = psbuf->st_ex_rdev;
4296 devno = psbuf->st_ex_dev;
4299 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4303 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4307 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4310 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4314 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4321 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4322 * the chflags(2) (or equivalent) flags.
4324 * XXX: this really should be behind the VFS interface. To do this, we would
4325 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4326 * Each VFS module could then implement its own mapping as appropriate for the
4327 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4329 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4333 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4337 { UF_IMMUTABLE, EXT_IMMUTABLE },
4341 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4345 { UF_HIDDEN, EXT_HIDDEN },
4348 /* Do not remove. We need to guarantee that this array has at least one
4349 * entry to build on HP-UX.
4355 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4356 uint32_t *smb_fflags, uint32_t *smb_fmask)
4360 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4361 *smb_fmask |= info2_flags_map[i].smb_fflag;
4362 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4363 *smb_fflags |= info2_flags_map[i].smb_fflag;
4368 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4369 const uint32_t smb_fflags,
4370 const uint32_t smb_fmask,
4373 uint32_t max_fmask = 0;
4376 *stat_fflags = psbuf->st_ex_flags;
4378 /* For each flags requested in smb_fmask, check the state of the
4379 * corresponding flag in smb_fflags and set or clear the matching
4383 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4384 max_fmask |= info2_flags_map[i].smb_fflag;
4385 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4386 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4387 *stat_fflags |= info2_flags_map[i].stat_fflag;
4389 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4394 /* If smb_fmask is asking to set any bits that are not supported by
4395 * our flag mappings, we should fail.
4397 if ((smb_fmask & max_fmask) != smb_fmask) {
4405 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4406 * of file flags and birth (create) time.
4408 static char *store_file_unix_basic_info2(connection_struct *conn,
4411 const SMB_STRUCT_STAT *psbuf)
4413 uint32_t file_flags = 0;
4414 uint32_t flags_mask = 0;
4416 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4418 /* Create (birth) time 64 bit */
4419 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4422 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4423 SIVAL(pdata, 0, file_flags); /* flags */
4424 SIVAL(pdata, 4, flags_mask); /* mask */
4430 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4431 const struct stream_struct *streams,
4433 unsigned int max_data_bytes,
4434 unsigned int *data_size)
4437 unsigned int ofs = 0;
4439 if (max_data_bytes < 32) {
4440 return NT_STATUS_INFO_LENGTH_MISMATCH;
4443 for (i = 0; i < num_streams; i++) {
4444 unsigned int next_offset;
4446 smb_ucs2_t *namebuf;
4448 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4449 streams[i].name, &namelen) ||
4452 return NT_STATUS_INVALID_PARAMETER;
4456 * name_buf is now null-terminated, we need to marshall as not
4463 * We cannot overflow ...
4465 if ((ofs + 24 + namelen) > max_data_bytes) {
4466 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4468 TALLOC_FREE(namebuf);
4469 return STATUS_BUFFER_OVERFLOW;
4472 SIVAL(data, ofs+4, namelen);
4473 SOFF_T(data, ofs+8, streams[i].size);
4474 SOFF_T(data, ofs+16, streams[i].alloc_size);
4475 memcpy(data+ofs+24, namebuf, namelen);
4476 TALLOC_FREE(namebuf);
4478 next_offset = ofs + 24 + namelen;
4480 if (i == num_streams-1) {
4481 SIVAL(data, ofs, 0);
4484 unsigned int align = ndr_align_size(next_offset, 8);
4486 if ((next_offset + align) > max_data_bytes) {
4487 DEBUG(10, ("refusing to overflow align "
4488 "reply at stream %u\n",
4490 TALLOC_FREE(namebuf);
4491 return STATUS_BUFFER_OVERFLOW;
4494 memset(data+next_offset, 0, align);
4495 next_offset += align;
4497 SIVAL(data, ofs, next_offset - ofs);
4504 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4508 return NT_STATUS_OK;
4511 /****************************************************************************
4512 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4513 ****************************************************************************/
4515 static void call_trans2qpipeinfo(connection_struct *conn,
4516 struct smb_request *req,
4517 unsigned int tran_call,
4518 char **pparams, int total_params,
4519 char **ppdata, int total_data,
4520 unsigned int max_data_bytes)
4522 char *params = *pparams;
4523 char *pdata = *ppdata;
4524 unsigned int data_size = 0;
4525 unsigned int param_size = 2;
4526 uint16_t info_level;
4530 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4534 if (total_params < 4) {
4535 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4539 fsp = file_fsp(req, SVAL(params,0));
4540 if (!fsp_is_np(fsp)) {
4541 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4545 info_level = SVAL(params,2);
4547 *pparams = (char *)SMB_REALLOC(*pparams,2);
4548 if (*pparams == NULL) {
4549 reply_nterror(req, NT_STATUS_NO_MEMORY);
4554 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4558 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4559 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4560 if (*ppdata == NULL ) {
4561 reply_nterror(req, NT_STATUS_NO_MEMORY);
4566 switch (info_level) {
4567 case SMB_FILE_STANDARD_INFORMATION:
4569 SOFF_T(pdata,0,4096LL);
4576 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4580 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4586 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4587 TALLOC_CTX *mem_ctx,
4588 uint16_t info_level,
4590 struct smb_filename *smb_fname,
4591 bool delete_pending,
4592 struct timespec write_time_ts,
4593 struct ea_list *ea_list,
4594 int lock_data_count,
4597 unsigned int max_data_bytes,
4598 size_t *fixed_portion,
4600 unsigned int *pdata_size)
4602 char *pdata = *ppdata;
4603 char *dstart, *dend;
4604 unsigned int data_size;
4605 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4606 time_t create_time, mtime, atime, c_time;
4607 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4614 uint64_t file_size = 0;
4616 uint64_t allocation_size = 0;
4617 uint64_t file_index = 0;
4618 uint32_t access_mask = 0;
4621 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4622 return NT_STATUS_INVALID_LEVEL;
4625 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4626 smb_fname_str_dbg(smb_fname),
4628 info_level, max_data_bytes));
4630 mode = dos_mode(conn, smb_fname);
4631 nlink = psbuf->st_ex_nlink;
4633 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4637 if ((nlink > 0) && delete_pending) {
4641 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4642 return NT_STATUS_INVALID_PARAMETER;
4645 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4646 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4647 if (*ppdata == NULL) {
4648 return NT_STATUS_NO_MEMORY;
4652 dend = dstart + data_size - 1;
4654 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4655 update_stat_ex_mtime(psbuf, write_time_ts);
4658 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4659 mtime_ts = psbuf->st_ex_mtime;
4660 atime_ts = psbuf->st_ex_atime;
4661 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4663 if (lp_dos_filetime_resolution(SNUM(conn))) {
4664 dos_filetime_timespec(&create_time_ts);
4665 dos_filetime_timespec(&mtime_ts);
4666 dos_filetime_timespec(&atime_ts);
4667 dos_filetime_timespec(&ctime_ts);
4670 create_time = convert_timespec_to_time_t(create_time_ts);
4671 mtime = convert_timespec_to_time_t(mtime_ts);
4672 atime = convert_timespec_to_time_t(atime_ts);
4673 c_time = convert_timespec_to_time_t(ctime_ts);
4675 p = strrchr_m(smb_fname->base_name,'/');
4677 base_name = smb_fname->base_name;
4681 /* NT expects the name to be in an exact form of the *full*
4682 filename. See the trans2 torture test */
4683 if (ISDOT(base_name)) {
4684 dos_fname = talloc_strdup(mem_ctx, "\\");
4686 return NT_STATUS_NO_MEMORY;
4689 dos_fname = talloc_asprintf(mem_ctx,
4691 smb_fname->base_name);
4693 return NT_STATUS_NO_MEMORY;
4695 if (is_ntfs_stream_smb_fname(smb_fname)) {
4696 dos_fname = talloc_asprintf(dos_fname, "%s",
4697 smb_fname->stream_name);
4699 return NT_STATUS_NO_MEMORY;
4703 string_replace(dos_fname, '/', '\\');
4706 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4709 /* Do we have this path open ? */
4711 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4712 fsp1 = file_find_di_first(conn->sconn, fileid);
4713 if (fsp1 && fsp1->initial_allocation_size) {
4714 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4718 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4719 file_size = get_file_size_stat(psbuf);
4723 pos = fsp->fh->position_information;
4727 access_mask = fsp->access_mask;
4729 /* GENERIC_EXECUTE mapping from Windows */
4730 access_mask = 0x12019F;
4733 /* This should be an index number - looks like
4736 I think this causes us to fail the IFSKIT
4737 BasicFileInformationTest. -tpot */
4738 file_index = get_FileIndex(conn, psbuf);
4742 switch (info_level) {
4743 case SMB_INFO_STANDARD:
4744 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4746 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4747 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4748 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4749 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4750 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4751 SSVAL(pdata,l1_attrFile,mode);
4754 case SMB_INFO_QUERY_EA_SIZE:
4756 unsigned int ea_size =
4757 estimate_ea_size(conn, fsp,
4759 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4761 srv_put_dos_date2(pdata,0,create_time);
4762 srv_put_dos_date2(pdata,4,atime);
4763 srv_put_dos_date2(pdata,8,mtime); /* write time */
4764 SIVAL(pdata,12,(uint32_t)file_size);
4765 SIVAL(pdata,16,(uint32_t)allocation_size);
4766 SSVAL(pdata,20,mode);
4767 SIVAL(pdata,22,ea_size);
4771 case SMB_INFO_IS_NAME_VALID:
4772 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4774 /* os/2 needs this ? really ?*/
4775 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4777 /* This is only reached for qpathinfo */
4781 case SMB_INFO_QUERY_EAS_FROM_LIST:
4783 size_t total_ea_len = 0;
4784 struct ea_list *ea_file_list = NULL;
4785 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4788 get_ea_list_from_file(mem_ctx, conn, fsp,
4790 &total_ea_len, &ea_file_list);
4791 if (!NT_STATUS_IS_OK(status)) {
4795 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4797 if (!ea_list || (total_ea_len > data_size)) {
4799 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4803 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4807 case SMB_INFO_QUERY_ALL_EAS:
4809 /* We have data_size bytes to put EA's into. */
4810 size_t total_ea_len = 0;
4811 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4813 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4815 &total_ea_len, &ea_list);
4816 if (!NT_STATUS_IS_OK(status)) {
4820 if (!ea_list || (total_ea_len > data_size)) {
4822 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4826 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4830 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4832 /* This is FileFullEaInformation - 0xF which maps to
4833 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4835 /* We have data_size bytes to put EA's into. */
4836 size_t total_ea_len = 0;
4837 struct ea_list *ea_file_list = NULL;
4839 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4841 /*TODO: add filtering and index handling */
4844 get_ea_list_from_file(mem_ctx, conn, fsp,
4846 &total_ea_len, &ea_file_list);
4847 if (!NT_STATUS_IS_OK(status)) {
4850 if (!ea_file_list) {
4851 return NT_STATUS_NO_EAS_ON_FILE;
4854 status = fill_ea_chained_buffer(mem_ctx,
4858 conn, ea_file_list);
4859 if (!NT_STATUS_IS_OK(status)) {
4865 case SMB_FILE_BASIC_INFORMATION:
4866 case SMB_QUERY_FILE_BASIC_INFO:
4868 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4869 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4870 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4872 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4876 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4877 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4878 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4879 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4880 SIVAL(pdata,32,mode);
4882 DEBUG(5,("SMB_QFBI - "));
4883 DEBUG(5,("create: %s ", ctime(&create_time)));
4884 DEBUG(5,("access: %s ", ctime(&atime)));
4885 DEBUG(5,("write: %s ", ctime(&mtime)));
4886 DEBUG(5,("change: %s ", ctime(&c_time)));
4887 DEBUG(5,("mode: %x\n", mode));
4888 *fixed_portion = data_size;
4891 case SMB_FILE_STANDARD_INFORMATION:
4892 case SMB_QUERY_FILE_STANDARD_INFO:
4894 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4896 SOFF_T(pdata,0,allocation_size);
4897 SOFF_T(pdata,8,file_size);
4898 SIVAL(pdata,16,nlink);
4899 SCVAL(pdata,20,delete_pending?1:0);
4900 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4901 SSVAL(pdata,22,0); /* Padding. */
4902 *fixed_portion = 24;
4905 case SMB_FILE_EA_INFORMATION:
4906 case SMB_QUERY_FILE_EA_INFO:
4908 unsigned int ea_size =
4909 estimate_ea_size(conn, fsp, smb_fname);
4910 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4913 SIVAL(pdata,0,ea_size);
4917 /* Get the 8.3 name - used if NT SMB was negotiated. */
4918 case SMB_QUERY_FILE_ALT_NAME_INFO:
4919 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4921 char mangled_name[13];
4922 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4923 if (!name_to_8_3(base_name,mangled_name,
4924 True,conn->params)) {
4925 return NT_STATUS_NO_MEMORY;
4927 status = srvstr_push(dstart, flags2,
4928 pdata+4, mangled_name,
4929 PTR_DIFF(dend, pdata+4),
4931 if (!NT_STATUS_IS_OK(status)) {
4934 data_size = 4 + len;
4940 case SMB_QUERY_FILE_NAME_INFO:
4943 this must be *exactly* right for ACLs on mapped drives to work
4945 status = srvstr_push(dstart, flags2,
4947 PTR_DIFF(dend, pdata+4),
4949 if (!NT_STATUS_IS_OK(status)) {
4952 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4953 data_size = 4 + len;
4958 case SMB_FILE_ALLOCATION_INFORMATION:
4959 case SMB_QUERY_FILE_ALLOCATION_INFO:
4960 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4962 SOFF_T(pdata,0,allocation_size);
4965 case SMB_FILE_END_OF_FILE_INFORMATION:
4966 case SMB_QUERY_FILE_END_OF_FILEINFO:
4967 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4969 SOFF_T(pdata,0,file_size);
4972 case SMB_QUERY_FILE_ALL_INFO:
4973 case SMB_FILE_ALL_INFORMATION:
4975 unsigned int ea_size =
4976 estimate_ea_size(conn, fsp, smb_fname);
4977 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4978 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4979 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4980 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4981 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4982 SIVAL(pdata,32,mode);
4983 SIVAL(pdata,36,0); /* padding. */
4985 SOFF_T(pdata,0,allocation_size);
4986 SOFF_T(pdata,8,file_size);
4987 SIVAL(pdata,16,nlink);
4988 SCVAL(pdata,20,delete_pending);
4989 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4992 SIVAL(pdata,0,ea_size);
4993 pdata += 4; /* EA info */
4994 status = srvstr_push(dstart, flags2,
4996 PTR_DIFF(dend, pdata+4),
4998 if (!NT_STATUS_IS_OK(status)) {
5003 data_size = PTR_DIFF(pdata,(*ppdata));
5004 *fixed_portion = 10;
5008 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5010 unsigned int ea_size =
5011 estimate_ea_size(conn, fsp, smb_fname);
5012 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5013 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5014 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5015 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5016 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5017 SIVAL(pdata, 0x20, mode);
5018 SIVAL(pdata, 0x24, 0); /* padding. */
5019 SBVAL(pdata, 0x28, allocation_size);
5020 SBVAL(pdata, 0x30, file_size);
5021 SIVAL(pdata, 0x38, nlink);
5022 SCVAL(pdata, 0x3C, delete_pending);
5023 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5024 SSVAL(pdata, 0x3E, 0); /* padding */
5025 SBVAL(pdata, 0x40, file_index);
5026 SIVAL(pdata, 0x48, ea_size);
5027 SIVAL(pdata, 0x4C, access_mask);
5028 SBVAL(pdata, 0x50, pos);
5029 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5030 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5034 status = srvstr_push(dstart, flags2,
5036 PTR_DIFF(dend, pdata+4),
5038 if (!NT_STATUS_IS_OK(status)) {
5043 data_size = PTR_DIFF(pdata,(*ppdata));
5044 *fixed_portion = 104;
5047 case SMB_FILE_INTERNAL_INFORMATION:
5049 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5050 SBVAL(pdata, 0, file_index);
5055 case SMB_FILE_ACCESS_INFORMATION:
5056 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5057 SIVAL(pdata, 0, access_mask);
5062 case SMB_FILE_NAME_INFORMATION:
5063 /* Pathname with leading '\'. */
5066 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5067 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5068 SIVAL(pdata,0,byte_len);
5069 data_size = 4 + byte_len;
5073 case SMB_FILE_DISPOSITION_INFORMATION:
5074 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5076 SCVAL(pdata,0,delete_pending);
5080 case SMB_FILE_POSITION_INFORMATION:
5081 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5083 SOFF_T(pdata,0,pos);
5087 case SMB_FILE_MODE_INFORMATION:
5088 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5089 SIVAL(pdata,0,mode);
5094 case SMB_FILE_ALIGNMENT_INFORMATION:
5095 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5096 SIVAL(pdata,0,0); /* No alignment needed. */
5102 * NT4 server just returns "invalid query" to this - if we try
5103 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5106 /* The first statement above is false - verified using Thursby
5107 * client against NT4 -- gcolley.
5109 case SMB_QUERY_FILE_STREAM_INFO:
5110 case SMB_FILE_STREAM_INFORMATION: {
5111 unsigned int num_streams = 0;
5112 struct stream_struct *streams = NULL;
5114 DEBUG(10,("smbd_do_qfilepathinfo: "
5115 "SMB_FILE_STREAM_INFORMATION\n"));
5117 if (is_ntfs_stream_smb_fname(smb_fname)) {
5118 return NT_STATUS_INVALID_PARAMETER;
5121 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
5122 talloc_tos(), &num_streams, &streams);
5124 if (!NT_STATUS_IS_OK(status)) {
5125 DEBUG(10, ("could not get stream info: %s\n",
5126 nt_errstr(status)));
5130 status = marshall_stream_info(num_streams, streams,
5131 pdata, max_data_bytes,
5134 if (!NT_STATUS_IS_OK(status)) {
5135 DEBUG(10, ("marshall_stream_info failed: %s\n",
5136 nt_errstr(status)));
5137 TALLOC_FREE(streams);
5141 TALLOC_FREE(streams);
5143 *fixed_portion = 32;
5147 case SMB_QUERY_COMPRESSION_INFO:
5148 case SMB_FILE_COMPRESSION_INFORMATION:
5149 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5150 SOFF_T(pdata,0,file_size);
5151 SIVAL(pdata,8,0); /* ??? */
5152 SIVAL(pdata,12,0); /* ??? */
5154 *fixed_portion = 16;
5157 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5158 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5159 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5160 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5161 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5162 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5163 SOFF_T(pdata,32,allocation_size);
5164 SOFF_T(pdata,40,file_size);
5165 SIVAL(pdata,48,mode);
5166 SIVAL(pdata,52,0); /* ??? */
5168 *fixed_portion = 56;
5171 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5172 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5173 SIVAL(pdata,0,mode);
5180 * CIFS UNIX Extensions.
5183 case SMB_QUERY_FILE_UNIX_BASIC:
5185 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5186 data_size = PTR_DIFF(pdata,(*ppdata));
5188 DEBUG(4,("smbd_do_qfilepathinfo: "
5189 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5190 dump_data(4, (uint8_t *)(*ppdata), data_size);
5194 case SMB_QUERY_FILE_UNIX_INFO2:
5196 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5197 data_size = PTR_DIFF(pdata,(*ppdata));
5201 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5203 for (i=0; i<100; i++)
5204 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5210 case SMB_QUERY_FILE_UNIX_LINK:
5213 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5216 return NT_STATUS_NO_MEMORY;
5219 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5221 if(!S_ISLNK(psbuf->st_ex_mode)) {
5222 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5225 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5227 link_len = SMB_VFS_READLINK(conn,
5228 smb_fname->base_name,
5230 if (link_len == -1) {
5231 return map_nt_error_from_unix(errno);
5233 buffer[link_len] = 0;
5234 status = srvstr_push(dstart, flags2,
5236 PTR_DIFF(dend, pdata),
5237 STR_TERMINATE, &len);
5238 if (!NT_STATUS_IS_OK(status)) {
5242 data_size = PTR_DIFF(pdata,(*ppdata));
5247 #if defined(HAVE_POSIX_ACLS)
5248 case SMB_QUERY_POSIX_ACL:
5250 SMB_ACL_T file_acl = NULL;
5251 SMB_ACL_T def_acl = NULL;
5252 uint16_t num_file_acls = 0;
5253 uint16_t num_def_acls = 0;
5255 if (fsp && fsp->fh->fd != -1) {
5256 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5260 SMB_VFS_SYS_ACL_GET_FILE(conn,
5261 smb_fname->base_name,
5262 SMB_ACL_TYPE_ACCESS,
5266 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5267 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5268 "not implemented on "
5269 "filesystem containing %s\n",
5270 smb_fname->base_name));
5271 return NT_STATUS_NOT_IMPLEMENTED;
5274 if (S_ISDIR(psbuf->st_ex_mode)) {
5275 if (fsp && fsp->is_directory) {
5277 SMB_VFS_SYS_ACL_GET_FILE(
5279 fsp->fsp_name->base_name,
5280 SMB_ACL_TYPE_DEFAULT,
5284 SMB_VFS_SYS_ACL_GET_FILE(
5286 smb_fname->base_name,
5287 SMB_ACL_TYPE_DEFAULT,
5290 def_acl = free_empty_sys_acl(conn, def_acl);
5293 num_file_acls = count_acl_entries(conn, file_acl);
5294 num_def_acls = count_acl_entries(conn, def_acl);
5296 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5297 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5299 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5300 SMB_POSIX_ACL_HEADER_SIZE) ));
5302 TALLOC_FREE(file_acl);
5305 TALLOC_FREE(def_acl);
5307 return NT_STATUS_BUFFER_TOO_SMALL;
5310 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5311 SSVAL(pdata,2,num_file_acls);
5312 SSVAL(pdata,4,num_def_acls);
5313 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5315 TALLOC_FREE(file_acl);
5318 TALLOC_FREE(def_acl);
5320 return NT_STATUS_INTERNAL_ERROR;
5322 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5324 TALLOC_FREE(file_acl);
5327 TALLOC_FREE(def_acl);
5329 return NT_STATUS_INTERNAL_ERROR;
5333 TALLOC_FREE(file_acl);
5336 TALLOC_FREE(def_acl);
5338 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5344 case SMB_QUERY_POSIX_LOCK:
5349 enum brl_type lock_type;
5351 /* We need an open file with a real fd for this. */
5352 if (!fsp || fsp->fh->fd == -1) {
5353 return NT_STATUS_INVALID_LEVEL;
5356 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5357 return NT_STATUS_INVALID_PARAMETER;
5360 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5361 case POSIX_LOCK_TYPE_READ:
5362 lock_type = READ_LOCK;
5364 case POSIX_LOCK_TYPE_WRITE:
5365 lock_type = WRITE_LOCK;
5367 case POSIX_LOCK_TYPE_UNLOCK:
5369 /* There's no point in asking for an unlock... */
5370 return NT_STATUS_INVALID_PARAMETER;
5373 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5374 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5375 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5377 status = query_lock(fsp,
5384 if (ERROR_WAS_LOCK_DENIED(status)) {
5385 /* Here we need to report who has it locked... */
5386 data_size = POSIX_LOCK_DATA_SIZE;
5388 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5389 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5390 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5391 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5392 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5394 } else if (NT_STATUS_IS_OK(status)) {
5395 /* For success we just return a copy of what we sent
5396 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5397 data_size = POSIX_LOCK_DATA_SIZE;
5398 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5399 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5407 return NT_STATUS_INVALID_LEVEL;
5410 *pdata_size = data_size;
5411 return NT_STATUS_OK;
5414 /****************************************************************************
5415 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5416 file name or file id).
5417 ****************************************************************************/
5419 static void call_trans2qfilepathinfo(connection_struct *conn,
5420 struct smb_request *req,
5421 unsigned int tran_call,
5422 char **pparams, int total_params,
5423 char **ppdata, int total_data,
5424 unsigned int max_data_bytes)
5426 char *params = *pparams;
5427 char *pdata = *ppdata;
5428 uint16_t info_level;
5429 unsigned int data_size = 0;
5430 unsigned int param_size = 2;
5431 struct smb_filename *smb_fname = NULL;
5432 bool delete_pending = False;
5433 struct timespec write_time_ts;
5434 files_struct *fsp = NULL;
5435 struct file_id fileid;
5436 struct ea_list *ea_list = NULL;
5437 int lock_data_count = 0;
5438 char *lock_data = NULL;
5439 size_t fixed_portion;
5440 NTSTATUS status = NT_STATUS_OK;
5443 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5447 ZERO_STRUCT(write_time_ts);
5449 if (tran_call == TRANSACT2_QFILEINFO) {
5450 if (total_params < 4) {
5451 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5456 call_trans2qpipeinfo(conn, req, tran_call,
5457 pparams, total_params,
5463 fsp = file_fsp(req, SVAL(params,0));
5464 info_level = SVAL(params,2);
5466 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5468 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5469 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5473 /* Initial check for valid fsp ptr. */
5474 if (!check_fsp_open(conn, req, fsp)) {
5478 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5479 if (smb_fname == NULL) {
5480 reply_nterror(req, NT_STATUS_NO_MEMORY);
5484 if(fsp->fake_file_handle) {
5486 * This is actually for the QUOTA_FAKE_FILE --metze
5489 /* We know this name is ok, it's already passed the checks. */
5491 } else if(fsp->fh->fd == -1) {
5493 * This is actually a QFILEINFO on a directory
5494 * handle (returned from an NT SMB). NT5.0 seems
5495 * to do this call. JRA.
5498 if (INFO_LEVEL_IS_UNIX(info_level)) {
5499 /* Always do lstat for UNIX calls. */
5500 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5501 DEBUG(3,("call_trans2qfilepathinfo: "
5502 "SMB_VFS_LSTAT of %s failed "
5504 smb_fname_str_dbg(smb_fname),
5507 map_nt_error_from_unix(errno));
5510 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5511 DEBUG(3,("call_trans2qfilepathinfo: "
5512 "SMB_VFS_STAT of %s failed (%s)\n",
5513 smb_fname_str_dbg(smb_fname),
5516 map_nt_error_from_unix(errno));
5520 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5521 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5524 * Original code - this is an open file.
5526 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5527 DEBUG(3, ("fstat of %s failed (%s)\n",
5528 fsp_fnum_dbg(fsp), strerror(errno)));
5530 map_nt_error_from_unix(errno));
5533 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5534 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5540 uint32_t ucf_flags = 0;
5543 if (total_params < 7) {
5544 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5548 info_level = SVAL(params,0);
5550 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5552 if (INFO_LEVEL_IS_UNIX(info_level)) {
5553 if (!lp_unix_extensions()) {
5554 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5557 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5558 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5559 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5560 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5564 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5566 STR_TERMINATE, &status);
5567 if (!NT_STATUS_IS_OK(status)) {
5568 reply_nterror(req, status);
5572 status = filename_convert(req,
5574 req->flags2 & FLAGS2_DFS_PATHNAMES,
5579 if (!NT_STATUS_IS_OK(status)) {
5580 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5581 reply_botherror(req,
5582 NT_STATUS_PATH_NOT_COVERED,
5583 ERRSRV, ERRbadpath);
5586 reply_nterror(req, status);
5590 /* If this is a stream, check if there is a delete_pending. */
5591 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5592 && is_ntfs_stream_smb_fname(smb_fname)) {
5593 struct smb_filename *smb_fname_base;
5595 /* Create an smb_filename with stream_name == NULL. */
5596 smb_fname_base = synthetic_smb_fname(
5597 talloc_tos(), smb_fname->base_name,
5599 if (smb_fname_base == NULL) {
5600 reply_nterror(req, NT_STATUS_NO_MEMORY);
5604 if (INFO_LEVEL_IS_UNIX(info_level)) {
5605 /* Always do lstat for UNIX calls. */
5606 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5607 DEBUG(3,("call_trans2qfilepathinfo: "
5608 "SMB_VFS_LSTAT of %s failed "
5610 smb_fname_str_dbg(smb_fname_base),
5612 TALLOC_FREE(smb_fname_base);
5614 map_nt_error_from_unix(errno));
5618 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5619 DEBUG(3,("call_trans2qfilepathinfo: "
5620 "fileinfo of %s failed "
5622 smb_fname_str_dbg(smb_fname_base),
5624 TALLOC_FREE(smb_fname_base);
5626 map_nt_error_from_unix(errno));
5631 status = file_name_hash(conn,
5632 smb_fname_str_dbg(smb_fname_base),
5634 if (!NT_STATUS_IS_OK(status)) {
5635 TALLOC_FREE(smb_fname_base);
5636 reply_nterror(req, status);
5640 fileid = vfs_file_id_from_sbuf(conn,
5641 &smb_fname_base->st);
5642 TALLOC_FREE(smb_fname_base);
5643 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5644 if (delete_pending) {
5645 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5650 if (INFO_LEVEL_IS_UNIX(info_level)) {
5651 /* Always do lstat for UNIX calls. */
5652 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5653 DEBUG(3,("call_trans2qfilepathinfo: "
5654 "SMB_VFS_LSTAT of %s failed (%s)\n",
5655 smb_fname_str_dbg(smb_fname),
5658 map_nt_error_from_unix(errno));
5663 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5664 DEBUG(3,("call_trans2qfilepathinfo: "
5665 "SMB_VFS_STAT of %s failed (%s)\n",
5666 smb_fname_str_dbg(smb_fname),
5669 map_nt_error_from_unix(errno));
5674 status = file_name_hash(conn,
5675 smb_fname_str_dbg(smb_fname),
5677 if (!NT_STATUS_IS_OK(status)) {
5678 reply_nterror(req, status);
5682 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5683 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5684 if (delete_pending) {
5685 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5690 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5691 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5693 info_level,tran_call,total_data));
5695 /* Pull out any data sent here before we realloc. */
5696 switch (info_level) {
5697 case SMB_INFO_QUERY_EAS_FROM_LIST:
5699 /* Pull any EA list from the data portion. */
5702 if (total_data < 4) {
5704 req, NT_STATUS_INVALID_PARAMETER);
5707 ea_size = IVAL(pdata,0);
5709 if (total_data > 0 && ea_size != total_data) {
5710 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5711 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5713 req, NT_STATUS_INVALID_PARAMETER);
5717 if (!lp_ea_support(SNUM(conn))) {
5718 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5722 /* Pull out the list of names. */
5723 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5726 req, NT_STATUS_INVALID_PARAMETER);
5732 case SMB_QUERY_POSIX_LOCK:
5734 if (fsp == NULL || fsp->fh->fd == -1) {
5735 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5739 if (total_data != POSIX_LOCK_DATA_SIZE) {
5741 req, NT_STATUS_INVALID_PARAMETER);
5745 /* Copy the lock range data. */
5746 lock_data = (char *)talloc_memdup(
5747 req, pdata, total_data);
5749 reply_nterror(req, NT_STATUS_NO_MEMORY);
5752 lock_data_count = total_data;
5758 *pparams = (char *)SMB_REALLOC(*pparams,2);
5759 if (*pparams == NULL) {
5760 reply_nterror(req, NT_STATUS_NO_MEMORY);
5767 * draft-leach-cifs-v1-spec-02.txt
5768 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5771 * The requested information is placed in the Data portion of the
5772 * transaction response. For the information levels greater than 0x100,
5773 * the transaction response has 1 parameter word which should be
5774 * ignored by the client.
5776 * However Windows only follows this rule for the IS_NAME_VALID call.
5778 switch (info_level) {
5779 case SMB_INFO_IS_NAME_VALID:
5784 if ((info_level & 0xFF00) == 0xFF00) {
5786 * We use levels that start with 0xFF00
5787 * internally to represent SMB2 specific levels
5789 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5793 status = smbd_do_qfilepathinfo(conn, req, info_level,
5795 delete_pending, write_time_ts,
5797 lock_data_count, lock_data,
5798 req->flags2, max_data_bytes,
5800 ppdata, &data_size);
5801 if (!NT_STATUS_IS_OK(status)) {
5802 reply_nterror(req, status);
5805 if (fixed_portion > max_data_bytes) {
5806 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5810 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5816 /****************************************************************************
5817 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5819 ****************************************************************************/
5821 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5822 connection_struct *conn,
5823 struct smb_request *req,
5824 bool overwrite_if_exists,
5825 const struct smb_filename *smb_fname_old,
5826 struct smb_filename *smb_fname_new)
5828 NTSTATUS status = NT_STATUS_OK;
5830 /* source must already exist. */
5831 if (!VALID_STAT(smb_fname_old->st)) {
5832 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5835 if (VALID_STAT(smb_fname_new->st)) {
5836 if (overwrite_if_exists) {
5837 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5838 return NT_STATUS_FILE_IS_A_DIRECTORY;
5840 status = unlink_internals(conn,
5842 FILE_ATTRIBUTE_NORMAL,
5845 if (!NT_STATUS_IS_OK(status)) {
5849 /* Disallow if newname already exists. */
5850 return NT_STATUS_OBJECT_NAME_COLLISION;
5854 /* No links from a directory. */
5855 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5856 return NT_STATUS_FILE_IS_A_DIRECTORY;
5859 /* Setting a hardlink to/from a stream isn't currently supported. */
5860 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5861 is_ntfs_stream_smb_fname(smb_fname_new)) {
5862 return NT_STATUS_INVALID_PARAMETER;
5865 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5866 smb_fname_old->base_name, smb_fname_new->base_name));
5868 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5869 smb_fname_new->base_name) != 0) {
5870 status = map_nt_error_from_unix(errno);
5871 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5872 nt_errstr(status), smb_fname_old->base_name,
5873 smb_fname_new->base_name));
5878 /****************************************************************************
5879 Deal with setting the time from any of the setfilepathinfo functions.
5880 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5881 calling this function.
5882 ****************************************************************************/
5884 NTSTATUS smb_set_file_time(connection_struct *conn,
5886 const struct smb_filename *smb_fname,
5887 struct smb_file_time *ft,
5888 bool setting_write_time)
5890 struct smb_filename smb_fname_base;
5892 FILE_NOTIFY_CHANGE_LAST_ACCESS
5893 |FILE_NOTIFY_CHANGE_LAST_WRITE
5894 |FILE_NOTIFY_CHANGE_CREATION;
5896 if (!VALID_STAT(smb_fname->st)) {
5897 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5900 /* get some defaults (no modifications) if any info is zero or -1. */
5901 if (null_timespec(ft->create_time)) {
5902 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5905 if (null_timespec(ft->atime)) {
5906 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5909 if (null_timespec(ft->mtime)) {
5910 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5913 if (!setting_write_time) {
5914 /* ft->mtime comes from change time, not write time. */
5915 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5918 /* Ensure the resolution is the correct for
5919 * what we can store on this filesystem. */
5921 round_timespec(conn->ts_res, &ft->create_time);
5922 round_timespec(conn->ts_res, &ft->ctime);
5923 round_timespec(conn->ts_res, &ft->atime);
5924 round_timespec(conn->ts_res, &ft->mtime);
5926 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5927 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5928 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5929 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5930 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5931 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5932 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5933 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5935 if (setting_write_time) {
5937 * This was a Windows setfileinfo on an open file.
5938 * NT does this a lot. We also need to
5939 * set the time here, as it can be read by
5940 * FindFirst/FindNext and with the patch for bug #2045
5941 * in smbd/fileio.c it ensures that this timestamp is
5942 * kept sticky even after a write. We save the request
5943 * away and will set it on file close and after a write. JRA.
5946 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5947 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5950 if (fsp->base_fsp) {
5951 set_sticky_write_time_fsp(fsp->base_fsp,
5954 set_sticky_write_time_fsp(fsp, ft->mtime);
5957 set_sticky_write_time_path(
5958 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5963 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5965 /* Always call ntimes on the base, even if a stream was passed in. */
5966 smb_fname_base = *smb_fname;
5967 smb_fname_base.stream_name = NULL;
5969 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5970 return map_nt_error_from_unix(errno);
5973 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5974 smb_fname->base_name);
5975 return NT_STATUS_OK;
5978 /****************************************************************************
5979 Deal with setting the dosmode from any of the setfilepathinfo functions.
5980 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5981 done before calling this function.
5982 ****************************************************************************/
5984 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5985 const struct smb_filename *smb_fname,
5988 struct smb_filename *smb_fname_base;
5991 if (!VALID_STAT(smb_fname->st)) {
5992 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5995 /* Always operate on the base_name, even if a stream was passed in. */
5996 smb_fname_base = synthetic_smb_fname(
5997 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5998 if (smb_fname_base == NULL) {
5999 return NT_STATUS_NO_MEMORY;
6003 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6004 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6006 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6010 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6012 /* check the mode isn't different, before changing it */
6013 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6014 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6015 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6016 (unsigned int)dosmode));
6018 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6020 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6022 smb_fname_str_dbg(smb_fname_base),
6024 status = map_nt_error_from_unix(errno);
6028 status = NT_STATUS_OK;
6030 TALLOC_FREE(smb_fname_base);
6034 /****************************************************************************
6035 Deal with setting the size from any of the setfilepathinfo functions.
6036 ****************************************************************************/
6038 static NTSTATUS smb_set_file_size(connection_struct *conn,
6039 struct smb_request *req,
6041 const struct smb_filename *smb_fname,
6042 const SMB_STRUCT_STAT *psbuf,
6044 bool fail_after_createfile)
6046 NTSTATUS status = NT_STATUS_OK;
6047 struct smb_filename *smb_fname_tmp = NULL;
6048 files_struct *new_fsp = NULL;
6050 if (!VALID_STAT(*psbuf)) {
6051 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6054 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6056 if (size == get_file_size_stat(psbuf)) {
6057 return NT_STATUS_OK;
6060 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6061 smb_fname_str_dbg(smb_fname), (double)size));
6063 if (fsp && fsp->fh->fd != -1) {
6064 /* Handle based call. */
6065 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6066 return NT_STATUS_ACCESS_DENIED;
6069 if (vfs_set_filelen(fsp, size) == -1) {
6070 return map_nt_error_from_unix(errno);
6072 trigger_write_time_update_immediate(fsp);
6073 return NT_STATUS_OK;
6076 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6077 if (smb_fname_tmp == NULL) {
6078 return NT_STATUS_NO_MEMORY;
6081 smb_fname_tmp->st = *psbuf;
6083 status = SMB_VFS_CREATE_FILE(
6086 0, /* root_dir_fid */
6087 smb_fname_tmp, /* fname */
6088 FILE_WRITE_DATA, /* access_mask */
6089 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6091 FILE_OPEN, /* create_disposition*/
6092 0, /* create_options */
6093 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6094 0, /* oplock_request */
6096 0, /* allocation_size */
6097 0, /* private_flags */
6100 &new_fsp, /* result */
6102 NULL, NULL); /* create context */
6104 TALLOC_FREE(smb_fname_tmp);
6106 if (!NT_STATUS_IS_OK(status)) {
6107 /* NB. We check for open_was_deferred in the caller. */
6111 /* See RAW-SFILEINFO-END-OF-FILE */
6112 if (fail_after_createfile) {
6113 close_file(req, new_fsp,NORMAL_CLOSE);
6114 return NT_STATUS_INVALID_LEVEL;
6117 if (vfs_set_filelen(new_fsp, size) == -1) {
6118 status = map_nt_error_from_unix(errno);
6119 close_file(req, new_fsp,NORMAL_CLOSE);
6123 trigger_write_time_update_immediate(new_fsp);
6124 close_file(req, new_fsp,NORMAL_CLOSE);
6125 return NT_STATUS_OK;
6128 /****************************************************************************
6129 Deal with SMB_INFO_SET_EA.
6130 ****************************************************************************/
6132 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6136 const struct smb_filename *smb_fname)
6138 struct ea_list *ea_list = NULL;
6139 TALLOC_CTX *ctx = NULL;
6140 NTSTATUS status = NT_STATUS_OK;
6142 if (total_data < 10) {
6144 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6145 length. They seem to have no effect. Bug #3212. JRA */
6147 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6148 /* We're done. We only get EA info in this call. */
6149 return NT_STATUS_OK;
6152 return NT_STATUS_INVALID_PARAMETER;
6155 if (IVAL(pdata,0) > total_data) {
6156 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6157 IVAL(pdata,0), (unsigned int)total_data));
6158 return NT_STATUS_INVALID_PARAMETER;
6162 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6164 return NT_STATUS_INVALID_PARAMETER;
6167 status = set_ea(conn, fsp, smb_fname, ea_list);
6172 /****************************************************************************
6173 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6174 ****************************************************************************/
6176 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6181 struct ea_list *ea_list = NULL;
6185 return NT_STATUS_INVALID_HANDLE;
6188 if (!lp_ea_support(SNUM(conn))) {
6189 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6190 "EA's not supported.\n",
6191 (unsigned int)total_data));
6192 return NT_STATUS_EAS_NOT_SUPPORTED;
6195 if (total_data < 10) {
6196 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6198 (unsigned int)total_data));
6199 return NT_STATUS_INVALID_PARAMETER;
6202 ea_list = read_nttrans_ea_list(talloc_tos(),
6207 return NT_STATUS_INVALID_PARAMETER;
6210 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6212 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6213 smb_fname_str_dbg(fsp->fsp_name),
6214 nt_errstr(status) ));
6220 /****************************************************************************
6221 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6222 ****************************************************************************/
6224 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6228 struct smb_filename *smb_fname)
6230 NTSTATUS status = NT_STATUS_OK;
6231 bool delete_on_close;
6232 uint32_t dosmode = 0;
6234 if (total_data < 1) {
6235 return NT_STATUS_INVALID_PARAMETER;
6239 return NT_STATUS_INVALID_HANDLE;
6242 delete_on_close = (CVAL(pdata,0) ? True : False);
6243 dosmode = dos_mode(conn, smb_fname);
6245 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6246 "delete_on_close = %u\n",
6247 smb_fname_str_dbg(smb_fname),
6248 (unsigned int)dosmode,
6249 (unsigned int)delete_on_close ));
6251 if (delete_on_close) {
6252 status = can_set_delete_on_close(fsp, dosmode);
6253 if (!NT_STATUS_IS_OK(status)) {
6258 /* The set is across all open files on this dev/inode pair. */
6259 if (!set_delete_on_close(fsp, delete_on_close,
6260 conn->session_info->security_token,
6261 conn->session_info->unix_token)) {
6262 return NT_STATUS_ACCESS_DENIED;
6264 return NT_STATUS_OK;
6267 /****************************************************************************
6268 Deal with SMB_FILE_POSITION_INFORMATION.
6269 ****************************************************************************/
6271 static NTSTATUS smb_file_position_information(connection_struct *conn,
6276 uint64_t position_information;
6278 if (total_data < 8) {
6279 return NT_STATUS_INVALID_PARAMETER;
6283 /* Ignore on pathname based set. */
6284 return NT_STATUS_OK;
6287 position_information = (uint64_t)IVAL(pdata,0);
6288 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6290 DEBUG(10,("smb_file_position_information: Set file position "
6291 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6292 (double)position_information));
6293 fsp->fh->position_information = position_information;
6294 return NT_STATUS_OK;
6297 /****************************************************************************
6298 Deal with SMB_FILE_MODE_INFORMATION.
6299 ****************************************************************************/
6301 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6307 if (total_data < 4) {
6308 return NT_STATUS_INVALID_PARAMETER;
6310 mode = IVAL(pdata,0);
6311 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6312 return NT_STATUS_INVALID_PARAMETER;
6314 return NT_STATUS_OK;
6317 /****************************************************************************
6318 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6319 ****************************************************************************/
6321 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6322 struct smb_request *req,
6325 const struct smb_filename *smb_fname)
6327 char *link_target = NULL;
6328 const char *newname = smb_fname->base_name;
6329 TALLOC_CTX *ctx = talloc_tos();
6331 /* Set a symbolic link. */
6332 /* Don't allow this if follow links is false. */
6334 if (total_data == 0) {
6335 return NT_STATUS_INVALID_PARAMETER;
6338 if (!lp_follow_symlinks(SNUM(conn))) {
6339 return NT_STATUS_ACCESS_DENIED;
6342 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6343 total_data, STR_TERMINATE);
6346 return NT_STATUS_INVALID_PARAMETER;
6349 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6350 newname, link_target ));
6352 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6353 return map_nt_error_from_unix(errno);
6356 return NT_STATUS_OK;
6359 /****************************************************************************
6360 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6361 ****************************************************************************/
6363 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6364 struct smb_request *req,
6365 const char *pdata, int total_data,
6366 struct smb_filename *smb_fname_new)
6368 char *oldname = NULL;
6369 struct smb_filename *smb_fname_old = NULL;
6370 TALLOC_CTX *ctx = talloc_tos();
6371 NTSTATUS status = NT_STATUS_OK;
6373 /* Set a hard link. */
6374 if (total_data == 0) {
6375 return NT_STATUS_INVALID_PARAMETER;
6378 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6379 total_data, STR_TERMINATE, &status);
6380 if (!NT_STATUS_IS_OK(status)) {
6384 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6385 smb_fname_str_dbg(smb_fname_new), oldname));
6387 status = filename_convert(ctx,
6389 req->flags2 & FLAGS2_DFS_PATHNAMES,
6394 if (!NT_STATUS_IS_OK(status)) {
6398 return hardlink_internals(ctx, conn, req, false,
6399 smb_fname_old, smb_fname_new);
6402 /****************************************************************************
6403 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6404 ****************************************************************************/
6406 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6407 struct smb_request *req,
6411 struct smb_filename *smb_fname_src)
6415 char *newname = NULL;
6416 struct smb_filename *smb_fname_dst = NULL;
6417 NTSTATUS status = NT_STATUS_OK;
6418 TALLOC_CTX *ctx = talloc_tos();
6421 return NT_STATUS_INVALID_HANDLE;
6424 if (total_data < 20) {
6425 return NT_STATUS_INVALID_PARAMETER;
6428 overwrite = (CVAL(pdata,0) ? True : False);
6429 len = IVAL(pdata,16);
6431 if (len > (total_data - 20) || (len == 0)) {
6432 return NT_STATUS_INVALID_PARAMETER;
6435 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6436 &pdata[20], len, STR_TERMINATE,
6438 if (!NT_STATUS_IS_OK(status)) {
6442 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6445 status = filename_convert(ctx,
6447 req->flags2 & FLAGS2_DFS_PATHNAMES,
6452 if (!NT_STATUS_IS_OK(status)) {
6456 if (fsp->base_fsp) {
6457 /* newname must be a stream name. */
6458 if (newname[0] != ':') {
6459 return NT_STATUS_NOT_SUPPORTED;
6462 /* Create an smb_fname to call rename_internals_fsp() with. */
6463 smb_fname_dst = synthetic_smb_fname(
6464 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6466 if (smb_fname_dst == NULL) {
6467 status = NT_STATUS_NO_MEMORY;
6472 * Set the original last component, since
6473 * rename_internals_fsp() requires it.
6475 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6477 if (smb_fname_dst->original_lcomp == NULL) {
6478 status = NT_STATUS_NO_MEMORY;
6484 DEBUG(10,("smb2_file_rename_information: "
6485 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6486 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6487 smb_fname_str_dbg(smb_fname_dst)));
6488 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6489 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6493 TALLOC_FREE(smb_fname_dst);
6497 static NTSTATUS smb_file_link_information(connection_struct *conn,
6498 struct smb_request *req,
6502 struct smb_filename *smb_fname_src)
6506 char *newname = NULL;
6507 struct smb_filename *smb_fname_dst = NULL;
6508 NTSTATUS status = NT_STATUS_OK;
6509 TALLOC_CTX *ctx = talloc_tos();
6512 return NT_STATUS_INVALID_HANDLE;
6515 if (total_data < 20) {
6516 return NT_STATUS_INVALID_PARAMETER;
6519 overwrite = (CVAL(pdata,0) ? true : false);
6520 len = IVAL(pdata,16);
6522 if (len > (total_data - 20) || (len == 0)) {
6523 return NT_STATUS_INVALID_PARAMETER;
6526 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6527 &pdata[20], len, STR_TERMINATE,
6529 if (!NT_STATUS_IS_OK(status)) {
6533 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6536 status = filename_convert(ctx,
6538 req->flags2 & FLAGS2_DFS_PATHNAMES,
6543 if (!NT_STATUS_IS_OK(status)) {
6547 if (fsp->base_fsp) {
6548 /* No stream names. */
6549 return NT_STATUS_NOT_SUPPORTED;
6552 DEBUG(10,("smb_file_link_information: "
6553 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6554 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6555 smb_fname_str_dbg(smb_fname_dst)));
6556 status = hardlink_internals(ctx,
6563 TALLOC_FREE(smb_fname_dst);
6567 /****************************************************************************
6568 Deal with SMB_FILE_RENAME_INFORMATION.
6569 ****************************************************************************/
6571 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6572 struct smb_request *req,
6576 struct smb_filename *smb_fname_src)
6581 char *newname = NULL;
6582 struct smb_filename *smb_fname_dst = NULL;
6583 bool dest_has_wcard = False;
6584 NTSTATUS status = NT_STATUS_OK;
6586 TALLOC_CTX *ctx = talloc_tos();
6588 if (total_data < 13) {
6589 return NT_STATUS_INVALID_PARAMETER;
6592 overwrite = (CVAL(pdata,0) ? True : False);
6593 root_fid = IVAL(pdata,4);
6594 len = IVAL(pdata,8);
6596 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6597 return NT_STATUS_INVALID_PARAMETER;
6600 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6603 if (!NT_STATUS_IS_OK(status)) {
6607 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6610 status = resolve_dfspath_wcard(ctx, conn,
6611 req->flags2 & FLAGS2_DFS_PATHNAMES,
6614 !conn->sconn->using_smb2,
6617 if (!NT_STATUS_IS_OK(status)) {
6621 /* Check the new name has no '/' characters. */
6622 if (strchr_m(newname, '/')) {
6623 return NT_STATUS_NOT_SUPPORTED;
6626 if (fsp && fsp->base_fsp) {
6627 /* newname must be a stream name. */
6628 if (newname[0] != ':') {
6629 return NT_STATUS_NOT_SUPPORTED;
6632 /* Create an smb_fname to call rename_internals_fsp() with. */
6633 smb_fname_dst = synthetic_smb_fname(
6634 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6636 if (smb_fname_dst == NULL) {
6637 status = NT_STATUS_NO_MEMORY;
6642 * Set the original last component, since
6643 * rename_internals_fsp() requires it.
6645 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6647 if (smb_fname_dst->original_lcomp == NULL) {
6648 status = NT_STATUS_NO_MEMORY;
6654 * Build up an smb_fname_dst based on the filename passed in.
6655 * We basically just strip off the last component, and put on
6656 * the newname instead.
6658 char *base_name = NULL;
6660 /* newname must *not* be a stream name. */
6661 if (newname[0] == ':') {
6662 return NT_STATUS_NOT_SUPPORTED;
6666 * Strip off the last component (filename) of the path passed
6669 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6671 return NT_STATUS_NO_MEMORY;
6673 p = strrchr_m(base_name, '/');
6677 base_name = talloc_strdup(ctx, "");
6679 return NT_STATUS_NO_MEMORY;
6682 /* Append the new name. */
6683 base_name = talloc_asprintf_append(base_name,
6687 return NT_STATUS_NO_MEMORY;
6690 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6693 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6696 /* If an error we expect this to be
6697 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6699 if (!NT_STATUS_IS_OK(status)) {
6700 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6704 /* Create an smb_fname to call rename_internals_fsp() */
6705 smb_fname_dst = synthetic_smb_fname(
6706 ctx, base_name, NULL, NULL);
6707 if (smb_fname_dst == NULL) {
6708 status = NT_STATUS_NO_MEMORY;
6715 DEBUG(10,("smb_file_rename_information: "
6716 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6717 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6718 smb_fname_str_dbg(smb_fname_dst)));
6719 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6722 DEBUG(10,("smb_file_rename_information: "
6723 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6724 smb_fname_str_dbg(smb_fname_src),
6725 smb_fname_str_dbg(smb_fname_dst)));
6726 status = rename_internals(ctx, conn, req, smb_fname_src,
6727 smb_fname_dst, 0, overwrite, false,
6729 FILE_WRITE_ATTRIBUTES);
6732 TALLOC_FREE(smb_fname_dst);
6736 /****************************************************************************
6737 Deal with SMB_SET_POSIX_ACL.
6738 ****************************************************************************/
6740 #if defined(HAVE_POSIX_ACLS)
6741 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6745 const struct smb_filename *smb_fname)
6747 uint16_t posix_acl_version;
6748 uint16_t num_file_acls;
6749 uint16_t num_def_acls;
6750 bool valid_file_acls = True;
6751 bool valid_def_acls = True;
6753 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6754 return NT_STATUS_INVALID_PARAMETER;
6756 posix_acl_version = SVAL(pdata,0);
6757 num_file_acls = SVAL(pdata,2);
6758 num_def_acls = SVAL(pdata,4);
6760 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6761 valid_file_acls = False;
6765 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6766 valid_def_acls = False;
6770 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6771 return NT_STATUS_INVALID_PARAMETER;
6774 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6775 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6776 return NT_STATUS_INVALID_PARAMETER;
6779 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6780 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6781 (unsigned int)num_file_acls,
6782 (unsigned int)num_def_acls));
6784 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6785 smb_fname->base_name, num_file_acls,
6786 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6787 return map_nt_error_from_unix(errno);
6790 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6791 smb_fname->base_name, &smb_fname->st, num_def_acls,
6792 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6793 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6794 return map_nt_error_from_unix(errno);
6796 return NT_STATUS_OK;
6800 /****************************************************************************
6801 Deal with SMB_SET_POSIX_LOCK.
6802 ****************************************************************************/
6804 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6805 struct smb_request *req,
6813 bool blocking_lock = False;
6814 enum brl_type lock_type;
6816 NTSTATUS status = NT_STATUS_OK;
6818 if (fsp == NULL || fsp->fh->fd == -1) {
6819 return NT_STATUS_INVALID_HANDLE;
6822 if (total_data != POSIX_LOCK_DATA_SIZE) {
6823 return NT_STATUS_INVALID_PARAMETER;
6826 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6827 case POSIX_LOCK_TYPE_READ:
6828 lock_type = READ_LOCK;
6830 case POSIX_LOCK_TYPE_WRITE:
6831 /* Return the right POSIX-mappable error code for files opened read-only. */
6832 if (!fsp->can_write) {
6833 return NT_STATUS_INVALID_HANDLE;
6835 lock_type = WRITE_LOCK;
6837 case POSIX_LOCK_TYPE_UNLOCK:
6838 lock_type = UNLOCK_LOCK;
6841 return NT_STATUS_INVALID_PARAMETER;
6844 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6845 blocking_lock = False;
6846 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6847 blocking_lock = True;
6849 return NT_STATUS_INVALID_PARAMETER;
6852 if (!lp_blocking_locks(SNUM(conn))) {
6853 blocking_lock = False;
6856 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6857 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6858 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6859 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6860 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6862 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6863 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6865 (unsigned int)lock_type,
6866 (unsigned long long)smblctx,
6870 if (lock_type == UNLOCK_LOCK) {
6871 status = do_unlock(req->sconn->msg_ctx,
6878 uint64_t block_smblctx;
6880 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6891 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6893 * A blocking lock was requested. Package up
6894 * this smb into a queued request and push it
6895 * onto the blocking lock queue.
6897 if(push_blocking_lock_request(br_lck,
6900 -1, /* infinite timeout. */
6908 TALLOC_FREE(br_lck);
6912 TALLOC_FREE(br_lck);
6918 /****************************************************************************
6919 Deal with SMB_SET_FILE_BASIC_INFO.
6920 ****************************************************************************/
6922 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6926 const struct smb_filename *smb_fname)
6928 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6929 struct smb_file_time ft;
6930 uint32_t dosmode = 0;
6931 NTSTATUS status = NT_STATUS_OK;
6935 if (total_data < 36) {
6936 return NT_STATUS_INVALID_PARAMETER;
6939 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6940 if (!NT_STATUS_IS_OK(status)) {
6944 /* Set the attributes */
6945 dosmode = IVAL(pdata,32);
6946 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6947 if (!NT_STATUS_IS_OK(status)) {
6952 ft.create_time = interpret_long_date(pdata);
6955 ft.atime = interpret_long_date(pdata+8);
6958 ft.mtime = interpret_long_date(pdata+16);
6961 ft.ctime = interpret_long_date(pdata+24);
6963 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6964 smb_fname_str_dbg(smb_fname)));
6966 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6970 /****************************************************************************
6971 Deal with SMB_INFO_STANDARD.
6972 ****************************************************************************/
6974 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6978 const struct smb_filename *smb_fname)
6981 struct smb_file_time ft;
6985 if (total_data < 12) {
6986 return NT_STATUS_INVALID_PARAMETER;
6990 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6992 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6994 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6996 DEBUG(10,("smb_set_info_standard: file %s\n",
6997 smb_fname_str_dbg(smb_fname)));
6999 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7000 if (!NT_STATUS_IS_OK(status)) {
7004 return smb_set_file_time(conn,
7011 /****************************************************************************
7012 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7013 ****************************************************************************/
7015 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7016 struct smb_request *req,
7020 struct smb_filename *smb_fname)
7022 uint64_t allocation_size = 0;
7023 NTSTATUS status = NT_STATUS_OK;
7024 files_struct *new_fsp = NULL;
7026 if (!VALID_STAT(smb_fname->st)) {
7027 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7030 if (total_data < 8) {
7031 return NT_STATUS_INVALID_PARAMETER;
7034 allocation_size = (uint64_t)IVAL(pdata,0);
7035 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7036 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7037 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7038 (double)allocation_size));
7040 if (allocation_size) {
7041 allocation_size = smb_roundup(conn, allocation_size);
7044 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7045 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7046 (double)allocation_size));
7048 if (fsp && fsp->fh->fd != -1) {
7049 /* Open file handle. */
7050 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7051 return NT_STATUS_ACCESS_DENIED;
7054 /* Only change if needed. */
7055 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7056 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7057 return map_nt_error_from_unix(errno);
7060 /* But always update the time. */
7062 * This is equivalent to a write. Ensure it's seen immediately
7063 * if there are no pending writes.
7065 trigger_write_time_update_immediate(fsp);
7066 return NT_STATUS_OK;
7069 /* Pathname or stat or directory file. */
7070 status = SMB_VFS_CREATE_FILE(
7073 0, /* root_dir_fid */
7074 smb_fname, /* fname */
7075 FILE_WRITE_DATA, /* access_mask */
7076 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7078 FILE_OPEN, /* create_disposition*/
7079 0, /* create_options */
7080 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7081 0, /* oplock_request */
7083 0, /* allocation_size */
7084 0, /* private_flags */
7087 &new_fsp, /* result */
7089 NULL, NULL); /* create context */
7091 if (!NT_STATUS_IS_OK(status)) {
7092 /* NB. We check for open_was_deferred in the caller. */
7096 /* Only change if needed. */
7097 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7098 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7099 status = map_nt_error_from_unix(errno);
7100 close_file(req, new_fsp, NORMAL_CLOSE);
7105 /* Changing the allocation size should set the last mod time. */
7107 * This is equivalent to a write. Ensure it's seen immediately
7108 * if there are no pending writes.
7110 trigger_write_time_update_immediate(new_fsp);
7111 close_file(req, new_fsp, NORMAL_CLOSE);
7112 return NT_STATUS_OK;
7115 /****************************************************************************
7116 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7117 ****************************************************************************/
7119 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7120 struct smb_request *req,
7124 const struct smb_filename *smb_fname,
7125 bool fail_after_createfile)
7129 if (total_data < 8) {
7130 return NT_STATUS_INVALID_PARAMETER;
7133 size = IVAL(pdata,0);
7134 size |= (((off_t)IVAL(pdata,4)) << 32);
7135 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7136 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7139 return smb_set_file_size(conn, req,
7144 fail_after_createfile);
7147 /****************************************************************************
7148 Allow a UNIX info mknod.
7149 ****************************************************************************/
7151 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7154 const struct smb_filename *smb_fname)
7156 uint32_t file_type = IVAL(pdata,56);
7157 #if defined(HAVE_MAKEDEV)
7158 uint32_t dev_major = IVAL(pdata,60);
7159 uint32_t dev_minor = IVAL(pdata,68);
7161 SMB_DEV_T dev = (SMB_DEV_T)0;
7162 uint32_t raw_unixmode = IVAL(pdata,84);
7166 if (total_data < 100) {
7167 return NT_STATUS_INVALID_PARAMETER;
7170 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7171 PERM_NEW_FILE, &unixmode);
7172 if (!NT_STATUS_IS_OK(status)) {
7176 #if defined(HAVE_MAKEDEV)
7177 dev = makedev(dev_major, dev_minor);
7180 switch (file_type) {
7181 #if defined(S_IFIFO)
7182 case UNIX_TYPE_FIFO:
7183 unixmode |= S_IFIFO;
7186 #if defined(S_IFSOCK)
7187 case UNIX_TYPE_SOCKET:
7188 unixmode |= S_IFSOCK;
7191 #if defined(S_IFCHR)
7192 case UNIX_TYPE_CHARDEV:
7193 unixmode |= S_IFCHR;
7196 #if defined(S_IFBLK)
7197 case UNIX_TYPE_BLKDEV:
7198 unixmode |= S_IFBLK;
7202 return NT_STATUS_INVALID_PARAMETER;
7205 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7206 "%.0f mode 0%o for file %s\n", (double)dev,
7207 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7209 /* Ok - do the mknod. */
7210 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7211 return map_nt_error_from_unix(errno);
7214 /* If any of the other "set" calls fail we
7215 * don't want to end up with a half-constructed mknod.
7218 if (lp_inherit_permissions(SNUM(conn))) {
7220 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7222 return NT_STATUS_NO_MEMORY;
7224 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7226 TALLOC_FREE(parent);
7229 return NT_STATUS_OK;
7232 /****************************************************************************
7233 Deal with SMB_SET_FILE_UNIX_BASIC.
7234 ****************************************************************************/
7236 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7237 struct smb_request *req,
7241 const struct smb_filename *smb_fname)
7243 struct smb_file_time ft;
7244 uint32_t raw_unixmode;
7247 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7248 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7249 NTSTATUS status = NT_STATUS_OK;
7250 bool delete_on_fail = False;
7251 enum perm_type ptype;
7252 files_struct *all_fsps = NULL;
7253 bool modify_mtime = true;
7255 struct smb_filename *smb_fname_tmp = NULL;
7256 SMB_STRUCT_STAT sbuf;
7260 if (total_data < 100) {
7261 return NT_STATUS_INVALID_PARAMETER;
7264 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7265 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7266 size=IVAL(pdata,0); /* first 8 Bytes are size */
7267 size |= (((off_t)IVAL(pdata,4)) << 32);
7270 ft.atime = interpret_long_date(pdata+24); /* access_time */
7271 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7272 set_owner = (uid_t)IVAL(pdata,40);
7273 set_grp = (gid_t)IVAL(pdata,48);
7274 raw_unixmode = IVAL(pdata,84);
7276 if (VALID_STAT(smb_fname->st)) {
7277 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7278 ptype = PERM_EXISTING_DIR;
7280 ptype = PERM_EXISTING_FILE;
7283 ptype = PERM_NEW_FILE;
7286 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7288 if (!NT_STATUS_IS_OK(status)) {
7292 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7293 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7294 smb_fname_str_dbg(smb_fname), (double)size,
7295 (unsigned int)set_owner, (unsigned int)set_grp,
7296 (int)raw_unixmode));
7298 sbuf = smb_fname->st;
7300 if (!VALID_STAT(sbuf)) {
7302 * The only valid use of this is to create character and block
7303 * devices, and named pipes. This is deprecated (IMHO) and
7304 * a new info level should be used for mknod. JRA.
7307 status = smb_unix_mknod(conn,
7311 if (!NT_STATUS_IS_OK(status)) {
7315 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7316 if (smb_fname_tmp == NULL) {
7317 return NT_STATUS_NO_MEMORY;
7320 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7321 status = map_nt_error_from_unix(errno);
7322 TALLOC_FREE(smb_fname_tmp);
7323 SMB_VFS_UNLINK(conn, smb_fname);
7327 sbuf = smb_fname_tmp->st;
7328 smb_fname = smb_fname_tmp;
7330 /* Ensure we don't try and change anything else. */
7331 raw_unixmode = SMB_MODE_NO_CHANGE;
7332 size = get_file_size_stat(&sbuf);
7333 ft.atime = sbuf.st_ex_atime;
7334 ft.mtime = sbuf.st_ex_mtime;
7336 * We continue here as we might want to change the
7339 delete_on_fail = True;
7343 /* Horrible backwards compatibility hack as an old server bug
7344 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7348 size = get_file_size_stat(&sbuf);
7353 * Deal with the UNIX specific mode set.
7356 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7359 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7360 "setting mode 0%o for file %s\n",
7361 (unsigned int)unixmode,
7362 smb_fname_str_dbg(smb_fname)));
7363 if (fsp && fsp->fh->fd != -1) {
7364 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7366 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7369 return map_nt_error_from_unix(errno);
7374 * Deal with the UNIX specific uid set.
7377 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7378 (sbuf.st_ex_uid != set_owner)) {
7381 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7382 "changing owner %u for path %s\n",
7383 (unsigned int)set_owner,
7384 smb_fname_str_dbg(smb_fname)));
7386 if (fsp && fsp->fh->fd != -1) {
7387 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7390 * UNIX extensions calls must always operate
7393 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7394 set_owner, (gid_t)-1);
7398 status = map_nt_error_from_unix(errno);
7399 if (delete_on_fail) {
7400 SMB_VFS_UNLINK(conn, smb_fname);
7407 * Deal with the UNIX specific gid set.
7410 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7411 (sbuf.st_ex_gid != set_grp)) {
7414 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7415 "changing group %u for file %s\n",
7416 (unsigned int)set_owner,
7417 smb_fname_str_dbg(smb_fname)));
7418 if (fsp && fsp->fh->fd != -1) {
7419 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7422 * UNIX extensions calls must always operate
7425 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7429 status = map_nt_error_from_unix(errno);
7430 if (delete_on_fail) {
7431 SMB_VFS_UNLINK(conn, smb_fname);
7437 /* Deal with any size changes. */
7439 status = smb_set_file_size(conn, req,
7445 if (!NT_STATUS_IS_OK(status)) {
7449 /* Deal with any time changes. */
7450 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7451 /* No change, don't cancel anything. */
7455 id = vfs_file_id_from_sbuf(conn, &sbuf);
7456 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7457 all_fsps = file_find_di_next(all_fsps)) {
7459 * We're setting the time explicitly for UNIX.
7460 * Cancel any pending changes over all handles.
7462 all_fsps->update_write_time_on_close = false;
7463 TALLOC_FREE(all_fsps->update_write_time_event);
7467 * Override the "setting_write_time"
7468 * parameter here as it almost does what
7469 * we need. Just remember if we modified
7470 * mtime and send the notify ourselves.
7472 if (null_timespec(ft.mtime)) {
7473 modify_mtime = false;
7476 status = smb_set_file_time(conn,
7482 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7483 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7488 /****************************************************************************
7489 Deal with SMB_SET_FILE_UNIX_INFO2.
7490 ****************************************************************************/
7492 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7493 struct smb_request *req,
7497 const struct smb_filename *smb_fname)
7500 uint32_t smb_fflags;
7503 if (total_data < 116) {
7504 return NT_STATUS_INVALID_PARAMETER;
7507 /* Start by setting all the fields that are common between UNIX_BASIC
7510 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7512 if (!NT_STATUS_IS_OK(status)) {
7516 smb_fflags = IVAL(pdata, 108);
7517 smb_fmask = IVAL(pdata, 112);
7519 /* NB: We should only attempt to alter the file flags if the client
7520 * sends a non-zero mask.
7522 if (smb_fmask != 0) {
7523 int stat_fflags = 0;
7525 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7526 smb_fmask, &stat_fflags)) {
7527 /* Client asked to alter a flag we don't understand. */
7528 return NT_STATUS_INVALID_PARAMETER;
7531 if (fsp && fsp->fh->fd != -1) {
7532 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7533 return NT_STATUS_NOT_SUPPORTED;
7535 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7536 stat_fflags) != 0) {
7537 return map_nt_error_from_unix(errno);
7542 /* XXX: need to add support for changing the create_time here. You
7543 * can do this for paths on Darwin with setattrlist(2). The right way
7544 * to hook this up is probably by extending the VFS utimes interface.
7547 return NT_STATUS_OK;
7550 /****************************************************************************
7551 Create a directory with POSIX semantics.
7552 ****************************************************************************/
7554 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7555 struct smb_request *req,
7558 struct smb_filename *smb_fname,
7559 int *pdata_return_size)
7561 NTSTATUS status = NT_STATUS_OK;
7562 uint32_t raw_unixmode = 0;
7563 uint32_t mod_unixmode = 0;
7564 mode_t unixmode = (mode_t)0;
7565 files_struct *fsp = NULL;
7566 uint16_t info_level_return = 0;
7568 char *pdata = *ppdata;
7570 if (total_data < 18) {
7571 return NT_STATUS_INVALID_PARAMETER;
7574 raw_unixmode = IVAL(pdata,8);
7575 /* Next 4 bytes are not yet defined. */
7577 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7578 PERM_NEW_DIR, &unixmode);
7579 if (!NT_STATUS_IS_OK(status)) {
7583 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7585 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7586 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7588 status = SMB_VFS_CREATE_FILE(
7591 0, /* root_dir_fid */
7592 smb_fname, /* fname */
7593 FILE_READ_ATTRIBUTES, /* access_mask */
7594 FILE_SHARE_NONE, /* share_access */
7595 FILE_CREATE, /* create_disposition*/
7596 FILE_DIRECTORY_FILE, /* create_options */
7597 mod_unixmode, /* file_attributes */
7598 0, /* oplock_request */
7600 0, /* allocation_size */
7601 0, /* private_flags */
7606 NULL, NULL); /* create context */
7608 if (NT_STATUS_IS_OK(status)) {
7609 close_file(req, fsp, NORMAL_CLOSE);
7612 info_level_return = SVAL(pdata,16);
7614 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7615 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7616 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7617 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7619 *pdata_return_size = 12;
7622 /* Realloc the data size */
7623 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7624 if (*ppdata == NULL) {
7625 *pdata_return_size = 0;
7626 return NT_STATUS_NO_MEMORY;
7630 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7631 SSVAL(pdata,2,0); /* No fnum. */
7632 SIVAL(pdata,4,info); /* Was directory created. */
7634 switch (info_level_return) {
7635 case SMB_QUERY_FILE_UNIX_BASIC:
7636 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7637 SSVAL(pdata,10,0); /* Padding. */
7638 store_file_unix_basic(conn, pdata + 12, fsp,
7641 case SMB_QUERY_FILE_UNIX_INFO2:
7642 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7643 SSVAL(pdata,10,0); /* Padding. */
7644 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7648 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7649 SSVAL(pdata,10,0); /* Padding. */
7656 /****************************************************************************
7657 Open/Create a file with POSIX semantics.
7658 ****************************************************************************/
7660 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7661 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7663 static NTSTATUS smb_posix_open(connection_struct *conn,
7664 struct smb_request *req,
7667 struct smb_filename *smb_fname,
7668 int *pdata_return_size)
7670 bool extended_oplock_granted = False;
7671 char *pdata = *ppdata;
7673 uint32_t wire_open_mode = 0;
7674 uint32_t raw_unixmode = 0;
7675 uint32_t mod_unixmode = 0;
7676 uint32_t create_disp = 0;
7677 uint32_t access_mask = 0;
7678 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
7679 NTSTATUS status = NT_STATUS_OK;
7680 mode_t unixmode = (mode_t)0;
7681 files_struct *fsp = NULL;
7682 int oplock_request = 0;
7684 uint16_t info_level_return = 0;
7686 if (total_data < 18) {
7687 return NT_STATUS_INVALID_PARAMETER;
7690 flags = IVAL(pdata,0);
7691 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7692 if (oplock_request) {
7693 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7696 wire_open_mode = IVAL(pdata,4);
7698 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7699 return smb_posix_mkdir(conn, req,
7706 switch (wire_open_mode & SMB_ACCMODE) {
7708 access_mask = SMB_O_RDONLY_MAPPING;
7711 access_mask = SMB_O_WRONLY_MAPPING;
7714 access_mask = (SMB_O_RDONLY_MAPPING|
7715 SMB_O_WRONLY_MAPPING);
7718 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7719 (unsigned int)wire_open_mode ));
7720 return NT_STATUS_INVALID_PARAMETER;
7723 wire_open_mode &= ~SMB_ACCMODE;
7725 /* First take care of O_CREAT|O_EXCL interactions. */
7726 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7727 case (SMB_O_CREAT | SMB_O_EXCL):
7728 /* File exists fail. File not exist create. */
7729 create_disp = FILE_CREATE;
7732 /* File exists open. File not exist create. */
7733 create_disp = FILE_OPEN_IF;
7736 /* O_EXCL on its own without O_CREAT is undefined.
7737 We deliberately ignore it as some versions of
7738 Linux CIFSFS can send a bare O_EXCL on the
7739 wire which other filesystems in the kernel
7740 ignore. See bug 9519 for details. */
7745 /* File exists open. File not exist fail. */
7746 create_disp = FILE_OPEN;
7749 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7750 (unsigned int)wire_open_mode ));
7751 return NT_STATUS_INVALID_PARAMETER;
7754 /* Next factor in the effects of O_TRUNC. */
7755 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7757 if (wire_open_mode & SMB_O_TRUNC) {
7758 switch (create_disp) {
7760 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7761 /* Leave create_disp alone as
7762 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7764 /* File exists fail. File not exist create. */
7767 /* SMB_O_CREAT | SMB_O_TRUNC */
7768 /* File exists overwrite. File not exist create. */
7769 create_disp = FILE_OVERWRITE_IF;
7773 /* File exists overwrite. File not exist fail. */
7774 create_disp = FILE_OVERWRITE;
7777 /* Cannot get here. */
7778 smb_panic("smb_posix_open: logic error");
7779 return NT_STATUS_INVALID_PARAMETER;
7783 raw_unixmode = IVAL(pdata,8);
7784 /* Next 4 bytes are not yet defined. */
7786 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7787 (VALID_STAT(smb_fname->st) ?
7788 PERM_EXISTING_FILE : PERM_NEW_FILE),
7791 if (!NT_STATUS_IS_OK(status)) {
7795 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7797 if (wire_open_mode & SMB_O_SYNC) {
7798 create_options |= FILE_WRITE_THROUGH;
7800 if (wire_open_mode & SMB_O_APPEND) {
7801 access_mask |= FILE_APPEND_DATA;
7803 if (wire_open_mode & SMB_O_DIRECT) {
7804 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7807 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7808 VALID_STAT_OF_DIR(smb_fname->st)) {
7809 if (access_mask != SMB_O_RDONLY_MAPPING) {
7810 return NT_STATUS_FILE_IS_A_DIRECTORY;
7812 create_options &= ~FILE_NON_DIRECTORY_FILE;
7813 create_options |= FILE_DIRECTORY_FILE;
7816 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7817 smb_fname_str_dbg(smb_fname),
7818 (unsigned int)wire_open_mode,
7819 (unsigned int)unixmode ));
7821 status = SMB_VFS_CREATE_FILE(
7824 0, /* root_dir_fid */
7825 smb_fname, /* fname */
7826 access_mask, /* access_mask */
7827 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7829 create_disp, /* create_disposition*/
7830 create_options, /* create_options */
7831 mod_unixmode, /* file_attributes */
7832 oplock_request, /* oplock_request */
7834 0, /* allocation_size */
7835 0, /* private_flags */
7840 NULL, NULL); /* create context */
7842 if (!NT_STATUS_IS_OK(status)) {
7846 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7847 extended_oplock_granted = True;
7850 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7851 extended_oplock_granted = True;
7854 info_level_return = SVAL(pdata,16);
7856 /* Allocate the correct return size. */
7858 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7859 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7860 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7861 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7863 *pdata_return_size = 12;
7866 /* Realloc the data size */
7867 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7868 if (*ppdata == NULL) {
7869 close_file(req, fsp, ERROR_CLOSE);
7870 *pdata_return_size = 0;
7871 return NT_STATUS_NO_MEMORY;
7875 if (extended_oplock_granted) {
7876 if (flags & REQUEST_BATCH_OPLOCK) {
7877 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7879 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7881 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7882 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7884 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7887 SSVAL(pdata,2,fsp->fnum);
7888 SIVAL(pdata,4,info); /* Was file created etc. */
7890 switch (info_level_return) {
7891 case SMB_QUERY_FILE_UNIX_BASIC:
7892 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7893 SSVAL(pdata,10,0); /* padding. */
7894 store_file_unix_basic(conn, pdata + 12, fsp,
7897 case SMB_QUERY_FILE_UNIX_INFO2:
7898 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7899 SSVAL(pdata,10,0); /* padding. */
7900 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7904 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7905 SSVAL(pdata,10,0); /* padding. */
7908 return NT_STATUS_OK;
7911 /****************************************************************************
7912 Delete a file with POSIX semantics.
7913 ****************************************************************************/
7915 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7916 struct smb_request *req,
7919 struct smb_filename *smb_fname)
7921 NTSTATUS status = NT_STATUS_OK;
7922 files_struct *fsp = NULL;
7926 int create_options = 0;
7928 struct share_mode_lock *lck = NULL;
7930 if (total_data < 2) {
7931 return NT_STATUS_INVALID_PARAMETER;
7934 flags = SVAL(pdata,0);
7936 if (!VALID_STAT(smb_fname->st)) {
7937 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7940 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7941 !VALID_STAT_OF_DIR(smb_fname->st)) {
7942 return NT_STATUS_NOT_A_DIRECTORY;
7945 DEBUG(10,("smb_posix_unlink: %s %s\n",
7946 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7947 smb_fname_str_dbg(smb_fname)));
7949 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7950 create_options |= FILE_DIRECTORY_FILE;
7953 status = SMB_VFS_CREATE_FILE(
7956 0, /* root_dir_fid */
7957 smb_fname, /* fname */
7958 DELETE_ACCESS, /* access_mask */
7959 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7961 FILE_OPEN, /* create_disposition*/
7962 create_options, /* create_options */
7963 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7964 0, /* oplock_request */
7966 0, /* allocation_size */
7967 0, /* private_flags */
7972 NULL, NULL); /* create context */
7974 if (!NT_STATUS_IS_OK(status)) {
7979 * Don't lie to client. If we can't really delete due to
7980 * non-POSIX opens return SHARING_VIOLATION.
7983 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7985 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7986 "lock for file %s\n", fsp_str_dbg(fsp)));
7987 close_file(req, fsp, NORMAL_CLOSE);
7988 return NT_STATUS_INVALID_PARAMETER;
7992 * See if others still have the file open. If this is the case, then
7993 * don't delete. If all opens are POSIX delete we can set the delete
7994 * on close disposition.
7996 for (i=0; i<lck->data->num_share_modes; i++) {
7997 struct share_mode_entry *e = &lck->data->share_modes[i];
7998 if (is_valid_share_mode_entry(e)) {
7999 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8002 if (share_mode_stale_pid(lck->data, i)) {
8005 /* Fail with sharing violation. */
8007 close_file(req, fsp, NORMAL_CLOSE);
8008 return NT_STATUS_SHARING_VIOLATION;
8013 * Set the delete on close.
8015 status = smb_set_file_disposition_info(conn,
8023 if (!NT_STATUS_IS_OK(status)) {
8024 close_file(req, fsp, NORMAL_CLOSE);
8027 return close_file(req, fsp, NORMAL_CLOSE);
8030 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8031 struct smb_request *req,
8032 TALLOC_CTX *mem_ctx,
8033 uint16_t info_level,
8035 struct smb_filename *smb_fname,
8036 char **ppdata, int total_data,
8039 char *pdata = *ppdata;
8040 NTSTATUS status = NT_STATUS_OK;
8041 int data_return_size = 0;
8045 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8046 return NT_STATUS_INVALID_LEVEL;
8049 if (!CAN_WRITE(conn)) {
8050 /* Allow POSIX opens. The open path will deny
8051 * any non-readonly opens. */
8052 if (info_level != SMB_POSIX_PATH_OPEN) {
8053 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8057 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8058 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8060 info_level, total_data));
8062 switch (info_level) {
8064 case SMB_INFO_STANDARD:
8066 status = smb_set_info_standard(conn,
8074 case SMB_INFO_SET_EA:
8076 status = smb_info_set_ea(conn,
8084 case SMB_SET_FILE_BASIC_INFO:
8085 case SMB_FILE_BASIC_INFORMATION:
8087 status = smb_set_file_basic_info(conn,
8095 case SMB_FILE_ALLOCATION_INFORMATION:
8096 case SMB_SET_FILE_ALLOCATION_INFO:
8098 status = smb_set_file_allocation_info(conn, req,
8106 case SMB_FILE_END_OF_FILE_INFORMATION:
8107 case SMB_SET_FILE_END_OF_FILE_INFO:
8110 * XP/Win7 both fail after the createfile with
8111 * SMB_SET_FILE_END_OF_FILE_INFO but not
8112 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8113 * The level is known here, so pass it down
8117 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8119 status = smb_set_file_end_of_file_info(conn, req,
8128 case SMB_FILE_DISPOSITION_INFORMATION:
8129 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8132 /* JRA - We used to just ignore this on a path ?
8133 * Shouldn't this be invalid level on a pathname
8136 if (tran_call != TRANSACT2_SETFILEINFO) {
8137 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8140 status = smb_set_file_disposition_info(conn,
8148 case SMB_FILE_POSITION_INFORMATION:
8150 status = smb_file_position_information(conn,
8157 case SMB_FILE_FULL_EA_INFORMATION:
8159 status = smb_set_file_full_ea_info(conn,
8166 /* From tridge Samba4 :
8167 * MODE_INFORMATION in setfileinfo (I have no
8168 * idea what "mode information" on a file is - it takes a value of 0,
8169 * 2, 4 or 6. What could it be?).
8172 case SMB_FILE_MODE_INFORMATION:
8174 status = smb_file_mode_information(conn,
8181 * CIFS UNIX extensions.
8184 case SMB_SET_FILE_UNIX_BASIC:
8186 status = smb_set_file_unix_basic(conn, req,
8194 case SMB_SET_FILE_UNIX_INFO2:
8196 status = smb_set_file_unix_info2(conn, req,
8204 case SMB_SET_FILE_UNIX_LINK:
8207 /* We must have a pathname for this. */
8208 return NT_STATUS_INVALID_LEVEL;
8210 status = smb_set_file_unix_link(conn, req, pdata,
8211 total_data, smb_fname);
8215 case SMB_SET_FILE_UNIX_HLINK:
8218 /* We must have a pathname for this. */
8219 return NT_STATUS_INVALID_LEVEL;
8221 status = smb_set_file_unix_hlink(conn, req,
8227 case SMB_FILE_RENAME_INFORMATION:
8229 status = smb_file_rename_information(conn, req,
8235 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8237 /* SMB2 rename information. */
8238 status = smb2_file_rename_information(conn, req,
8244 case SMB_FILE_LINK_INFORMATION:
8246 status = smb_file_link_information(conn, req,
8252 #if defined(HAVE_POSIX_ACLS)
8253 case SMB_SET_POSIX_ACL:
8255 status = smb_set_posix_acl(conn,
8264 case SMB_SET_POSIX_LOCK:
8267 return NT_STATUS_INVALID_LEVEL;
8269 status = smb_set_posix_lock(conn, req,
8270 pdata, total_data, fsp);
8274 case SMB_POSIX_PATH_OPEN:
8277 /* We must have a pathname for this. */
8278 return NT_STATUS_INVALID_LEVEL;
8281 status = smb_posix_open(conn, req,
8289 case SMB_POSIX_PATH_UNLINK:
8292 /* We must have a pathname for this. */
8293 return NT_STATUS_INVALID_LEVEL;
8296 status = smb_posix_unlink(conn, req,
8304 return NT_STATUS_INVALID_LEVEL;
8307 if (!NT_STATUS_IS_OK(status)) {
8311 *ret_data_size = data_return_size;
8312 return NT_STATUS_OK;
8315 /****************************************************************************
8316 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8317 ****************************************************************************/
8319 static void call_trans2setfilepathinfo(connection_struct *conn,
8320 struct smb_request *req,
8321 unsigned int tran_call,
8322 char **pparams, int total_params,
8323 char **ppdata, int total_data,
8324 unsigned int max_data_bytes)
8326 char *params = *pparams;
8327 char *pdata = *ppdata;
8328 uint16_t info_level;
8329 struct smb_filename *smb_fname = NULL;
8330 files_struct *fsp = NULL;
8331 NTSTATUS status = NT_STATUS_OK;
8332 int data_return_size = 0;
8335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8339 if (tran_call == TRANSACT2_SETFILEINFO) {
8340 if (total_params < 4) {
8341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8345 fsp = file_fsp(req, SVAL(params,0));
8346 /* Basic check for non-null fsp. */
8347 if (!check_fsp_open(conn, req, fsp)) {
8350 info_level = SVAL(params,2);
8352 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8353 if (smb_fname == NULL) {
8354 reply_nterror(req, NT_STATUS_NO_MEMORY);
8358 if(fsp->fh->fd == -1) {
8360 * This is actually a SETFILEINFO on a directory
8361 * handle (returned from an NT SMB). NT5.0 seems
8362 * to do this call. JRA.
8364 if (INFO_LEVEL_IS_UNIX(info_level)) {
8365 /* Always do lstat for UNIX calls. */
8366 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8367 DEBUG(3,("call_trans2setfilepathinfo: "
8368 "SMB_VFS_LSTAT of %s failed "
8370 smb_fname_str_dbg(smb_fname),
8372 reply_nterror(req, map_nt_error_from_unix(errno));
8376 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8377 DEBUG(3,("call_trans2setfilepathinfo: "
8378 "fileinfo of %s failed (%s)\n",
8379 smb_fname_str_dbg(smb_fname),
8381 reply_nterror(req, map_nt_error_from_unix(errno));
8385 } else if (fsp->print_file) {
8387 * Doing a DELETE_ON_CLOSE should cancel a print job.
8389 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8390 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8392 DEBUG(3,("call_trans2setfilepathinfo: "
8393 "Cancelling print job (%s)\n",
8397 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8403 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8408 * Original code - this is an open file.
8410 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8411 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8412 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8414 reply_nterror(req, map_nt_error_from_unix(errno));
8420 uint32_t ucf_flags = 0;
8423 if (total_params < 7) {
8424 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8428 info_level = SVAL(params,0);
8429 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8430 total_params - 6, STR_TERMINATE,
8432 if (!NT_STATUS_IS_OK(status)) {
8433 reply_nterror(req, status);
8437 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8438 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8439 info_level == SMB_FILE_RENAME_INFORMATION ||
8440 info_level == SMB_POSIX_PATH_UNLINK) {
8441 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8444 status = filename_convert(req, conn,
8445 req->flags2 & FLAGS2_DFS_PATHNAMES,
8450 if (!NT_STATUS_IS_OK(status)) {
8451 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8452 reply_botherror(req,
8453 NT_STATUS_PATH_NOT_COVERED,
8454 ERRSRV, ERRbadpath);
8457 reply_nterror(req, status);
8461 if (INFO_LEVEL_IS_UNIX(info_level)) {
8463 * For CIFS UNIX extensions the target name may not exist.
8466 /* Always do lstat for UNIX calls. */
8467 SMB_VFS_LSTAT(conn, smb_fname);
8469 } else if (!VALID_STAT(smb_fname->st) &&
8470 SMB_VFS_STAT(conn, smb_fname)) {
8471 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8473 smb_fname_str_dbg(smb_fname),
8475 reply_nterror(req, map_nt_error_from_unix(errno));
8480 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8481 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8483 info_level,total_data));
8485 /* Realloc the parameter size */
8486 *pparams = (char *)SMB_REALLOC(*pparams,2);
8487 if (*pparams == NULL) {
8488 reply_nterror(req, NT_STATUS_NO_MEMORY);
8495 status = smbd_do_setfilepathinfo(conn, req, req,
8501 if (!NT_STATUS_IS_OK(status)) {
8502 if (open_was_deferred(req->xconn, req->mid)) {
8503 /* We have re-scheduled this call. */
8506 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8507 /* We have re-scheduled this call. */
8510 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8511 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8512 ERRSRV, ERRbadpath);
8515 if (info_level == SMB_POSIX_PATH_OPEN) {
8516 reply_openerror(req, status);
8521 * Invalid EA name needs to return 2 param bytes,
8522 * not a zero-length error packet.
8524 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8525 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8528 reply_nterror(req, status);
8533 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8539 /****************************************************************************
8540 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8541 ****************************************************************************/
8543 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8544 char **pparams, int total_params,
8545 char **ppdata, int total_data,
8546 unsigned int max_data_bytes)
8548 struct smb_filename *smb_dname = NULL;
8549 char *params = *pparams;
8550 char *pdata = *ppdata;
8551 char *directory = NULL;
8552 NTSTATUS status = NT_STATUS_OK;
8553 struct ea_list *ea_list = NULL;
8554 TALLOC_CTX *ctx = talloc_tos();
8556 if (!CAN_WRITE(conn)) {
8557 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8561 if (total_params < 5) {
8562 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8566 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8567 total_params - 4, STR_TERMINATE,
8569 if (!NT_STATUS_IS_OK(status)) {
8570 reply_nterror(req, status);
8574 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8576 status = filename_convert(ctx,
8578 req->flags2 & FLAGS2_DFS_PATHNAMES,
8584 if (!NT_STATUS_IS_OK(status)) {
8585 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8586 reply_botherror(req,
8587 NT_STATUS_PATH_NOT_COVERED,
8588 ERRSRV, ERRbadpath);
8591 reply_nterror(req, status);
8596 * OS/2 workplace shell seems to send SET_EA requests of "null"
8597 * length (4 bytes containing IVAL 4).
8598 * They seem to have no effect. Bug #3212. JRA.
8601 if (total_data && (total_data != 4)) {
8602 /* Any data in this call is an EA list. */
8603 if (total_data < 10) {
8604 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8608 if (IVAL(pdata,0) > total_data) {
8609 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8610 IVAL(pdata,0), (unsigned int)total_data));
8611 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8615 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8618 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8622 if (!lp_ea_support(SNUM(conn))) {
8623 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8627 /* If total_data == 4 Windows doesn't care what values
8628 * are placed in that field, it just ignores them.
8629 * The System i QNTC IBM SMB client puts bad values here,
8630 * so ignore them. */
8632 status = create_directory(conn, req, smb_dname);
8634 if (!NT_STATUS_IS_OK(status)) {
8635 reply_nterror(req, status);
8639 /* Try and set any given EA. */
8641 status = set_ea(conn, NULL, smb_dname, ea_list);
8642 if (!NT_STATUS_IS_OK(status)) {
8643 reply_nterror(req, status);
8648 /* Realloc the parameter and data sizes */
8649 *pparams = (char *)SMB_REALLOC(*pparams,2);
8650 if(*pparams == NULL) {
8651 reply_nterror(req, NT_STATUS_NO_MEMORY);
8658 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8661 TALLOC_FREE(smb_dname);
8665 /****************************************************************************
8666 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8667 We don't actually do this - we just send a null response.
8668 ****************************************************************************/
8670 static void call_trans2findnotifyfirst(connection_struct *conn,
8671 struct smb_request *req,
8672 char **pparams, int total_params,
8673 char **ppdata, int total_data,
8674 unsigned int max_data_bytes)
8676 char *params = *pparams;
8677 uint16_t info_level;
8679 if (total_params < 6) {
8680 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8684 info_level = SVAL(params,4);
8685 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8687 switch (info_level) {
8692 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8696 /* Realloc the parameter and data sizes */
8697 *pparams = (char *)SMB_REALLOC(*pparams,6);
8698 if (*pparams == NULL) {
8699 reply_nterror(req, NT_STATUS_NO_MEMORY);
8704 SSVAL(params,0,fnf_handle);
8705 SSVAL(params,2,0); /* No changes */
8706 SSVAL(params,4,0); /* No EA errors */
8713 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8718 /****************************************************************************
8719 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8720 changes). Currently this does nothing.
8721 ****************************************************************************/
8723 static void call_trans2findnotifynext(connection_struct *conn,
8724 struct smb_request *req,
8725 char **pparams, int total_params,
8726 char **ppdata, int total_data,
8727 unsigned int max_data_bytes)
8729 char *params = *pparams;
8731 DEBUG(3,("call_trans2findnotifynext\n"));
8733 /* Realloc the parameter and data sizes */
8734 *pparams = (char *)SMB_REALLOC(*pparams,4);
8735 if (*pparams == NULL) {
8736 reply_nterror(req, NT_STATUS_NO_MEMORY);
8741 SSVAL(params,0,0); /* No changes */
8742 SSVAL(params,2,0); /* No EA errors */
8744 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8749 /****************************************************************************
8750 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8751 ****************************************************************************/
8753 static void call_trans2getdfsreferral(connection_struct *conn,
8754 struct smb_request *req,
8755 char **pparams, int total_params,
8756 char **ppdata, int total_data,
8757 unsigned int max_data_bytes)
8759 char *params = *pparams;
8760 char *pathname = NULL;
8762 int max_referral_level;
8763 NTSTATUS status = NT_STATUS_OK;
8764 TALLOC_CTX *ctx = talloc_tos();
8766 DEBUG(10,("call_trans2getdfsreferral\n"));
8768 if (total_params < 3) {
8769 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8773 max_referral_level = SVAL(params,0);
8775 if(!lp_host_msdfs()) {
8776 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8780 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8781 total_params - 2, STR_TERMINATE);
8783 reply_nterror(req, NT_STATUS_NOT_FOUND);
8786 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8787 ppdata,&status)) < 0) {
8788 reply_nterror(req, status);
8792 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8793 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8794 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8799 #define LMCAT_SPL 0x53
8800 #define LMFUNC_GETJOBID 0x60
8802 /****************************************************************************
8803 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8804 ****************************************************************************/
8806 static void call_trans2ioctl(connection_struct *conn,
8807 struct smb_request *req,
8808 char **pparams, int total_params,
8809 char **ppdata, int total_data,
8810 unsigned int max_data_bytes)
8812 char *pdata = *ppdata;
8813 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8817 /* check for an invalid fid before proceeding */
8820 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8824 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8825 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8826 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8827 if (*ppdata == NULL) {
8828 reply_nterror(req, NT_STATUS_NO_MEMORY);
8833 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8834 CAN ACCEPT THIS IN UNICODE. JRA. */
8837 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8839 status = srvstr_push(pdata, req->flags2, pdata + 2,
8840 lp_netbios_name(), 15,
8841 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
8842 if (!NT_STATUS_IS_OK(status)) {
8843 reply_nterror(req, status);
8846 status = srvstr_push(pdata, req->flags2, pdata+18,
8847 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8848 STR_ASCII|STR_TERMINATE, &len); /* Service name */
8849 if (!NT_STATUS_IS_OK(status)) {
8850 reply_nterror(req, status);
8853 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8858 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8859 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8862 /****************************************************************************
8863 Reply to a SMBfindclose (stop trans2 directory search).
8864 ****************************************************************************/
8866 void reply_findclose(struct smb_request *req)
8869 struct smbd_server_connection *sconn = req->sconn;
8871 START_PROFILE(SMBfindclose);
8874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8875 END_PROFILE(SMBfindclose);
8879 dptr_num = SVALS(req->vwv+0, 0);
8881 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8883 dptr_close(sconn, &dptr_num);
8885 reply_outbuf(req, 0, 0);
8887 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8889 END_PROFILE(SMBfindclose);
8893 /****************************************************************************
8894 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8895 ****************************************************************************/
8897 void reply_findnclose(struct smb_request *req)
8901 START_PROFILE(SMBfindnclose);
8904 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8905 END_PROFILE(SMBfindnclose);
8909 dptr_num = SVAL(req->vwv+0, 0);
8911 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8913 /* We never give out valid handles for a
8914 findnotifyfirst - so any dptr_num is ok here.
8917 reply_outbuf(req, 0, 0);
8919 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8921 END_PROFILE(SMBfindnclose);
8925 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8926 struct trans_state *state)
8928 if (get_Protocol() >= PROTOCOL_NT1) {
8929 req->flags2 |= 0x40; /* IS_LONG_NAME */
8930 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8933 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8934 if (state->call != TRANSACT2_QFSINFO &&
8935 state->call != TRANSACT2_SETFSINFO) {
8936 DEBUG(0,("handle_trans2: encryption required "
8938 (unsigned int)state->call));
8939 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8944 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8946 /* Now we must call the relevant TRANS2 function */
8947 switch(state->call) {
8948 case TRANSACT2_OPEN:
8950 START_PROFILE(Trans2_open);
8951 call_trans2open(conn, req,
8952 &state->param, state->total_param,
8953 &state->data, state->total_data,
8954 state->max_data_return);
8955 END_PROFILE(Trans2_open);
8959 case TRANSACT2_FINDFIRST:
8961 START_PROFILE(Trans2_findfirst);
8962 call_trans2findfirst(conn, req,
8963 &state->param, state->total_param,
8964 &state->data, state->total_data,
8965 state->max_data_return);
8966 END_PROFILE(Trans2_findfirst);
8970 case TRANSACT2_FINDNEXT:
8972 START_PROFILE(Trans2_findnext);
8973 call_trans2findnext(conn, req,
8974 &state->param, state->total_param,
8975 &state->data, state->total_data,
8976 state->max_data_return);
8977 END_PROFILE(Trans2_findnext);
8981 case TRANSACT2_QFSINFO:
8983 START_PROFILE(Trans2_qfsinfo);
8984 call_trans2qfsinfo(conn, req,
8985 &state->param, state->total_param,
8986 &state->data, state->total_data,
8987 state->max_data_return);
8988 END_PROFILE(Trans2_qfsinfo);
8992 case TRANSACT2_SETFSINFO:
8994 START_PROFILE(Trans2_setfsinfo);
8995 call_trans2setfsinfo(conn, req,
8996 &state->param, state->total_param,
8997 &state->data, state->total_data,
8998 state->max_data_return);
8999 END_PROFILE(Trans2_setfsinfo);
9003 case TRANSACT2_QPATHINFO:
9004 case TRANSACT2_QFILEINFO:
9006 START_PROFILE(Trans2_qpathinfo);
9007 call_trans2qfilepathinfo(conn, req, state->call,
9008 &state->param, state->total_param,
9009 &state->data, state->total_data,
9010 state->max_data_return);
9011 END_PROFILE(Trans2_qpathinfo);
9015 case TRANSACT2_SETPATHINFO:
9016 case TRANSACT2_SETFILEINFO:
9018 START_PROFILE(Trans2_setpathinfo);
9019 call_trans2setfilepathinfo(conn, req, state->call,
9020 &state->param, state->total_param,
9021 &state->data, state->total_data,
9022 state->max_data_return);
9023 END_PROFILE(Trans2_setpathinfo);
9027 case TRANSACT2_FINDNOTIFYFIRST:
9029 START_PROFILE(Trans2_findnotifyfirst);
9030 call_trans2findnotifyfirst(conn, req,
9031 &state->param, state->total_param,
9032 &state->data, state->total_data,
9033 state->max_data_return);
9034 END_PROFILE(Trans2_findnotifyfirst);
9038 case TRANSACT2_FINDNOTIFYNEXT:
9040 START_PROFILE(Trans2_findnotifynext);
9041 call_trans2findnotifynext(conn, req,
9042 &state->param, state->total_param,
9043 &state->data, state->total_data,
9044 state->max_data_return);
9045 END_PROFILE(Trans2_findnotifynext);
9049 case TRANSACT2_MKDIR:
9051 START_PROFILE(Trans2_mkdir);
9052 call_trans2mkdir(conn, req,
9053 &state->param, state->total_param,
9054 &state->data, state->total_data,
9055 state->max_data_return);
9056 END_PROFILE(Trans2_mkdir);
9060 case TRANSACT2_GET_DFS_REFERRAL:
9062 START_PROFILE(Trans2_get_dfs_referral);
9063 call_trans2getdfsreferral(conn, req,
9064 &state->param, state->total_param,
9065 &state->data, state->total_data,
9066 state->max_data_return);
9067 END_PROFILE(Trans2_get_dfs_referral);
9071 case TRANSACT2_IOCTL:
9073 START_PROFILE(Trans2_ioctl);
9074 call_trans2ioctl(conn, req,
9075 &state->param, state->total_param,
9076 &state->data, state->total_data,
9077 state->max_data_return);
9078 END_PROFILE(Trans2_ioctl);
9083 /* Error in request */
9084 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9085 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9089 /****************************************************************************
9090 Reply to a SMBtrans2.
9091 ****************************************************************************/
9093 void reply_trans2(struct smb_request *req)
9095 connection_struct *conn = req->conn;
9100 unsigned int tran_call;
9101 struct trans_state *state;
9104 START_PROFILE(SMBtrans2);
9106 if (req->wct < 14) {
9107 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9108 END_PROFILE(SMBtrans2);
9112 dsoff = SVAL(req->vwv+12, 0);
9113 dscnt = SVAL(req->vwv+11, 0);
9114 psoff = SVAL(req->vwv+10, 0);
9115 pscnt = SVAL(req->vwv+9, 0);
9116 tran_call = SVAL(req->vwv+14, 0);
9118 result = allow_new_trans(conn->pending_trans, req->mid);
9119 if (!NT_STATUS_IS_OK(result)) {
9120 DEBUG(2, ("Got invalid trans2 request: %s\n",
9121 nt_errstr(result)));
9122 reply_nterror(req, result);
9123 END_PROFILE(SMBtrans2);
9128 switch (tran_call) {
9129 /* List the allowed trans2 calls on IPC$ */
9130 case TRANSACT2_OPEN:
9131 case TRANSACT2_GET_DFS_REFERRAL:
9132 case TRANSACT2_QFILEINFO:
9133 case TRANSACT2_QFSINFO:
9134 case TRANSACT2_SETFSINFO:
9137 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9138 END_PROFILE(SMBtrans2);
9143 if ((state = talloc(conn, struct trans_state)) == NULL) {
9144 DEBUG(0, ("talloc failed\n"));
9145 reply_nterror(req, NT_STATUS_NO_MEMORY);
9146 END_PROFILE(SMBtrans2);
9150 state->cmd = SMBtrans2;
9152 state->mid = req->mid;
9153 state->vuid = req->vuid;
9154 state->setup_count = SVAL(req->vwv+13, 0);
9155 state->setup = NULL;
9156 state->total_param = SVAL(req->vwv+0, 0);
9157 state->param = NULL;
9158 state->total_data = SVAL(req->vwv+1, 0);
9160 state->max_param_return = SVAL(req->vwv+2, 0);
9161 state->max_data_return = SVAL(req->vwv+3, 0);
9162 state->max_setup_return = SVAL(req->vwv+4, 0);
9163 state->close_on_completion = BITSETW(req->vwv+5, 0);
9164 state->one_way = BITSETW(req->vwv+5, 1);
9166 state->call = tran_call;
9168 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9169 is so as a sanity check */
9170 if (state->setup_count != 1) {
9172 * Need to have rc=0 for ioctl to get job id for OS/2.
9173 * Network printing will fail if function is not successful.
9174 * Similar function in reply.c will be used if protocol
9175 * is LANMAN1.0 instead of LM1.2X002.
9176 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9177 * outbuf doesn't have to be set(only job id is used).
9179 if ( (state->setup_count == 4)
9180 && (tran_call == TRANSACT2_IOCTL)
9181 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9182 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9183 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9185 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9186 DEBUG(2,("Transaction is %d\n",tran_call));
9188 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9189 END_PROFILE(SMBtrans2);
9194 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9197 if (state->total_data) {
9199 if (trans_oob(state->total_data, 0, dscnt)
9200 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9204 /* Can't use talloc here, the core routines do realloc on the
9205 * params and data. */
9206 state->data = (char *)SMB_MALLOC(state->total_data);
9207 if (state->data == NULL) {
9208 DEBUG(0,("reply_trans2: data malloc fail for %u "
9209 "bytes !\n", (unsigned int)state->total_data));
9211 reply_nterror(req, NT_STATUS_NO_MEMORY);
9212 END_PROFILE(SMBtrans2);
9216 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9219 if (state->total_param) {
9221 if (trans_oob(state->total_param, 0, pscnt)
9222 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9226 /* Can't use talloc here, the core routines do realloc on the
9227 * params and data. */
9228 state->param = (char *)SMB_MALLOC(state->total_param);
9229 if (state->param == NULL) {
9230 DEBUG(0,("reply_trans: param malloc fail for %u "
9231 "bytes !\n", (unsigned int)state->total_param));
9232 SAFE_FREE(state->data);
9234 reply_nterror(req, NT_STATUS_NO_MEMORY);
9235 END_PROFILE(SMBtrans2);
9239 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9242 state->received_data = dscnt;
9243 state->received_param = pscnt;
9245 if ((state->received_param == state->total_param) &&
9246 (state->received_data == state->total_data)) {
9248 handle_trans2(conn, req, state);
9250 SAFE_FREE(state->data);
9251 SAFE_FREE(state->param);
9253 END_PROFILE(SMBtrans2);
9257 DLIST_ADD(conn->pending_trans, state);
9259 /* We need to send an interim response then receive the rest
9260 of the parameter/data bytes */
9261 reply_outbuf(req, 0, 0);
9262 show_msg((char *)req->outbuf);
9263 END_PROFILE(SMBtrans2);
9268 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9269 SAFE_FREE(state->data);
9270 SAFE_FREE(state->param);
9272 END_PROFILE(SMBtrans2);
9273 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9277 /****************************************************************************
9278 Reply to a SMBtranss2
9279 ****************************************************************************/
9281 void reply_transs2(struct smb_request *req)
9283 connection_struct *conn = req->conn;
9284 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9285 struct trans_state *state;
9287 START_PROFILE(SMBtranss2);
9289 show_msg((const char *)req->inbuf);
9291 /* Windows clients expect all replies to
9292 a transact secondary (SMBtranss2 0x33)
9293 to have a command code of transact
9294 (SMBtrans2 0x32). See bug #8989
9295 and also [MS-CIFS] section 2.2.4.47.2
9298 req->cmd = SMBtrans2;
9301 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9302 END_PROFILE(SMBtranss2);
9306 for (state = conn->pending_trans; state != NULL;
9307 state = state->next) {
9308 if (state->mid == req->mid) {
9313 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9314 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9315 END_PROFILE(SMBtranss2);
9319 /* Revise state->total_param and state->total_data in case they have
9320 changed downwards */
9322 if (SVAL(req->vwv+0, 0) < state->total_param)
9323 state->total_param = SVAL(req->vwv+0, 0);
9324 if (SVAL(req->vwv+1, 0) < state->total_data)
9325 state->total_data = SVAL(req->vwv+1, 0);
9327 pcnt = SVAL(req->vwv+2, 0);
9328 poff = SVAL(req->vwv+3, 0);
9329 pdisp = SVAL(req->vwv+4, 0);
9331 dcnt = SVAL(req->vwv+5, 0);
9332 doff = SVAL(req->vwv+6, 0);
9333 ddisp = SVAL(req->vwv+7, 0);
9335 state->received_param += pcnt;
9336 state->received_data += dcnt;
9338 if ((state->received_data > state->total_data) ||
9339 (state->received_param > state->total_param))
9343 if (trans_oob(state->total_param, pdisp, pcnt)
9344 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9347 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9351 if (trans_oob(state->total_data, ddisp, dcnt)
9352 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9355 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9358 if ((state->received_param < state->total_param) ||
9359 (state->received_data < state->total_data)) {
9360 END_PROFILE(SMBtranss2);
9364 handle_trans2(conn, req, state);
9366 DLIST_REMOVE(conn->pending_trans, state);
9367 SAFE_FREE(state->data);
9368 SAFE_FREE(state->param);
9371 END_PROFILE(SMBtranss2);
9376 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9377 DLIST_REMOVE(conn->pending_trans, state);
9378 SAFE_FREE(state->data);
9379 SAFE_FREE(state->param);
9381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9382 END_PROFILE(SMBtranss2);