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 Check if an open file handle or pathname is a symlink.
59 ****************************************************************************/
61 static NTSTATUS refuse_symlink(connection_struct *conn,
62 const files_struct *fsp,
66 const SMB_STRUCT_STAT *pst = NULL;
69 pst = &fsp->fsp_name->st;
71 int ret = vfs_stat_smb_basename(conn,
75 return map_nt_error_from_unix(errno);
79 if (S_ISLNK(pst->st_ex_mode)) {
80 return NT_STATUS_ACCESS_DENIED;
85 NTSTATUS check_access_fsp(const struct files_struct *fsp,
88 if (!(fsp->access_mask & access_mask)) {
89 return NT_STATUS_ACCESS_DENIED;
94 /********************************************************************
95 The canonical "check access" based on object handle or path function.
96 ********************************************************************/
98 NTSTATUS check_access(connection_struct *conn,
100 const struct smb_filename *smb_fname,
101 uint32_t access_mask)
106 status = check_access_fsp(fsp, access_mask);
108 status = smbd_check_access_rights(conn, smb_fname,
115 /********************************************************************
116 Roundup a value to the nearest allocation roundup size boundary.
117 Only do this for Windows clients.
118 ********************************************************************/
120 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
122 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
124 /* Only roundup for Windows clients. */
125 enum remote_arch_types ra_type = get_remote_arch();
126 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
127 val = SMB_ROUNDUP(val,rval);
132 /********************************************************************
133 Create a 64 bit FileIndex. If the file is on the same device as
134 the root of the share, just return the 64-bit inode. If it isn't,
135 mangle as we used to do.
136 ********************************************************************/
138 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
141 if (conn->base_share_dev == psbuf->st_ex_dev) {
142 return (uint64_t)psbuf->st_ex_ino;
144 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
145 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
149 /****************************************************************************
150 Utility functions for dealing with extended attributes.
151 ****************************************************************************/
153 /****************************************************************************
154 Refuse to allow clients to overwrite our private xattrs.
155 ****************************************************************************/
157 bool samba_private_attr_name(const char *unix_ea_name)
159 static const char * const prohibited_ea_names[] = {
160 SAMBA_POSIX_INHERITANCE_EA_NAME,
161 SAMBA_XATTR_DOS_ATTRIB,
169 for (i = 0; prohibited_ea_names[i]; i++) {
170 if (strequal( prohibited_ea_names[i], unix_ea_name))
173 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
174 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
180 /****************************************************************************
181 Get one EA value. Fill in a struct ea_struct.
182 ****************************************************************************/
184 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
185 files_struct *fsp, const char *fname,
186 const char *ea_name, struct ea_struct *pea)
188 /* Get the value of this xattr. Max size is 64k. */
189 size_t attr_size = 256;
195 val = talloc_realloc(mem_ctx, val, char, attr_size);
197 return NT_STATUS_NO_MEMORY;
200 if (fsp && fsp->fh->fd != -1) {
201 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
203 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
206 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
212 return map_nt_error_from_unix(errno);
215 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
216 dump_data(10, (uint8_t *)val, sizeret);
219 if (strnequal(ea_name, "user.", 5)) {
220 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
222 pea->name = talloc_strdup(mem_ctx, ea_name);
224 if (pea->name == NULL) {
226 return NT_STATUS_NO_MEMORY;
228 pea->value.data = (unsigned char *)val;
229 pea->value.length = (size_t)sizeret;
233 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
234 connection_struct *conn,
236 const struct smb_filename *smb_fname,
240 /* Get a list of all xattrs. Max namesize is 64k. */
241 size_t ea_namelist_size = 1024;
242 char *ea_namelist = NULL;
247 ssize_t sizeret = -1;
255 if (!lp_ea_support(SNUM(conn))) {
259 status = refuse_symlink(conn, fsp, smb_fname->base_name);
260 if (!NT_STATUS_IS_OK(status)) {
262 * Just return no EA's on a symlink.
268 * TALLOC the result early to get the talloc hierarchy right.
271 names = talloc_array(mem_ctx, char *, 1);
273 DEBUG(0, ("talloc failed\n"));
274 return NT_STATUS_NO_MEMORY;
277 while (ea_namelist_size <= 65536) {
279 ea_namelist = talloc_realloc(
280 names, ea_namelist, char, ea_namelist_size);
281 if (ea_namelist == NULL) {
282 DEBUG(0, ("talloc failed\n"));
284 return NT_STATUS_NO_MEMORY;
287 if (fsp && fsp->fh->fd != -1) {
288 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
291 sizeret = SMB_VFS_LISTXATTR(conn,
292 smb_fname->base_name,
297 if ((sizeret == -1) && (errno == ERANGE)) {
298 ea_namelist_size *= 2;
307 return map_nt_error_from_unix(errno);
310 DEBUG(10, ("%s: ea_namelist size = %u\n",
311 __func__, (unsigned int)sizeret));
319 * Ensure the result is 0-terminated
322 if (ea_namelist[sizeret-1] != '\0') {
324 return NT_STATUS_INTERNAL_ERROR;
332 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
336 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
338 DEBUG(0, ("talloc failed\n"));
340 return NT_STATUS_NO_MEMORY;
346 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
347 names[num_names++] = p;
355 *pnum_names = num_names;
359 /****************************************************************************
360 Return a linked list of the total EA's. Plus the total size
361 ****************************************************************************/
363 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
364 connection_struct *conn,
366 const struct smb_filename *smb_fname,
367 size_t *pea_total_len,
368 struct ea_list **ea_list)
370 /* Get a list of all xattrs. Max namesize is 64k. */
373 struct ea_list *ea_list_head = NULL;
379 status = get_ea_names_from_file(talloc_tos(),
386 if (!NT_STATUS_IS_OK(status)) {
390 if (num_names == 0) {
395 for (i=0; i<num_names; i++) {
396 struct ea_list *listp;
399 if (strnequal(names[i], "system.", 7)
400 || samba_private_attr_name(names[i]))
404 * Filter out any underlying POSIX EA names
405 * that a Windows client can't handle.
407 if (!lp_posix_pathnames() &&
408 is_invalid_windows_ea_name(names[i])) {
412 listp = talloc(mem_ctx, struct ea_list);
414 return NT_STATUS_NO_MEMORY;
417 status = get_ea_value(listp,
420 smb_fname->base_name,
424 if (!NT_STATUS_IS_OK(status)) {
429 if (listp->ea.value.length == 0) {
431 * We can never return a zero length EA.
432 * Windows reports the EA's as corrupted.
438 push_ascii_fstring(dos_ea_name, listp->ea.name);
441 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
443 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
444 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
445 (unsigned int)listp->ea.value.length));
447 DLIST_ADD_END(ea_list_head, listp);
451 /* Add on 4 for total length. */
452 if (*pea_total_len) {
456 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
457 (unsigned int)*pea_total_len));
459 *ea_list = ea_list_head;
463 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
464 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
469 if (!lp_ea_support(SNUM(conn))) {
473 if (is_ntfs_stream_smb_fname(smb_fname)) {
474 return NT_STATUS_INVALID_PARAMETER;
477 return get_ea_list_from_file_path(mem_ctx,
485 /****************************************************************************
486 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
488 ****************************************************************************/
490 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
491 connection_struct *conn, struct ea_list *ea_list)
493 unsigned int ret_data_size = 4;
496 SMB_ASSERT(total_data_size >= 4);
498 if (!lp_ea_support(SNUM(conn))) {
503 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
506 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
507 dos_namelen = strlen(dos_ea_name);
508 if (dos_namelen > 255 || dos_namelen == 0) {
511 if (ea_list->ea.value.length > 65535) {
514 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
518 /* We know we have room. */
519 SCVAL(p,0,ea_list->ea.flags);
520 SCVAL(p,1,dos_namelen);
521 SSVAL(p,2,ea_list->ea.value.length);
522 strlcpy(p+4, dos_ea_name, dos_namelen+1);
523 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
525 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
526 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
529 ret_data_size = PTR_DIFF(p, pdata);
530 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
531 SIVAL(pdata,0,ret_data_size);
532 return ret_data_size;
535 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
537 unsigned int total_data_size,
538 unsigned int *ret_data_size,
539 connection_struct *conn,
540 struct ea_list *ea_list)
542 uint8_t *p = (uint8_t *)pdata;
543 uint8_t *last_start = NULL;
544 bool do_store_data = (pdata != NULL);
548 if (!lp_ea_support(SNUM(conn))) {
549 return NT_STATUS_NO_EAS_ON_FILE;
552 for (; ea_list; ea_list = ea_list->next) {
558 if (last_start != NULL && do_store_data) {
559 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
563 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
564 dos_namelen = strlen(dos_ea_name);
565 if (dos_namelen > 255 || dos_namelen == 0) {
566 return NT_STATUS_INTERNAL_ERROR;
568 if (ea_list->ea.value.length > 65535) {
569 return NT_STATUS_INTERNAL_ERROR;
572 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
575 pad = (4 - (this_size % 4)) % 4;
580 if (this_size > total_data_size) {
581 return NT_STATUS_INFO_LENGTH_MISMATCH;
584 /* We know we have room. */
585 SIVAL(p, 0x00, 0); /* next offset */
586 SCVAL(p, 0x04, ea_list->ea.flags);
587 SCVAL(p, 0x05, dos_namelen);
588 SSVAL(p, 0x06, ea_list->ea.value.length);
589 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
590 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
592 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
596 total_data_size -= this_size;
602 *ret_data_size = PTR_DIFF(p, pdata);
603 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
607 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
609 size_t total_ea_len = 0;
611 struct ea_list *ea_list = NULL;
613 if (!lp_ea_support(SNUM(conn))) {
616 mem_ctx = talloc_stackframe();
618 /* If this is a stream fsp, then we need to instead find the
619 * estimated ea len from the main file, not the stream
620 * (streams cannot have EAs), but the estimate isn't just 0 in
622 if (is_ntfs_stream_smb_fname(smb_fname)) {
625 (void)get_ea_list_from_file_path(mem_ctx,
631 if(conn->sconn->using_smb2) {
633 unsigned int ret_data_size;
635 * We're going to be using fill_ea_chained_buffer() to
636 * marshall EA's - this size is significantly larger
637 * than the SMB1 buffer. Re-calculate the size without
640 status = fill_ea_chained_buffer(mem_ctx,
646 if (!NT_STATUS_IS_OK(status)) {
649 total_ea_len = ret_data_size;
651 TALLOC_FREE(mem_ctx);
655 /****************************************************************************
656 Ensure the EA name is case insensitive by matching any existing EA name.
657 ****************************************************************************/
659 static void canonicalize_ea_name(connection_struct *conn,
661 const struct smb_filename *smb_fname,
662 fstring unix_ea_name)
665 TALLOC_CTX *mem_ctx = talloc_tos();
666 struct ea_list *ea_list;
667 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
673 if (!NT_STATUS_IS_OK(status)) {
677 for (; ea_list; ea_list = ea_list->next) {
678 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
679 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
680 &unix_ea_name[5], ea_list->ea.name));
681 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
687 /****************************************************************************
688 Set or delete an extended attribute.
689 ****************************************************************************/
691 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
692 const struct smb_filename *smb_fname, struct ea_list *ea_list)
696 if (!lp_ea_support(SNUM(conn))) {
697 return NT_STATUS_EAS_NOT_SUPPORTED;
700 status = refuse_symlink(conn, fsp, smb_fname->base_name);
701 if (!NT_STATUS_IS_OK(status)) {
705 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
706 if (!NT_STATUS_IS_OK(status)) {
710 /* Setting EAs on streams isn't supported. */
711 if (is_ntfs_stream_smb_fname(smb_fname)) {
712 return NT_STATUS_INVALID_PARAMETER;
716 * Filter out invalid Windows EA names - before
717 * we set *any* of them.
720 if (ea_list_has_invalid_name(ea_list)) {
721 return STATUS_INVALID_EA_NAME;
724 for (;ea_list; ea_list = ea_list->next) {
726 fstring unix_ea_name;
728 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
729 fstrcat(unix_ea_name, ea_list->ea.name);
731 canonicalize_ea_name(conn,
736 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
738 if (samba_private_attr_name(unix_ea_name)) {
739 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
740 return NT_STATUS_ACCESS_DENIED;
743 if (ea_list->ea.value.length == 0) {
744 /* Remove the attribute. */
745 if (fsp && (fsp->fh->fd != -1)) {
746 DEBUG(10,("set_ea: deleting ea name %s on "
747 "file %s by file descriptor.\n",
748 unix_ea_name, fsp_str_dbg(fsp)));
749 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
751 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
752 unix_ea_name, smb_fname->base_name));
753 ret = SMB_VFS_REMOVEXATTR(conn,
754 smb_fname->base_name,
758 /* Removing a non existent attribute always succeeds. */
759 if (ret == -1 && errno == ENOATTR) {
760 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
766 if (fsp && (fsp->fh->fd != -1)) {
767 DEBUG(10,("set_ea: setting ea name %s on file "
768 "%s by file descriptor.\n",
769 unix_ea_name, fsp_str_dbg(fsp)));
770 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
771 ea_list->ea.value.data, ea_list->ea.value.length, 0);
773 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
774 unix_ea_name, smb_fname->base_name));
775 ret = SMB_VFS_SETXATTR(conn,
776 smb_fname->base_name,
778 ea_list->ea.value.data,
779 ea_list->ea.value.length,
786 if (errno == ENOTSUP) {
787 return NT_STATUS_EAS_NOT_SUPPORTED;
790 return map_nt_error_from_unix(errno);
796 /****************************************************************************
797 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
798 ****************************************************************************/
800 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
802 struct ea_list *ea_list_head = NULL;
803 size_t converted_size, offset = 0;
805 while (offset + 2 < data_size) {
806 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
807 unsigned int namelen = CVAL(pdata,offset);
809 offset++; /* Go past the namelen byte. */
811 /* integer wrap paranioa. */
812 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
813 (offset > data_size) || (namelen > data_size) ||
814 (offset + namelen >= data_size)) {
817 /* Ensure the name is null terminated. */
818 if (pdata[offset + namelen] != '\0') {
821 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
823 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
824 "failed: %s", strerror(errno)));
830 offset += (namelen + 1); /* Go past the name + terminating zero. */
831 DLIST_ADD_END(ea_list_head, eal);
832 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
838 /****************************************************************************
839 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
840 ****************************************************************************/
842 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
844 struct ea_list *ea_list_head = NULL;
846 size_t bytes_used = 0;
848 while (offset < data_size) {
849 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
855 DLIST_ADD_END(ea_list_head, eal);
856 offset += bytes_used;
862 /****************************************************************************
863 Count the total EA size needed.
864 ****************************************************************************/
866 static size_t ea_list_size(struct ea_list *ealist)
869 struct ea_list *listp;
872 for (listp = ealist; listp; listp = listp->next) {
873 push_ascii_fstring(dos_ea_name, listp->ea.name);
874 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
876 /* Add on 4 for total length. */
884 /****************************************************************************
885 Return a union of EA's from a file list and a list of names.
886 The TALLOC context for the two lists *MUST* be identical as we steal
887 memory from one list to add to another. JRA.
888 ****************************************************************************/
890 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
892 struct ea_list *nlistp, *flistp;
894 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
895 for (flistp = file_list; flistp; flistp = flistp->next) {
896 if (strequal(nlistp->ea.name, flistp->ea.name)) {
902 /* Copy the data from this entry. */
903 nlistp->ea.flags = flistp->ea.flags;
904 nlistp->ea.value = flistp->ea.value;
907 nlistp->ea.flags = 0;
908 ZERO_STRUCT(nlistp->ea.value);
912 *total_ea_len = ea_list_size(name_list);
916 /****************************************************************************
917 Send the required number of replies back.
918 We assume all fields other than the data fields are
919 set correctly for the type of call.
920 HACK ! Always assumes smb_setup field is zero.
921 ****************************************************************************/
923 void send_trans2_replies(connection_struct *conn,
924 struct smb_request *req,
932 /* As we are using a protocol > LANMAN1 then the max_send
933 variable must have been set in the sessetupX call.
934 This takes precedence over the max_xmit field in the
935 global struct. These different max_xmit variables should
936 be merged as this is now too confusing */
938 int data_to_send = datasize;
939 int params_to_send = paramsize;
941 const char *pp = params;
942 const char *pd = pdata;
943 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
944 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
945 int data_alignment_offset = 0;
946 bool overflow = False;
947 struct smbXsrv_connection *xconn = req->xconn;
948 int max_send = xconn->smb1.sessions.max_send;
950 /* Modify the data_to_send and datasize and set the error if
951 we're trying to send more than max_data_bytes. We still send
952 the part of the packet(s) that fit. Strange, but needed
955 if (max_data_bytes > 0 && datasize > max_data_bytes) {
956 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
957 max_data_bytes, datasize ));
958 datasize = data_to_send = max_data_bytes;
962 /* If there genuinely are no parameters or data to send just send the empty packet */
964 if(params_to_send == 0 && data_to_send == 0) {
965 reply_outbuf(req, 10, 0);
966 if (NT_STATUS_V(status)) {
969 ntstatus_to_dos(status, &eclass, &ecode);
970 error_packet_set((char *)req->outbuf,
971 eclass, ecode, status,
974 show_msg((char *)req->outbuf);
975 if (!srv_send_smb(xconn,
978 IS_CONN_ENCRYPTED(conn),
980 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
982 TALLOC_FREE(req->outbuf);
986 /* When sending params and data ensure that both are nicely aligned */
987 /* Only do this alignment when there is also data to send - else
988 can cause NT redirector problems. */
990 if (((params_to_send % 4) != 0) && (data_to_send != 0))
991 data_alignment_offset = 4 - (params_to_send % 4);
993 /* Space is bufsize minus Netbios over TCP header minus SMB header */
994 /* The alignment_offset is to align the param bytes on an even byte
995 boundary. NT 4.0 Beta needs this to work correctly. */
997 useable_space = max_send - (smb_size
1000 + data_alignment_offset);
1002 if (useable_space < 0) {
1003 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1004 "= %d!!!", useable_space));
1005 exit_server_cleanly("send_trans2_replies: Not enough space");
1008 while (params_to_send || data_to_send) {
1009 /* Calculate whether we will totally or partially fill this packet */
1011 total_sent_thistime = params_to_send + data_to_send;
1013 /* We can never send more than useable_space */
1015 * Note that 'useable_space' does not include the alignment offsets,
1016 * but we must include the alignment offsets in the calculation of
1017 * the length of the data we send over the wire, as the alignment offsets
1018 * are sent here. Fix from Marc_Jacobsen@hp.com.
1021 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1023 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1024 + data_alignment_offset);
1026 /* Set total params and data to be sent */
1027 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1028 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1030 /* Calculate how many parameters and data we can fit into
1031 * this packet. Parameters get precedence
1034 params_sent_thistime = MIN(params_to_send,useable_space);
1035 data_sent_thistime = useable_space - params_sent_thistime;
1036 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1038 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1040 /* smb_proff is the offset from the start of the SMB header to the
1041 parameter bytes, however the first 4 bytes of outbuf are
1042 the Netbios over TCP header. Thus use smb_base() to subtract
1043 them from the calculation */
1045 SSVAL(req->outbuf,smb_proff,
1046 ((smb_buf(req->outbuf)+alignment_offset)
1047 - smb_base(req->outbuf)));
1049 if(params_sent_thistime == 0)
1050 SSVAL(req->outbuf,smb_prdisp,0);
1052 /* Absolute displacement of param bytes sent in this packet */
1053 SSVAL(req->outbuf,smb_prdisp,pp - params);
1055 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1056 if(data_sent_thistime == 0) {
1057 SSVAL(req->outbuf,smb_droff,0);
1058 SSVAL(req->outbuf,smb_drdisp, 0);
1060 /* The offset of the data bytes is the offset of the
1061 parameter bytes plus the number of parameters being sent this time */
1062 SSVAL(req->outbuf, smb_droff,
1063 ((smb_buf(req->outbuf)+alignment_offset)
1064 - smb_base(req->outbuf))
1065 + params_sent_thistime + data_alignment_offset);
1066 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1069 /* Initialize the padding for alignment */
1071 if (alignment_offset != 0) {
1072 memset(smb_buf(req->outbuf), 0, alignment_offset);
1075 /* Copy the param bytes into the packet */
1077 if(params_sent_thistime) {
1078 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1079 params_sent_thistime);
1082 /* Copy in the data bytes */
1083 if(data_sent_thistime) {
1084 if (data_alignment_offset != 0) {
1085 memset((smb_buf(req->outbuf)+alignment_offset+
1086 params_sent_thistime), 0,
1087 data_alignment_offset);
1089 memcpy(smb_buf(req->outbuf)+alignment_offset
1090 +params_sent_thistime+data_alignment_offset,
1091 pd,data_sent_thistime);
1094 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1095 params_sent_thistime, data_sent_thistime, useable_space));
1096 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1097 params_to_send, data_to_send, paramsize, datasize));
1100 error_packet_set((char *)req->outbuf,
1101 ERRDOS,ERRbufferoverflow,
1102 STATUS_BUFFER_OVERFLOW,
1104 } else if (NT_STATUS_V(status)) {
1107 ntstatus_to_dos(status, &eclass, &ecode);
1108 error_packet_set((char *)req->outbuf,
1109 eclass, ecode, status,
1113 /* Send the packet */
1114 show_msg((char *)req->outbuf);
1115 if (!srv_send_smb(xconn,
1116 (char *)req->outbuf,
1117 true, req->seqnum+1,
1118 IS_CONN_ENCRYPTED(conn),
1120 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1122 TALLOC_FREE(req->outbuf);
1124 pp += params_sent_thistime;
1125 pd += data_sent_thistime;
1127 params_to_send -= params_sent_thistime;
1128 data_to_send -= data_sent_thistime;
1131 if(params_to_send < 0 || data_to_send < 0) {
1132 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1133 params_to_send, data_to_send));
1141 /****************************************************************************
1142 Reply to a TRANSACT2_OPEN.
1143 ****************************************************************************/
1145 static void call_trans2open(connection_struct *conn,
1146 struct smb_request *req,
1147 char **pparams, int total_params,
1148 char **ppdata, int total_data,
1149 unsigned int max_data_bytes)
1151 struct smb_filename *smb_fname = NULL;
1152 char *params = *pparams;
1153 char *pdata = *ppdata;
1156 bool oplock_request;
1158 bool return_additional_info;
1167 int fattr=0,mtime=0;
1168 SMB_INO_T inode = 0;
1171 struct ea_list *ea_list = NULL;
1174 uint32_t access_mask;
1175 uint32_t share_mode;
1176 uint32_t create_disposition;
1177 uint32_t create_options = 0;
1178 uint32_t private_flags = 0;
1179 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1180 TALLOC_CTX *ctx = talloc_tos();
1183 * Ensure we have enough parameters to perform the operation.
1186 if (total_params < 29) {
1187 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1191 flags = SVAL(params, 0);
1192 deny_mode = SVAL(params, 2);
1193 open_attr = SVAL(params,6);
1194 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1195 if (oplock_request) {
1196 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1200 return_additional_info = BITSETW(params,0);
1201 open_sattr = SVAL(params, 4);
1202 open_time = make_unix_date3(params+8);
1204 open_ofun = SVAL(params,12);
1205 open_size = IVAL(params,14);
1206 pname = ¶ms[28];
1209 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1213 if (req->posix_pathnames) {
1214 srvstr_get_path_posix(ctx,
1223 srvstr_get_path(ctx,
1232 if (!NT_STATUS_IS_OK(status)) {
1233 reply_nterror(req, status);
1237 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1238 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1239 (unsigned int)open_ofun, open_size));
1241 status = filename_convert(ctx,
1243 req->flags2 & FLAGS2_DFS_PATHNAMES,
1248 if (!NT_STATUS_IS_OK(status)) {
1249 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1250 reply_botherror(req,
1251 NT_STATUS_PATH_NOT_COVERED,
1252 ERRSRV, ERRbadpath);
1255 reply_nterror(req, status);
1259 if (open_ofun == 0) {
1260 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1264 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1266 &access_mask, &share_mode,
1267 &create_disposition,
1270 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1274 /* Any data in this call is an EA list. */
1275 if (total_data && (total_data != 4)) {
1276 if (total_data < 10) {
1277 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1281 if (IVAL(pdata,0) > total_data) {
1282 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1283 IVAL(pdata,0), (unsigned int)total_data));
1284 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1288 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1291 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1295 if (!lp_ea_support(SNUM(conn))) {
1296 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1300 if (ea_list_has_invalid_name(ea_list)) {
1302 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1303 if(*pparams == NULL ) {
1304 reply_nterror(req, NT_STATUS_NO_MEMORY);
1308 memset(params, '\0', param_len);
1309 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1310 params, param_len, NULL, 0, max_data_bytes);
1315 status = SMB_VFS_CREATE_FILE(
1318 0, /* root_dir_fid */
1319 smb_fname, /* fname */
1320 access_mask, /* access_mask */
1321 share_mode, /* share_access */
1322 create_disposition, /* create_disposition*/
1323 create_options, /* create_options */
1324 open_attr, /* file_attributes */
1325 oplock_request, /* oplock_request */
1327 open_size, /* allocation_size */
1330 ea_list, /* ea_list */
1332 &smb_action, /* psbuf */
1333 NULL, NULL); /* create context */
1335 if (!NT_STATUS_IS_OK(status)) {
1336 if (open_was_deferred(req->xconn, req->mid)) {
1337 /* We have re-scheduled this call. */
1340 reply_openerror(req, status);
1344 size = get_file_size_stat(&smb_fname->st);
1345 fattr = dos_mode(conn, smb_fname);
1346 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1347 inode = smb_fname->st.st_ex_ino;
1348 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1349 close_file(req, fsp, ERROR_CLOSE);
1350 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1354 /* Realloc the size of parameters and data we will return */
1355 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1356 if(*pparams == NULL ) {
1357 reply_nterror(req, NT_STATUS_NO_MEMORY);
1362 SSVAL(params,0,fsp->fnum);
1363 SSVAL(params,2,fattr);
1364 srv_put_dos_date2(params,4, mtime);
1365 SIVAL(params,8, (uint32_t)size);
1366 SSVAL(params,12,deny_mode);
1367 SSVAL(params,14,0); /* open_type - file or directory. */
1368 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1370 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1371 smb_action |= EXTENDED_OPLOCK_GRANTED;
1374 SSVAL(params,18,smb_action);
1377 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1379 SIVAL(params,20,inode);
1380 SSVAL(params,24,0); /* Padding. */
1382 uint32_t ea_size = estimate_ea_size(conn, fsp,
1384 SIVAL(params, 26, ea_size);
1386 SIVAL(params, 26, 0);
1389 /* Send the required number of replies */
1390 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1392 TALLOC_FREE(smb_fname);
1395 /*********************************************************
1396 Routine to check if a given string matches exactly.
1397 as a special case a mask of "." does NOT match. That
1398 is required for correct wildcard semantics
1399 Case can be significant or not.
1400 **********************************************************/
1402 static bool exact_match(bool has_wild,
1403 bool case_sensitive,
1407 if (mask[0] == '.' && mask[1] == 0) {
1415 if (case_sensitive) {
1416 return strcmp(str,mask)==0;
1418 return strcasecmp_m(str,mask) == 0;
1422 /****************************************************************************
1423 Return the filetype for UNIX extensions.
1424 ****************************************************************************/
1426 static uint32_t unix_filetype(mode_t mode)
1429 return UNIX_TYPE_FILE;
1430 else if(S_ISDIR(mode))
1431 return UNIX_TYPE_DIR;
1433 else if(S_ISLNK(mode))
1434 return UNIX_TYPE_SYMLINK;
1437 else if(S_ISCHR(mode))
1438 return UNIX_TYPE_CHARDEV;
1441 else if(S_ISBLK(mode))
1442 return UNIX_TYPE_BLKDEV;
1445 else if(S_ISFIFO(mode))
1446 return UNIX_TYPE_FIFO;
1449 else if(S_ISSOCK(mode))
1450 return UNIX_TYPE_SOCKET;
1453 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1454 return UNIX_TYPE_UNKNOWN;
1457 /****************************************************************************
1458 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1459 ****************************************************************************/
1461 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1463 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1464 const SMB_STRUCT_STAT *psbuf,
1466 enum perm_type ptype,
1471 if (perms == SMB_MODE_NO_CHANGE) {
1472 if (!VALID_STAT(*psbuf)) {
1473 return NT_STATUS_INVALID_PARAMETER;
1475 *ret_perms = psbuf->st_ex_mode;
1476 return NT_STATUS_OK;
1480 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1481 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1482 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1483 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1484 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1485 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1486 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1487 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1488 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1490 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1493 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1496 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1499 if (ptype == PERM_NEW_FILE) {
1501 * "create mask"/"force create mode" are
1502 * only applied to new files, not existing ones.
1504 ret &= lp_create_mask(SNUM(conn));
1505 /* Add in force bits */
1506 ret |= lp_force_create_mode(SNUM(conn));
1507 } else if (ptype == PERM_NEW_DIR) {
1509 * "directory mask"/"force directory mode" are
1510 * only applied to new directories, not existing ones.
1512 ret &= lp_directory_mask(SNUM(conn));
1513 /* Add in force bits */
1514 ret |= lp_force_directory_mode(SNUM(conn));
1518 return NT_STATUS_OK;
1521 /****************************************************************************
1522 Needed to show the msdfs symlinks as directories. Modifies psbuf
1523 to be a directory if it's a msdfs link.
1524 ****************************************************************************/
1526 static bool check_msdfs_link(connection_struct *conn,
1527 const char *pathname,
1528 SMB_STRUCT_STAT *psbuf)
1530 int saved_errno = errno;
1531 if(lp_host_msdfs() &&
1532 lp_msdfs_root(SNUM(conn)) &&
1533 is_msdfs_link(conn, pathname, psbuf)) {
1535 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1538 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1539 errno = saved_errno;
1542 errno = saved_errno;
1547 /****************************************************************************
1548 Get a level dependent lanman2 dir entry.
1549 ****************************************************************************/
1551 struct smbd_dirptr_lanman2_state {
1552 connection_struct *conn;
1553 uint32_t info_level;
1554 bool check_mangled_names;
1556 bool got_exact_match;
1559 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1565 struct smbd_dirptr_lanman2_state *state =
1566 (struct smbd_dirptr_lanman2_state *)private_data;
1568 char mangled_name[13]; /* mangled 8.3 name. */
1572 /* Mangle fname if it's an illegal name. */
1573 if (mangle_must_mangle(dname, state->conn->params)) {
1575 * Slow path - ensure we can push the original name as UCS2. If
1576 * not, then just don't return this name.
1580 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1581 uint8_t *tmp = talloc_array(talloc_tos(),
1585 status = srvstr_push(NULL,
1586 FLAGS2_UNICODE_STRINGS,
1595 if (!NT_STATUS_IS_OK(status)) {
1599 ok = name_to_8_3(dname, mangled_name,
1600 true, state->conn->params);
1604 fname = mangled_name;
1609 got_match = exact_match(state->has_wild,
1610 state->conn->case_sensitive,
1612 state->got_exact_match = got_match;
1614 got_match = mask_match(fname, mask,
1615 state->conn->case_sensitive);
1618 if(!got_match && state->check_mangled_names &&
1619 !mangle_is_8_3(fname, false, state->conn->params)) {
1621 * It turns out that NT matches wildcards against
1622 * both long *and* short names. This may explain some
1623 * of the wildcard wierdness from old DOS clients
1624 * that some people have been seeing.... JRA.
1626 /* Force the mangling into 8.3. */
1627 ok = name_to_8_3(fname, mangled_name,
1628 false, state->conn->params);
1633 got_match = exact_match(state->has_wild,
1634 state->conn->case_sensitive,
1635 mangled_name, mask);
1636 state->got_exact_match = got_match;
1638 got_match = mask_match(mangled_name, mask,
1639 state->conn->case_sensitive);
1647 *_fname = talloc_strdup(ctx, fname);
1648 if (*_fname == NULL) {
1655 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1657 struct smb_filename *smb_fname,
1660 struct smbd_dirptr_lanman2_state *state =
1661 (struct smbd_dirptr_lanman2_state *)private_data;
1662 bool ms_dfs_link = false;
1665 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1666 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1667 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1668 "Couldn't lstat [%s] (%s)\n",
1669 smb_fname_str_dbg(smb_fname),
1673 } else if (!VALID_STAT(smb_fname->st) &&
1674 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1675 /* Needed to show the msdfs symlinks as
1678 ms_dfs_link = check_msdfs_link(state->conn,
1679 smb_fname->base_name,
1682 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1683 "Couldn't stat [%s] (%s)\n",
1684 smb_fname_str_dbg(smb_fname),
1691 mode = dos_mode_msdfs(state->conn, smb_fname);
1693 mode = dos_mode(state->conn, smb_fname);
1700 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1701 connection_struct *conn,
1703 uint32_t info_level,
1704 struct ea_list *name_list,
1705 bool check_mangled_names,
1706 bool requires_resume_key,
1709 const struct smb_filename *smb_fname,
1710 int space_remaining,
1716 uint64_t *last_entry_off)
1718 char *p, *q, *pdata = *ppdata;
1720 uint64_t file_size = 0;
1721 uint64_t allocation_size = 0;
1722 uint64_t file_index = 0;
1724 struct timespec mdate_ts = {0};
1725 struct timespec adate_ts = {0};
1726 struct timespec cdate_ts = {0};
1727 struct timespec create_date_ts = {0};
1728 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1730 char *last_entry_ptr;
1735 struct readdir_attr_data *readdir_attr_data = NULL;
1737 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1738 file_size = get_file_size_stat(&smb_fname->st);
1740 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1742 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1743 if (!NT_STATUS_IS_OK(status)) {
1744 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1749 file_index = get_FileIndex(conn, &smb_fname->st);
1751 mdate_ts = smb_fname->st.st_ex_mtime;
1752 adate_ts = smb_fname->st.st_ex_atime;
1753 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1754 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1756 if (lp_dos_filetime_resolution(SNUM(conn))) {
1757 dos_filetime_timespec(&create_date_ts);
1758 dos_filetime_timespec(&mdate_ts);
1759 dos_filetime_timespec(&adate_ts);
1760 dos_filetime_timespec(&cdate_ts);
1763 create_date = convert_timespec_to_time_t(create_date_ts);
1764 mdate = convert_timespec_to_time_t(mdate_ts);
1765 adate = convert_timespec_to_time_t(adate_ts);
1767 /* align the record */
1768 SMB_ASSERT(align >= 1);
1770 off = (int)PTR_DIFF(pdata, base_data);
1771 pad = (off + (align-1)) & ~(align-1);
1774 if (pad && pad > space_remaining) {
1775 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1776 "for padding (wanted %u, had %d)\n",
1779 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1783 /* initialize padding to 0 */
1785 memset(pdata, 0, pad);
1787 space_remaining -= pad;
1789 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1799 switch (info_level) {
1800 case SMB_FIND_INFO_STANDARD:
1801 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1802 if(requires_resume_key) {
1806 srv_put_dos_date2(p,0,create_date);
1807 srv_put_dos_date2(p,4,adate);
1808 srv_put_dos_date2(p,8,mdate);
1809 SIVAL(p,12,(uint32_t)file_size);
1810 SIVAL(p,16,(uint32_t)allocation_size);
1814 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1815 p += ucs2_align(base_data, p, 0);
1817 status = srvstr_push(base_data, flags2, p,
1818 fname, PTR_DIFF(end_data, p),
1819 STR_TERMINATE, &len);
1820 if (!NT_STATUS_IS_OK(status)) {
1823 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1825 SCVAL(nameptr, -1, len - 2);
1827 SCVAL(nameptr, -1, 0);
1831 SCVAL(nameptr, -1, len - 1);
1833 SCVAL(nameptr, -1, 0);
1839 case SMB_FIND_EA_SIZE:
1840 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1841 if (requires_resume_key) {
1845 srv_put_dos_date2(p,0,create_date);
1846 srv_put_dos_date2(p,4,adate);
1847 srv_put_dos_date2(p,8,mdate);
1848 SIVAL(p,12,(uint32_t)file_size);
1849 SIVAL(p,16,(uint32_t)allocation_size);
1852 unsigned int ea_size = estimate_ea_size(conn, NULL,
1854 SIVAL(p,22,ea_size); /* Extended attributes */
1858 status = srvstr_push(base_data, flags2,
1859 p, fname, PTR_DIFF(end_data, p),
1860 STR_TERMINATE | STR_NOALIGN, &len);
1861 if (!NT_STATUS_IS_OK(status)) {
1864 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1877 SCVAL(nameptr,0,len);
1879 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1882 case SMB_FIND_EA_LIST:
1884 struct ea_list *file_list = NULL;
1887 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1889 return NT_STATUS_INVALID_PARAMETER;
1891 if (requires_resume_key) {
1895 srv_put_dos_date2(p,0,create_date);
1896 srv_put_dos_date2(p,4,adate);
1897 srv_put_dos_date2(p,8,mdate);
1898 SIVAL(p,12,(uint32_t)file_size);
1899 SIVAL(p,16,(uint32_t)allocation_size);
1901 p += 22; /* p now points to the EA area. */
1903 status = get_ea_list_from_file(ctx, conn, NULL,
1905 &ea_len, &file_list);
1906 if (!NT_STATUS_IS_OK(status)) {
1909 name_list = ea_list_union(name_list, file_list, &ea_len);
1911 /* We need to determine if this entry will fit in the space available. */
1912 /* Max string size is 255 bytes. */
1913 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1914 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1915 "(wanted %u, had %d)\n",
1916 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1918 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1921 /* Push the ea_data followed by the name. */
1922 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1924 status = srvstr_push(base_data, flags2,
1925 p + 1, fname, PTR_DIFF(end_data, p+1),
1926 STR_TERMINATE | STR_NOALIGN, &len);
1927 if (!NT_STATUS_IS_OK(status)) {
1930 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1943 SCVAL(nameptr,0,len);
1945 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1949 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1950 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1951 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1953 SIVAL(p,0,reskey); p += 4;
1954 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1955 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1956 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1957 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1958 SOFF_T(p,0,file_size); p += 8;
1959 SOFF_T(p,0,allocation_size); p += 8;
1960 SIVAL(p,0,mode); p += 4;
1961 q = p; p += 4; /* q is placeholder for name length. */
1962 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1963 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1965 unsigned int ea_size = estimate_ea_size(conn, NULL,
1967 SIVAL(p,0,ea_size); /* Extended attributes */
1970 /* Clear the short name buffer. This is
1971 * IMPORTANT as not doing so will trigger
1972 * a Win2k client bug. JRA.
1974 if (!was_8_3 && check_mangled_names) {
1975 char mangled_name[13]; /* mangled 8.3 name. */
1976 if (!name_to_8_3(fname,mangled_name,True,
1978 /* Error - mangle failed ! */
1979 memset(mangled_name,'\0',12);
1981 mangled_name[12] = 0;
1982 status = srvstr_push(base_data, flags2,
1983 p+2, mangled_name, 24,
1984 STR_UPPER|STR_UNICODE, &len);
1985 if (!NT_STATUS_IS_OK(status)) {
1989 memset(p + 2 + len,'\0',24 - len);
1996 status = srvstr_push(base_data, flags2, p,
1997 fname, PTR_DIFF(end_data, p),
1998 STR_TERMINATE_ASCII, &len);
1999 if (!NT_STATUS_IS_OK(status)) {
2005 len = PTR_DIFF(p, pdata);
2006 pad = (len + (align-1)) & ~(align-1);
2008 * offset to the next entry, the caller
2009 * will overwrite it for the last entry
2010 * that's why we always include the padding
2014 * set padding to zero
2017 memset(p, 0, pad - len);
2024 case SMB_FIND_FILE_DIRECTORY_INFO:
2025 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2027 SIVAL(p,0,reskey); p += 4;
2028 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2029 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2030 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2031 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2032 SOFF_T(p,0,file_size); p += 8;
2033 SOFF_T(p,0,allocation_size); p += 8;
2034 SIVAL(p,0,mode); p += 4;
2035 status = srvstr_push(base_data, flags2,
2036 p + 4, fname, PTR_DIFF(end_data, p+4),
2037 STR_TERMINATE_ASCII, &len);
2038 if (!NT_STATUS_IS_OK(status)) {
2044 len = PTR_DIFF(p, pdata);
2045 pad = (len + (align-1)) & ~(align-1);
2047 * offset to the next entry, the caller
2048 * will overwrite it for the last entry
2049 * that's why we always include the padding
2053 * set padding to zero
2056 memset(p, 0, pad - len);
2063 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2064 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2066 SIVAL(p,0,reskey); p += 4;
2067 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2068 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2069 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2070 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2071 SOFF_T(p,0,file_size); p += 8;
2072 SOFF_T(p,0,allocation_size); p += 8;
2073 SIVAL(p,0,mode); p += 4;
2074 q = p; p += 4; /* q is placeholder for name length. */
2076 unsigned int ea_size = estimate_ea_size(conn, NULL,
2078 SIVAL(p,0,ea_size); /* Extended attributes */
2081 status = srvstr_push(base_data, flags2, p,
2082 fname, PTR_DIFF(end_data, p),
2083 STR_TERMINATE_ASCII, &len);
2084 if (!NT_STATUS_IS_OK(status)) {
2090 len = PTR_DIFF(p, pdata);
2091 pad = (len + (align-1)) & ~(align-1);
2093 * offset to the next entry, the caller
2094 * will overwrite it for the last entry
2095 * that's why we always include the padding
2099 * set padding to zero
2102 memset(p, 0, pad - len);
2109 case SMB_FIND_FILE_NAMES_INFO:
2110 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2112 SIVAL(p,0,reskey); p += 4;
2114 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2115 acl on a dir (tridge) */
2116 status = srvstr_push(base_data, flags2, p,
2117 fname, PTR_DIFF(end_data, p),
2118 STR_TERMINATE_ASCII, &len);
2119 if (!NT_STATUS_IS_OK(status)) {
2125 len = PTR_DIFF(p, pdata);
2126 pad = (len + (align-1)) & ~(align-1);
2128 * offset to the next entry, the caller
2129 * will overwrite it for the last entry
2130 * that's why we always include the padding
2134 * set padding to zero
2137 memset(p, 0, pad - len);
2144 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2145 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2147 SIVAL(p,0,reskey); p += 4;
2148 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2149 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2150 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2151 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2152 SOFF_T(p,0,file_size); p += 8;
2153 SOFF_T(p,0,allocation_size); p += 8;
2154 SIVAL(p,0,mode); p += 4;
2155 q = p; p += 4; /* q is placeholder for name length. */
2156 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2157 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2159 unsigned int ea_size = estimate_ea_size(conn, NULL,
2161 SIVAL(p,0,ea_size); /* Extended attributes */
2164 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2165 SBVAL(p,0,file_index); p += 8;
2166 status = srvstr_push(base_data, flags2, p,
2167 fname, PTR_DIFF(end_data, p),
2168 STR_TERMINATE_ASCII, &len);
2169 if (!NT_STATUS_IS_OK(status)) {
2175 len = PTR_DIFF(p, pdata);
2176 pad = (len + (align-1)) & ~(align-1);
2178 * offset to the next entry, the caller
2179 * will overwrite it for the last entry
2180 * that's why we always include the padding
2184 * set padding to zero
2187 memset(p, 0, pad - len);
2194 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2195 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2196 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2198 SIVAL(p,0,reskey); p += 4;
2199 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2200 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2201 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2202 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2203 SOFF_T(p,0,file_size); p += 8;
2204 SOFF_T(p,0,allocation_size); p += 8;
2205 SIVAL(p,0,mode); p += 4;
2206 q = p; p += 4; /* q is placeholder for name length */
2207 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2208 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2209 } else if (readdir_attr_data &&
2210 readdir_attr_data->type == RDATTR_AAPL) {
2212 * OS X specific SMB2 extension negotiated via
2213 * AAPL create context: return max_access in
2216 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2218 unsigned int ea_size = estimate_ea_size(conn, NULL,
2220 SIVAL(p,0,ea_size); /* Extended attributes */
2224 if (readdir_attr_data &&
2225 readdir_attr_data->type == RDATTR_AAPL) {
2227 * OS X specific SMB2 extension negotiated via
2228 * AAPL create context: return resource fork
2229 * length and compressed FinderInfo in
2232 * According to documentation short_name_len
2233 * should be 0, but on the wire behaviour
2234 * shows its set to 24 by clients.
2238 /* Resourefork length */
2239 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2241 /* Compressed FinderInfo */
2242 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2243 } else if (!was_8_3 && check_mangled_names) {
2244 char mangled_name[13]; /* mangled 8.3 name. */
2245 if (!name_to_8_3(fname,mangled_name,True,
2247 /* Error - mangle failed ! */
2248 memset(mangled_name,'\0',12);
2250 mangled_name[12] = 0;
2251 status = srvstr_push(base_data, flags2,
2252 p+2, mangled_name, 24,
2253 STR_UPPER|STR_UNICODE, &len);
2254 if (!NT_STATUS_IS_OK(status)) {
2259 memset(p + 2 + len,'\0',24 - len);
2263 /* Clear the short name buffer. This is
2264 * IMPORTANT as not doing so will trigger
2265 * a Win2k client bug. JRA.
2272 if (readdir_attr_data &&
2273 readdir_attr_data->type == RDATTR_AAPL) {
2275 * OS X specific SMB2 extension negotiated via
2276 * AAPL create context: return UNIX mode in
2279 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2280 SSVAL(p, 0, aapl_mode);
2286 SBVAL(p,0,file_index); p += 8;
2287 status = srvstr_push(base_data, flags2, p,
2288 fname, PTR_DIFF(end_data, p),
2289 STR_TERMINATE_ASCII, &len);
2290 if (!NT_STATUS_IS_OK(status)) {
2296 len = PTR_DIFF(p, pdata);
2297 pad = (len + (align-1)) & ~(align-1);
2299 * offset to the next entry, the caller
2300 * will overwrite it for the last entry
2301 * that's why we always include the padding
2305 * set padding to zero
2308 memset(p, 0, pad - len);
2315 /* CIFS UNIX Extension. */
2317 case SMB_FIND_FILE_UNIX:
2318 case SMB_FIND_FILE_UNIX_INFO2:
2320 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2322 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2324 if (info_level == SMB_FIND_FILE_UNIX) {
2325 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2326 p = store_file_unix_basic(conn, p,
2327 NULL, &smb_fname->st);
2328 status = srvstr_push(base_data, flags2, p,
2329 fname, PTR_DIFF(end_data, p),
2330 STR_TERMINATE, &len);
2331 if (!NT_STATUS_IS_OK(status)) {
2335 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2336 p = store_file_unix_basic_info2(conn, p,
2337 NULL, &smb_fname->st);
2340 status = srvstr_push(base_data, flags2, p, fname,
2341 PTR_DIFF(end_data, p), 0, &len);
2342 if (!NT_STATUS_IS_OK(status)) {
2345 SIVAL(nameptr, 0, len);
2350 len = PTR_DIFF(p, pdata);
2351 pad = (len + (align-1)) & ~(align-1);
2353 * offset to the next entry, the caller
2354 * will overwrite it for the last entry
2355 * that's why we always include the padding
2359 * set padding to zero
2362 memset(p, 0, pad - len);
2367 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2372 return NT_STATUS_INVALID_LEVEL;
2375 if (PTR_DIFF(p,pdata) > space_remaining) {
2376 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2377 "(wanted %u, had %d)\n",
2378 (unsigned int)PTR_DIFF(p,pdata),
2380 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2383 /* Setup the last entry pointer, as an offset from base_data */
2384 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2385 /* Advance the data pointer to the next slot */
2388 return NT_STATUS_OK;
2391 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2392 connection_struct *conn,
2393 struct dptr_struct *dirptr,
2395 const char *path_mask,
2398 int requires_resume_key,
2406 int space_remaining,
2407 bool *got_exact_match,
2408 int *_last_entry_off,
2409 struct ea_list *name_list)
2412 const char *mask = NULL;
2413 long prev_dirpos = 0;
2416 struct smb_filename *smb_fname = NULL;
2417 struct smbd_dirptr_lanman2_state state;
2419 uint64_t last_entry_off = 0;
2424 state.info_level = info_level;
2425 state.check_mangled_names = lp_mangled_names(conn->params);
2426 state.has_wild = dptr_has_wild(dirptr);
2427 state.got_exact_match = false;
2429 *got_exact_match = false;
2431 p = strrchr_m(path_mask,'/');
2442 ok = smbd_dirptr_get_entry(ctx,
2448 smbd_dirptr_lanman2_match_fn,
2449 smbd_dirptr_lanman2_mode_fn,
2456 return NT_STATUS_END_OF_FILE;
2459 *got_exact_match = state.got_exact_match;
2461 status = smbd_marshall_dir_entry(ctx,
2466 state.check_mangled_names,
2467 requires_resume_key,
2478 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2479 DEBUG(1,("Conversion error: illegal character: %s\n",
2480 smb_fname_str_dbg(smb_fname)));
2483 TALLOC_FREE(smb_fname);
2484 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2485 dptr_SeekDir(dirptr, prev_dirpos);
2488 if (!NT_STATUS_IS_OK(status)) {
2492 *_last_entry_off = last_entry_off;
2493 return NT_STATUS_OK;
2496 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2497 connection_struct *conn,
2498 struct dptr_struct *dirptr,
2500 const char *path_mask,
2503 bool requires_resume_key,
2509 int space_remaining,
2510 bool *got_exact_match,
2511 int *last_entry_off,
2512 struct ea_list *name_list)
2515 const bool do_pad = true;
2517 if (info_level >= 1 && info_level <= 3) {
2518 /* No alignment on earlier info levels. */
2522 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2523 path_mask, dirtype, info_level,
2524 requires_resume_key, dont_descend, ask_sharemode,
2526 ppdata, base_data, end_data,
2529 last_entry_off, name_list);
2532 /****************************************************************************
2533 Reply to a TRANS2_FINDFIRST.
2534 ****************************************************************************/
2536 static void call_trans2findfirst(connection_struct *conn,
2537 struct smb_request *req,
2538 char **pparams, int total_params,
2539 char **ppdata, int total_data,
2540 unsigned int max_data_bytes)
2542 /* We must be careful here that we don't return more than the
2543 allowed number of data bytes. If this means returning fewer than
2544 maxentries then so be it. We assume that the redirector has
2545 enough room for the fixed number of parameter bytes it has
2547 struct smb_filename *smb_dname = NULL;
2548 char *params = *pparams;
2549 char *pdata = *ppdata;
2553 uint16_t findfirst_flags;
2554 bool close_after_first;
2556 bool requires_resume_key;
2558 char *directory = NULL;
2561 int last_entry_off=0;
2565 bool finished = False;
2566 bool dont_descend = False;
2567 bool out_of_space = False;
2568 int space_remaining;
2569 bool mask_contains_wcard = False;
2570 struct ea_list *ea_list = NULL;
2571 NTSTATUS ntstatus = NT_STATUS_OK;
2572 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2573 struct dptr_struct *dirptr = NULL;
2574 struct smbd_server_connection *sconn = req->sconn;
2575 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2576 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2577 bool backup_priv = false;
2578 bool as_root = false;
2580 if (total_params < 13) {
2581 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2585 dirtype = SVAL(params,0);
2586 maxentries = SVAL(params,2);
2587 findfirst_flags = SVAL(params,4);
2588 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2589 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2590 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2591 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2592 security_token_has_privilege(get_current_nttok(conn),
2595 info_level = SVAL(params,6);
2597 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2598 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2599 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2601 info_level, max_data_bytes));
2604 /* W2K3 seems to treat zero as 1. */
2608 switch (info_level) {
2609 case SMB_FIND_INFO_STANDARD:
2610 case SMB_FIND_EA_SIZE:
2611 case SMB_FIND_EA_LIST:
2612 case SMB_FIND_FILE_DIRECTORY_INFO:
2613 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2614 case SMB_FIND_FILE_NAMES_INFO:
2615 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2616 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2617 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2619 case SMB_FIND_FILE_UNIX:
2620 case SMB_FIND_FILE_UNIX_INFO2:
2621 /* Always use filesystem for UNIX mtime query. */
2622 ask_sharemode = false;
2623 if (!lp_unix_extensions()) {
2624 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2627 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2630 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2634 if (req->posix_pathnames) {
2635 srvstr_get_path_wcard_posix(talloc_tos(),
2643 &mask_contains_wcard);
2645 srvstr_get_path_wcard(talloc_tos(),
2653 &mask_contains_wcard);
2655 if (!NT_STATUS_IS_OK(ntstatus)) {
2656 reply_nterror(req, ntstatus);
2663 ntstatus = filename_convert_with_privilege(talloc_tos(),
2668 &mask_contains_wcard,
2671 ntstatus = filename_convert(talloc_tos(), conn,
2672 req->flags2 & FLAGS2_DFS_PATHNAMES,
2675 &mask_contains_wcard,
2679 if (!NT_STATUS_IS_OK(ntstatus)) {
2680 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2681 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2682 ERRSRV, ERRbadpath);
2685 reply_nterror(req, ntstatus);
2689 mask = smb_dname->original_lcomp;
2691 directory = smb_dname->base_name;
2693 p = strrchr_m(directory,'/');
2695 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2696 if((directory[0] == '.') && (directory[1] == '\0')) {
2697 mask = talloc_strdup(talloc_tos(),"*");
2699 reply_nterror(req, NT_STATUS_NO_MEMORY);
2702 mask_contains_wcard = True;
2708 if (p == NULL || p == directory) {
2709 /* Ensure we don't have a directory name of "". */
2710 directory = talloc_strdup(talloc_tos(), ".");
2712 reply_nterror(req, NT_STATUS_NO_MEMORY);
2715 /* Ensure smb_dname->base_name matches. */
2716 smb_dname->base_name = directory;
2719 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2721 if (info_level == SMB_FIND_EA_LIST) {
2724 if (total_data < 4) {
2725 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2729 ea_size = IVAL(pdata,0);
2730 if (ea_size != total_data) {
2731 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2732 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2737 if (!lp_ea_support(SNUM(conn))) {
2738 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2742 /* Pull out the list of names. */
2743 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2750 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2751 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2755 *ppdata = (char *)SMB_REALLOC(
2756 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2757 if(*ppdata == NULL ) {
2758 reply_nterror(req, NT_STATUS_NO_MEMORY);
2762 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2764 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2767 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2768 /* Realloc the params space */
2769 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2770 if (*pparams == NULL) {
2771 reply_nterror(req, NT_STATUS_NO_MEMORY);
2776 /* Save the wildcard match and attribs we are using on this directory -
2777 needed as lanman2 assumes these are being saved between calls */
2779 ntstatus = dptr_create(conn,
2787 mask_contains_wcard,
2791 if (!NT_STATUS_IS_OK(ntstatus)) {
2792 reply_nterror(req, ntstatus);
2797 /* Remember this in case we have
2798 to do a findnext. */
2799 dptr_set_priv(dirptr);
2802 dptr_num = dptr_dnum(dirptr);
2803 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2805 /* Initialize per TRANS2_FIND_FIRST operation data */
2806 dptr_init_search_op(dirptr);
2808 /* We don't need to check for VOL here as this is returned by
2809 a different TRANS2 call. */
2811 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2812 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2813 if (in_list(directory,
2814 lp_dont_descend(talloc_tos(), SNUM(conn)),
2815 conn->case_sensitive)) {
2816 dont_descend = True;
2820 space_remaining = max_data_bytes;
2821 out_of_space = False;
2823 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2824 bool got_exact_match = False;
2826 /* this is a heuristic to avoid seeking the dirptr except when
2827 absolutely necessary. It allows for a filename of about 40 chars */
2828 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2829 out_of_space = True;
2832 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2836 mask,dirtype,info_level,
2837 requires_resume_key,dont_descend,
2842 &last_entry_off, ea_list);
2843 if (NT_STATUS_EQUAL(ntstatus,
2844 NT_STATUS_ILLEGAL_CHARACTER)) {
2846 * Bad character conversion on name. Ignore this
2851 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2852 out_of_space = true;
2854 finished = !NT_STATUS_IS_OK(ntstatus);
2858 if (!finished && !out_of_space)
2862 * As an optimisation if we know we aren't looking
2863 * for a wildcard name (ie. the name matches the wildcard exactly)
2864 * then we can finish on any (first) match.
2865 * This speeds up large directory searches. JRA.
2871 /* Ensure space_remaining never goes -ve. */
2872 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2873 space_remaining = 0;
2874 out_of_space = true;
2876 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2880 /* Check if we can close the dirptr */
2881 if(close_after_first || (finished && close_if_end)) {
2882 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2883 dptr_close(sconn, &dptr_num);
2887 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2888 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2889 * the protocol level is less than NT1. Tested with smbclient. JRA.
2890 * This should fix the OS/2 client bug #2335.
2893 if(numentries == 0) {
2894 dptr_close(sconn, &dptr_num);
2895 if (get_Protocol() < PROTOCOL_NT1) {
2896 reply_force_doserror(req, ERRDOS, ERRnofiles);
2899 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2900 ERRDOS, ERRbadfile);
2905 /* At this point pdata points to numentries directory entries. */
2907 /* Set up the return parameter block */
2908 SSVAL(params,0,dptr_num);
2909 SSVAL(params,2,numentries);
2910 SSVAL(params,4,finished);
2911 SSVAL(params,6,0); /* Never an EA error */
2912 SSVAL(params,8,last_entry_off);
2914 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2917 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2918 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2920 reply_nterror(req, NT_STATUS_NO_MEMORY);
2924 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2925 smb_fn_name(req->cmd),
2926 mask, directory, dirtype, numentries ) );
2929 * Force a name mangle here to ensure that the
2930 * mask as an 8.3 name is top of the mangled cache.
2931 * The reasons for this are subtle. Don't remove
2932 * this code unless you know what you are doing
2933 * (see PR#13758). JRA.
2936 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2937 char mangled_name[13];
2938 name_to_8_3(mask, mangled_name, True, conn->params);
2946 TALLOC_FREE(smb_dname);
2950 /****************************************************************************
2951 Reply to a TRANS2_FINDNEXT.
2952 ****************************************************************************/
2954 static void call_trans2findnext(connection_struct *conn,
2955 struct smb_request *req,
2956 char **pparams, int total_params,
2957 char **ppdata, int total_data,
2958 unsigned int max_data_bytes)
2960 /* We must be careful here that we don't return more than the
2961 allowed number of data bytes. If this means returning fewer than
2962 maxentries then so be it. We assume that the redirector has
2963 enough room for the fixed number of parameter bytes it has
2965 char *params = *pparams;
2966 char *pdata = *ppdata;
2970 uint16_t info_level;
2971 uint32_t resume_key;
2972 uint16_t findnext_flags;
2973 bool close_after_request;
2975 bool requires_resume_key;
2977 bool mask_contains_wcard = False;
2978 char *resume_name = NULL;
2979 const char *mask = NULL;
2980 const char *directory = NULL;
2984 int i, last_entry_off=0;
2985 bool finished = False;
2986 bool dont_descend = False;
2987 bool out_of_space = False;
2988 int space_remaining;
2989 struct ea_list *ea_list = NULL;
2990 NTSTATUS ntstatus = NT_STATUS_OK;
2991 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2992 TALLOC_CTX *ctx = talloc_tos();
2993 struct dptr_struct *dirptr;
2994 struct smbd_server_connection *sconn = req->sconn;
2995 bool backup_priv = false;
2996 bool as_root = false;
2998 if (total_params < 13) {
2999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3003 dptr_num = SVAL(params,0);
3004 maxentries = SVAL(params,2);
3005 info_level = SVAL(params,4);
3006 resume_key = IVAL(params,6);
3007 findnext_flags = SVAL(params,10);
3008 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3009 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3010 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3011 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3013 if (!continue_bit) {
3014 /* We only need resume_name if continue_bit is zero. */
3015 if (req->posix_pathnames) {
3016 srvstr_get_path_wcard_posix(ctx,
3024 &mask_contains_wcard);
3026 srvstr_get_path_wcard(ctx,
3034 &mask_contains_wcard);
3036 if (!NT_STATUS_IS_OK(ntstatus)) {
3037 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3038 complain (it thinks we're asking for the directory above the shared
3039 path or an invalid name). Catch this as the resume name is only compared, never used in
3040 a file access. JRA. */
3041 srvstr_pull_talloc(ctx, params, req->flags2,
3042 &resume_name, params+12,
3046 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3047 reply_nterror(req, ntstatus);
3053 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3054 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3055 resume_key = %d resume name = %s continue=%d level = %d\n",
3056 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3057 requires_resume_key, resume_key,
3058 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3061 /* W2K3 seems to treat zero as 1. */
3065 switch (info_level) {
3066 case SMB_FIND_INFO_STANDARD:
3067 case SMB_FIND_EA_SIZE:
3068 case SMB_FIND_EA_LIST:
3069 case SMB_FIND_FILE_DIRECTORY_INFO:
3070 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3071 case SMB_FIND_FILE_NAMES_INFO:
3072 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3073 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3074 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3076 case SMB_FIND_FILE_UNIX:
3077 case SMB_FIND_FILE_UNIX_INFO2:
3078 /* Always use filesystem for UNIX mtime query. */
3079 ask_sharemode = false;
3080 if (!lp_unix_extensions()) {
3081 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3086 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3090 if (info_level == SMB_FIND_EA_LIST) {
3093 if (total_data < 4) {
3094 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3098 ea_size = IVAL(pdata,0);
3099 if (ea_size != total_data) {
3100 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3101 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3102 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3106 if (!lp_ea_support(SNUM(conn))) {
3107 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3111 /* Pull out the list of names. */
3112 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3114 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3119 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3120 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3124 *ppdata = (char *)SMB_REALLOC(
3125 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3126 if(*ppdata == NULL) {
3127 reply_nterror(req, NT_STATUS_NO_MEMORY);
3132 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3135 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3138 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3139 /* Realloc the params space */
3140 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3141 if(*pparams == NULL ) {
3142 reply_nterror(req, NT_STATUS_NO_MEMORY);
3148 /* Check that the dptr is valid */
3149 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3150 reply_nterror(req, STATUS_NO_MORE_FILES);
3154 directory = dptr_path(sconn, dptr_num);
3156 /* Get the wildcard mask from the dptr */
3157 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3158 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3159 reply_nterror(req, STATUS_NO_MORE_FILES);
3163 /* Get the attr mask from the dptr */
3164 dirtype = dptr_attr(sconn, dptr_num);
3166 backup_priv = dptr_get_priv(dirptr);
3168 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3169 "backup_priv = %d\n",
3170 dptr_num, mask, dirtype,
3172 dptr_TellDir(dirptr),
3175 /* Initialize per TRANS2_FIND_NEXT operation data */
3176 dptr_init_search_op(dirptr);
3178 /* We don't need to check for VOL here as this is returned by
3179 a different TRANS2 call. */
3181 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3182 directory,lp_dont_descend(ctx, SNUM(conn))));
3183 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3184 dont_descend = True;
3187 space_remaining = max_data_bytes;
3188 out_of_space = False;
3196 * Seek to the correct position. We no longer use the resume key but
3197 * depend on the last file name instead.
3200 if(!continue_bit && resume_name && *resume_name) {
3203 long current_pos = 0;
3205 * Remember, name_to_8_3 is called by
3206 * get_lanman2_dir_entry(), so the resume name
3207 * could be mangled. Ensure we check the unmangled name.
3210 if (mangle_is_mangled(resume_name, conn->params)) {
3211 char *new_resume_name = NULL;
3212 mangle_lookup_name_from_8_3(ctx,
3216 if (new_resume_name) {
3217 resume_name = new_resume_name;
3222 * Fix for NT redirector problem triggered by resume key indexes
3223 * changing between directory scans. We now return a resume key of 0
3224 * and instead look for the filename to continue from (also given
3225 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3226 * findfirst/findnext (as is usual) then the directory pointer
3227 * should already be at the correct place.
3230 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
3231 } /* end if resume_name && !continue_bit */
3233 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3234 bool got_exact_match = False;
3236 /* this is a heuristic to avoid seeking the dirptr except when
3237 absolutely necessary. It allows for a filename of about 40 chars */
3238 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3239 out_of_space = True;
3242 ntstatus = get_lanman2_dir_entry(ctx,
3246 mask,dirtype,info_level,
3247 requires_resume_key,dont_descend,
3252 &last_entry_off, ea_list);
3253 if (NT_STATUS_EQUAL(ntstatus,
3254 NT_STATUS_ILLEGAL_CHARACTER)) {
3256 * Bad character conversion on name. Ignore this
3261 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3262 out_of_space = true;
3264 finished = !NT_STATUS_IS_OK(ntstatus);
3268 if (!finished && !out_of_space)
3272 * As an optimisation if we know we aren't looking
3273 * for a wildcard name (ie. the name matches the wildcard exactly)
3274 * then we can finish on any (first) match.
3275 * This speeds up large directory searches. JRA.
3281 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3284 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3285 smb_fn_name(req->cmd),
3286 mask, directory, dirtype, numentries ) );
3288 /* Check if we can close the dirptr */
3289 if(close_after_request || (finished && close_if_end)) {
3290 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3291 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3298 /* Set up the return parameter block */
3299 SSVAL(params,0,numentries);
3300 SSVAL(params,2,finished);
3301 SSVAL(params,4,0); /* Never an EA error */
3302 SSVAL(params,6,last_entry_off);
3304 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3310 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3312 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3316 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3318 SMB_ASSERT(extended_info != NULL);
3320 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3321 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3322 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3323 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3324 #ifdef SAMBA_VERSION_REVISION
3325 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3327 extended_info->samba_subversion = 0;
3328 #ifdef SAMBA_VERSION_RC_RELEASE
3329 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3331 #ifdef SAMBA_VERSION_PRE_RELEASE
3332 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3335 #ifdef SAMBA_VERSION_VENDOR_PATCH
3336 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3338 extended_info->samba_gitcommitdate = 0;
3339 #ifdef SAMBA_VERSION_COMMIT_TIME
3340 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3343 memset(extended_info->samba_version_string, 0,
3344 sizeof(extended_info->samba_version_string));
3346 snprintf (extended_info->samba_version_string,
3347 sizeof(extended_info->samba_version_string),
3348 "%s", samba_version_string());
3351 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3352 connection_struct *conn,
3353 TALLOC_CTX *mem_ctx,
3354 uint16_t info_level,
3356 unsigned int max_data_bytes,
3357 size_t *fixed_portion,
3358 struct smb_filename *fname,
3362 char *pdata, *end_data;
3365 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3366 int snum = SNUM(conn);
3367 const char *fstype = lp_fstype(SNUM(conn));
3368 const char *filename = NULL;
3369 const uint64_t bytes_per_sector = 512;
3370 uint32_t additional_flags = 0;
3371 struct smb_filename smb_fname;
3373 NTSTATUS status = NT_STATUS_OK;
3376 if (fname == NULL || fname->base_name == NULL) {
3379 filename = fname->base_name;
3383 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3384 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3385 "info level (0x%x) on IPC$.\n",
3386 (unsigned int)info_level));
3387 return NT_STATUS_ACCESS_DENIED;
3391 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3393 ZERO_STRUCT(smb_fname);
3394 smb_fname.base_name = discard_const_p(char, filename);
3396 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3397 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3398 return map_nt_error_from_unix(errno);
3403 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3404 return NT_STATUS_INVALID_PARAMETER;
3407 *ppdata = (char *)SMB_REALLOC(
3408 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3409 if (*ppdata == NULL) {
3410 return NT_STATUS_NO_MEMORY;
3414 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3415 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3419 switch (info_level) {
3420 case SMB_INFO_ALLOCATION:
3422 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3424 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3426 if (df_ret == (uint64_t)-1) {
3427 return map_nt_error_from_unix(errno);
3430 block_size = lp_block_size(snum);
3431 if (bsize < block_size) {
3432 uint64_t factor = block_size/bsize;
3437 if (bsize > block_size) {
3438 uint64_t factor = bsize/block_size;
3443 sectors_per_unit = bsize/bytes_per_sector;
3445 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3446 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3447 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3449 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3450 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3451 SIVAL(pdata,l1_cUnit,dsize);
3452 SIVAL(pdata,l1_cUnitAvail,dfree);
3453 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3457 case SMB_INFO_VOLUME:
3458 /* Return volume name */
3460 * Add volume serial number - hash of a combination of
3461 * the called hostname and the service name.
3463 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3465 * Win2k3 and previous mess this up by sending a name length
3466 * one byte short. I believe only older clients (OS/2 Win9x) use
3467 * this call so try fixing this by adding a terminating null to
3468 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3470 status = srvstr_push(
3472 pdata+l2_vol_szVolLabel, vname,
3473 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3474 STR_NOALIGN|STR_TERMINATE, &len);
3475 if (!NT_STATUS_IS_OK(status)) {
3478 SCVAL(pdata,l2_vol_cch,len);
3479 data_len = l2_vol_szVolLabel + len;
3480 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3481 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3482 (unsigned)len, vname));
3485 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3486 case SMB_FS_ATTRIBUTE_INFORMATION:
3488 additional_flags = 0;
3489 #if defined(HAVE_SYS_QUOTAS)
3490 additional_flags |= FILE_VOLUME_QUOTAS;
3493 if(lp_nt_acl_support(SNUM(conn))) {
3494 additional_flags |= FILE_PERSISTENT_ACLS;
3497 /* Capabilities are filled in at connection time through STATVFS call */
3498 additional_flags |= conn->fs_capabilities;
3499 additional_flags |= lp_parm_int(conn->params->service,
3500 "share", "fake_fscaps",
3503 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3504 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3505 additional_flags); /* FS ATTRIBUTES */
3507 SIVAL(pdata,4,255); /* Max filename component length */
3508 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3509 and will think we can't do long filenames */
3510 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3511 PTR_DIFF(end_data, pdata+12),
3513 if (!NT_STATUS_IS_OK(status)) {
3517 data_len = 12 + len;
3518 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3519 /* the client only requested a portion of the
3521 data_len = max_data_bytes;
3522 status = STATUS_BUFFER_OVERFLOW;
3524 *fixed_portion = 16;
3527 case SMB_QUERY_FS_LABEL_INFO:
3528 case SMB_FS_LABEL_INFORMATION:
3529 status = srvstr_push(pdata, flags2, pdata+4, vname,
3530 PTR_DIFF(end_data, pdata+4), 0, &len);
3531 if (!NT_STATUS_IS_OK(status)) {
3538 case SMB_QUERY_FS_VOLUME_INFO:
3539 case SMB_FS_VOLUME_INFORMATION:
3542 * Add volume serial number - hash of a combination of
3543 * the called hostname and the service name.
3545 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3546 (str_checksum(get_local_machine_name())<<16));
3548 /* Max label len is 32 characters. */
3549 status = srvstr_push(pdata, flags2, pdata+18, vname,
3550 PTR_DIFF(end_data, pdata+18),
3552 if (!NT_STATUS_IS_OK(status)) {
3555 SIVAL(pdata,12,len);
3558 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3559 (int)strlen(vname),vname,
3560 lp_servicename(talloc_tos(), snum)));
3561 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3562 /* the client only requested a portion of the
3564 data_len = max_data_bytes;
3565 status = STATUS_BUFFER_OVERFLOW;
3567 *fixed_portion = 24;
3570 case SMB_QUERY_FS_SIZE_INFO:
3571 case SMB_FS_SIZE_INFORMATION:
3573 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3575 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3577 if (df_ret == (uint64_t)-1) {
3578 return map_nt_error_from_unix(errno);
3580 block_size = lp_block_size(snum);
3581 if (bsize < block_size) {
3582 uint64_t factor = block_size/bsize;
3587 if (bsize > block_size) {
3588 uint64_t factor = bsize/block_size;
3593 sectors_per_unit = bsize/bytes_per_sector;
3594 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3595 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3596 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3597 SBIG_UINT(pdata,0,dsize);
3598 SBIG_UINT(pdata,8,dfree);
3599 SIVAL(pdata,16,sectors_per_unit);
3600 SIVAL(pdata,20,bytes_per_sector);
3601 *fixed_portion = 24;
3605 case SMB_FS_FULL_SIZE_INFORMATION:
3607 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3609 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3611 if (df_ret == (uint64_t)-1) {
3612 return map_nt_error_from_unix(errno);
3614 block_size = lp_block_size(snum);
3615 if (bsize < block_size) {
3616 uint64_t factor = block_size/bsize;
3621 if (bsize > block_size) {
3622 uint64_t factor = bsize/block_size;
3627 sectors_per_unit = bsize/bytes_per_sector;
3628 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3629 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3630 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3631 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3632 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3633 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3634 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3635 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3636 *fixed_portion = 32;
3640 case SMB_QUERY_FS_DEVICE_INFO:
3641 case SMB_FS_DEVICE_INFORMATION:
3643 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3645 if (!CAN_WRITE(conn)) {
3646 characteristics |= FILE_READ_ONLY_DEVICE;
3649 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3650 SIVAL(pdata,4,characteristics);
3655 #ifdef HAVE_SYS_QUOTAS
3656 case SMB_FS_QUOTA_INFORMATION:
3658 * what we have to send --metze:
3660 * Unknown1: 24 NULL bytes
3661 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3662 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3663 * Quota Flags: 2 byte :
3664 * Unknown3: 6 NULL bytes
3668 * details for Quota Flags:
3670 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3671 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3672 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3673 * 0x0001 Enable Quotas: enable quota for this fs
3677 /* we need to fake up a fsp here,
3678 * because its not send in this call
3681 SMB_NTQUOTA_STRUCT quotas;
3684 ZERO_STRUCT(quotas);
3687 fsp.fnum = FNUM_FIELD_INVALID;
3690 if (get_current_uid(conn) != 0) {
3691 DEBUG(0,("get_user_quota: access_denied "
3692 "service [%s] user [%s]\n",
3693 lp_servicename(talloc_tos(), SNUM(conn)),
3694 conn->session_info->unix_info->unix_name));
3695 return NT_STATUS_ACCESS_DENIED;
3698 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3699 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3700 return map_nt_error_from_unix(errno);
3705 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3706 lp_servicename(talloc_tos(), SNUM(conn))));
3708 /* Unknown1 24 NULL bytes*/
3709 SBIG_UINT(pdata,0,(uint64_t)0);
3710 SBIG_UINT(pdata,8,(uint64_t)0);
3711 SBIG_UINT(pdata,16,(uint64_t)0);
3713 /* Default Soft Quota 8 bytes */
3714 SBIG_UINT(pdata,24,quotas.softlim);
3716 /* Default Hard Quota 8 bytes */
3717 SBIG_UINT(pdata,32,quotas.hardlim);
3719 /* Quota flag 2 bytes */
3720 SSVAL(pdata,40,quotas.qflags);
3722 /* Unknown3 6 NULL bytes */
3728 #endif /* HAVE_SYS_QUOTAS */
3729 case SMB_FS_OBJECTID_INFORMATION:
3731 unsigned char objid[16];
3732 struct smb_extended_info extended_info;
3733 memcpy(pdata,create_volume_objectid(conn, objid),16);
3734 samba_extended_info_version (&extended_info);
3735 SIVAL(pdata,16,extended_info.samba_magic);
3736 SIVAL(pdata,20,extended_info.samba_version);
3737 SIVAL(pdata,24,extended_info.samba_subversion);
3738 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3739 memcpy(pdata+36,extended_info.samba_version_string,28);
3744 case SMB_FS_SECTOR_SIZE_INFORMATION:
3748 * These values match a physical Windows Server 2012
3749 * share backed by NTFS atop spinning rust.
3751 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3752 /* logical_bytes_per_sector */
3753 SIVAL(pdata, 0, bytes_per_sector);
3754 /* phys_bytes_per_sector_atomic */
3755 SIVAL(pdata, 4, bytes_per_sector);
3756 /* phys_bytes_per_sector_perf */
3757 SIVAL(pdata, 8, bytes_per_sector);
3758 /* fs_effective_phys_bytes_per_sector_atomic */
3759 SIVAL(pdata, 12, bytes_per_sector);
3761 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3762 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3763 /* byte_off_sector_align */
3764 SIVAL(pdata, 20, 0);
3765 /* byte_off_partition_align */
3766 SIVAL(pdata, 24, 0);
3767 *fixed_portion = 28;
3773 * Query the version and capabilities of the CIFS UNIX extensions
3777 case SMB_QUERY_CIFS_UNIX_INFO:
3779 bool large_write = lp_min_receive_file_size() &&
3780 !srv_is_signing_active(xconn);
3781 bool large_read = !srv_is_signing_active(xconn);
3782 int encrypt_caps = 0;
3784 if (!lp_unix_extensions()) {
3785 return NT_STATUS_INVALID_LEVEL;
3788 switch (conn->encrypt_level) {
3789 case SMB_SIGNING_OFF:
3792 case SMB_SIGNING_DESIRED:
3793 case SMB_SIGNING_IF_REQUIRED:
3794 case SMB_SIGNING_DEFAULT:
3795 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3797 case SMB_SIGNING_REQUIRED:
3798 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3799 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3800 large_write = false;
3806 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3807 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3809 /* We have POSIX ACLs, pathname, encryption,
3810 * large read/write, and locking capability. */
3812 SBIG_UINT(pdata,4,((uint64_t)(
3813 CIFS_UNIX_POSIX_ACLS_CAP|
3814 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3815 CIFS_UNIX_FCNTL_LOCKS_CAP|
3816 CIFS_UNIX_EXTATTR_CAP|
3817 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3819 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3821 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3825 case SMB_QUERY_POSIX_FS_INFO:
3828 vfs_statvfs_struct svfs;
3830 if (!lp_unix_extensions()) {
3831 return NT_STATUS_INVALID_LEVEL;
3834 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3838 SIVAL(pdata,0,svfs.OptimalTransferSize);
3839 SIVAL(pdata,4,svfs.BlockSize);
3840 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3841 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3842 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3843 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3844 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3845 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3846 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3848 } else if (rc == EOPNOTSUPP) {
3849 return NT_STATUS_INVALID_LEVEL;
3850 #endif /* EOPNOTSUPP */
3852 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3853 return NT_STATUS_DOS(ERRSRV, ERRerror);
3858 case SMB_QUERY_POSIX_WHOAMI:
3864 if (!lp_unix_extensions()) {
3865 return NT_STATUS_INVALID_LEVEL;
3868 if (max_data_bytes < 40) {
3869 return NT_STATUS_BUFFER_TOO_SMALL;
3872 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3873 flags |= SMB_WHOAMI_GUEST;
3876 /* NOTE: 8 bytes for UID/GID, irrespective of native
3877 * platform size. This matches
3878 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3880 data_len = 4 /* flags */
3887 + 4 /* pad/reserved */
3888 + (conn->session_info->unix_token->ngroups * 8)
3890 + (conn->session_info->security_token->num_sids *
3894 SIVAL(pdata, 0, flags);
3895 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3897 (uint64_t)conn->session_info->unix_token->uid);
3898 SBIG_UINT(pdata, 16,
3899 (uint64_t)conn->session_info->unix_token->gid);
3902 if (data_len >= max_data_bytes) {
3903 /* Potential overflow, skip the GIDs and SIDs. */
3905 SIVAL(pdata, 24, 0); /* num_groups */
3906 SIVAL(pdata, 28, 0); /* num_sids */
3907 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3908 SIVAL(pdata, 36, 0); /* reserved */
3914 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3915 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3917 /* We walk the SID list twice, but this call is fairly
3918 * infrequent, and I don't expect that it's performance
3919 * sensitive -- jpeach
3921 for (i = 0, sid_bytes = 0;
3922 i < conn->session_info->security_token->num_sids; ++i) {
3923 sid_bytes += ndr_size_dom_sid(
3924 &conn->session_info->security_token->sids[i],
3928 /* SID list byte count */
3929 SIVAL(pdata, 32, sid_bytes);
3931 /* 4 bytes pad/reserved - must be zero */
3932 SIVAL(pdata, 36, 0);
3936 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3937 SBIG_UINT(pdata, data_len,
3938 (uint64_t)conn->session_info->unix_token->groups[i]);
3944 i < conn->session_info->security_token->num_sids; ++i) {
3945 int sid_len = ndr_size_dom_sid(
3946 &conn->session_info->security_token->sids[i],
3949 sid_linearize((uint8_t *)(pdata + data_len),
3951 &conn->session_info->security_token->sids[i]);
3952 data_len += sid_len;
3958 case SMB_MAC_QUERY_FS_INFO:
3960 * Thursby MAC extension... ONLY on NTFS filesystems
3961 * once we do streams then we don't need this
3963 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3965 SIVAL(pdata,84,0x100); /* Don't support mac... */
3970 return NT_STATUS_INVALID_LEVEL;
3973 *ret_data_len = data_len;
3977 /****************************************************************************
3978 Reply to a TRANS2_QFSINFO (query filesystem info).
3979 ****************************************************************************/
3981 static void call_trans2qfsinfo(connection_struct *conn,
3982 struct smb_request *req,
3983 char **pparams, int total_params,
3984 char **ppdata, int total_data,
3985 unsigned int max_data_bytes)
3987 char *params = *pparams;
3988 uint16_t info_level;
3990 size_t fixed_portion;
3993 if (total_params < 2) {
3994 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3998 info_level = SVAL(params,0);
4000 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4001 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4002 DEBUG(0,("call_trans2qfsinfo: encryption required "
4003 "and info level 0x%x sent.\n",
4004 (unsigned int)info_level));
4005 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4010 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4012 status = smbd_do_qfsinfo(req->xconn, conn, req,
4019 if (!NT_STATUS_IS_OK(status)) {
4020 reply_nterror(req, status);
4024 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4027 DEBUG( 4, ( "%s info_level = %d\n",
4028 smb_fn_name(req->cmd), info_level) );
4033 /****************************************************************************
4034 Reply to a TRANS2_SETFSINFO (set filesystem info).
4035 ****************************************************************************/
4037 static void call_trans2setfsinfo(connection_struct *conn,
4038 struct smb_request *req,
4039 char **pparams, int total_params,
4040 char **ppdata, int total_data,
4041 unsigned int max_data_bytes)
4043 struct smbXsrv_connection *xconn = req->xconn;
4044 char *pdata = *ppdata;
4045 char *params = *pparams;
4046 uint16_t info_level;
4048 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4049 lp_servicename(talloc_tos(), SNUM(conn))));
4052 if (total_params < 4) {
4053 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4055 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4059 info_level = SVAL(params,2);
4062 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4063 info_level != SMB_SET_CIFS_UNIX_INFO) {
4064 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4065 "info level (0x%x) on IPC$.\n",
4066 (unsigned int)info_level));
4067 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4072 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4073 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4074 DEBUG(0,("call_trans2setfsinfo: encryption required "
4075 "and info level 0x%x sent.\n",
4076 (unsigned int)info_level));
4077 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4082 switch(info_level) {
4083 case SMB_SET_CIFS_UNIX_INFO:
4084 if (!lp_unix_extensions()) {
4085 DEBUG(2,("call_trans2setfsinfo: "
4086 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4087 "unix extensions off\n"));
4089 NT_STATUS_INVALID_LEVEL);
4093 /* There should be 12 bytes of capabilities set. */
4094 if (total_data < 12) {
4097 NT_STATUS_INVALID_PARAMETER);
4100 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4101 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4102 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4103 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4104 /* Just print these values for now. */
4105 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4106 "major = %u, minor = %u cap_low = 0x%x, "
4108 (unsigned int)xconn->
4109 smb1.unix_info.client_major,
4110 (unsigned int)xconn->
4111 smb1.unix_info.client_minor,
4112 (unsigned int)xconn->
4113 smb1.unix_info.client_cap_low,
4114 (unsigned int)xconn->
4115 smb1.unix_info.client_cap_high));
4117 /* Here is where we must switch to posix pathname processing... */
4118 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4119 lp_set_posix_pathnames();
4120 mangle_change_to_posix();
4123 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4124 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4125 /* Client that knows how to do posix locks,
4126 * but not posix open/mkdir operations. Set a
4127 * default type for read/write checks. */
4129 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4134 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4137 size_t param_len = 0;
4138 size_t data_len = total_data;
4140 if (!lp_unix_extensions()) {
4143 NT_STATUS_INVALID_LEVEL);
4147 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4150 NT_STATUS_NOT_SUPPORTED);
4154 if (xconn->smb1.echo_handler.trusted_fde) {
4155 DEBUG( 2,("call_trans2setfsinfo: "
4156 "request transport encryption disabled"
4157 "with 'fork echo handler = yes'\n"));
4160 NT_STATUS_NOT_SUPPORTED);
4164 DEBUG( 4,("call_trans2setfsinfo: "
4165 "request transport encryption.\n"));
4167 status = srv_request_encryption_setup(conn,
4168 (unsigned char **)ppdata,
4170 (unsigned char **)pparams,
4173 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4174 !NT_STATUS_IS_OK(status)) {
4175 reply_nterror(req, status);
4179 send_trans2_replies(conn, req,
4187 if (NT_STATUS_IS_OK(status)) {
4188 /* Server-side transport
4189 * encryption is now *on*. */
4190 status = srv_encryption_start(conn);
4191 if (!NT_STATUS_IS_OK(status)) {
4192 char *reason = talloc_asprintf(talloc_tos(),
4193 "Failure in setting "
4194 "up encrypted transport: %s",
4196 exit_server_cleanly(reason);
4202 case SMB_FS_QUOTA_INFORMATION:
4204 files_struct *fsp = NULL;
4205 SMB_NTQUOTA_STRUCT quotas;
4207 ZERO_STRUCT(quotas);
4210 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4211 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
4212 lp_servicename(talloc_tos(), SNUM(conn)),
4213 conn->session_info->unix_info->unix_name));
4214 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4218 /* note: normally there're 48 bytes,
4219 * but we didn't use the last 6 bytes for now
4222 fsp = file_fsp(req, SVAL(params,0));
4224 if (!check_fsp_ntquota_handle(conn, req,
4226 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
4228 req, NT_STATUS_INVALID_HANDLE);
4232 if (total_data < 42) {
4233 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
4237 NT_STATUS_INVALID_PARAMETER);
4241 /* unknown_1 24 NULL bytes in pdata*/
4243 /* the soft quotas 8 bytes (uint64_t)*/
4244 quotas.softlim = BVAL(pdata,24);
4246 /* the hard quotas 8 bytes (uint64_t)*/
4247 quotas.hardlim = BVAL(pdata,32);
4249 /* quota_flags 2 bytes **/
4250 quotas.qflags = SVAL(pdata,40);
4252 /* unknown_2 6 NULL bytes follow*/
4254 /* now set the quotas */
4255 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
4256 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
4257 reply_nterror(req, map_nt_error_from_unix(errno));
4264 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4266 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4272 * sending this reply works fine,
4273 * but I'm not sure it's the same
4274 * like windows do...
4277 reply_outbuf(req, 10, 0);
4280 #if defined(HAVE_POSIX_ACLS)
4281 /****************************************************************************
4282 Utility function to count the number of entries in a POSIX acl.
4283 ****************************************************************************/
4285 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4287 unsigned int ace_count = 0;
4288 int entry_id = SMB_ACL_FIRST_ENTRY;
4289 SMB_ACL_ENTRY_T entry;
4291 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4293 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4294 entry_id = SMB_ACL_NEXT_ENTRY;
4301 /****************************************************************************
4302 Utility function to marshall a POSIX acl into wire format.
4303 ****************************************************************************/
4305 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4307 int entry_id = SMB_ACL_FIRST_ENTRY;
4308 SMB_ACL_ENTRY_T entry;
4310 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4311 SMB_ACL_TAG_T tagtype;
4312 SMB_ACL_PERMSET_T permset;
4313 unsigned char perms = 0;
4314 unsigned int own_grp;
4317 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4318 entry_id = SMB_ACL_NEXT_ENTRY;
4321 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4322 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4326 if (sys_acl_get_permset(entry, &permset) == -1) {
4327 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4331 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4332 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4333 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4335 SCVAL(pdata,1,perms);
4338 case SMB_ACL_USER_OBJ:
4339 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4340 own_grp = (unsigned int)pst->st_ex_uid;
4341 SIVAL(pdata,2,own_grp);
4346 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4348 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4351 own_grp = (unsigned int)*puid;
4352 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4353 SIVAL(pdata,2,own_grp);
4357 case SMB_ACL_GROUP_OBJ:
4358 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4359 own_grp = (unsigned int)pst->st_ex_gid;
4360 SIVAL(pdata,2,own_grp);
4365 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4367 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4370 own_grp = (unsigned int)*pgid;
4371 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4372 SIVAL(pdata,2,own_grp);
4377 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4378 SIVAL(pdata,2,0xFFFFFFFF);
4379 SIVAL(pdata,6,0xFFFFFFFF);
4382 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4383 SIVAL(pdata,2,0xFFFFFFFF);
4384 SIVAL(pdata,6,0xFFFFFFFF);
4387 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4390 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4397 /****************************************************************************
4398 Store the FILE_UNIX_BASIC info.
4399 ****************************************************************************/
4401 static char *store_file_unix_basic(connection_struct *conn,
4404 const SMB_STRUCT_STAT *psbuf)
4406 uint64_t file_index = get_FileIndex(conn, psbuf);
4409 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4410 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4412 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4415 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4418 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4419 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4420 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4423 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4427 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4431 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4434 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4435 devno = psbuf->st_ex_rdev;
4437 devno = psbuf->st_ex_dev;
4440 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4444 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4448 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4451 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4455 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4462 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4463 * the chflags(2) (or equivalent) flags.
4465 * XXX: this really should be behind the VFS interface. To do this, we would
4466 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4467 * Each VFS module could then implement its own mapping as appropriate for the
4468 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4470 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4474 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4478 { UF_IMMUTABLE, EXT_IMMUTABLE },
4482 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4486 { UF_HIDDEN, EXT_HIDDEN },
4489 /* Do not remove. We need to guarantee that this array has at least one
4490 * entry to build on HP-UX.
4496 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4497 uint32_t *smb_fflags, uint32_t *smb_fmask)
4501 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4502 *smb_fmask |= info2_flags_map[i].smb_fflag;
4503 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4504 *smb_fflags |= info2_flags_map[i].smb_fflag;
4509 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4510 const uint32_t smb_fflags,
4511 const uint32_t smb_fmask,
4514 uint32_t max_fmask = 0;
4517 *stat_fflags = psbuf->st_ex_flags;
4519 /* For each flags requested in smb_fmask, check the state of the
4520 * corresponding flag in smb_fflags and set or clear the matching
4524 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4525 max_fmask |= info2_flags_map[i].smb_fflag;
4526 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4527 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4528 *stat_fflags |= info2_flags_map[i].stat_fflag;
4530 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4535 /* If smb_fmask is asking to set any bits that are not supported by
4536 * our flag mappings, we should fail.
4538 if ((smb_fmask & max_fmask) != smb_fmask) {
4546 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4547 * of file flags and birth (create) time.
4549 static char *store_file_unix_basic_info2(connection_struct *conn,
4552 const SMB_STRUCT_STAT *psbuf)
4554 uint32_t file_flags = 0;
4555 uint32_t flags_mask = 0;
4557 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4559 /* Create (birth) time 64 bit */
4560 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4563 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4564 SIVAL(pdata, 0, file_flags); /* flags */
4565 SIVAL(pdata, 4, flags_mask); /* mask */
4571 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4572 const struct stream_struct *streams,
4574 unsigned int max_data_bytes,
4575 unsigned int *data_size)
4578 unsigned int ofs = 0;
4580 if (max_data_bytes < 32) {
4581 return NT_STATUS_INFO_LENGTH_MISMATCH;
4584 for (i = 0; i < num_streams; i++) {
4585 unsigned int next_offset;
4587 smb_ucs2_t *namebuf;
4589 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4590 streams[i].name, &namelen) ||
4593 return NT_STATUS_INVALID_PARAMETER;
4597 * name_buf is now null-terminated, we need to marshall as not
4604 * We cannot overflow ...
4606 if ((ofs + 24 + namelen) > max_data_bytes) {
4607 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4609 TALLOC_FREE(namebuf);
4610 return STATUS_BUFFER_OVERFLOW;
4613 SIVAL(data, ofs+4, namelen);
4614 SOFF_T(data, ofs+8, streams[i].size);
4615 SOFF_T(data, ofs+16, streams[i].alloc_size);
4616 memcpy(data+ofs+24, namebuf, namelen);
4617 TALLOC_FREE(namebuf);
4619 next_offset = ofs + 24 + namelen;
4621 if (i == num_streams-1) {
4622 SIVAL(data, ofs, 0);
4625 unsigned int align = ndr_align_size(next_offset, 8);
4627 if ((next_offset + align) > max_data_bytes) {
4628 DEBUG(10, ("refusing to overflow align "
4629 "reply at stream %u\n",
4631 TALLOC_FREE(namebuf);
4632 return STATUS_BUFFER_OVERFLOW;
4635 memset(data+next_offset, 0, align);
4636 next_offset += align;
4638 SIVAL(data, ofs, next_offset - ofs);
4645 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4649 return NT_STATUS_OK;
4652 /****************************************************************************
4653 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4654 ****************************************************************************/
4656 static void call_trans2qpipeinfo(connection_struct *conn,
4657 struct smb_request *req,
4658 unsigned int tran_call,
4659 char **pparams, int total_params,
4660 char **ppdata, int total_data,
4661 unsigned int max_data_bytes)
4663 char *params = *pparams;
4664 char *pdata = *ppdata;
4665 unsigned int data_size = 0;
4666 unsigned int param_size = 2;
4667 uint16_t info_level;
4671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4675 if (total_params < 4) {
4676 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4680 fsp = file_fsp(req, SVAL(params,0));
4681 if (!fsp_is_np(fsp)) {
4682 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4686 info_level = SVAL(params,2);
4688 *pparams = (char *)SMB_REALLOC(*pparams,2);
4689 if (*pparams == NULL) {
4690 reply_nterror(req, NT_STATUS_NO_MEMORY);
4695 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4699 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4700 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4701 if (*ppdata == NULL ) {
4702 reply_nterror(req, NT_STATUS_NO_MEMORY);
4707 switch (info_level) {
4708 case SMB_FILE_STANDARD_INFORMATION:
4710 SOFF_T(pdata,0,4096LL);
4717 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4721 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4727 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4728 TALLOC_CTX *mem_ctx,
4729 uint16_t info_level,
4731 struct smb_filename *smb_fname,
4732 bool delete_pending,
4733 struct timespec write_time_ts,
4734 struct ea_list *ea_list,
4735 int lock_data_count,
4738 unsigned int max_data_bytes,
4739 size_t *fixed_portion,
4741 unsigned int *pdata_size)
4743 char *pdata = *ppdata;
4744 char *dstart, *dend;
4745 unsigned int data_size;
4746 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4747 time_t create_time, mtime, atime, c_time;
4748 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4755 uint64_t file_size = 0;
4757 uint64_t allocation_size = 0;
4758 uint64_t file_index = 0;
4759 uint32_t access_mask = 0;
4762 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4763 return NT_STATUS_INVALID_LEVEL;
4766 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4767 smb_fname_str_dbg(smb_fname),
4769 info_level, max_data_bytes));
4771 mode = dos_mode(conn, smb_fname);
4772 nlink = psbuf->st_ex_nlink;
4774 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4778 if ((nlink > 0) && delete_pending) {
4782 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4783 return NT_STATUS_INVALID_PARAMETER;
4786 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4787 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4788 if (*ppdata == NULL) {
4789 return NT_STATUS_NO_MEMORY;
4793 dend = dstart + data_size - 1;
4795 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4796 update_stat_ex_mtime(psbuf, write_time_ts);
4799 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4800 mtime_ts = psbuf->st_ex_mtime;
4801 atime_ts = psbuf->st_ex_atime;
4802 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4804 if (lp_dos_filetime_resolution(SNUM(conn))) {
4805 dos_filetime_timespec(&create_time_ts);
4806 dos_filetime_timespec(&mtime_ts);
4807 dos_filetime_timespec(&atime_ts);
4808 dos_filetime_timespec(&ctime_ts);
4811 create_time = convert_timespec_to_time_t(create_time_ts);
4812 mtime = convert_timespec_to_time_t(mtime_ts);
4813 atime = convert_timespec_to_time_t(atime_ts);
4814 c_time = convert_timespec_to_time_t(ctime_ts);
4816 p = strrchr_m(smb_fname->base_name,'/');
4818 base_name = smb_fname->base_name;
4822 /* NT expects the name to be in an exact form of the *full*
4823 filename. See the trans2 torture test */
4824 if (ISDOT(base_name)) {
4825 dos_fname = talloc_strdup(mem_ctx, "\\");
4827 return NT_STATUS_NO_MEMORY;
4830 dos_fname = talloc_asprintf(mem_ctx,
4832 smb_fname->base_name);
4834 return NT_STATUS_NO_MEMORY;
4836 if (is_ntfs_stream_smb_fname(smb_fname)) {
4837 dos_fname = talloc_asprintf(dos_fname, "%s",
4838 smb_fname->stream_name);
4840 return NT_STATUS_NO_MEMORY;
4844 string_replace(dos_fname, '/', '\\');
4847 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4850 /* Do we have this path open ? */
4852 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4853 fsp1 = file_find_di_first(conn->sconn, fileid);
4854 if (fsp1 && fsp1->initial_allocation_size) {
4855 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4859 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4860 file_size = get_file_size_stat(psbuf);
4864 pos = fsp->fh->position_information;
4868 access_mask = fsp->access_mask;
4870 /* GENERIC_EXECUTE mapping from Windows */
4871 access_mask = 0x12019F;
4874 /* This should be an index number - looks like
4877 I think this causes us to fail the IFSKIT
4878 BasicFileInformationTest. -tpot */
4879 file_index = get_FileIndex(conn, psbuf);
4883 switch (info_level) {
4884 case SMB_INFO_STANDARD:
4885 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4887 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4888 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4889 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4890 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4891 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4892 SSVAL(pdata,l1_attrFile,mode);
4895 case SMB_INFO_QUERY_EA_SIZE:
4897 unsigned int ea_size =
4898 estimate_ea_size(conn, fsp,
4900 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4902 srv_put_dos_date2(pdata,0,create_time);
4903 srv_put_dos_date2(pdata,4,atime);
4904 srv_put_dos_date2(pdata,8,mtime); /* write time */
4905 SIVAL(pdata,12,(uint32_t)file_size);
4906 SIVAL(pdata,16,(uint32_t)allocation_size);
4907 SSVAL(pdata,20,mode);
4908 SIVAL(pdata,22,ea_size);
4912 case SMB_INFO_IS_NAME_VALID:
4913 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4915 /* os/2 needs this ? really ?*/
4916 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4918 /* This is only reached for qpathinfo */
4922 case SMB_INFO_QUERY_EAS_FROM_LIST:
4924 size_t total_ea_len = 0;
4925 struct ea_list *ea_file_list = NULL;
4926 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4929 get_ea_list_from_file(mem_ctx, conn, fsp,
4931 &total_ea_len, &ea_file_list);
4932 if (!NT_STATUS_IS_OK(status)) {
4936 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4938 if (!ea_list || (total_ea_len > data_size)) {
4940 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4944 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4948 case SMB_INFO_QUERY_ALL_EAS:
4950 /* We have data_size bytes to put EA's into. */
4951 size_t total_ea_len = 0;
4952 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4954 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4956 &total_ea_len, &ea_list);
4957 if (!NT_STATUS_IS_OK(status)) {
4961 if (!ea_list || (total_ea_len > data_size)) {
4963 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4967 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4971 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4973 /* This is FileFullEaInformation - 0xF which maps to
4974 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4976 /* We have data_size bytes to put EA's into. */
4977 size_t total_ea_len = 0;
4978 struct ea_list *ea_file_list = NULL;
4980 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4982 /*TODO: add filtering and index handling */
4985 get_ea_list_from_file(mem_ctx, conn, fsp,
4987 &total_ea_len, &ea_file_list);
4988 if (!NT_STATUS_IS_OK(status)) {
4991 if (!ea_file_list) {
4992 return NT_STATUS_NO_EAS_ON_FILE;
4995 status = fill_ea_chained_buffer(mem_ctx,
4999 conn, ea_file_list);
5000 if (!NT_STATUS_IS_OK(status)) {
5006 case SMB_FILE_BASIC_INFORMATION:
5007 case SMB_QUERY_FILE_BASIC_INFO:
5009 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5010 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5011 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5013 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5017 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5018 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5019 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5020 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5021 SIVAL(pdata,32,mode);
5023 DEBUG(5,("SMB_QFBI - "));
5024 DEBUG(5,("create: %s ", ctime(&create_time)));
5025 DEBUG(5,("access: %s ", ctime(&atime)));
5026 DEBUG(5,("write: %s ", ctime(&mtime)));
5027 DEBUG(5,("change: %s ", ctime(&c_time)));
5028 DEBUG(5,("mode: %x\n", mode));
5029 *fixed_portion = data_size;
5032 case SMB_FILE_STANDARD_INFORMATION:
5033 case SMB_QUERY_FILE_STANDARD_INFO:
5035 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5037 SOFF_T(pdata,0,allocation_size);
5038 SOFF_T(pdata,8,file_size);
5039 SIVAL(pdata,16,nlink);
5040 SCVAL(pdata,20,delete_pending?1:0);
5041 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5042 SSVAL(pdata,22,0); /* Padding. */
5043 *fixed_portion = 24;
5046 case SMB_FILE_EA_INFORMATION:
5047 case SMB_QUERY_FILE_EA_INFO:
5049 unsigned int ea_size =
5050 estimate_ea_size(conn, fsp, smb_fname);
5051 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5054 SIVAL(pdata,0,ea_size);
5058 /* Get the 8.3 name - used if NT SMB was negotiated. */
5059 case SMB_QUERY_FILE_ALT_NAME_INFO:
5060 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5062 char mangled_name[13];
5063 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5064 if (!name_to_8_3(base_name,mangled_name,
5065 True,conn->params)) {
5066 return NT_STATUS_NO_MEMORY;
5068 status = srvstr_push(dstart, flags2,
5069 pdata+4, mangled_name,
5070 PTR_DIFF(dend, pdata+4),
5072 if (!NT_STATUS_IS_OK(status)) {
5075 data_size = 4 + len;
5081 case SMB_QUERY_FILE_NAME_INFO:
5084 this must be *exactly* right for ACLs on mapped drives to work
5086 status = srvstr_push(dstart, flags2,
5088 PTR_DIFF(dend, pdata+4),
5090 if (!NT_STATUS_IS_OK(status)) {
5093 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5094 data_size = 4 + len;
5099 case SMB_FILE_ALLOCATION_INFORMATION:
5100 case SMB_QUERY_FILE_ALLOCATION_INFO:
5101 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5103 SOFF_T(pdata,0,allocation_size);
5106 case SMB_FILE_END_OF_FILE_INFORMATION:
5107 case SMB_QUERY_FILE_END_OF_FILEINFO:
5108 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5110 SOFF_T(pdata,0,file_size);
5113 case SMB_QUERY_FILE_ALL_INFO:
5114 case SMB_FILE_ALL_INFORMATION:
5116 unsigned int ea_size =
5117 estimate_ea_size(conn, fsp, smb_fname);
5118 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5119 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5120 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5121 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5122 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5123 SIVAL(pdata,32,mode);
5124 SIVAL(pdata,36,0); /* padding. */
5126 SOFF_T(pdata,0,allocation_size);
5127 SOFF_T(pdata,8,file_size);
5128 SIVAL(pdata,16,nlink);
5129 SCVAL(pdata,20,delete_pending);
5130 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5133 SIVAL(pdata,0,ea_size);
5134 pdata += 4; /* EA info */
5135 status = srvstr_push(dstart, flags2,
5137 PTR_DIFF(dend, pdata+4),
5139 if (!NT_STATUS_IS_OK(status)) {
5144 data_size = PTR_DIFF(pdata,(*ppdata));
5145 *fixed_portion = 10;
5149 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5151 unsigned int ea_size =
5152 estimate_ea_size(conn, fsp, smb_fname);
5153 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5154 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5155 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5156 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5157 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5158 SIVAL(pdata, 0x20, mode);
5159 SIVAL(pdata, 0x24, 0); /* padding. */
5160 SBVAL(pdata, 0x28, allocation_size);
5161 SBVAL(pdata, 0x30, file_size);
5162 SIVAL(pdata, 0x38, nlink);
5163 SCVAL(pdata, 0x3C, delete_pending);
5164 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5165 SSVAL(pdata, 0x3E, 0); /* padding */
5166 SBVAL(pdata, 0x40, file_index);
5167 SIVAL(pdata, 0x48, ea_size);
5168 SIVAL(pdata, 0x4C, access_mask);
5169 SBVAL(pdata, 0x50, pos);
5170 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5171 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5175 status = srvstr_push(dstart, flags2,
5177 PTR_DIFF(dend, pdata+4),
5179 if (!NT_STATUS_IS_OK(status)) {
5184 data_size = PTR_DIFF(pdata,(*ppdata));
5185 *fixed_portion = 104;
5188 case SMB_FILE_INTERNAL_INFORMATION:
5190 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5191 SBVAL(pdata, 0, file_index);
5196 case SMB_FILE_ACCESS_INFORMATION:
5197 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5198 SIVAL(pdata, 0, access_mask);
5203 case SMB_FILE_NAME_INFORMATION:
5204 /* Pathname with leading '\'. */
5207 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5208 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5209 SIVAL(pdata,0,byte_len);
5210 data_size = 4 + byte_len;
5214 case SMB_FILE_DISPOSITION_INFORMATION:
5215 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5217 SCVAL(pdata,0,delete_pending);
5221 case SMB_FILE_POSITION_INFORMATION:
5222 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5224 SOFF_T(pdata,0,pos);
5228 case SMB_FILE_MODE_INFORMATION:
5229 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5230 SIVAL(pdata,0,mode);
5235 case SMB_FILE_ALIGNMENT_INFORMATION:
5236 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5237 SIVAL(pdata,0,0); /* No alignment needed. */
5243 * NT4 server just returns "invalid query" to this - if we try
5244 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5247 /* The first statement above is false - verified using Thursby
5248 * client against NT4 -- gcolley.
5250 case SMB_QUERY_FILE_STREAM_INFO:
5251 case SMB_FILE_STREAM_INFORMATION: {
5252 unsigned int num_streams = 0;
5253 struct stream_struct *streams = NULL;
5255 DEBUG(10,("smbd_do_qfilepathinfo: "
5256 "SMB_FILE_STREAM_INFORMATION\n"));
5258 if (is_ntfs_stream_smb_fname(smb_fname)) {
5259 return NT_STATUS_INVALID_PARAMETER;
5262 status = vfs_streaminfo(conn,
5269 if (!NT_STATUS_IS_OK(status)) {
5270 DEBUG(10, ("could not get stream info: %s\n",
5271 nt_errstr(status)));
5275 status = marshall_stream_info(num_streams, streams,
5276 pdata, max_data_bytes,
5279 if (!NT_STATUS_IS_OK(status)) {
5280 DEBUG(10, ("marshall_stream_info failed: %s\n",
5281 nt_errstr(status)));
5282 TALLOC_FREE(streams);
5286 TALLOC_FREE(streams);
5288 *fixed_portion = 32;
5292 case SMB_QUERY_COMPRESSION_INFO:
5293 case SMB_FILE_COMPRESSION_INFORMATION:
5294 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5295 SOFF_T(pdata,0,file_size);
5296 SIVAL(pdata,8,0); /* ??? */
5297 SIVAL(pdata,12,0); /* ??? */
5299 *fixed_portion = 16;
5302 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5303 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5304 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5305 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5306 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5307 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5308 SOFF_T(pdata,32,allocation_size);
5309 SOFF_T(pdata,40,file_size);
5310 SIVAL(pdata,48,mode);
5311 SIVAL(pdata,52,0); /* ??? */
5313 *fixed_portion = 56;
5316 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5317 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5318 SIVAL(pdata,0,mode);
5325 * CIFS UNIX Extensions.
5328 case SMB_QUERY_FILE_UNIX_BASIC:
5330 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5331 data_size = PTR_DIFF(pdata,(*ppdata));
5333 DEBUG(4,("smbd_do_qfilepathinfo: "
5334 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5335 dump_data(4, (uint8_t *)(*ppdata), data_size);
5339 case SMB_QUERY_FILE_UNIX_INFO2:
5341 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5342 data_size = PTR_DIFF(pdata,(*ppdata));
5346 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5348 for (i=0; i<100; i++)
5349 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5355 case SMB_QUERY_FILE_UNIX_LINK:
5358 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5361 return NT_STATUS_NO_MEMORY;
5364 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5366 if(!S_ISLNK(psbuf->st_ex_mode)) {
5367 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5370 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5372 link_len = SMB_VFS_READLINK(conn,
5373 smb_fname->base_name,
5375 if (link_len == -1) {
5376 return map_nt_error_from_unix(errno);
5378 buffer[link_len] = 0;
5379 status = srvstr_push(dstart, flags2,
5381 PTR_DIFF(dend, pdata),
5382 STR_TERMINATE, &len);
5383 if (!NT_STATUS_IS_OK(status)) {
5387 data_size = PTR_DIFF(pdata,(*ppdata));
5392 #if defined(HAVE_POSIX_ACLS)
5393 case SMB_QUERY_POSIX_ACL:
5395 SMB_ACL_T file_acl = NULL;
5396 SMB_ACL_T def_acl = NULL;
5397 uint16_t num_file_acls = 0;
5398 uint16_t num_def_acls = 0;
5400 status = refuse_symlink(conn,
5402 smb_fname->base_name);
5403 if (!NT_STATUS_IS_OK(status)) {
5407 if (fsp && fsp->fh->fd != -1) {
5408 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5412 SMB_VFS_SYS_ACL_GET_FILE(conn,
5413 smb_fname->base_name,
5414 SMB_ACL_TYPE_ACCESS,
5418 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5419 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5420 "not implemented on "
5421 "filesystem containing %s\n",
5422 smb_fname->base_name));
5423 return NT_STATUS_NOT_IMPLEMENTED;
5426 if (S_ISDIR(psbuf->st_ex_mode)) {
5427 if (fsp && fsp->is_directory) {
5429 SMB_VFS_SYS_ACL_GET_FILE(
5431 fsp->fsp_name->base_name,
5432 SMB_ACL_TYPE_DEFAULT,
5436 SMB_VFS_SYS_ACL_GET_FILE(
5438 smb_fname->base_name,
5439 SMB_ACL_TYPE_DEFAULT,
5442 def_acl = free_empty_sys_acl(conn, def_acl);
5445 num_file_acls = count_acl_entries(conn, file_acl);
5446 num_def_acls = count_acl_entries(conn, def_acl);
5448 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5449 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5451 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5452 SMB_POSIX_ACL_HEADER_SIZE) ));
5454 TALLOC_FREE(file_acl);
5457 TALLOC_FREE(def_acl);
5459 return NT_STATUS_BUFFER_TOO_SMALL;
5462 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5463 SSVAL(pdata,2,num_file_acls);
5464 SSVAL(pdata,4,num_def_acls);
5465 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5467 TALLOC_FREE(file_acl);
5470 TALLOC_FREE(def_acl);
5472 return NT_STATUS_INTERNAL_ERROR;
5474 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5476 TALLOC_FREE(file_acl);
5479 TALLOC_FREE(def_acl);
5481 return NT_STATUS_INTERNAL_ERROR;
5485 TALLOC_FREE(file_acl);
5488 TALLOC_FREE(def_acl);
5490 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5496 case SMB_QUERY_POSIX_LOCK:
5501 enum brl_type lock_type;
5503 /* We need an open file with a real fd for this. */
5504 if (!fsp || fsp->fh->fd == -1) {
5505 return NT_STATUS_INVALID_LEVEL;
5508 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5509 return NT_STATUS_INVALID_PARAMETER;
5512 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5513 case POSIX_LOCK_TYPE_READ:
5514 lock_type = READ_LOCK;
5516 case POSIX_LOCK_TYPE_WRITE:
5517 lock_type = WRITE_LOCK;
5519 case POSIX_LOCK_TYPE_UNLOCK:
5521 /* There's no point in asking for an unlock... */
5522 return NT_STATUS_INVALID_PARAMETER;
5525 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5526 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5527 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5529 status = query_lock(fsp,
5536 if (ERROR_WAS_LOCK_DENIED(status)) {
5537 /* Here we need to report who has it locked... */
5538 data_size = POSIX_LOCK_DATA_SIZE;
5540 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5541 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5542 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5543 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5544 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5546 } else if (NT_STATUS_IS_OK(status)) {
5547 /* For success we just return a copy of what we sent
5548 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5549 data_size = POSIX_LOCK_DATA_SIZE;
5550 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5551 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5559 return NT_STATUS_INVALID_LEVEL;
5562 *pdata_size = data_size;
5563 return NT_STATUS_OK;
5566 /****************************************************************************
5567 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5568 file name or file id).
5569 ****************************************************************************/
5571 static void call_trans2qfilepathinfo(connection_struct *conn,
5572 struct smb_request *req,
5573 unsigned int tran_call,
5574 char **pparams, int total_params,
5575 char **ppdata, int total_data,
5576 unsigned int max_data_bytes)
5578 char *params = *pparams;
5579 char *pdata = *ppdata;
5580 uint16_t info_level;
5581 unsigned int data_size = 0;
5582 unsigned int param_size = 2;
5583 struct smb_filename *smb_fname = NULL;
5584 bool delete_pending = False;
5585 struct timespec write_time_ts;
5586 files_struct *fsp = NULL;
5587 struct file_id fileid;
5588 struct ea_list *ea_list = NULL;
5589 int lock_data_count = 0;
5590 char *lock_data = NULL;
5591 size_t fixed_portion;
5592 NTSTATUS status = NT_STATUS_OK;
5595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5599 ZERO_STRUCT(write_time_ts);
5601 if (tran_call == TRANSACT2_QFILEINFO) {
5602 if (total_params < 4) {
5603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5608 call_trans2qpipeinfo(conn, req, tran_call,
5609 pparams, total_params,
5615 fsp = file_fsp(req, SVAL(params,0));
5616 info_level = SVAL(params,2);
5618 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5620 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5621 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5625 /* Initial check for valid fsp ptr. */
5626 if (!check_fsp_open(conn, req, fsp)) {
5630 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5631 if (smb_fname == NULL) {
5632 reply_nterror(req, NT_STATUS_NO_MEMORY);
5636 if(fsp->fake_file_handle) {
5638 * This is actually for the QUOTA_FAKE_FILE --metze
5641 /* We know this name is ok, it's already passed the checks. */
5643 } else if(fsp->fh->fd == -1) {
5645 * This is actually a QFILEINFO on a directory
5646 * handle (returned from an NT SMB). NT5.0 seems
5647 * to do this call. JRA.
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 "
5656 smb_fname_str_dbg(smb_fname),
5659 map_nt_error_from_unix(errno));
5662 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5663 DEBUG(3,("call_trans2qfilepathinfo: "
5664 "SMB_VFS_STAT of %s failed (%s)\n",
5665 smb_fname_str_dbg(smb_fname),
5668 map_nt_error_from_unix(errno));
5672 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5673 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5676 * Original code - this is an open file.
5678 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5679 DEBUG(3, ("fstat of %s failed (%s)\n",
5680 fsp_fnum_dbg(fsp), strerror(errno)));
5682 map_nt_error_from_unix(errno));
5685 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5686 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5692 uint32_t ucf_flags = (req->posix_pathnames ?
5693 UCF_POSIX_PATHNAMES : 0);
5696 if (total_params < 7) {
5697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5701 info_level = SVAL(params,0);
5703 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5705 if (INFO_LEVEL_IS_UNIX(info_level)) {
5706 if (!lp_unix_extensions()) {
5707 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5710 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5711 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5712 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5713 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5717 if (req->posix_pathnames) {
5718 srvstr_get_path_posix(req,
5727 srvstr_get_path(req,
5736 if (!NT_STATUS_IS_OK(status)) {
5737 reply_nterror(req, status);
5741 status = filename_convert(req,
5743 req->flags2 & FLAGS2_DFS_PATHNAMES,
5748 if (!NT_STATUS_IS_OK(status)) {
5749 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5750 reply_botherror(req,
5751 NT_STATUS_PATH_NOT_COVERED,
5752 ERRSRV, ERRbadpath);
5755 reply_nterror(req, status);
5759 /* If this is a stream, check if there is a delete_pending. */
5760 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5761 && is_ntfs_stream_smb_fname(smb_fname)) {
5762 struct smb_filename *smb_fname_base;
5764 /* Create an smb_filename with stream_name == NULL. */
5765 smb_fname_base = synthetic_smb_fname(
5766 talloc_tos(), smb_fname->base_name,
5768 if (smb_fname_base == NULL) {
5769 reply_nterror(req, NT_STATUS_NO_MEMORY);
5773 if (INFO_LEVEL_IS_UNIX(info_level)) {
5774 /* Always do lstat for UNIX calls. */
5775 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5776 DEBUG(3,("call_trans2qfilepathinfo: "
5777 "SMB_VFS_LSTAT of %s failed "
5779 smb_fname_str_dbg(smb_fname_base),
5781 TALLOC_FREE(smb_fname_base);
5783 map_nt_error_from_unix(errno));
5787 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5788 DEBUG(3,("call_trans2qfilepathinfo: "
5789 "fileinfo of %s failed "
5791 smb_fname_str_dbg(smb_fname_base),
5793 TALLOC_FREE(smb_fname_base);
5795 map_nt_error_from_unix(errno));
5800 status = file_name_hash(conn,
5801 smb_fname_str_dbg(smb_fname_base),
5803 if (!NT_STATUS_IS_OK(status)) {
5804 TALLOC_FREE(smb_fname_base);
5805 reply_nterror(req, status);
5809 fileid = vfs_file_id_from_sbuf(conn,
5810 &smb_fname_base->st);
5811 TALLOC_FREE(smb_fname_base);
5812 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5813 if (delete_pending) {
5814 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5819 if (INFO_LEVEL_IS_UNIX(info_level)) {
5820 /* Always do lstat for UNIX calls. */
5821 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5822 DEBUG(3,("call_trans2qfilepathinfo: "
5823 "SMB_VFS_LSTAT of %s failed (%s)\n",
5824 smb_fname_str_dbg(smb_fname),
5827 map_nt_error_from_unix(errno));
5832 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5833 DEBUG(3,("call_trans2qfilepathinfo: "
5834 "SMB_VFS_STAT of %s failed (%s)\n",
5835 smb_fname_str_dbg(smb_fname),
5838 map_nt_error_from_unix(errno));
5843 status = file_name_hash(conn,
5844 smb_fname_str_dbg(smb_fname),
5846 if (!NT_STATUS_IS_OK(status)) {
5847 reply_nterror(req, status);
5851 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5852 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5853 if (delete_pending) {
5854 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5859 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5860 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5862 info_level,tran_call,total_data));
5864 /* Pull out any data sent here before we realloc. */
5865 switch (info_level) {
5866 case SMB_INFO_QUERY_EAS_FROM_LIST:
5868 /* Pull any EA list from the data portion. */
5871 if (total_data < 4) {
5873 req, NT_STATUS_INVALID_PARAMETER);
5876 ea_size = IVAL(pdata,0);
5878 if (total_data > 0 && ea_size != total_data) {
5879 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5880 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5882 req, NT_STATUS_INVALID_PARAMETER);
5886 if (!lp_ea_support(SNUM(conn))) {
5887 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5891 /* Pull out the list of names. */
5892 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5895 req, NT_STATUS_INVALID_PARAMETER);
5901 case SMB_QUERY_POSIX_LOCK:
5903 if (fsp == NULL || fsp->fh->fd == -1) {
5904 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5908 if (total_data != POSIX_LOCK_DATA_SIZE) {
5910 req, NT_STATUS_INVALID_PARAMETER);
5914 /* Copy the lock range data. */
5915 lock_data = (char *)talloc_memdup(
5916 req, pdata, total_data);
5918 reply_nterror(req, NT_STATUS_NO_MEMORY);
5921 lock_data_count = total_data;
5927 *pparams = (char *)SMB_REALLOC(*pparams,2);
5928 if (*pparams == NULL) {
5929 reply_nterror(req, NT_STATUS_NO_MEMORY);
5936 * draft-leach-cifs-v1-spec-02.txt
5937 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5940 * The requested information is placed in the Data portion of the
5941 * transaction response. For the information levels greater than 0x100,
5942 * the transaction response has 1 parameter word which should be
5943 * ignored by the client.
5945 * However Windows only follows this rule for the IS_NAME_VALID call.
5947 switch (info_level) {
5948 case SMB_INFO_IS_NAME_VALID:
5953 if ((info_level & 0xFF00) == 0xFF00) {
5955 * We use levels that start with 0xFF00
5956 * internally to represent SMB2 specific levels
5958 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5962 status = smbd_do_qfilepathinfo(conn, req, info_level,
5964 delete_pending, write_time_ts,
5966 lock_data_count, lock_data,
5967 req->flags2, max_data_bytes,
5969 ppdata, &data_size);
5970 if (!NT_STATUS_IS_OK(status)) {
5971 reply_nterror(req, status);
5974 if (fixed_portion > max_data_bytes) {
5975 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5979 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5985 /****************************************************************************
5986 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5988 ****************************************************************************/
5990 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5991 connection_struct *conn,
5992 struct smb_request *req,
5993 bool overwrite_if_exists,
5994 const struct smb_filename *smb_fname_old,
5995 struct smb_filename *smb_fname_new)
5997 NTSTATUS status = NT_STATUS_OK;
5999 /* source must already exist. */
6000 if (!VALID_STAT(smb_fname_old->st)) {
6001 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6004 if (VALID_STAT(smb_fname_new->st)) {
6005 if (overwrite_if_exists) {
6006 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6007 return NT_STATUS_FILE_IS_A_DIRECTORY;
6009 status = unlink_internals(conn,
6011 FILE_ATTRIBUTE_NORMAL,
6014 if (!NT_STATUS_IS_OK(status)) {
6018 /* Disallow if newname already exists. */
6019 return NT_STATUS_OBJECT_NAME_COLLISION;
6023 /* No links from a directory. */
6024 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6025 return NT_STATUS_FILE_IS_A_DIRECTORY;
6028 /* Setting a hardlink to/from a stream isn't currently supported. */
6029 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6030 is_ntfs_stream_smb_fname(smb_fname_new)) {
6031 return NT_STATUS_INVALID_PARAMETER;
6034 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6035 smb_fname_old->base_name, smb_fname_new->base_name));
6037 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
6038 smb_fname_new->base_name) != 0) {
6039 status = map_nt_error_from_unix(errno);
6040 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6041 nt_errstr(status), smb_fname_old->base_name,
6042 smb_fname_new->base_name));
6047 /****************************************************************************
6048 Deal with setting the time from any of the setfilepathinfo functions.
6049 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6050 calling this function.
6051 ****************************************************************************/
6053 NTSTATUS smb_set_file_time(connection_struct *conn,
6055 const struct smb_filename *smb_fname,
6056 struct smb_file_time *ft,
6057 bool setting_write_time)
6059 struct smb_filename smb_fname_base;
6061 FILE_NOTIFY_CHANGE_LAST_ACCESS
6062 |FILE_NOTIFY_CHANGE_LAST_WRITE
6063 |FILE_NOTIFY_CHANGE_CREATION;
6065 if (!VALID_STAT(smb_fname->st)) {
6066 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6069 /* get some defaults (no modifications) if any info is zero or -1. */
6070 if (null_timespec(ft->create_time)) {
6071 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6074 if (null_timespec(ft->atime)) {
6075 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6078 if (null_timespec(ft->mtime)) {
6079 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6082 if (!setting_write_time) {
6083 /* ft->mtime comes from change time, not write time. */
6084 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6087 /* Ensure the resolution is the correct for
6088 * what we can store on this filesystem. */
6090 round_timespec(conn->ts_res, &ft->create_time);
6091 round_timespec(conn->ts_res, &ft->ctime);
6092 round_timespec(conn->ts_res, &ft->atime);
6093 round_timespec(conn->ts_res, &ft->mtime);
6095 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6096 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6097 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6098 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6099 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6100 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6101 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6102 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6104 if (setting_write_time) {
6106 * This was a Windows setfileinfo on an open file.
6107 * NT does this a lot. We also need to
6108 * set the time here, as it can be read by
6109 * FindFirst/FindNext and with the patch for bug #2045
6110 * in smbd/fileio.c it ensures that this timestamp is
6111 * kept sticky even after a write. We save the request
6112 * away and will set it on file close and after a write. JRA.
6115 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6116 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6119 if (fsp->base_fsp) {
6120 set_sticky_write_time_fsp(fsp->base_fsp,
6123 set_sticky_write_time_fsp(fsp, ft->mtime);
6126 set_sticky_write_time_path(
6127 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6132 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6134 /* Always call ntimes on the base, even if a stream was passed in. */
6135 smb_fname_base = *smb_fname;
6136 smb_fname_base.stream_name = NULL;
6138 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6139 return map_nt_error_from_unix(errno);
6142 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6143 smb_fname->base_name);
6144 return NT_STATUS_OK;
6147 /****************************************************************************
6148 Deal with setting the dosmode from any of the setfilepathinfo functions.
6149 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6150 done before calling this function.
6151 ****************************************************************************/
6153 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6154 const struct smb_filename *smb_fname,
6157 struct smb_filename *smb_fname_base;
6160 if (!VALID_STAT(smb_fname->st)) {
6161 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6164 /* Always operate on the base_name, even if a stream was passed in. */
6165 smb_fname_base = synthetic_smb_fname(
6166 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
6167 if (smb_fname_base == NULL) {
6168 return NT_STATUS_NO_MEMORY;
6172 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6173 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6175 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6179 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6181 /* check the mode isn't different, before changing it */
6182 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6183 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6184 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6185 (unsigned int)dosmode));
6187 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6189 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6191 smb_fname_str_dbg(smb_fname_base),
6193 status = map_nt_error_from_unix(errno);
6197 status = NT_STATUS_OK;
6199 TALLOC_FREE(smb_fname_base);
6203 /****************************************************************************
6204 Deal with setting the size from any of the setfilepathinfo functions.
6205 ****************************************************************************/
6207 static NTSTATUS smb_set_file_size(connection_struct *conn,
6208 struct smb_request *req,
6210 const struct smb_filename *smb_fname,
6211 const SMB_STRUCT_STAT *psbuf,
6213 bool fail_after_createfile)
6215 NTSTATUS status = NT_STATUS_OK;
6216 struct smb_filename *smb_fname_tmp = NULL;
6217 files_struct *new_fsp = NULL;
6219 if (!VALID_STAT(*psbuf)) {
6220 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6223 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6225 if (size == get_file_size_stat(psbuf)) {
6226 return NT_STATUS_OK;
6229 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6230 smb_fname_str_dbg(smb_fname), (double)size));
6232 if (fsp && fsp->fh->fd != -1) {
6233 /* Handle based call. */
6234 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6235 return NT_STATUS_ACCESS_DENIED;
6238 if (vfs_set_filelen(fsp, size) == -1) {
6239 return map_nt_error_from_unix(errno);
6241 trigger_write_time_update_immediate(fsp);
6242 return NT_STATUS_OK;
6245 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6246 if (smb_fname_tmp == NULL) {
6247 return NT_STATUS_NO_MEMORY;
6250 smb_fname_tmp->st = *psbuf;
6252 status = SMB_VFS_CREATE_FILE(
6255 0, /* root_dir_fid */
6256 smb_fname_tmp, /* fname */
6257 FILE_WRITE_DATA, /* access_mask */
6258 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6260 FILE_OPEN, /* create_disposition*/
6261 0, /* create_options */
6262 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6263 0, /* oplock_request */
6265 0, /* allocation_size */
6266 0, /* private_flags */
6269 &new_fsp, /* result */
6271 NULL, NULL); /* create context */
6273 TALLOC_FREE(smb_fname_tmp);
6275 if (!NT_STATUS_IS_OK(status)) {
6276 /* NB. We check for open_was_deferred in the caller. */
6280 /* See RAW-SFILEINFO-END-OF-FILE */
6281 if (fail_after_createfile) {
6282 close_file(req, new_fsp,NORMAL_CLOSE);
6283 return NT_STATUS_INVALID_LEVEL;
6286 if (vfs_set_filelen(new_fsp, size) == -1) {
6287 status = map_nt_error_from_unix(errno);
6288 close_file(req, new_fsp,NORMAL_CLOSE);
6292 trigger_write_time_update_immediate(new_fsp);
6293 close_file(req, new_fsp,NORMAL_CLOSE);
6294 return NT_STATUS_OK;
6297 /****************************************************************************
6298 Deal with SMB_INFO_SET_EA.
6299 ****************************************************************************/
6301 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6305 const struct smb_filename *smb_fname)
6307 struct ea_list *ea_list = NULL;
6308 TALLOC_CTX *ctx = NULL;
6309 NTSTATUS status = NT_STATUS_OK;
6311 if (total_data < 10) {
6313 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6314 length. They seem to have no effect. Bug #3212. JRA */
6316 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6317 /* We're done. We only get EA info in this call. */
6318 return NT_STATUS_OK;
6321 return NT_STATUS_INVALID_PARAMETER;
6324 if (IVAL(pdata,0) > total_data) {
6325 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6326 IVAL(pdata,0), (unsigned int)total_data));
6327 return NT_STATUS_INVALID_PARAMETER;
6331 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6333 return NT_STATUS_INVALID_PARAMETER;
6336 status = set_ea(conn, fsp, smb_fname, ea_list);
6341 /****************************************************************************
6342 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6343 ****************************************************************************/
6345 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6350 struct ea_list *ea_list = NULL;
6354 return NT_STATUS_INVALID_HANDLE;
6357 if (!lp_ea_support(SNUM(conn))) {
6358 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6359 "EA's not supported.\n",
6360 (unsigned int)total_data));
6361 return NT_STATUS_EAS_NOT_SUPPORTED;
6364 if (total_data < 10) {
6365 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6367 (unsigned int)total_data));
6368 return NT_STATUS_INVALID_PARAMETER;
6371 ea_list = read_nttrans_ea_list(talloc_tos(),
6376 return NT_STATUS_INVALID_PARAMETER;
6379 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6381 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6382 smb_fname_str_dbg(fsp->fsp_name),
6383 nt_errstr(status) ));
6389 /****************************************************************************
6390 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6391 ****************************************************************************/
6393 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6397 struct smb_filename *smb_fname)
6399 NTSTATUS status = NT_STATUS_OK;
6400 bool delete_on_close;
6401 uint32_t dosmode = 0;
6403 if (total_data < 1) {
6404 return NT_STATUS_INVALID_PARAMETER;
6408 return NT_STATUS_INVALID_HANDLE;
6411 delete_on_close = (CVAL(pdata,0) ? True : False);
6412 dosmode = dos_mode(conn, smb_fname);
6414 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6415 "delete_on_close = %u\n",
6416 smb_fname_str_dbg(smb_fname),
6417 (unsigned int)dosmode,
6418 (unsigned int)delete_on_close ));
6420 if (delete_on_close) {
6421 status = can_set_delete_on_close(fsp, dosmode);
6422 if (!NT_STATUS_IS_OK(status)) {
6427 /* The set is across all open files on this dev/inode pair. */
6428 if (!set_delete_on_close(fsp, delete_on_close,
6429 conn->session_info->security_token,
6430 conn->session_info->unix_token)) {
6431 return NT_STATUS_ACCESS_DENIED;
6433 return NT_STATUS_OK;
6436 /****************************************************************************
6437 Deal with SMB_FILE_POSITION_INFORMATION.
6438 ****************************************************************************/
6440 static NTSTATUS smb_file_position_information(connection_struct *conn,
6445 uint64_t position_information;
6447 if (total_data < 8) {
6448 return NT_STATUS_INVALID_PARAMETER;
6452 /* Ignore on pathname based set. */
6453 return NT_STATUS_OK;
6456 position_information = (uint64_t)IVAL(pdata,0);
6457 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6459 DEBUG(10,("smb_file_position_information: Set file position "
6460 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6461 (double)position_information));
6462 fsp->fh->position_information = position_information;
6463 return NT_STATUS_OK;
6466 /****************************************************************************
6467 Deal with SMB_FILE_MODE_INFORMATION.
6468 ****************************************************************************/
6470 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6476 if (total_data < 4) {
6477 return NT_STATUS_INVALID_PARAMETER;
6479 mode = IVAL(pdata,0);
6480 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6481 return NT_STATUS_INVALID_PARAMETER;
6483 return NT_STATUS_OK;
6486 /****************************************************************************
6487 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6488 ****************************************************************************/
6490 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6491 struct smb_request *req,
6494 const struct smb_filename *smb_fname)
6496 char *link_target = NULL;
6497 const char *newname = smb_fname->base_name;
6498 TALLOC_CTX *ctx = talloc_tos();
6500 /* Set a symbolic link. */
6501 /* Don't allow this if follow links is false. */
6503 if (total_data == 0) {
6504 return NT_STATUS_INVALID_PARAMETER;
6507 if (!lp_follow_symlinks(SNUM(conn))) {
6508 return NT_STATUS_ACCESS_DENIED;
6511 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6512 total_data, STR_TERMINATE);
6515 return NT_STATUS_INVALID_PARAMETER;
6518 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6519 newname, link_target ));
6521 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6522 return map_nt_error_from_unix(errno);
6525 return NT_STATUS_OK;
6528 /****************************************************************************
6529 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6530 ****************************************************************************/
6532 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6533 struct smb_request *req,
6534 const char *pdata, int total_data,
6535 struct smb_filename *smb_fname_new)
6537 char *oldname = NULL;
6538 struct smb_filename *smb_fname_old = NULL;
6539 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6540 TALLOC_CTX *ctx = talloc_tos();
6541 NTSTATUS status = NT_STATUS_OK;
6543 /* Set a hard link. */
6544 if (total_data == 0) {
6545 return NT_STATUS_INVALID_PARAMETER;
6548 if (req->posix_pathnames) {
6549 srvstr_get_path_posix(ctx,
6558 srvstr_get_path(ctx,
6567 if (!NT_STATUS_IS_OK(status)) {
6571 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6572 smb_fname_str_dbg(smb_fname_new), oldname));
6574 status = filename_convert(ctx,
6576 req->flags2 & FLAGS2_DFS_PATHNAMES,
6581 if (!NT_STATUS_IS_OK(status)) {
6585 return hardlink_internals(ctx, conn, req, false,
6586 smb_fname_old, smb_fname_new);
6589 /****************************************************************************
6590 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6591 ****************************************************************************/
6593 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6594 struct smb_request *req,
6598 struct smb_filename *smb_fname_src)
6602 char *newname = NULL;
6603 struct smb_filename *smb_fname_dst = NULL;
6604 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6605 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6606 NTSTATUS status = NT_STATUS_OK;
6607 TALLOC_CTX *ctx = talloc_tos();
6610 return NT_STATUS_INVALID_HANDLE;
6613 if (total_data < 20) {
6614 return NT_STATUS_INVALID_PARAMETER;
6617 overwrite = (CVAL(pdata,0) ? True : False);
6618 len = IVAL(pdata,16);
6620 if (len > (total_data - 20) || (len == 0)) {
6621 return NT_STATUS_INVALID_PARAMETER;
6624 if (req->posix_pathnames) {
6625 srvstr_get_path_posix(ctx,
6634 srvstr_get_path(ctx,
6643 if (!NT_STATUS_IS_OK(status)) {
6647 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6650 status = filename_convert(ctx,
6652 req->flags2 & FLAGS2_DFS_PATHNAMES,
6657 if (!NT_STATUS_IS_OK(status)) {
6661 if (fsp->base_fsp) {
6662 /* newname must be a stream name. */
6663 if (newname[0] != ':') {
6664 return NT_STATUS_NOT_SUPPORTED;
6667 /* Create an smb_fname to call rename_internals_fsp() with. */
6668 smb_fname_dst = synthetic_smb_fname(
6669 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6671 if (smb_fname_dst == NULL) {
6672 status = NT_STATUS_NO_MEMORY;
6677 * Set the original last component, since
6678 * rename_internals_fsp() requires it.
6680 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6682 if (smb_fname_dst->original_lcomp == NULL) {
6683 status = NT_STATUS_NO_MEMORY;
6689 DEBUG(10,("smb2_file_rename_information: "
6690 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6691 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6692 smb_fname_str_dbg(smb_fname_dst)));
6693 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6694 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6698 TALLOC_FREE(smb_fname_dst);
6702 static NTSTATUS smb_file_link_information(connection_struct *conn,
6703 struct smb_request *req,
6707 struct smb_filename *smb_fname_src)
6711 char *newname = NULL;
6712 struct smb_filename *smb_fname_dst = NULL;
6713 NTSTATUS status = NT_STATUS_OK;
6714 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6715 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6716 TALLOC_CTX *ctx = talloc_tos();
6719 return NT_STATUS_INVALID_HANDLE;
6722 if (total_data < 20) {
6723 return NT_STATUS_INVALID_PARAMETER;
6726 overwrite = (CVAL(pdata,0) ? true : false);
6727 len = IVAL(pdata,16);
6729 if (len > (total_data - 20) || (len == 0)) {
6730 return NT_STATUS_INVALID_PARAMETER;
6733 if (req->posix_pathnames) {
6734 srvstr_get_path_posix(ctx,
6743 srvstr_get_path(ctx,
6752 if (!NT_STATUS_IS_OK(status)) {
6756 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6759 status = filename_convert(ctx,
6761 req->flags2 & FLAGS2_DFS_PATHNAMES,
6766 if (!NT_STATUS_IS_OK(status)) {
6770 if (fsp->base_fsp) {
6771 /* No stream names. */
6772 return NT_STATUS_NOT_SUPPORTED;
6775 DEBUG(10,("smb_file_link_information: "
6776 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6777 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6778 smb_fname_str_dbg(smb_fname_dst)));
6779 status = hardlink_internals(ctx,
6786 TALLOC_FREE(smb_fname_dst);
6790 /****************************************************************************
6791 Deal with SMB_FILE_RENAME_INFORMATION.
6792 ****************************************************************************/
6794 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6795 struct smb_request *req,
6799 struct smb_filename *smb_fname_src)
6804 char *newname = NULL;
6805 struct smb_filename *smb_fname_dst = NULL;
6806 bool dest_has_wcard = False;
6807 NTSTATUS status = NT_STATUS_OK;
6809 TALLOC_CTX *ctx = talloc_tos();
6811 if (total_data < 13) {
6812 return NT_STATUS_INVALID_PARAMETER;
6815 overwrite = (CVAL(pdata,0) ? True : False);
6816 root_fid = IVAL(pdata,4);
6817 len = IVAL(pdata,8);
6819 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6820 return NT_STATUS_INVALID_PARAMETER;
6823 if (req->posix_pathnames) {
6824 srvstr_get_path_wcard_posix(ctx,
6834 srvstr_get_path_wcard(ctx,
6844 if (!NT_STATUS_IS_OK(status)) {
6848 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6851 status = resolve_dfspath_wcard(ctx, conn,
6852 req->flags2 & FLAGS2_DFS_PATHNAMES,
6855 !conn->sconn->using_smb2,
6858 if (!NT_STATUS_IS_OK(status)) {
6862 /* Check the new name has no '/' characters. */
6863 if (strchr_m(newname, '/')) {
6864 return NT_STATUS_NOT_SUPPORTED;
6867 if (fsp && fsp->base_fsp) {
6868 /* newname must be a stream name. */
6869 if (newname[0] != ':') {
6870 return NT_STATUS_NOT_SUPPORTED;
6873 /* Create an smb_fname to call rename_internals_fsp() with. */
6874 smb_fname_dst = synthetic_smb_fname(
6875 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6877 if (smb_fname_dst == NULL) {
6878 status = NT_STATUS_NO_MEMORY;
6883 * Set the original last component, since
6884 * rename_internals_fsp() requires it.
6886 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6888 if (smb_fname_dst->original_lcomp == NULL) {
6889 status = NT_STATUS_NO_MEMORY;
6895 * Build up an smb_fname_dst based on the filename passed in.
6896 * We basically just strip off the last component, and put on
6897 * the newname instead.
6899 char *base_name = NULL;
6901 /* newname must *not* be a stream name. */
6902 if (newname[0] == ':') {
6903 return NT_STATUS_NOT_SUPPORTED;
6907 * Strip off the last component (filename) of the path passed
6910 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6912 return NT_STATUS_NO_MEMORY;
6914 p = strrchr_m(base_name, '/');
6918 base_name = talloc_strdup(ctx, "");
6920 return NT_STATUS_NO_MEMORY;
6923 /* Append the new name. */
6924 base_name = talloc_asprintf_append(base_name,
6928 return NT_STATUS_NO_MEMORY;
6931 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6934 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6937 /* If an error we expect this to be
6938 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6940 if (!NT_STATUS_IS_OK(status)) {
6941 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6945 /* Create an smb_fname to call rename_internals_fsp() */
6946 smb_fname_dst = synthetic_smb_fname(
6947 ctx, base_name, NULL, NULL);
6948 if (smb_fname_dst == NULL) {
6949 status = NT_STATUS_NO_MEMORY;
6956 DEBUG(10,("smb_file_rename_information: "
6957 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6958 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6959 smb_fname_str_dbg(smb_fname_dst)));
6960 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6963 DEBUG(10,("smb_file_rename_information: "
6964 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6965 smb_fname_str_dbg(smb_fname_src),
6966 smb_fname_str_dbg(smb_fname_dst)));
6967 status = rename_internals(ctx, conn, req, smb_fname_src,
6968 smb_fname_dst, 0, overwrite, false,
6970 FILE_WRITE_ATTRIBUTES);
6973 TALLOC_FREE(smb_fname_dst);
6977 /****************************************************************************
6978 Deal with SMB_SET_POSIX_ACL.
6979 ****************************************************************************/
6981 #if defined(HAVE_POSIX_ACLS)
6982 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6986 const struct smb_filename *smb_fname)
6988 uint16_t posix_acl_version;
6989 uint16_t num_file_acls;
6990 uint16_t num_def_acls;
6991 bool valid_file_acls = True;
6992 bool valid_def_acls = True;
6995 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6996 return NT_STATUS_INVALID_PARAMETER;
6998 posix_acl_version = SVAL(pdata,0);
6999 num_file_acls = SVAL(pdata,2);
7000 num_def_acls = SVAL(pdata,4);
7002 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7003 valid_file_acls = False;
7007 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7008 valid_def_acls = False;
7012 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7013 return NT_STATUS_INVALID_PARAMETER;
7016 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7017 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7018 return NT_STATUS_INVALID_PARAMETER;
7021 status = refuse_symlink(conn, fsp, smb_fname->base_name);
7022 if (!NT_STATUS_IS_OK(status)) {
7026 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7027 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7028 (unsigned int)num_file_acls,
7029 (unsigned int)num_def_acls));
7031 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7032 smb_fname->base_name, num_file_acls,
7033 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7034 return map_nt_error_from_unix(errno);
7037 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7038 smb_fname->base_name, &smb_fname->st, num_def_acls,
7039 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7040 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7041 return map_nt_error_from_unix(errno);
7043 return NT_STATUS_OK;
7047 /****************************************************************************
7048 Deal with SMB_SET_POSIX_LOCK.
7049 ****************************************************************************/
7051 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7052 struct smb_request *req,
7060 bool blocking_lock = False;
7061 enum brl_type lock_type;
7063 NTSTATUS status = NT_STATUS_OK;
7065 if (fsp == NULL || fsp->fh->fd == -1) {
7066 return NT_STATUS_INVALID_HANDLE;
7069 if (total_data != POSIX_LOCK_DATA_SIZE) {
7070 return NT_STATUS_INVALID_PARAMETER;
7073 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7074 case POSIX_LOCK_TYPE_READ:
7075 lock_type = READ_LOCK;
7077 case POSIX_LOCK_TYPE_WRITE:
7078 /* Return the right POSIX-mappable error code for files opened read-only. */
7079 if (!fsp->can_write) {
7080 return NT_STATUS_INVALID_HANDLE;
7082 lock_type = WRITE_LOCK;
7084 case POSIX_LOCK_TYPE_UNLOCK:
7085 lock_type = UNLOCK_LOCK;
7088 return NT_STATUS_INVALID_PARAMETER;
7091 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7092 blocking_lock = False;
7093 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7094 blocking_lock = True;
7096 return NT_STATUS_INVALID_PARAMETER;
7099 if (!lp_blocking_locks(SNUM(conn))) {
7100 blocking_lock = False;
7103 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7104 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7105 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7106 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7107 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7109 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7110 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7112 (unsigned int)lock_type,
7113 (unsigned long long)smblctx,
7117 if (lock_type == UNLOCK_LOCK) {
7118 status = do_unlock(req->sconn->msg_ctx,
7125 uint64_t block_smblctx;
7127 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7138 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7140 * A blocking lock was requested. Package up
7141 * this smb into a queued request and push it
7142 * onto the blocking lock queue.
7144 if(push_blocking_lock_request(br_lck,
7147 -1, /* infinite timeout. */
7155 TALLOC_FREE(br_lck);
7159 TALLOC_FREE(br_lck);
7165 /****************************************************************************
7166 Deal with SMB_SET_FILE_BASIC_INFO.
7167 ****************************************************************************/
7169 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7173 const struct smb_filename *smb_fname)
7175 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7176 struct smb_file_time ft;
7177 uint32_t dosmode = 0;
7178 NTSTATUS status = NT_STATUS_OK;
7182 if (total_data < 36) {
7183 return NT_STATUS_INVALID_PARAMETER;
7186 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7187 if (!NT_STATUS_IS_OK(status)) {
7191 /* Set the attributes */
7192 dosmode = IVAL(pdata,32);
7193 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7194 if (!NT_STATUS_IS_OK(status)) {
7199 ft.create_time = interpret_long_date(pdata);
7202 ft.atime = interpret_long_date(pdata+8);
7205 ft.mtime = interpret_long_date(pdata+16);
7208 ft.ctime = interpret_long_date(pdata+24);
7210 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7211 smb_fname_str_dbg(smb_fname)));
7213 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7217 /****************************************************************************
7218 Deal with SMB_INFO_STANDARD.
7219 ****************************************************************************/
7221 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7225 const struct smb_filename *smb_fname)
7228 struct smb_file_time ft;
7232 if (total_data < 12) {
7233 return NT_STATUS_INVALID_PARAMETER;
7237 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7239 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7241 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7243 DEBUG(10,("smb_set_info_standard: file %s\n",
7244 smb_fname_str_dbg(smb_fname)));
7246 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7247 if (!NT_STATUS_IS_OK(status)) {
7251 return smb_set_file_time(conn,
7258 /****************************************************************************
7259 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7260 ****************************************************************************/
7262 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7263 struct smb_request *req,
7267 struct smb_filename *smb_fname)
7269 uint64_t allocation_size = 0;
7270 NTSTATUS status = NT_STATUS_OK;
7271 files_struct *new_fsp = NULL;
7273 if (!VALID_STAT(smb_fname->st)) {
7274 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7277 if (total_data < 8) {
7278 return NT_STATUS_INVALID_PARAMETER;
7281 allocation_size = (uint64_t)IVAL(pdata,0);
7282 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7283 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7284 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7285 (double)allocation_size));
7287 if (allocation_size) {
7288 allocation_size = smb_roundup(conn, allocation_size);
7291 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7292 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7293 (double)allocation_size));
7295 if (fsp && fsp->fh->fd != -1) {
7296 /* Open file handle. */
7297 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7298 return NT_STATUS_ACCESS_DENIED;
7301 /* Only change if needed. */
7302 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7303 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7304 return map_nt_error_from_unix(errno);
7307 /* But always update the time. */
7309 * This is equivalent to a write. Ensure it's seen immediately
7310 * if there are no pending writes.
7312 trigger_write_time_update_immediate(fsp);
7313 return NT_STATUS_OK;
7316 /* Pathname or stat or directory file. */
7317 status = SMB_VFS_CREATE_FILE(
7320 0, /* root_dir_fid */
7321 smb_fname, /* fname */
7322 FILE_WRITE_DATA, /* access_mask */
7323 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7325 FILE_OPEN, /* create_disposition*/
7326 0, /* create_options */
7327 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7328 0, /* oplock_request */
7330 0, /* allocation_size */
7331 0, /* private_flags */
7334 &new_fsp, /* result */
7336 NULL, NULL); /* create context */
7338 if (!NT_STATUS_IS_OK(status)) {
7339 /* NB. We check for open_was_deferred in the caller. */
7343 /* Only change if needed. */
7344 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7345 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7346 status = map_nt_error_from_unix(errno);
7347 close_file(req, new_fsp, NORMAL_CLOSE);
7352 /* Changing the allocation size should set the last mod time. */
7354 * This is equivalent to a write. Ensure it's seen immediately
7355 * if there are no pending writes.
7357 trigger_write_time_update_immediate(new_fsp);
7358 close_file(req, new_fsp, NORMAL_CLOSE);
7359 return NT_STATUS_OK;
7362 /****************************************************************************
7363 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7364 ****************************************************************************/
7366 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7367 struct smb_request *req,
7371 const struct smb_filename *smb_fname,
7372 bool fail_after_createfile)
7376 if (total_data < 8) {
7377 return NT_STATUS_INVALID_PARAMETER;
7380 size = IVAL(pdata,0);
7381 size |= (((off_t)IVAL(pdata,4)) << 32);
7382 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7383 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7386 return smb_set_file_size(conn, req,
7391 fail_after_createfile);
7394 /****************************************************************************
7395 Allow a UNIX info mknod.
7396 ****************************************************************************/
7398 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7401 const struct smb_filename *smb_fname)
7403 uint32_t file_type = IVAL(pdata,56);
7404 #if defined(HAVE_MAKEDEV)
7405 uint32_t dev_major = IVAL(pdata,60);
7406 uint32_t dev_minor = IVAL(pdata,68);
7408 SMB_DEV_T dev = (SMB_DEV_T)0;
7409 uint32_t raw_unixmode = IVAL(pdata,84);
7413 if (total_data < 100) {
7414 return NT_STATUS_INVALID_PARAMETER;
7417 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7418 PERM_NEW_FILE, &unixmode);
7419 if (!NT_STATUS_IS_OK(status)) {
7423 #if defined(HAVE_MAKEDEV)
7424 dev = makedev(dev_major, dev_minor);
7427 switch (file_type) {
7428 #if defined(S_IFIFO)
7429 case UNIX_TYPE_FIFO:
7430 unixmode |= S_IFIFO;
7433 #if defined(S_IFSOCK)
7434 case UNIX_TYPE_SOCKET:
7435 unixmode |= S_IFSOCK;
7438 #if defined(S_IFCHR)
7439 case UNIX_TYPE_CHARDEV:
7440 unixmode |= S_IFCHR;
7443 #if defined(S_IFBLK)
7444 case UNIX_TYPE_BLKDEV:
7445 unixmode |= S_IFBLK;
7449 return NT_STATUS_INVALID_PARAMETER;
7452 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7453 "%.0f mode 0%o for file %s\n", (double)dev,
7454 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7456 /* Ok - do the mknod. */
7457 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7458 return map_nt_error_from_unix(errno);
7461 /* If any of the other "set" calls fail we
7462 * don't want to end up with a half-constructed mknod.
7465 if (lp_inherit_permissions(SNUM(conn))) {
7467 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7469 return NT_STATUS_NO_MEMORY;
7471 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7473 TALLOC_FREE(parent);
7476 return NT_STATUS_OK;
7479 /****************************************************************************
7480 Deal with SMB_SET_FILE_UNIX_BASIC.
7481 ****************************************************************************/
7483 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7484 struct smb_request *req,
7488 const struct smb_filename *smb_fname)
7490 struct smb_file_time ft;
7491 uint32_t raw_unixmode;
7494 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7495 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7496 NTSTATUS status = NT_STATUS_OK;
7497 bool delete_on_fail = False;
7498 enum perm_type ptype;
7499 files_struct *all_fsps = NULL;
7500 bool modify_mtime = true;
7502 struct smb_filename *smb_fname_tmp = NULL;
7503 SMB_STRUCT_STAT sbuf;
7507 if (total_data < 100) {
7508 return NT_STATUS_INVALID_PARAMETER;
7511 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7512 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7513 size=IVAL(pdata,0); /* first 8 Bytes are size */
7514 size |= (((off_t)IVAL(pdata,4)) << 32);
7517 ft.atime = interpret_long_date(pdata+24); /* access_time */
7518 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7519 set_owner = (uid_t)IVAL(pdata,40);
7520 set_grp = (gid_t)IVAL(pdata,48);
7521 raw_unixmode = IVAL(pdata,84);
7523 if (VALID_STAT(smb_fname->st)) {
7524 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7525 ptype = PERM_EXISTING_DIR;
7527 ptype = PERM_EXISTING_FILE;
7530 ptype = PERM_NEW_FILE;
7533 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7535 if (!NT_STATUS_IS_OK(status)) {
7539 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7540 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7541 smb_fname_str_dbg(smb_fname), (double)size,
7542 (unsigned int)set_owner, (unsigned int)set_grp,
7543 (int)raw_unixmode));
7545 sbuf = smb_fname->st;
7547 if (!VALID_STAT(sbuf)) {
7549 * The only valid use of this is to create character and block
7550 * devices, and named pipes. This is deprecated (IMHO) and
7551 * a new info level should be used for mknod. JRA.
7554 status = smb_unix_mknod(conn,
7558 if (!NT_STATUS_IS_OK(status)) {
7562 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7563 if (smb_fname_tmp == NULL) {
7564 return NT_STATUS_NO_MEMORY;
7567 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7568 status = map_nt_error_from_unix(errno);
7569 TALLOC_FREE(smb_fname_tmp);
7570 SMB_VFS_UNLINK(conn, smb_fname);
7574 sbuf = smb_fname_tmp->st;
7575 smb_fname = smb_fname_tmp;
7577 /* Ensure we don't try and change anything else. */
7578 raw_unixmode = SMB_MODE_NO_CHANGE;
7579 size = get_file_size_stat(&sbuf);
7580 ft.atime = sbuf.st_ex_atime;
7581 ft.mtime = sbuf.st_ex_mtime;
7583 * We continue here as we might want to change the
7586 delete_on_fail = True;
7590 /* Horrible backwards compatibility hack as an old server bug
7591 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7595 size = get_file_size_stat(&sbuf);
7600 * Deal with the UNIX specific mode set.
7603 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7606 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7607 "setting mode 0%o for file %s\n",
7608 (unsigned int)unixmode,
7609 smb_fname_str_dbg(smb_fname)));
7610 if (fsp && fsp->fh->fd != -1) {
7611 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7613 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7616 return map_nt_error_from_unix(errno);
7621 * Deal with the UNIX specific uid set.
7624 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7625 (sbuf.st_ex_uid != set_owner)) {
7628 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7629 "changing owner %u for path %s\n",
7630 (unsigned int)set_owner,
7631 smb_fname_str_dbg(smb_fname)));
7633 if (fsp && fsp->fh->fd != -1) {
7634 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7637 * UNIX extensions calls must always operate
7640 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7641 set_owner, (gid_t)-1);
7645 status = map_nt_error_from_unix(errno);
7646 if (delete_on_fail) {
7647 SMB_VFS_UNLINK(conn, smb_fname);
7654 * Deal with the UNIX specific gid set.
7657 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7658 (sbuf.st_ex_gid != set_grp)) {
7661 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7662 "changing group %u for file %s\n",
7663 (unsigned int)set_owner,
7664 smb_fname_str_dbg(smb_fname)));
7665 if (fsp && fsp->fh->fd != -1) {
7666 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7669 * UNIX extensions calls must always operate
7672 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7676 status = map_nt_error_from_unix(errno);
7677 if (delete_on_fail) {
7678 SMB_VFS_UNLINK(conn, smb_fname);
7684 /* Deal with any size changes. */
7686 status = smb_set_file_size(conn, req,
7692 if (!NT_STATUS_IS_OK(status)) {
7696 /* Deal with any time changes. */
7697 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7698 /* No change, don't cancel anything. */
7702 id = vfs_file_id_from_sbuf(conn, &sbuf);
7703 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7704 all_fsps = file_find_di_next(all_fsps)) {
7706 * We're setting the time explicitly for UNIX.
7707 * Cancel any pending changes over all handles.
7709 all_fsps->update_write_time_on_close = false;
7710 TALLOC_FREE(all_fsps->update_write_time_event);
7714 * Override the "setting_write_time"
7715 * parameter here as it almost does what
7716 * we need. Just remember if we modified
7717 * mtime and send the notify ourselves.
7719 if (null_timespec(ft.mtime)) {
7720 modify_mtime = false;
7723 status = smb_set_file_time(conn,
7729 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7730 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7735 /****************************************************************************
7736 Deal with SMB_SET_FILE_UNIX_INFO2.
7737 ****************************************************************************/
7739 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7740 struct smb_request *req,
7744 const struct smb_filename *smb_fname)
7747 uint32_t smb_fflags;
7750 if (total_data < 116) {
7751 return NT_STATUS_INVALID_PARAMETER;
7754 /* Start by setting all the fields that are common between UNIX_BASIC
7757 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7759 if (!NT_STATUS_IS_OK(status)) {
7763 smb_fflags = IVAL(pdata, 108);
7764 smb_fmask = IVAL(pdata, 112);
7766 /* NB: We should only attempt to alter the file flags if the client
7767 * sends a non-zero mask.
7769 if (smb_fmask != 0) {
7770 int stat_fflags = 0;
7772 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7773 smb_fmask, &stat_fflags)) {
7774 /* Client asked to alter a flag we don't understand. */
7775 return NT_STATUS_INVALID_PARAMETER;
7778 if (fsp && fsp->fh->fd != -1) {
7779 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7780 return NT_STATUS_NOT_SUPPORTED;
7782 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7783 stat_fflags) != 0) {
7784 return map_nt_error_from_unix(errno);
7789 /* XXX: need to add support for changing the create_time here. You
7790 * can do this for paths on Darwin with setattrlist(2). The right way
7791 * to hook this up is probably by extending the VFS utimes interface.
7794 return NT_STATUS_OK;
7797 /****************************************************************************
7798 Create a directory with POSIX semantics.
7799 ****************************************************************************/
7801 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7802 struct smb_request *req,
7805 struct smb_filename *smb_fname,
7806 int *pdata_return_size)
7808 NTSTATUS status = NT_STATUS_OK;
7809 uint32_t raw_unixmode = 0;
7810 uint32_t mod_unixmode = 0;
7811 mode_t unixmode = (mode_t)0;
7812 files_struct *fsp = NULL;
7813 uint16_t info_level_return = 0;
7815 char *pdata = *ppdata;
7817 if (total_data < 18) {
7818 return NT_STATUS_INVALID_PARAMETER;
7821 raw_unixmode = IVAL(pdata,8);
7822 /* Next 4 bytes are not yet defined. */
7824 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7825 PERM_NEW_DIR, &unixmode);
7826 if (!NT_STATUS_IS_OK(status)) {
7830 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7832 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7833 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7835 status = SMB_VFS_CREATE_FILE(
7838 0, /* root_dir_fid */
7839 smb_fname, /* fname */
7840 FILE_READ_ATTRIBUTES, /* access_mask */
7841 FILE_SHARE_NONE, /* share_access */
7842 FILE_CREATE, /* create_disposition*/
7843 FILE_DIRECTORY_FILE, /* create_options */
7844 mod_unixmode, /* file_attributes */
7845 0, /* oplock_request */
7847 0, /* allocation_size */
7848 0, /* private_flags */
7853 NULL, NULL); /* create context */
7855 if (NT_STATUS_IS_OK(status)) {
7856 close_file(req, fsp, NORMAL_CLOSE);
7859 info_level_return = SVAL(pdata,16);
7861 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7862 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7863 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7864 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7866 *pdata_return_size = 12;
7869 /* Realloc the data size */
7870 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7871 if (*ppdata == NULL) {
7872 *pdata_return_size = 0;
7873 return NT_STATUS_NO_MEMORY;
7877 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7878 SSVAL(pdata,2,0); /* No fnum. */
7879 SIVAL(pdata,4,info); /* Was directory created. */
7881 switch (info_level_return) {
7882 case SMB_QUERY_FILE_UNIX_BASIC:
7883 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7884 SSVAL(pdata,10,0); /* Padding. */
7885 store_file_unix_basic(conn, pdata + 12, fsp,
7888 case SMB_QUERY_FILE_UNIX_INFO2:
7889 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7890 SSVAL(pdata,10,0); /* Padding. */
7891 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7895 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7896 SSVAL(pdata,10,0); /* Padding. */
7903 /****************************************************************************
7904 Open/Create a file with POSIX semantics.
7905 ****************************************************************************/
7907 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7908 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7910 static NTSTATUS smb_posix_open(connection_struct *conn,
7911 struct smb_request *req,
7914 struct smb_filename *smb_fname,
7915 int *pdata_return_size)
7917 bool extended_oplock_granted = False;
7918 char *pdata = *ppdata;
7920 uint32_t wire_open_mode = 0;
7921 uint32_t raw_unixmode = 0;
7922 uint32_t mod_unixmode = 0;
7923 uint32_t create_disp = 0;
7924 uint32_t access_mask = 0;
7925 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
7926 NTSTATUS status = NT_STATUS_OK;
7927 mode_t unixmode = (mode_t)0;
7928 files_struct *fsp = NULL;
7929 int oplock_request = 0;
7931 uint16_t info_level_return = 0;
7933 if (total_data < 18) {
7934 return NT_STATUS_INVALID_PARAMETER;
7937 flags = IVAL(pdata,0);
7938 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7939 if (oplock_request) {
7940 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7943 wire_open_mode = IVAL(pdata,4);
7945 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7946 return smb_posix_mkdir(conn, req,
7953 switch (wire_open_mode & SMB_ACCMODE) {
7955 access_mask = SMB_O_RDONLY_MAPPING;
7958 access_mask = SMB_O_WRONLY_MAPPING;
7961 access_mask = (SMB_O_RDONLY_MAPPING|
7962 SMB_O_WRONLY_MAPPING);
7965 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7966 (unsigned int)wire_open_mode ));
7967 return NT_STATUS_INVALID_PARAMETER;
7970 wire_open_mode &= ~SMB_ACCMODE;
7972 /* First take care of O_CREAT|O_EXCL interactions. */
7973 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7974 case (SMB_O_CREAT | SMB_O_EXCL):
7975 /* File exists fail. File not exist create. */
7976 create_disp = FILE_CREATE;
7979 /* File exists open. File not exist create. */
7980 create_disp = FILE_OPEN_IF;
7983 /* O_EXCL on its own without O_CREAT is undefined.
7984 We deliberately ignore it as some versions of
7985 Linux CIFSFS can send a bare O_EXCL on the
7986 wire which other filesystems in the kernel
7987 ignore. See bug 9519 for details. */
7992 /* File exists open. File not exist fail. */
7993 create_disp = FILE_OPEN;
7996 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7997 (unsigned int)wire_open_mode ));
7998 return NT_STATUS_INVALID_PARAMETER;
8001 /* Next factor in the effects of O_TRUNC. */
8002 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8004 if (wire_open_mode & SMB_O_TRUNC) {
8005 switch (create_disp) {
8007 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8008 /* Leave create_disp alone as
8009 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8011 /* File exists fail. File not exist create. */
8014 /* SMB_O_CREAT | SMB_O_TRUNC */
8015 /* File exists overwrite. File not exist create. */
8016 create_disp = FILE_OVERWRITE_IF;
8020 /* File exists overwrite. File not exist fail. */
8021 create_disp = FILE_OVERWRITE;
8024 /* Cannot get here. */
8025 smb_panic("smb_posix_open: logic error");
8026 return NT_STATUS_INVALID_PARAMETER;
8030 raw_unixmode = IVAL(pdata,8);
8031 /* Next 4 bytes are not yet defined. */
8033 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8034 (VALID_STAT(smb_fname->st) ?
8035 PERM_EXISTING_FILE : PERM_NEW_FILE),
8038 if (!NT_STATUS_IS_OK(status)) {
8042 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8044 if (wire_open_mode & SMB_O_SYNC) {
8045 create_options |= FILE_WRITE_THROUGH;
8047 if (wire_open_mode & SMB_O_APPEND) {
8048 access_mask |= FILE_APPEND_DATA;
8050 if (wire_open_mode & SMB_O_DIRECT) {
8051 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8054 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8055 VALID_STAT_OF_DIR(smb_fname->st)) {
8056 if (access_mask != SMB_O_RDONLY_MAPPING) {
8057 return NT_STATUS_FILE_IS_A_DIRECTORY;
8059 create_options &= ~FILE_NON_DIRECTORY_FILE;
8060 create_options |= FILE_DIRECTORY_FILE;
8063 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8064 smb_fname_str_dbg(smb_fname),
8065 (unsigned int)wire_open_mode,
8066 (unsigned int)unixmode ));
8068 status = SMB_VFS_CREATE_FILE(
8071 0, /* root_dir_fid */
8072 smb_fname, /* fname */
8073 access_mask, /* access_mask */
8074 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8076 create_disp, /* create_disposition*/
8077 create_options, /* create_options */
8078 mod_unixmode, /* file_attributes */
8079 oplock_request, /* oplock_request */
8081 0, /* allocation_size */
8082 0, /* private_flags */
8087 NULL, NULL); /* create context */
8089 if (!NT_STATUS_IS_OK(status)) {
8093 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8094 extended_oplock_granted = True;
8097 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8098 extended_oplock_granted = True;
8101 info_level_return = SVAL(pdata,16);
8103 /* Allocate the correct return size. */
8105 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8106 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8107 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8108 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8110 *pdata_return_size = 12;
8113 /* Realloc the data size */
8114 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8115 if (*ppdata == NULL) {
8116 close_file(req, fsp, ERROR_CLOSE);
8117 *pdata_return_size = 0;
8118 return NT_STATUS_NO_MEMORY;
8122 if (extended_oplock_granted) {
8123 if (flags & REQUEST_BATCH_OPLOCK) {
8124 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8126 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8128 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8129 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8131 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8134 SSVAL(pdata,2,fsp->fnum);
8135 SIVAL(pdata,4,info); /* Was file created etc. */
8137 switch (info_level_return) {
8138 case SMB_QUERY_FILE_UNIX_BASIC:
8139 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8140 SSVAL(pdata,10,0); /* padding. */
8141 store_file_unix_basic(conn, pdata + 12, fsp,
8144 case SMB_QUERY_FILE_UNIX_INFO2:
8145 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8146 SSVAL(pdata,10,0); /* padding. */
8147 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8151 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8152 SSVAL(pdata,10,0); /* padding. */
8155 return NT_STATUS_OK;
8158 /****************************************************************************
8159 Delete a file with POSIX semantics.
8160 ****************************************************************************/
8162 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8163 struct smb_request *req,
8166 struct smb_filename *smb_fname)
8168 NTSTATUS status = NT_STATUS_OK;
8169 files_struct *fsp = NULL;
8173 int create_options = 0;
8175 struct share_mode_lock *lck = NULL;
8177 if (total_data < 2) {
8178 return NT_STATUS_INVALID_PARAMETER;
8181 flags = SVAL(pdata,0);
8183 if (!VALID_STAT(smb_fname->st)) {
8184 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8187 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8188 !VALID_STAT_OF_DIR(smb_fname->st)) {
8189 return NT_STATUS_NOT_A_DIRECTORY;
8192 DEBUG(10,("smb_posix_unlink: %s %s\n",
8193 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8194 smb_fname_str_dbg(smb_fname)));
8196 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8197 create_options |= FILE_DIRECTORY_FILE;
8200 status = SMB_VFS_CREATE_FILE(
8203 0, /* root_dir_fid */
8204 smb_fname, /* fname */
8205 DELETE_ACCESS, /* access_mask */
8206 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8208 FILE_OPEN, /* create_disposition*/
8209 create_options, /* create_options */
8210 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8211 0, /* oplock_request */
8213 0, /* allocation_size */
8214 0, /* private_flags */
8219 NULL, NULL); /* create context */
8221 if (!NT_STATUS_IS_OK(status)) {
8226 * Don't lie to client. If we can't really delete due to
8227 * non-POSIX opens return SHARING_VIOLATION.
8230 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8232 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8233 "lock for file %s\n", fsp_str_dbg(fsp)));
8234 close_file(req, fsp, NORMAL_CLOSE);
8235 return NT_STATUS_INVALID_PARAMETER;
8239 * See if others still have the file open. If this is the case, then
8240 * don't delete. If all opens are POSIX delete we can set the delete
8241 * on close disposition.
8243 for (i=0; i<lck->data->num_share_modes; i++) {
8244 struct share_mode_entry *e = &lck->data->share_modes[i];
8245 if (is_valid_share_mode_entry(e)) {
8246 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8249 if (share_mode_stale_pid(lck->data, i)) {
8252 /* Fail with sharing violation. */
8254 close_file(req, fsp, NORMAL_CLOSE);
8255 return NT_STATUS_SHARING_VIOLATION;
8260 * Set the delete on close.
8262 status = smb_set_file_disposition_info(conn,
8270 if (!NT_STATUS_IS_OK(status)) {
8271 close_file(req, fsp, NORMAL_CLOSE);
8274 return close_file(req, fsp, NORMAL_CLOSE);
8277 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8278 struct smb_request *req,
8279 TALLOC_CTX *mem_ctx,
8280 uint16_t info_level,
8282 struct smb_filename *smb_fname,
8283 char **ppdata, int total_data,
8286 char *pdata = *ppdata;
8287 NTSTATUS status = NT_STATUS_OK;
8288 int data_return_size = 0;
8292 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8293 return NT_STATUS_INVALID_LEVEL;
8296 if (!CAN_WRITE(conn)) {
8297 /* Allow POSIX opens. The open path will deny
8298 * any non-readonly opens. */
8299 if (info_level != SMB_POSIX_PATH_OPEN) {
8300 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8304 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8305 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8307 info_level, total_data));
8309 switch (info_level) {
8311 case SMB_INFO_STANDARD:
8313 status = smb_set_info_standard(conn,
8321 case SMB_INFO_SET_EA:
8323 status = smb_info_set_ea(conn,
8331 case SMB_SET_FILE_BASIC_INFO:
8332 case SMB_FILE_BASIC_INFORMATION:
8334 status = smb_set_file_basic_info(conn,
8342 case SMB_FILE_ALLOCATION_INFORMATION:
8343 case SMB_SET_FILE_ALLOCATION_INFO:
8345 status = smb_set_file_allocation_info(conn, req,
8353 case SMB_FILE_END_OF_FILE_INFORMATION:
8354 case SMB_SET_FILE_END_OF_FILE_INFO:
8357 * XP/Win7 both fail after the createfile with
8358 * SMB_SET_FILE_END_OF_FILE_INFO but not
8359 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8360 * The level is known here, so pass it down
8364 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8366 status = smb_set_file_end_of_file_info(conn, req,
8375 case SMB_FILE_DISPOSITION_INFORMATION:
8376 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8379 /* JRA - We used to just ignore this on a path ?
8380 * Shouldn't this be invalid level on a pathname
8383 if (tran_call != TRANSACT2_SETFILEINFO) {
8384 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8387 status = smb_set_file_disposition_info(conn,
8395 case SMB_FILE_POSITION_INFORMATION:
8397 status = smb_file_position_information(conn,
8404 case SMB_FILE_FULL_EA_INFORMATION:
8406 status = smb_set_file_full_ea_info(conn,
8413 /* From tridge Samba4 :
8414 * MODE_INFORMATION in setfileinfo (I have no
8415 * idea what "mode information" on a file is - it takes a value of 0,
8416 * 2, 4 or 6. What could it be?).
8419 case SMB_FILE_MODE_INFORMATION:
8421 status = smb_file_mode_information(conn,
8428 * CIFS UNIX extensions.
8431 case SMB_SET_FILE_UNIX_BASIC:
8433 status = smb_set_file_unix_basic(conn, req,
8441 case SMB_SET_FILE_UNIX_INFO2:
8443 status = smb_set_file_unix_info2(conn, req,
8451 case SMB_SET_FILE_UNIX_LINK:
8454 /* We must have a pathname for this. */
8455 return NT_STATUS_INVALID_LEVEL;
8457 status = smb_set_file_unix_link(conn, req, pdata,
8458 total_data, smb_fname);
8462 case SMB_SET_FILE_UNIX_HLINK:
8465 /* We must have a pathname for this. */
8466 return NT_STATUS_INVALID_LEVEL;
8468 status = smb_set_file_unix_hlink(conn, req,
8474 case SMB_FILE_RENAME_INFORMATION:
8476 status = smb_file_rename_information(conn, req,
8482 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8484 /* SMB2 rename information. */
8485 status = smb2_file_rename_information(conn, req,
8491 case SMB_FILE_LINK_INFORMATION:
8493 status = smb_file_link_information(conn, req,
8499 #if defined(HAVE_POSIX_ACLS)
8500 case SMB_SET_POSIX_ACL:
8502 status = smb_set_posix_acl(conn,
8511 case SMB_SET_POSIX_LOCK:
8514 return NT_STATUS_INVALID_LEVEL;
8516 status = smb_set_posix_lock(conn, req,
8517 pdata, total_data, fsp);
8521 case SMB_POSIX_PATH_OPEN:
8524 /* We must have a pathname for this. */
8525 return NT_STATUS_INVALID_LEVEL;
8528 status = smb_posix_open(conn, req,
8536 case SMB_POSIX_PATH_UNLINK:
8539 /* We must have a pathname for this. */
8540 return NT_STATUS_INVALID_LEVEL;
8543 status = smb_posix_unlink(conn, req,
8551 return NT_STATUS_INVALID_LEVEL;
8554 if (!NT_STATUS_IS_OK(status)) {
8558 *ret_data_size = data_return_size;
8559 return NT_STATUS_OK;
8562 /****************************************************************************
8563 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8564 ****************************************************************************/
8566 static void call_trans2setfilepathinfo(connection_struct *conn,
8567 struct smb_request *req,
8568 unsigned int tran_call,
8569 char **pparams, int total_params,
8570 char **ppdata, int total_data,
8571 unsigned int max_data_bytes)
8573 char *params = *pparams;
8574 char *pdata = *ppdata;
8575 uint16_t info_level;
8576 struct smb_filename *smb_fname = NULL;
8577 files_struct *fsp = NULL;
8578 NTSTATUS status = NT_STATUS_OK;
8579 int data_return_size = 0;
8582 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8586 if (tran_call == TRANSACT2_SETFILEINFO) {
8587 if (total_params < 4) {
8588 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8592 fsp = file_fsp(req, SVAL(params,0));
8593 /* Basic check for non-null fsp. */
8594 if (!check_fsp_open(conn, req, fsp)) {
8597 info_level = SVAL(params,2);
8599 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8600 if (smb_fname == NULL) {
8601 reply_nterror(req, NT_STATUS_NO_MEMORY);
8605 if(fsp->fh->fd == -1) {
8607 * This is actually a SETFILEINFO on a directory
8608 * handle (returned from an NT SMB). NT5.0 seems
8609 * to do this call. JRA.
8611 if (INFO_LEVEL_IS_UNIX(info_level)) {
8612 /* Always do lstat for UNIX calls. */
8613 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8614 DEBUG(3,("call_trans2setfilepathinfo: "
8615 "SMB_VFS_LSTAT of %s failed "
8617 smb_fname_str_dbg(smb_fname),
8619 reply_nterror(req, map_nt_error_from_unix(errno));
8623 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8624 DEBUG(3,("call_trans2setfilepathinfo: "
8625 "fileinfo of %s failed (%s)\n",
8626 smb_fname_str_dbg(smb_fname),
8628 reply_nterror(req, map_nt_error_from_unix(errno));
8632 } else if (fsp->print_file) {
8634 * Doing a DELETE_ON_CLOSE should cancel a print job.
8636 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8637 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8639 DEBUG(3,("call_trans2setfilepathinfo: "
8640 "Cancelling print job (%s)\n",
8644 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8650 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8655 * Original code - this is an open file.
8657 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8658 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8659 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8661 reply_nterror(req, map_nt_error_from_unix(errno));
8667 uint32_t ucf_flags = (req->posix_pathnames ?
8668 UCF_POSIX_PATHNAMES : 0);
8671 if (total_params < 7) {
8672 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8676 info_level = SVAL(params,0);
8677 if (req->posix_pathnames) {
8678 srvstr_get_path_posix(req,
8687 srvstr_get_path(req,
8696 if (!NT_STATUS_IS_OK(status)) {
8697 reply_nterror(req, status);
8701 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8702 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8703 info_level == SMB_FILE_RENAME_INFORMATION ||
8704 info_level == SMB_POSIX_PATH_UNLINK) {
8705 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8708 status = filename_convert(req, conn,
8709 req->flags2 & FLAGS2_DFS_PATHNAMES,
8714 if (!NT_STATUS_IS_OK(status)) {
8715 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8716 reply_botherror(req,
8717 NT_STATUS_PATH_NOT_COVERED,
8718 ERRSRV, ERRbadpath);
8721 reply_nterror(req, status);
8725 if (INFO_LEVEL_IS_UNIX(info_level)) {
8727 * For CIFS UNIX extensions the target name may not exist.
8730 /* Always do lstat for UNIX calls. */
8731 SMB_VFS_LSTAT(conn, smb_fname);
8733 } else if (!VALID_STAT(smb_fname->st) &&
8734 SMB_VFS_STAT(conn, smb_fname)) {
8735 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8737 smb_fname_str_dbg(smb_fname),
8739 reply_nterror(req, map_nt_error_from_unix(errno));
8744 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8745 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8747 info_level,total_data));
8749 /* Realloc the parameter size */
8750 *pparams = (char *)SMB_REALLOC(*pparams,2);
8751 if (*pparams == NULL) {
8752 reply_nterror(req, NT_STATUS_NO_MEMORY);
8759 status = smbd_do_setfilepathinfo(conn, req, req,
8765 if (!NT_STATUS_IS_OK(status)) {
8766 if (open_was_deferred(req->xconn, req->mid)) {
8767 /* We have re-scheduled this call. */
8770 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8771 /* We have re-scheduled this call. */
8774 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8775 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8776 ERRSRV, ERRbadpath);
8779 if (info_level == SMB_POSIX_PATH_OPEN) {
8780 reply_openerror(req, status);
8785 * Invalid EA name needs to return 2 param bytes,
8786 * not a zero-length error packet.
8788 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8789 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8792 reply_nterror(req, status);
8797 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8803 /****************************************************************************
8804 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8805 ****************************************************************************/
8807 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8808 char **pparams, int total_params,
8809 char **ppdata, int total_data,
8810 unsigned int max_data_bytes)
8812 struct smb_filename *smb_dname = NULL;
8813 char *params = *pparams;
8814 char *pdata = *ppdata;
8815 char *directory = NULL;
8816 NTSTATUS status = NT_STATUS_OK;
8817 struct ea_list *ea_list = NULL;
8818 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
8819 TALLOC_CTX *ctx = talloc_tos();
8821 if (!CAN_WRITE(conn)) {
8822 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8826 if (total_params < 5) {
8827 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8831 if (req->posix_pathnames) {
8832 srvstr_get_path_posix(ctx,
8841 srvstr_get_path(ctx,
8850 if (!NT_STATUS_IS_OK(status)) {
8851 reply_nterror(req, status);
8855 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8857 status = filename_convert(ctx,
8859 req->flags2 & FLAGS2_DFS_PATHNAMES,
8865 if (!NT_STATUS_IS_OK(status)) {
8866 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8867 reply_botherror(req,
8868 NT_STATUS_PATH_NOT_COVERED,
8869 ERRSRV, ERRbadpath);
8872 reply_nterror(req, status);
8877 * OS/2 workplace shell seems to send SET_EA requests of "null"
8878 * length (4 bytes containing IVAL 4).
8879 * They seem to have no effect. Bug #3212. JRA.
8882 if (total_data && (total_data != 4)) {
8883 /* Any data in this call is an EA list. */
8884 if (total_data < 10) {
8885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8889 if (IVAL(pdata,0) > total_data) {
8890 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8891 IVAL(pdata,0), (unsigned int)total_data));
8892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8896 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8903 if (!lp_ea_support(SNUM(conn))) {
8904 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8908 /* If total_data == 4 Windows doesn't care what values
8909 * are placed in that field, it just ignores them.
8910 * The System i QNTC IBM SMB client puts bad values here,
8911 * so ignore them. */
8913 status = create_directory(conn, req, smb_dname);
8915 if (!NT_STATUS_IS_OK(status)) {
8916 reply_nterror(req, status);
8920 /* Try and set any given EA. */
8922 status = set_ea(conn, NULL, smb_dname, ea_list);
8923 if (!NT_STATUS_IS_OK(status)) {
8924 reply_nterror(req, status);
8929 /* Realloc the parameter and data sizes */
8930 *pparams = (char *)SMB_REALLOC(*pparams,2);
8931 if(*pparams == NULL) {
8932 reply_nterror(req, NT_STATUS_NO_MEMORY);
8939 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8942 TALLOC_FREE(smb_dname);
8946 /****************************************************************************
8947 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8948 We don't actually do this - we just send a null response.
8949 ****************************************************************************/
8951 static void call_trans2findnotifyfirst(connection_struct *conn,
8952 struct smb_request *req,
8953 char **pparams, int total_params,
8954 char **ppdata, int total_data,
8955 unsigned int max_data_bytes)
8957 char *params = *pparams;
8958 uint16_t info_level;
8960 if (total_params < 6) {
8961 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8965 info_level = SVAL(params,4);
8966 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8968 switch (info_level) {
8973 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8977 /* Realloc the parameter and data sizes */
8978 *pparams = (char *)SMB_REALLOC(*pparams,6);
8979 if (*pparams == NULL) {
8980 reply_nterror(req, NT_STATUS_NO_MEMORY);
8985 SSVAL(params,0,fnf_handle);
8986 SSVAL(params,2,0); /* No changes */
8987 SSVAL(params,4,0); /* No EA errors */
8994 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8999 /****************************************************************************
9000 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9001 changes). Currently this does nothing.
9002 ****************************************************************************/
9004 static void call_trans2findnotifynext(connection_struct *conn,
9005 struct smb_request *req,
9006 char **pparams, int total_params,
9007 char **ppdata, int total_data,
9008 unsigned int max_data_bytes)
9010 char *params = *pparams;
9012 DEBUG(3,("call_trans2findnotifynext\n"));
9014 /* Realloc the parameter and data sizes */
9015 *pparams = (char *)SMB_REALLOC(*pparams,4);
9016 if (*pparams == NULL) {
9017 reply_nterror(req, NT_STATUS_NO_MEMORY);
9022 SSVAL(params,0,0); /* No changes */
9023 SSVAL(params,2,0); /* No EA errors */
9025 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9030 /****************************************************************************
9031 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9032 ****************************************************************************/
9034 static void call_trans2getdfsreferral(connection_struct *conn,
9035 struct smb_request *req,
9036 char **pparams, int total_params,
9037 char **ppdata, int total_data,
9038 unsigned int max_data_bytes)
9040 char *params = *pparams;
9041 char *pathname = NULL;
9043 int max_referral_level;
9044 NTSTATUS status = NT_STATUS_OK;
9045 TALLOC_CTX *ctx = talloc_tos();
9047 DEBUG(10,("call_trans2getdfsreferral\n"));
9049 if (total_params < 3) {
9050 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9054 max_referral_level = SVAL(params,0);
9056 if(!lp_host_msdfs()) {
9057 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9061 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
9062 total_params - 2, STR_TERMINATE);
9064 reply_nterror(req, NT_STATUS_NOT_FOUND);
9067 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9068 ppdata,&status)) < 0) {
9069 reply_nterror(req, status);
9073 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9074 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9075 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9080 #define LMCAT_SPL 0x53
9081 #define LMFUNC_GETJOBID 0x60
9083 /****************************************************************************
9084 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9085 ****************************************************************************/
9087 static void call_trans2ioctl(connection_struct *conn,
9088 struct smb_request *req,
9089 char **pparams, int total_params,
9090 char **ppdata, int total_data,
9091 unsigned int max_data_bytes)
9093 char *pdata = *ppdata;
9094 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9098 /* check for an invalid fid before proceeding */
9101 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9105 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9106 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9107 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9108 if (*ppdata == NULL) {
9109 reply_nterror(req, NT_STATUS_NO_MEMORY);
9114 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9115 CAN ACCEPT THIS IN UNICODE. JRA. */
9118 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9120 status = srvstr_push(pdata, req->flags2, pdata + 2,
9121 lp_netbios_name(), 15,
9122 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9123 if (!NT_STATUS_IS_OK(status)) {
9124 reply_nterror(req, status);
9127 status = srvstr_push(pdata, req->flags2, pdata+18,
9128 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9129 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9130 if (!NT_STATUS_IS_OK(status)) {
9131 reply_nterror(req, status);
9134 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9139 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9140 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9143 /****************************************************************************
9144 Reply to a SMBfindclose (stop trans2 directory search).
9145 ****************************************************************************/
9147 void reply_findclose(struct smb_request *req)
9150 struct smbd_server_connection *sconn = req->sconn;
9152 START_PROFILE(SMBfindclose);
9155 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9156 END_PROFILE(SMBfindclose);
9160 dptr_num = SVALS(req->vwv+0, 0);
9162 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9164 dptr_close(sconn, &dptr_num);
9166 reply_outbuf(req, 0, 0);
9168 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9170 END_PROFILE(SMBfindclose);
9174 /****************************************************************************
9175 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9176 ****************************************************************************/
9178 void reply_findnclose(struct smb_request *req)
9182 START_PROFILE(SMBfindnclose);
9185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9186 END_PROFILE(SMBfindnclose);
9190 dptr_num = SVAL(req->vwv+0, 0);
9192 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9194 /* We never give out valid handles for a
9195 findnotifyfirst - so any dptr_num is ok here.
9198 reply_outbuf(req, 0, 0);
9200 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9202 END_PROFILE(SMBfindnclose);
9206 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9207 struct trans_state *state)
9209 if (get_Protocol() >= PROTOCOL_NT1) {
9210 req->flags2 |= 0x40; /* IS_LONG_NAME */
9211 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9214 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9215 if (state->call != TRANSACT2_QFSINFO &&
9216 state->call != TRANSACT2_SETFSINFO) {
9217 DEBUG(0,("handle_trans2: encryption required "
9219 (unsigned int)state->call));
9220 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9225 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9227 /* Now we must call the relevant TRANS2 function */
9228 switch(state->call) {
9229 case TRANSACT2_OPEN:
9231 START_PROFILE(Trans2_open);
9232 call_trans2open(conn, req,
9233 &state->param, state->total_param,
9234 &state->data, state->total_data,
9235 state->max_data_return);
9236 END_PROFILE(Trans2_open);
9240 case TRANSACT2_FINDFIRST:
9242 START_PROFILE(Trans2_findfirst);
9243 call_trans2findfirst(conn, req,
9244 &state->param, state->total_param,
9245 &state->data, state->total_data,
9246 state->max_data_return);
9247 END_PROFILE(Trans2_findfirst);
9251 case TRANSACT2_FINDNEXT:
9253 START_PROFILE(Trans2_findnext);
9254 call_trans2findnext(conn, req,
9255 &state->param, state->total_param,
9256 &state->data, state->total_data,
9257 state->max_data_return);
9258 END_PROFILE(Trans2_findnext);
9262 case TRANSACT2_QFSINFO:
9264 START_PROFILE(Trans2_qfsinfo);
9265 call_trans2qfsinfo(conn, req,
9266 &state->param, state->total_param,
9267 &state->data, state->total_data,
9268 state->max_data_return);
9269 END_PROFILE(Trans2_qfsinfo);
9273 case TRANSACT2_SETFSINFO:
9275 START_PROFILE(Trans2_setfsinfo);
9276 call_trans2setfsinfo(conn, req,
9277 &state->param, state->total_param,
9278 &state->data, state->total_data,
9279 state->max_data_return);
9280 END_PROFILE(Trans2_setfsinfo);
9284 case TRANSACT2_QPATHINFO:
9285 case TRANSACT2_QFILEINFO:
9287 START_PROFILE(Trans2_qpathinfo);
9288 call_trans2qfilepathinfo(conn, req, state->call,
9289 &state->param, state->total_param,
9290 &state->data, state->total_data,
9291 state->max_data_return);
9292 END_PROFILE(Trans2_qpathinfo);
9296 case TRANSACT2_SETPATHINFO:
9297 case TRANSACT2_SETFILEINFO:
9299 START_PROFILE(Trans2_setpathinfo);
9300 call_trans2setfilepathinfo(conn, req, state->call,
9301 &state->param, state->total_param,
9302 &state->data, state->total_data,
9303 state->max_data_return);
9304 END_PROFILE(Trans2_setpathinfo);
9308 case TRANSACT2_FINDNOTIFYFIRST:
9310 START_PROFILE(Trans2_findnotifyfirst);
9311 call_trans2findnotifyfirst(conn, req,
9312 &state->param, state->total_param,
9313 &state->data, state->total_data,
9314 state->max_data_return);
9315 END_PROFILE(Trans2_findnotifyfirst);
9319 case TRANSACT2_FINDNOTIFYNEXT:
9321 START_PROFILE(Trans2_findnotifynext);
9322 call_trans2findnotifynext(conn, req,
9323 &state->param, state->total_param,
9324 &state->data, state->total_data,
9325 state->max_data_return);
9326 END_PROFILE(Trans2_findnotifynext);
9330 case TRANSACT2_MKDIR:
9332 START_PROFILE(Trans2_mkdir);
9333 call_trans2mkdir(conn, req,
9334 &state->param, state->total_param,
9335 &state->data, state->total_data,
9336 state->max_data_return);
9337 END_PROFILE(Trans2_mkdir);
9341 case TRANSACT2_GET_DFS_REFERRAL:
9343 START_PROFILE(Trans2_get_dfs_referral);
9344 call_trans2getdfsreferral(conn, req,
9345 &state->param, state->total_param,
9346 &state->data, state->total_data,
9347 state->max_data_return);
9348 END_PROFILE(Trans2_get_dfs_referral);
9352 case TRANSACT2_IOCTL:
9354 START_PROFILE(Trans2_ioctl);
9355 call_trans2ioctl(conn, req,
9356 &state->param, state->total_param,
9357 &state->data, state->total_data,
9358 state->max_data_return);
9359 END_PROFILE(Trans2_ioctl);
9364 /* Error in request */
9365 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9366 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9370 /****************************************************************************
9371 Reply to a SMBtrans2.
9372 ****************************************************************************/
9374 void reply_trans2(struct smb_request *req)
9376 connection_struct *conn = req->conn;
9381 unsigned int tran_call;
9382 struct trans_state *state;
9385 START_PROFILE(SMBtrans2);
9387 if (req->wct < 14) {
9388 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9389 END_PROFILE(SMBtrans2);
9393 dsoff = SVAL(req->vwv+12, 0);
9394 dscnt = SVAL(req->vwv+11, 0);
9395 psoff = SVAL(req->vwv+10, 0);
9396 pscnt = SVAL(req->vwv+9, 0);
9397 tran_call = SVAL(req->vwv+14, 0);
9399 result = allow_new_trans(conn->pending_trans, req->mid);
9400 if (!NT_STATUS_IS_OK(result)) {
9401 DEBUG(2, ("Got invalid trans2 request: %s\n",
9402 nt_errstr(result)));
9403 reply_nterror(req, result);
9404 END_PROFILE(SMBtrans2);
9409 switch (tran_call) {
9410 /* List the allowed trans2 calls on IPC$ */
9411 case TRANSACT2_OPEN:
9412 case TRANSACT2_GET_DFS_REFERRAL:
9413 case TRANSACT2_QFILEINFO:
9414 case TRANSACT2_QFSINFO:
9415 case TRANSACT2_SETFSINFO:
9418 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9419 END_PROFILE(SMBtrans2);
9424 if ((state = talloc(conn, struct trans_state)) == NULL) {
9425 DEBUG(0, ("talloc failed\n"));
9426 reply_nterror(req, NT_STATUS_NO_MEMORY);
9427 END_PROFILE(SMBtrans2);
9431 state->cmd = SMBtrans2;
9433 state->mid = req->mid;
9434 state->vuid = req->vuid;
9435 state->setup_count = SVAL(req->vwv+13, 0);
9436 state->setup = NULL;
9437 state->total_param = SVAL(req->vwv+0, 0);
9438 state->param = NULL;
9439 state->total_data = SVAL(req->vwv+1, 0);
9441 state->max_param_return = SVAL(req->vwv+2, 0);
9442 state->max_data_return = SVAL(req->vwv+3, 0);
9443 state->max_setup_return = SVAL(req->vwv+4, 0);
9444 state->close_on_completion = BITSETW(req->vwv+5, 0);
9445 state->one_way = BITSETW(req->vwv+5, 1);
9447 state->call = tran_call;
9449 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9450 is so as a sanity check */
9451 if (state->setup_count != 1) {
9453 * Need to have rc=0 for ioctl to get job id for OS/2.
9454 * Network printing will fail if function is not successful.
9455 * Similar function in reply.c will be used if protocol
9456 * is LANMAN1.0 instead of LM1.2X002.
9457 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9458 * outbuf doesn't have to be set(only job id is used).
9460 if ( (state->setup_count == 4)
9461 && (tran_call == TRANSACT2_IOCTL)
9462 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9463 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9464 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9466 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9467 DEBUG(2,("Transaction is %d\n",tran_call));
9469 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9470 END_PROFILE(SMBtrans2);
9475 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9478 if (state->total_data) {
9480 if (trans_oob(state->total_data, 0, dscnt)
9481 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9485 /* Can't use talloc here, the core routines do realloc on the
9486 * params and data. */
9487 state->data = (char *)SMB_MALLOC(state->total_data);
9488 if (state->data == NULL) {
9489 DEBUG(0,("reply_trans2: data malloc fail for %u "
9490 "bytes !\n", (unsigned int)state->total_data));
9492 reply_nterror(req, NT_STATUS_NO_MEMORY);
9493 END_PROFILE(SMBtrans2);
9497 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9500 if (state->total_param) {
9502 if (trans_oob(state->total_param, 0, pscnt)
9503 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9507 /* Can't use talloc here, the core routines do realloc on the
9508 * params and data. */
9509 state->param = (char *)SMB_MALLOC(state->total_param);
9510 if (state->param == NULL) {
9511 DEBUG(0,("reply_trans: param malloc fail for %u "
9512 "bytes !\n", (unsigned int)state->total_param));
9513 SAFE_FREE(state->data);
9515 reply_nterror(req, NT_STATUS_NO_MEMORY);
9516 END_PROFILE(SMBtrans2);
9520 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9523 state->received_data = dscnt;
9524 state->received_param = pscnt;
9526 if ((state->received_param == state->total_param) &&
9527 (state->received_data == state->total_data)) {
9529 handle_trans2(conn, req, state);
9531 SAFE_FREE(state->data);
9532 SAFE_FREE(state->param);
9534 END_PROFILE(SMBtrans2);
9538 DLIST_ADD(conn->pending_trans, state);
9540 /* We need to send an interim response then receive the rest
9541 of the parameter/data bytes */
9542 reply_outbuf(req, 0, 0);
9543 show_msg((char *)req->outbuf);
9544 END_PROFILE(SMBtrans2);
9549 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9550 SAFE_FREE(state->data);
9551 SAFE_FREE(state->param);
9553 END_PROFILE(SMBtrans2);
9554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9558 /****************************************************************************
9559 Reply to a SMBtranss2
9560 ****************************************************************************/
9562 void reply_transs2(struct smb_request *req)
9564 connection_struct *conn = req->conn;
9565 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9566 struct trans_state *state;
9568 START_PROFILE(SMBtranss2);
9570 show_msg((const char *)req->inbuf);
9572 /* Windows clients expect all replies to
9573 a transact secondary (SMBtranss2 0x33)
9574 to have a command code of transact
9575 (SMBtrans2 0x32). See bug #8989
9576 and also [MS-CIFS] section 2.2.4.47.2
9579 req->cmd = SMBtrans2;
9582 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9583 END_PROFILE(SMBtranss2);
9587 for (state = conn->pending_trans; state != NULL;
9588 state = state->next) {
9589 if (state->mid == req->mid) {
9594 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9595 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9596 END_PROFILE(SMBtranss2);
9600 /* Revise state->total_param and state->total_data in case they have
9601 changed downwards */
9603 if (SVAL(req->vwv+0, 0) < state->total_param)
9604 state->total_param = SVAL(req->vwv+0, 0);
9605 if (SVAL(req->vwv+1, 0) < state->total_data)
9606 state->total_data = SVAL(req->vwv+1, 0);
9608 pcnt = SVAL(req->vwv+2, 0);
9609 poff = SVAL(req->vwv+3, 0);
9610 pdisp = SVAL(req->vwv+4, 0);
9612 dcnt = SVAL(req->vwv+5, 0);
9613 doff = SVAL(req->vwv+6, 0);
9614 ddisp = SVAL(req->vwv+7, 0);
9616 state->received_param += pcnt;
9617 state->received_data += dcnt;
9619 if ((state->received_data > state->total_data) ||
9620 (state->received_param > state->total_param))
9624 if (trans_oob(state->total_param, pdisp, pcnt)
9625 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9628 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9632 if (trans_oob(state->total_data, ddisp, dcnt)
9633 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9636 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9639 if ((state->received_param < state->total_param) ||
9640 (state->received_data < state->total_data)) {
9641 END_PROFILE(SMBtranss2);
9645 handle_trans2(conn, req, state);
9647 DLIST_REMOVE(conn->pending_trans, state);
9648 SAFE_FREE(state->data);
9649 SAFE_FREE(state->param);
9652 END_PROFILE(SMBtranss2);
9657 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9658 DLIST_REMOVE(conn->pending_trans, state);
9659 SAFE_FREE(state->data);
9660 SAFE_FREE(state->param);
9662 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9663 END_PROFILE(SMBtranss2);