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"
44 #define DIR_ENTRY_SAFETY_MARGIN 4096
46 static char *store_file_unix_basic(connection_struct *conn,
49 const SMB_STRUCT_STAT *psbuf);
51 static char *store_file_unix_basic_info2(connection_struct *conn,
54 const SMB_STRUCT_STAT *psbuf);
56 /********************************************************************
57 The canonical "check access" based on object handle or path function.
58 ********************************************************************/
60 NTSTATUS check_access(connection_struct *conn,
62 const struct smb_filename *smb_fname,
66 if (!(fsp->access_mask & access_mask)) {
67 return NT_STATUS_ACCESS_DENIED;
70 NTSTATUS status = smbd_check_access_rights(conn,
74 if (!NT_STATUS_IS_OK(status)) {
81 /********************************************************************
82 Roundup a value to the nearest allocation roundup size boundary.
83 Only do this for Windows clients.
84 ********************************************************************/
86 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
88 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
90 /* Only roundup for Windows clients. */
91 enum remote_arch_types ra_type = get_remote_arch();
92 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
93 val = SMB_ROUNDUP(val,rval);
98 /********************************************************************
99 Create a 64 bit FileIndex. If the file is on the same device as
100 the root of the share, just return the 64-bit inode. If it isn't,
101 mangle as we used to do.
102 ********************************************************************/
104 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
107 if (conn->base_share_dev == psbuf->st_ex_dev) {
108 return (uint64_t)psbuf->st_ex_ino;
110 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
111 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
115 /****************************************************************************
116 Utility functions for dealing with extended attributes.
117 ****************************************************************************/
119 /****************************************************************************
120 Refuse to allow clients to overwrite our private xattrs.
121 ****************************************************************************/
123 static bool samba_private_attr_name(const char *unix_ea_name)
125 static const char * const prohibited_ea_names[] = {
126 SAMBA_POSIX_INHERITANCE_EA_NAME,
127 SAMBA_XATTR_DOS_ATTRIB,
135 for (i = 0; prohibited_ea_names[i]; i++) {
136 if (strequal( prohibited_ea_names[i], unix_ea_name))
139 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
140 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
146 /****************************************************************************
147 Get one EA value. Fill in a struct ea_struct.
148 ****************************************************************************/
150 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
151 files_struct *fsp, const char *fname,
152 const char *ea_name, struct ea_struct *pea)
154 /* Get the value of this xattr. Max size is 64k. */
155 size_t attr_size = 256;
161 val = talloc_realloc(mem_ctx, val, char, attr_size);
163 return NT_STATUS_NO_MEMORY;
166 if (fsp && fsp->fh->fd != -1) {
167 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
169 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
172 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
178 return map_nt_error_from_unix(errno);
181 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
182 dump_data(10, (uint8 *)val, sizeret);
185 if (strnequal(ea_name, "user.", 5)) {
186 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
188 pea->name = talloc_strdup(mem_ctx, ea_name);
190 if (pea->name == NULL) {
192 return NT_STATUS_NO_MEMORY;
194 pea->value.data = (unsigned char *)val;
195 pea->value.length = (size_t)sizeret;
199 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
200 files_struct *fsp, const char *fname,
201 char ***pnames, size_t *pnum_names)
203 /* Get a list of all xattrs. Max namesize is 64k. */
204 size_t ea_namelist_size = 1024;
205 char *ea_namelist = NULL;
210 ssize_t sizeret = -1;
212 if (!lp_ea_support(SNUM(conn))) {
221 * TALLOC the result early to get the talloc hierarchy right.
224 names = talloc_array(mem_ctx, char *, 1);
226 DEBUG(0, ("talloc failed\n"));
227 return NT_STATUS_NO_MEMORY;
230 while (ea_namelist_size <= 65536) {
232 ea_namelist = talloc_realloc(
233 names, ea_namelist, char, ea_namelist_size);
234 if (ea_namelist == NULL) {
235 DEBUG(0, ("talloc failed\n"));
237 return NT_STATUS_NO_MEMORY;
240 if (fsp && fsp->fh->fd != -1) {
241 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
244 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
248 if ((sizeret == -1) && (errno == ERANGE)) {
249 ea_namelist_size *= 2;
258 return map_nt_error_from_unix(errno);
261 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
262 (unsigned int)sizeret));
274 * Ensure the result is 0-terminated
277 if (ea_namelist[sizeret-1] != '\0') {
279 return NT_STATUS_INTERNAL_ERROR;
287 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
291 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
293 DEBUG(0, ("talloc failed\n"));
295 return NT_STATUS_NO_MEMORY;
301 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
302 names[num_names++] = p;
310 *pnum_names = num_names;
314 /****************************************************************************
315 Return a linked list of the total EA's. Plus the total size
316 ****************************************************************************/
318 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
319 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
321 /* Get a list of all xattrs. Max namesize is 64k. */
324 struct ea_list *ea_list_head = NULL;
330 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
333 if (!NT_STATUS_IS_OK(status)) {
337 if (num_names == 0) {
342 for (i=0; i<num_names; i++) {
343 struct ea_list *listp;
346 if (strnequal(names[i], "system.", 7)
347 || samba_private_attr_name(names[i]))
351 * Filter out any underlying POSIX EA names
352 * that a Windows client can't handle.
354 if (!lp_posix_pathnames() &&
355 is_invalid_windows_ea_name(names[i])) {
359 listp = talloc(mem_ctx, struct ea_list);
361 return NT_STATUS_NO_MEMORY;
364 status = get_ea_value(listp, conn, fsp,
368 if (!NT_STATUS_IS_OK(status)) {
373 if (listp->ea.value.length == 0) {
375 * We can never return a zero length EA.
376 * Windows reports the EA's as corrupted.
382 push_ascii_fstring(dos_ea_name, listp->ea.name);
385 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
387 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
388 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
389 (unsigned int)listp->ea.value.length));
391 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
395 /* Add on 4 for total length. */
396 if (*pea_total_len) {
400 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
401 (unsigned int)*pea_total_len));
403 *ea_list = ea_list_head;
407 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
408 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
413 if (!lp_ea_support(SNUM(conn))) {
417 if (is_ntfs_stream_smb_fname(smb_fname)) {
418 return NT_STATUS_INVALID_PARAMETER;
421 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
424 /****************************************************************************
425 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
427 ****************************************************************************/
429 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
430 connection_struct *conn, struct ea_list *ea_list)
432 unsigned int ret_data_size = 4;
435 SMB_ASSERT(total_data_size >= 4);
437 if (!lp_ea_support(SNUM(conn))) {
442 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
445 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
446 dos_namelen = strlen(dos_ea_name);
447 if (dos_namelen > 255 || dos_namelen == 0) {
450 if (ea_list->ea.value.length > 65535) {
453 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
457 /* We know we have room. */
458 SCVAL(p,0,ea_list->ea.flags);
459 SCVAL(p,1,dos_namelen);
460 SSVAL(p,2,ea_list->ea.value.length);
461 strlcpy(p+4, dos_ea_name, dos_namelen+1);
462 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
464 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
465 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
468 ret_data_size = PTR_DIFF(p, pdata);
469 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
470 SIVAL(pdata,0,ret_data_size);
471 return ret_data_size;
474 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
476 unsigned int total_data_size,
477 unsigned int *ret_data_size,
478 connection_struct *conn,
479 struct ea_list *ea_list)
481 uint8_t *p = (uint8_t *)pdata;
482 uint8_t *last_start = NULL;
483 bool do_store_data = (pdata != NULL);
487 if (!lp_ea_support(SNUM(conn))) {
488 return NT_STATUS_NO_EAS_ON_FILE;
491 for (; ea_list; ea_list = ea_list->next) {
497 if (last_start != NULL && do_store_data) {
498 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
502 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
503 dos_namelen = strlen(dos_ea_name);
504 if (dos_namelen > 255 || dos_namelen == 0) {
505 return NT_STATUS_INTERNAL_ERROR;
507 if (ea_list->ea.value.length > 65535) {
508 return NT_STATUS_INTERNAL_ERROR;
511 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
514 pad = (4 - (this_size % 4)) % 4;
519 if (this_size > total_data_size) {
520 return NT_STATUS_INFO_LENGTH_MISMATCH;
523 /* We know we have room. */
524 SIVAL(p, 0x00, 0); /* next offset */
525 SCVAL(p, 0x04, ea_list->ea.flags);
526 SCVAL(p, 0x05, dos_namelen);
527 SSVAL(p, 0x06, ea_list->ea.value.length);
528 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
529 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
531 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
535 total_data_size -= this_size;
541 *ret_data_size = PTR_DIFF(p, pdata);
542 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
546 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
548 size_t total_ea_len = 0;
550 struct ea_list *ea_list = NULL;
552 if (!lp_ea_support(SNUM(conn))) {
555 mem_ctx = talloc_stackframe();
557 /* If this is a stream fsp, then we need to instead find the
558 * estimated ea len from the main file, not the stream
559 * (streams cannot have EAs), but the estimate isn't just 0 in
561 if (is_ntfs_stream_smb_fname(smb_fname)) {
564 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
565 if(conn->sconn->using_smb2) {
567 unsigned int ret_data_size;
569 * We're going to be using fill_ea_chained_buffer() to
570 * marshall EA's - this size is significantly larger
571 * than the SMB1 buffer. Re-calculate the size without
574 status = fill_ea_chained_buffer(mem_ctx,
580 if (!NT_STATUS_IS_OK(status)) {
583 total_ea_len = ret_data_size;
585 TALLOC_FREE(mem_ctx);
589 /****************************************************************************
590 Ensure the EA name is case insensitive by matching any existing EA name.
591 ****************************************************************************/
593 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
596 TALLOC_CTX *mem_ctx = talloc_tos();
597 struct ea_list *ea_list;
598 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
599 if (!NT_STATUS_IS_OK(status)) {
603 for (; ea_list; ea_list = ea_list->next) {
604 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
605 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
606 &unix_ea_name[5], ea_list->ea.name));
607 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
613 /****************************************************************************
614 Set or delete an extended attribute.
615 ****************************************************************************/
617 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
618 const struct smb_filename *smb_fname, struct ea_list *ea_list)
623 if (!lp_ea_support(SNUM(conn))) {
624 return NT_STATUS_EAS_NOT_SUPPORTED;
627 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
628 if (!NT_STATUS_IS_OK(status)) {
632 /* Setting EAs on streams isn't supported. */
633 if (is_ntfs_stream_smb_fname(smb_fname)) {
634 return NT_STATUS_INVALID_PARAMETER;
638 * Filter out invalid Windows EA names - before
639 * we set *any* of them.
642 if (ea_list_has_invalid_name(ea_list)) {
643 return STATUS_INVALID_EA_NAME;
646 fname = smb_fname->base_name;
648 for (;ea_list; ea_list = ea_list->next) {
650 fstring unix_ea_name;
652 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
653 fstrcat(unix_ea_name, ea_list->ea.name);
655 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
657 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
659 if (samba_private_attr_name(unix_ea_name)) {
660 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
661 return NT_STATUS_ACCESS_DENIED;
664 if (ea_list->ea.value.length == 0) {
665 /* Remove the attribute. */
666 if (fsp && (fsp->fh->fd != -1)) {
667 DEBUG(10,("set_ea: deleting ea name %s on "
668 "file %s by file descriptor.\n",
669 unix_ea_name, fsp_str_dbg(fsp)));
670 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
672 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
673 unix_ea_name, fname));
674 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
677 /* Removing a non existent attribute always succeeds. */
678 if (ret == -1 && errno == ENOATTR) {
679 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
685 if (fsp && (fsp->fh->fd != -1)) {
686 DEBUG(10,("set_ea: setting ea name %s on file "
687 "%s by file descriptor.\n",
688 unix_ea_name, fsp_str_dbg(fsp)));
689 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
690 ea_list->ea.value.data, ea_list->ea.value.length, 0);
692 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
693 unix_ea_name, fname));
694 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
695 ea_list->ea.value.data, ea_list->ea.value.length, 0);
701 if (errno == ENOTSUP) {
702 return NT_STATUS_EAS_NOT_SUPPORTED;
705 return map_nt_error_from_unix(errno);
711 /****************************************************************************
712 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
713 ****************************************************************************/
715 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
717 struct ea_list *ea_list_head = NULL;
718 size_t converted_size, offset = 0;
720 while (offset + 2 < data_size) {
721 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
722 unsigned int namelen = CVAL(pdata,offset);
724 offset++; /* Go past the namelen byte. */
726 /* integer wrap paranioa. */
727 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
728 (offset > data_size) || (namelen > data_size) ||
729 (offset + namelen >= data_size)) {
732 /* Ensure the name is null terminated. */
733 if (pdata[offset + namelen] != '\0') {
736 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
738 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
739 "failed: %s", strerror(errno)));
745 offset += (namelen + 1); /* Go past the name + terminating zero. */
746 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
747 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
753 /****************************************************************************
754 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
755 ****************************************************************************/
757 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
759 struct ea_list *ea_list_head = NULL;
761 size_t bytes_used = 0;
763 while (offset < data_size) {
764 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
770 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
771 offset += bytes_used;
777 /****************************************************************************
778 Count the total EA size needed.
779 ****************************************************************************/
781 static size_t ea_list_size(struct ea_list *ealist)
784 struct ea_list *listp;
787 for (listp = ealist; listp; listp = listp->next) {
788 push_ascii_fstring(dos_ea_name, listp->ea.name);
789 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
791 /* Add on 4 for total length. */
799 /****************************************************************************
800 Return a union of EA's from a file list and a list of names.
801 The TALLOC context for the two lists *MUST* be identical as we steal
802 memory from one list to add to another. JRA.
803 ****************************************************************************/
805 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
807 struct ea_list *nlistp, *flistp;
809 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
810 for (flistp = file_list; flistp; flistp = flistp->next) {
811 if (strequal(nlistp->ea.name, flistp->ea.name)) {
817 /* Copy the data from this entry. */
818 nlistp->ea.flags = flistp->ea.flags;
819 nlistp->ea.value = flistp->ea.value;
822 nlistp->ea.flags = 0;
823 ZERO_STRUCT(nlistp->ea.value);
827 *total_ea_len = ea_list_size(name_list);
831 /****************************************************************************
832 Send the required number of replies back.
833 We assume all fields other than the data fields are
834 set correctly for the type of call.
835 HACK ! Always assumes smb_setup field is zero.
836 ****************************************************************************/
838 void send_trans2_replies(connection_struct *conn,
839 struct smb_request *req,
847 /* As we are using a protocol > LANMAN1 then the max_send
848 variable must have been set in the sessetupX call.
849 This takes precedence over the max_xmit field in the
850 global struct. These different max_xmit variables should
851 be merged as this is now too confusing */
853 int data_to_send = datasize;
854 int params_to_send = paramsize;
856 const char *pp = params;
857 const char *pd = pdata;
858 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
859 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
860 int data_alignment_offset = 0;
861 bool overflow = False;
862 struct smbd_server_connection *sconn = req->sconn;
863 int max_send = sconn->smb1.sessions.max_send;
865 /* Modify the data_to_send and datasize and set the error if
866 we're trying to send more than max_data_bytes. We still send
867 the part of the packet(s) that fit. Strange, but needed
870 if (max_data_bytes > 0 && datasize > max_data_bytes) {
871 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
872 max_data_bytes, datasize ));
873 datasize = data_to_send = max_data_bytes;
877 /* If there genuinely are no parameters or data to send just send the empty packet */
879 if(params_to_send == 0 && data_to_send == 0) {
880 reply_outbuf(req, 10, 0);
881 if (NT_STATUS_V(status)) {
884 ntstatus_to_dos(status, &eclass, &ecode);
885 error_packet_set((char *)req->outbuf,
886 eclass, ecode, status,
889 show_msg((char *)req->outbuf);
890 if (!srv_send_smb(sconn,
893 IS_CONN_ENCRYPTED(conn),
895 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
897 TALLOC_FREE(req->outbuf);
901 /* When sending params and data ensure that both are nicely aligned */
902 /* Only do this alignment when there is also data to send - else
903 can cause NT redirector problems. */
905 if (((params_to_send % 4) != 0) && (data_to_send != 0))
906 data_alignment_offset = 4 - (params_to_send % 4);
908 /* Space is bufsize minus Netbios over TCP header minus SMB header */
909 /* The alignment_offset is to align the param bytes on an even byte
910 boundary. NT 4.0 Beta needs this to work correctly. */
912 useable_space = max_send - (smb_size
915 + data_alignment_offset);
917 if (useable_space < 0) {
918 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
919 "= %d!!!", useable_space));
920 exit_server_cleanly("send_trans2_replies: Not enough space");
923 while (params_to_send || data_to_send) {
924 /* Calculate whether we will totally or partially fill this packet */
926 total_sent_thistime = params_to_send + data_to_send;
928 /* We can never send more than useable_space */
930 * Note that 'useable_space' does not include the alignment offsets,
931 * but we must include the alignment offsets in the calculation of
932 * the length of the data we send over the wire, as the alignment offsets
933 * are sent here. Fix from Marc_Jacobsen@hp.com.
936 total_sent_thistime = MIN(total_sent_thistime, useable_space);
938 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
939 + data_alignment_offset);
941 /* Set total params and data to be sent */
942 SSVAL(req->outbuf,smb_tprcnt,paramsize);
943 SSVAL(req->outbuf,smb_tdrcnt,datasize);
945 /* Calculate how many parameters and data we can fit into
946 * this packet. Parameters get precedence
949 params_sent_thistime = MIN(params_to_send,useable_space);
950 data_sent_thistime = useable_space - params_sent_thistime;
951 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
953 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
955 /* smb_proff is the offset from the start of the SMB header to the
956 parameter bytes, however the first 4 bytes of outbuf are
957 the Netbios over TCP header. Thus use smb_base() to subtract
958 them from the calculation */
960 SSVAL(req->outbuf,smb_proff,
961 ((smb_buf(req->outbuf)+alignment_offset)
962 - smb_base(req->outbuf)));
964 if(params_sent_thistime == 0)
965 SSVAL(req->outbuf,smb_prdisp,0);
967 /* Absolute displacement of param bytes sent in this packet */
968 SSVAL(req->outbuf,smb_prdisp,pp - params);
970 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
971 if(data_sent_thistime == 0) {
972 SSVAL(req->outbuf,smb_droff,0);
973 SSVAL(req->outbuf,smb_drdisp, 0);
975 /* The offset of the data bytes is the offset of the
976 parameter bytes plus the number of parameters being sent this time */
977 SSVAL(req->outbuf, smb_droff,
978 ((smb_buf(req->outbuf)+alignment_offset)
979 - smb_base(req->outbuf))
980 + params_sent_thistime + data_alignment_offset);
981 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
984 /* Initialize the padding for alignment */
986 if (alignment_offset != 0) {
987 memset(smb_buf(req->outbuf), 0, alignment_offset);
990 /* Copy the param bytes into the packet */
992 if(params_sent_thistime) {
993 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
994 params_sent_thistime);
997 /* Copy in the data bytes */
998 if(data_sent_thistime) {
999 if (data_alignment_offset != 0) {
1000 memset((smb_buf(req->outbuf)+alignment_offset+
1001 params_sent_thistime), 0,
1002 data_alignment_offset);
1004 memcpy(smb_buf(req->outbuf)+alignment_offset
1005 +params_sent_thistime+data_alignment_offset,
1006 pd,data_sent_thistime);
1009 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1010 params_sent_thistime, data_sent_thistime, useable_space));
1011 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1012 params_to_send, data_to_send, paramsize, datasize));
1015 error_packet_set((char *)req->outbuf,
1016 ERRDOS,ERRbufferoverflow,
1017 STATUS_BUFFER_OVERFLOW,
1019 } else if (NT_STATUS_V(status)) {
1022 ntstatus_to_dos(status, &eclass, &ecode);
1023 error_packet_set((char *)req->outbuf,
1024 eclass, ecode, status,
1028 /* Send the packet */
1029 show_msg((char *)req->outbuf);
1030 if (!srv_send_smb(sconn,
1031 (char *)req->outbuf,
1032 true, req->seqnum+1,
1033 IS_CONN_ENCRYPTED(conn),
1035 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1037 TALLOC_FREE(req->outbuf);
1039 pp += params_sent_thistime;
1040 pd += data_sent_thistime;
1042 params_to_send -= params_sent_thistime;
1043 data_to_send -= data_sent_thistime;
1046 if(params_to_send < 0 || data_to_send < 0) {
1047 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1048 params_to_send, data_to_send));
1056 /****************************************************************************
1057 Reply to a TRANSACT2_OPEN.
1058 ****************************************************************************/
1060 static void call_trans2open(connection_struct *conn,
1061 struct smb_request *req,
1062 char **pparams, int total_params,
1063 char **ppdata, int total_data,
1064 unsigned int max_data_bytes)
1066 struct smb_filename *smb_fname = NULL;
1067 char *params = *pparams;
1068 char *pdata = *ppdata;
1071 bool oplock_request;
1073 bool return_additional_info;
1082 int fattr=0,mtime=0;
1083 SMB_INO_T inode = 0;
1086 struct ea_list *ea_list = NULL;
1091 uint32 create_disposition;
1092 uint32 create_options = 0;
1093 uint32_t private_flags = 0;
1094 TALLOC_CTX *ctx = talloc_tos();
1097 * Ensure we have enough parameters to perform the operation.
1100 if (total_params < 29) {
1101 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1105 flags = SVAL(params, 0);
1106 deny_mode = SVAL(params, 2);
1107 open_attr = SVAL(params,6);
1108 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1109 if (oplock_request) {
1110 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1114 return_additional_info = BITSETW(params,0);
1115 open_sattr = SVAL(params, 4);
1116 open_time = make_unix_date3(params+8);
1118 open_ofun = SVAL(params,12);
1119 open_size = IVAL(params,14);
1120 pname = ¶ms[28];
1123 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1127 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1128 total_params - 28, STR_TERMINATE,
1130 if (!NT_STATUS_IS_OK(status)) {
1131 reply_nterror(req, status);
1135 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1136 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1137 (unsigned int)open_ofun, open_size));
1139 status = filename_convert(ctx,
1141 req->flags2 & FLAGS2_DFS_PATHNAMES,
1146 if (!NT_STATUS_IS_OK(status)) {
1147 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1148 reply_botherror(req,
1149 NT_STATUS_PATH_NOT_COVERED,
1150 ERRSRV, ERRbadpath);
1153 reply_nterror(req, status);
1157 if (open_ofun == 0) {
1158 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1162 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1164 &access_mask, &share_mode,
1165 &create_disposition,
1168 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1172 /* Any data in this call is an EA list. */
1173 if (total_data && (total_data != 4)) {
1174 if (total_data < 10) {
1175 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1179 if (IVAL(pdata,0) > total_data) {
1180 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1181 IVAL(pdata,0), (unsigned int)total_data));
1182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1186 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1189 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1193 if (!lp_ea_support(SNUM(conn))) {
1194 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1198 if (ea_list_has_invalid_name(ea_list)) {
1200 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1201 if(*pparams == NULL ) {
1202 reply_nterror(req, NT_STATUS_NO_MEMORY);
1206 memset(params, '\0', param_len);
1207 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1208 params, param_len, NULL, 0, max_data_bytes);
1213 status = SMB_VFS_CREATE_FILE(
1216 0, /* root_dir_fid */
1217 smb_fname, /* fname */
1218 access_mask, /* access_mask */
1219 share_mode, /* share_access */
1220 create_disposition, /* create_disposition*/
1221 create_options, /* create_options */
1222 open_attr, /* file_attributes */
1223 oplock_request, /* oplock_request */
1224 open_size, /* allocation_size */
1227 ea_list, /* ea_list */
1229 &smb_action); /* psbuf */
1231 if (!NT_STATUS_IS_OK(status)) {
1232 if (open_was_deferred(req->sconn, req->mid)) {
1233 /* We have re-scheduled this call. */
1236 reply_openerror(req, status);
1240 size = get_file_size_stat(&smb_fname->st);
1241 fattr = dos_mode(conn, smb_fname);
1242 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1243 inode = smb_fname->st.st_ex_ino;
1244 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1245 close_file(req, fsp, ERROR_CLOSE);
1246 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1250 /* Realloc the size of parameters and data we will return */
1251 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1252 if(*pparams == NULL ) {
1253 reply_nterror(req, NT_STATUS_NO_MEMORY);
1258 SSVAL(params,0,fsp->fnum);
1259 SSVAL(params,2,fattr);
1260 srv_put_dos_date2(params,4, mtime);
1261 SIVAL(params,8, (uint32)size);
1262 SSVAL(params,12,deny_mode);
1263 SSVAL(params,14,0); /* open_type - file or directory. */
1264 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1266 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1267 smb_action |= EXTENDED_OPLOCK_GRANTED;
1270 SSVAL(params,18,smb_action);
1273 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1275 SIVAL(params,20,inode);
1276 SSVAL(params,24,0); /* Padding. */
1278 uint32 ea_size = estimate_ea_size(conn, fsp,
1280 SIVAL(params, 26, ea_size);
1282 SIVAL(params, 26, 0);
1285 /* Send the required number of replies */
1286 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1288 TALLOC_FREE(smb_fname);
1291 /*********************************************************
1292 Routine to check if a given string matches exactly.
1293 as a special case a mask of "." does NOT match. That
1294 is required for correct wildcard semantics
1295 Case can be significant or not.
1296 **********************************************************/
1298 static bool exact_match(bool has_wild,
1299 bool case_sensitive,
1303 if (mask[0] == '.' && mask[1] == 0) {
1311 if (case_sensitive) {
1312 return strcmp(str,mask)==0;
1314 return strcasecmp_m(str,mask) == 0;
1318 /****************************************************************************
1319 Return the filetype for UNIX extensions.
1320 ****************************************************************************/
1322 static uint32 unix_filetype(mode_t mode)
1325 return UNIX_TYPE_FILE;
1326 else if(S_ISDIR(mode))
1327 return UNIX_TYPE_DIR;
1329 else if(S_ISLNK(mode))
1330 return UNIX_TYPE_SYMLINK;
1333 else if(S_ISCHR(mode))
1334 return UNIX_TYPE_CHARDEV;
1337 else if(S_ISBLK(mode))
1338 return UNIX_TYPE_BLKDEV;
1341 else if(S_ISFIFO(mode))
1342 return UNIX_TYPE_FIFO;
1345 else if(S_ISSOCK(mode))
1346 return UNIX_TYPE_SOCKET;
1349 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1350 return UNIX_TYPE_UNKNOWN;
1353 /****************************************************************************
1354 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1355 ****************************************************************************/
1357 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1359 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1360 const SMB_STRUCT_STAT *psbuf,
1362 enum perm_type ptype,
1367 if (perms == SMB_MODE_NO_CHANGE) {
1368 if (!VALID_STAT(*psbuf)) {
1369 return NT_STATUS_INVALID_PARAMETER;
1371 *ret_perms = psbuf->st_ex_mode;
1372 return NT_STATUS_OK;
1376 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1377 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1378 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1379 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1380 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1381 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1382 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1383 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1384 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1386 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1389 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1392 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1395 if (ptype == PERM_NEW_FILE) {
1397 * "create mask"/"force create mode" are
1398 * only applied to new files, not existing ones.
1400 ret &= lp_create_mask(SNUM(conn));
1401 /* Add in force bits */
1402 ret |= lp_force_create_mode(SNUM(conn));
1403 } else if (ptype == PERM_NEW_DIR) {
1405 * "directory mask"/"force directory mode" are
1406 * only applied to new directories, not existing ones.
1408 ret &= lp_dir_mask(SNUM(conn));
1409 /* Add in force bits */
1410 ret |= lp_force_dir_mode(SNUM(conn));
1414 return NT_STATUS_OK;
1417 /****************************************************************************
1418 Needed to show the msdfs symlinks as directories. Modifies psbuf
1419 to be a directory if it's a msdfs link.
1420 ****************************************************************************/
1422 static bool check_msdfs_link(connection_struct *conn,
1423 const char *pathname,
1424 SMB_STRUCT_STAT *psbuf)
1426 int saved_errno = errno;
1427 if(lp_host_msdfs() &&
1428 lp_msdfs_root(SNUM(conn)) &&
1429 is_msdfs_link(conn, pathname, psbuf)) {
1431 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1434 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1435 errno = saved_errno;
1438 errno = saved_errno;
1443 /****************************************************************************
1444 Get a level dependent lanman2 dir entry.
1445 ****************************************************************************/
1447 struct smbd_dirptr_lanman2_state {
1448 connection_struct *conn;
1449 uint32_t info_level;
1450 bool check_mangled_names;
1452 bool got_exact_match;
1455 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1461 struct smbd_dirptr_lanman2_state *state =
1462 (struct smbd_dirptr_lanman2_state *)private_data;
1464 char mangled_name[13]; /* mangled 8.3 name. */
1468 /* Mangle fname if it's an illegal name. */
1469 if (mangle_must_mangle(dname, state->conn->params)) {
1470 ok = name_to_8_3(dname, mangled_name,
1471 true, state->conn->params);
1475 fname = mangled_name;
1480 got_match = exact_match(state->has_wild,
1481 state->conn->case_sensitive,
1483 state->got_exact_match = got_match;
1485 got_match = mask_match(fname, mask,
1486 state->conn->case_sensitive);
1489 if(!got_match && state->check_mangled_names &&
1490 !mangle_is_8_3(fname, false, state->conn->params)) {
1492 * It turns out that NT matches wildcards against
1493 * both long *and* short names. This may explain some
1494 * of the wildcard wierdness from old DOS clients
1495 * that some people have been seeing.... JRA.
1497 /* Force the mangling into 8.3. */
1498 ok = name_to_8_3(fname, mangled_name,
1499 false, state->conn->params);
1504 got_match = exact_match(state->has_wild,
1505 state->conn->case_sensitive,
1506 mangled_name, mask);
1507 state->got_exact_match = got_match;
1509 got_match = mask_match(mangled_name, mask,
1510 state->conn->case_sensitive);
1518 *_fname = talloc_strdup(ctx, fname);
1519 if (*_fname == NULL) {
1526 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1528 struct smb_filename *smb_fname,
1531 struct smbd_dirptr_lanman2_state *state =
1532 (struct smbd_dirptr_lanman2_state *)private_data;
1533 bool ms_dfs_link = false;
1536 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1537 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1538 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1539 "Couldn't lstat [%s] (%s)\n",
1540 smb_fname_str_dbg(smb_fname),
1544 } else if (!VALID_STAT(smb_fname->st) &&
1545 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1546 /* Needed to show the msdfs symlinks as
1549 ms_dfs_link = check_msdfs_link(state->conn,
1550 smb_fname->base_name,
1553 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1554 "Couldn't stat [%s] (%s)\n",
1555 smb_fname_str_dbg(smb_fname),
1562 mode = dos_mode_msdfs(state->conn, smb_fname);
1564 mode = dos_mode(state->conn, smb_fname);
1571 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1572 connection_struct *conn,
1574 uint32_t info_level,
1575 struct ea_list *name_list,
1576 bool check_mangled_names,
1577 bool requires_resume_key,
1580 const struct smb_filename *smb_fname,
1581 int space_remaining,
1588 uint64_t *last_entry_off)
1590 char *p, *q, *pdata = *ppdata;
1592 uint64_t file_size = 0;
1593 uint64_t allocation_size = 0;
1594 uint64_t file_index = 0;
1596 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1597 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1599 char *last_entry_ptr;
1604 *out_of_space = false;
1606 ZERO_STRUCT(mdate_ts);
1607 ZERO_STRUCT(adate_ts);
1608 ZERO_STRUCT(create_date_ts);
1609 ZERO_STRUCT(cdate_ts);
1611 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1612 file_size = get_file_size_stat(&smb_fname->st);
1614 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1616 file_index = get_FileIndex(conn, &smb_fname->st);
1618 mdate_ts = smb_fname->st.st_ex_mtime;
1619 adate_ts = smb_fname->st.st_ex_atime;
1620 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1621 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1623 if (lp_dos_filetime_resolution(SNUM(conn))) {
1624 dos_filetime_timespec(&create_date_ts);
1625 dos_filetime_timespec(&mdate_ts);
1626 dos_filetime_timespec(&adate_ts);
1627 dos_filetime_timespec(&cdate_ts);
1630 create_date = convert_timespec_to_time_t(create_date_ts);
1631 mdate = convert_timespec_to_time_t(mdate_ts);
1632 adate = convert_timespec_to_time_t(adate_ts);
1634 /* align the record */
1635 SMB_ASSERT(align >= 1);
1637 off = (int)PTR_DIFF(pdata, base_data);
1638 pad = (off + (align-1)) & ~(align-1);
1641 if (pad && pad > space_remaining) {
1642 *out_of_space = true;
1643 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1644 "for padding (wanted %u, had %d)\n",
1647 return false; /* Not finished - just out of space */
1651 /* initialize padding to 0 */
1653 memset(pdata, 0, pad);
1655 space_remaining -= pad;
1657 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1667 switch (info_level) {
1668 case SMB_FIND_INFO_STANDARD:
1669 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1670 if(requires_resume_key) {
1674 srv_put_dos_date2(p,0,create_date);
1675 srv_put_dos_date2(p,4,adate);
1676 srv_put_dos_date2(p,8,mdate);
1677 SIVAL(p,12,(uint32)file_size);
1678 SIVAL(p,16,(uint32)allocation_size);
1682 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1683 p += ucs2_align(base_data, p, 0);
1685 len = srvstr_push(base_data, flags2, p,
1686 fname, PTR_DIFF(end_data, p),
1688 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1690 SCVAL(nameptr, -1, len - 2);
1692 SCVAL(nameptr, -1, 0);
1696 SCVAL(nameptr, -1, len - 1);
1698 SCVAL(nameptr, -1, 0);
1704 case SMB_FIND_EA_SIZE:
1705 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1706 if (requires_resume_key) {
1710 srv_put_dos_date2(p,0,create_date);
1711 srv_put_dos_date2(p,4,adate);
1712 srv_put_dos_date2(p,8,mdate);
1713 SIVAL(p,12,(uint32)file_size);
1714 SIVAL(p,16,(uint32)allocation_size);
1717 unsigned int ea_size = estimate_ea_size(conn, NULL,
1719 SIVAL(p,22,ea_size); /* Extended attributes */
1723 len = srvstr_push(base_data, flags2,
1724 p, fname, PTR_DIFF(end_data, p),
1725 STR_TERMINATE | STR_NOALIGN);
1726 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1739 SCVAL(nameptr,0,len);
1741 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1744 case SMB_FIND_EA_LIST:
1746 struct ea_list *file_list = NULL;
1750 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1754 if (requires_resume_key) {
1758 srv_put_dos_date2(p,0,create_date);
1759 srv_put_dos_date2(p,4,adate);
1760 srv_put_dos_date2(p,8,mdate);
1761 SIVAL(p,12,(uint32)file_size);
1762 SIVAL(p,16,(uint32)allocation_size);
1764 p += 22; /* p now points to the EA area. */
1766 status = get_ea_list_from_file(ctx, conn, NULL,
1768 &ea_len, &file_list);
1769 if (!NT_STATUS_IS_OK(status)) {
1772 name_list = ea_list_union(name_list, file_list, &ea_len);
1774 /* We need to determine if this entry will fit in the space available. */
1775 /* Max string size is 255 bytes. */
1776 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1777 *out_of_space = true;
1778 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1779 "(wanted %u, had %d)\n",
1780 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1782 return False; /* Not finished - just out of space */
1785 /* Push the ea_data followed by the name. */
1786 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1788 len = srvstr_push(base_data, flags2,
1789 p + 1, fname, PTR_DIFF(end_data, p+1),
1790 STR_TERMINATE | STR_NOALIGN);
1791 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1804 SCVAL(nameptr,0,len);
1806 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1810 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1811 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1812 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1814 SIVAL(p,0,reskey); p += 4;
1815 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1816 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1817 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1818 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1819 SOFF_T(p,0,file_size); p += 8;
1820 SOFF_T(p,0,allocation_size); p += 8;
1821 SIVAL(p,0,mode); p += 4;
1822 q = p; p += 4; /* q is placeholder for name length. */
1823 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1824 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1826 unsigned int ea_size = estimate_ea_size(conn, NULL,
1828 SIVAL(p,0,ea_size); /* Extended attributes */
1831 /* Clear the short name buffer. This is
1832 * IMPORTANT as not doing so will trigger
1833 * a Win2k client bug. JRA.
1835 if (!was_8_3 && check_mangled_names) {
1836 char mangled_name[13]; /* mangled 8.3 name. */
1837 if (!name_to_8_3(fname,mangled_name,True,
1839 /* Error - mangle failed ! */
1840 memset(mangled_name,'\0',12);
1842 mangled_name[12] = 0;
1843 len = srvstr_push(base_data, flags2,
1844 p+2, mangled_name, 24,
1845 STR_UPPER|STR_UNICODE);
1847 memset(p + 2 + len,'\0',24 - len);
1854 len = srvstr_push(base_data, flags2, p,
1855 fname, PTR_DIFF(end_data, p),
1856 STR_TERMINATE_ASCII);
1860 len = PTR_DIFF(p, pdata);
1861 pad = (len + (align-1)) & ~(align-1);
1863 * offset to the next entry, the caller
1864 * will overwrite it for the last entry
1865 * that's why we always include the padding
1869 * set padding to zero
1872 memset(p, 0, pad - len);
1879 case SMB_FIND_FILE_DIRECTORY_INFO:
1880 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1882 SIVAL(p,0,reskey); p += 4;
1883 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1884 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1885 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1886 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1887 SOFF_T(p,0,file_size); p += 8;
1888 SOFF_T(p,0,allocation_size); p += 8;
1889 SIVAL(p,0,mode); p += 4;
1890 len = srvstr_push(base_data, flags2,
1891 p + 4, fname, PTR_DIFF(end_data, p+4),
1892 STR_TERMINATE_ASCII);
1896 len = PTR_DIFF(p, pdata);
1897 pad = (len + (align-1)) & ~(align-1);
1899 * offset to the next entry, the caller
1900 * will overwrite it for the last entry
1901 * that's why we always include the padding
1905 * set padding to zero
1908 memset(p, 0, pad - len);
1915 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1916 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1918 SIVAL(p,0,reskey); p += 4;
1919 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1920 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1921 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1922 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1923 SOFF_T(p,0,file_size); p += 8;
1924 SOFF_T(p,0,allocation_size); p += 8;
1925 SIVAL(p,0,mode); p += 4;
1926 q = p; p += 4; /* q is placeholder for name length. */
1928 unsigned int ea_size = estimate_ea_size(conn, NULL,
1930 SIVAL(p,0,ea_size); /* Extended attributes */
1933 len = srvstr_push(base_data, flags2, p,
1934 fname, PTR_DIFF(end_data, p),
1935 STR_TERMINATE_ASCII);
1939 len = PTR_DIFF(p, pdata);
1940 pad = (len + (align-1)) & ~(align-1);
1942 * offset to the next entry, the caller
1943 * will overwrite it for the last entry
1944 * that's why we always include the padding
1948 * set padding to zero
1951 memset(p, 0, pad - len);
1958 case SMB_FIND_FILE_NAMES_INFO:
1959 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1961 SIVAL(p,0,reskey); p += 4;
1963 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1964 acl on a dir (tridge) */
1965 len = srvstr_push(base_data, flags2, p,
1966 fname, PTR_DIFF(end_data, p),
1967 STR_TERMINATE_ASCII);
1971 len = PTR_DIFF(p, pdata);
1972 pad = (len + (align-1)) & ~(align-1);
1974 * offset to the next entry, the caller
1975 * will overwrite it for the last entry
1976 * that's why we always include the padding
1980 * set padding to zero
1983 memset(p, 0, pad - len);
1990 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1991 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1993 SIVAL(p,0,reskey); p += 4;
1994 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1995 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1996 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1997 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1998 SOFF_T(p,0,file_size); p += 8;
1999 SOFF_T(p,0,allocation_size); p += 8;
2000 SIVAL(p,0,mode); p += 4;
2001 q = p; p += 4; /* q is placeholder for name length. */
2002 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2003 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2005 unsigned int ea_size = estimate_ea_size(conn, NULL,
2007 SIVAL(p,0,ea_size); /* Extended attributes */
2010 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2011 SBVAL(p,0,file_index); p += 8;
2012 len = srvstr_push(base_data, flags2, p,
2013 fname, PTR_DIFF(end_data, p),
2014 STR_TERMINATE_ASCII);
2018 len = PTR_DIFF(p, pdata);
2019 pad = (len + (align-1)) & ~(align-1);
2021 * offset to the next entry, the caller
2022 * will overwrite it for the last entry
2023 * that's why we always include the padding
2027 * set padding to zero
2030 memset(p, 0, pad - len);
2037 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2038 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2039 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2041 SIVAL(p,0,reskey); p += 4;
2042 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2043 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2044 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2045 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2046 SOFF_T(p,0,file_size); p += 8;
2047 SOFF_T(p,0,allocation_size); p += 8;
2048 SIVAL(p,0,mode); p += 4;
2049 q = p; p += 4; /* q is placeholder for name length */
2050 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2051 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2053 unsigned int ea_size = estimate_ea_size(conn, NULL,
2055 SIVAL(p,0,ea_size); /* Extended attributes */
2058 /* Clear the short name buffer. This is
2059 * IMPORTANT as not doing so will trigger
2060 * a Win2k client bug. JRA.
2062 if (!was_8_3 && check_mangled_names) {
2063 char mangled_name[13]; /* mangled 8.3 name. */
2064 if (!name_to_8_3(fname,mangled_name,True,
2066 /* Error - mangle failed ! */
2067 memset(mangled_name,'\0',12);
2069 mangled_name[12] = 0;
2070 len = srvstr_push(base_data, flags2,
2071 p+2, mangled_name, 24,
2072 STR_UPPER|STR_UNICODE);
2075 memset(p + 2 + len,'\0',24 - len);
2082 SSVAL(p,0,0); p += 2; /* Reserved ? */
2083 SBVAL(p,0,file_index); p += 8;
2084 len = srvstr_push(base_data, flags2, p,
2085 fname, PTR_DIFF(end_data, p),
2086 STR_TERMINATE_ASCII);
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 /* CIFS UNIX Extension. */
2111 case SMB_FIND_FILE_UNIX:
2112 case SMB_FIND_FILE_UNIX_INFO2:
2114 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2116 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2118 if (info_level == SMB_FIND_FILE_UNIX) {
2119 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2120 p = store_file_unix_basic(conn, p,
2121 NULL, &smb_fname->st);
2122 len = srvstr_push(base_data, flags2, p,
2123 fname, PTR_DIFF(end_data, p),
2126 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2127 p = store_file_unix_basic_info2(conn, p,
2128 NULL, &smb_fname->st);
2131 len = srvstr_push(base_data, flags2, p, fname,
2132 PTR_DIFF(end_data, p), 0);
2133 SIVAL(nameptr, 0, len);
2138 len = PTR_DIFF(p, pdata);
2139 pad = (len + (align-1)) & ~(align-1);
2141 * offset to the next entry, the caller
2142 * will overwrite it for the last entry
2143 * that's why we always include the padding
2147 * set padding to zero
2150 memset(p, 0, pad - len);
2155 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2163 if (PTR_DIFF(p,pdata) > space_remaining) {
2164 *out_of_space = true;
2165 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2166 "(wanted %u, had %d)\n",
2167 (unsigned int)PTR_DIFF(p,pdata),
2169 return false; /* Not finished - just out of space */
2172 /* Setup the last entry pointer, as an offset from base_data */
2173 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2174 /* Advance the data pointer to the next slot */
2180 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2181 connection_struct *conn,
2182 struct dptr_struct *dirptr,
2184 const char *path_mask,
2187 int requires_resume_key,
2195 int space_remaining,
2197 bool *got_exact_match,
2198 int *_last_entry_off,
2199 struct ea_list *name_list)
2202 const char *mask = NULL;
2203 long prev_dirpos = 0;
2206 struct smb_filename *smb_fname = NULL;
2207 struct smbd_dirptr_lanman2_state state;
2209 uint64_t last_entry_off = 0;
2213 state.info_level = info_level;
2214 state.check_mangled_names = lp_manglednames(conn->params);
2215 state.has_wild = dptr_has_wild(dirptr);
2216 state.got_exact_match = false;
2218 *out_of_space = false;
2219 *got_exact_match = false;
2221 p = strrchr_m(path_mask,'/');
2232 ok = smbd_dirptr_get_entry(ctx,
2238 smbd_dirptr_lanman2_match_fn,
2239 smbd_dirptr_lanman2_mode_fn,
2249 *got_exact_match = state.got_exact_match;
2251 ok = smbd_marshall_dir_entry(ctx,
2256 state.check_mangled_names,
2257 requires_resume_key,
2270 TALLOC_FREE(smb_fname);
2271 if (*out_of_space) {
2272 dptr_SeekDir(dirptr, prev_dirpos);
2279 *_last_entry_off = last_entry_off;
2283 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2284 connection_struct *conn,
2285 struct dptr_struct *dirptr,
2287 const char *path_mask,
2290 bool requires_resume_key,
2296 int space_remaining,
2298 bool *got_exact_match,
2299 int *last_entry_off,
2300 struct ea_list *name_list)
2303 const bool do_pad = true;
2305 if (info_level >= 1 && info_level <= 3) {
2306 /* No alignment on earlier info levels. */
2310 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2311 path_mask, dirtype, info_level,
2312 requires_resume_key, dont_descend, ask_sharemode,
2314 ppdata, base_data, end_data,
2316 out_of_space, got_exact_match,
2317 last_entry_off, name_list);
2320 /****************************************************************************
2321 Reply to a TRANS2_FINDFIRST.
2322 ****************************************************************************/
2324 static void call_trans2findfirst(connection_struct *conn,
2325 struct smb_request *req,
2326 char **pparams, int total_params,
2327 char **ppdata, int total_data,
2328 unsigned int max_data_bytes)
2330 /* We must be careful here that we don't return more than the
2331 allowed number of data bytes. If this means returning fewer than
2332 maxentries then so be it. We assume that the redirector has
2333 enough room for the fixed number of parameter bytes it has
2335 struct smb_filename *smb_dname = NULL;
2336 char *params = *pparams;
2337 char *pdata = *ppdata;
2341 uint16 findfirst_flags;
2342 bool close_after_first;
2344 bool requires_resume_key;
2346 char *directory = NULL;
2349 int last_entry_off=0;
2353 bool finished = False;
2354 bool dont_descend = False;
2355 bool out_of_space = False;
2356 int space_remaining;
2357 bool mask_contains_wcard = False;
2358 struct ea_list *ea_list = NULL;
2359 NTSTATUS ntstatus = NT_STATUS_OK;
2360 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2361 TALLOC_CTX *ctx = talloc_tos();
2362 struct dptr_struct *dirptr = NULL;
2363 struct smbd_server_connection *sconn = req->sconn;
2364 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2365 bool backup_priv = false;
2366 bool as_root = false;
2368 if (total_params < 13) {
2369 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2373 dirtype = SVAL(params,0);
2374 maxentries = SVAL(params,2);
2375 findfirst_flags = SVAL(params,4);
2376 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2377 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2378 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2379 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2380 security_token_has_privilege(get_current_nttok(conn),
2383 info_level = SVAL(params,6);
2385 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2386 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2387 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2389 info_level, max_data_bytes));
2392 /* W2K3 seems to treat zero as 1. */
2396 switch (info_level) {
2397 case SMB_FIND_INFO_STANDARD:
2398 case SMB_FIND_EA_SIZE:
2399 case SMB_FIND_EA_LIST:
2400 case SMB_FIND_FILE_DIRECTORY_INFO:
2401 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2402 case SMB_FIND_FILE_NAMES_INFO:
2403 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2404 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2405 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2407 case SMB_FIND_FILE_UNIX:
2408 case SMB_FIND_FILE_UNIX_INFO2:
2409 /* Always use filesystem for UNIX mtime query. */
2410 ask_sharemode = false;
2411 if (!lp_unix_extensions()) {
2412 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2415 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2418 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2422 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2423 params+12, total_params - 12,
2424 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2425 if (!NT_STATUS_IS_OK(ntstatus)) {
2426 reply_nterror(req, ntstatus);
2433 ntstatus = filename_convert_with_privilege(ctx,
2438 &mask_contains_wcard,
2441 ntstatus = filename_convert(ctx, conn,
2442 req->flags2 & FLAGS2_DFS_PATHNAMES,
2445 &mask_contains_wcard,
2449 if (!NT_STATUS_IS_OK(ntstatus)) {
2450 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2451 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2452 ERRSRV, ERRbadpath);
2455 reply_nterror(req, ntstatus);
2459 mask = smb_dname->original_lcomp;
2461 directory = smb_dname->base_name;
2463 p = strrchr_m(directory,'/');
2465 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2466 if((directory[0] == '.') && (directory[1] == '\0')) {
2467 mask = talloc_strdup(ctx,"*");
2469 reply_nterror(req, NT_STATUS_NO_MEMORY);
2472 mask_contains_wcard = True;
2478 if (p == NULL || p == directory) {
2479 /* Ensure we don't have a directory name of "". */
2480 directory = talloc_strdup(talloc_tos(), ".");
2482 reply_nterror(req, NT_STATUS_NO_MEMORY);
2487 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2489 if (info_level == SMB_FIND_EA_LIST) {
2492 if (total_data < 4) {
2493 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2497 ea_size = IVAL(pdata,0);
2498 if (ea_size != total_data) {
2499 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2500 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2501 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2505 if (!lp_ea_support(SNUM(conn))) {
2506 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2510 /* Pull out the list of names. */
2511 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2513 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2518 *ppdata = (char *)SMB_REALLOC(
2519 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2520 if(*ppdata == NULL ) {
2521 reply_nterror(req, NT_STATUS_NO_MEMORY);
2525 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2527 /* Realloc the params space */
2528 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2529 if (*pparams == NULL) {
2530 reply_nterror(req, NT_STATUS_NO_MEMORY);
2535 /* Save the wildcard match and attribs we are using on this directory -
2536 needed as lanman2 assumes these are being saved between calls */
2538 ntstatus = dptr_create(conn,
2546 mask_contains_wcard,
2550 if (!NT_STATUS_IS_OK(ntstatus)) {
2551 reply_nterror(req, ntstatus);
2556 /* Remember this in case we have
2557 to do a findnext. */
2558 dptr_set_priv(dirptr);
2561 dptr_num = dptr_dnum(dirptr);
2562 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2564 /* Initialize per TRANS2_FIND_FIRST operation data */
2565 dptr_init_search_op(dirptr);
2567 /* We don't need to check for VOL here as this is returned by
2568 a different TRANS2 call. */
2570 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2571 directory,lp_dontdescend(ctx, SNUM(conn))));
2572 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2573 dont_descend = True;
2576 space_remaining = max_data_bytes;
2577 out_of_space = False;
2579 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2580 bool got_exact_match = False;
2582 /* this is a heuristic to avoid seeking the dirptr except when
2583 absolutely necessary. It allows for a filename of about 40 chars */
2584 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2585 out_of_space = True;
2588 finished = !get_lanman2_dir_entry(ctx,
2592 mask,dirtype,info_level,
2593 requires_resume_key,dont_descend,
2596 space_remaining, &out_of_space,
2598 &last_entry_off, ea_list);
2601 if (finished && out_of_space)
2604 if (!finished && !out_of_space)
2608 * As an optimisation if we know we aren't looking
2609 * for a wildcard name (ie. the name matches the wildcard exactly)
2610 * then we can finish on any (first) match.
2611 * This speeds up large directory searches. JRA.
2617 /* Ensure space_remaining never goes -ve. */
2618 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2619 space_remaining = 0;
2620 out_of_space = true;
2622 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2626 /* Check if we can close the dirptr */
2627 if(close_after_first || (finished && close_if_end)) {
2628 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2629 dptr_close(sconn, &dptr_num);
2633 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2634 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2635 * the protocol level is less than NT1. Tested with smbclient. JRA.
2636 * This should fix the OS/2 client bug #2335.
2639 if(numentries == 0) {
2640 dptr_close(sconn, &dptr_num);
2641 if (get_Protocol() < PROTOCOL_NT1) {
2642 reply_force_doserror(req, ERRDOS, ERRnofiles);
2645 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2646 ERRDOS, ERRbadfile);
2651 /* At this point pdata points to numentries directory entries. */
2653 /* Set up the return parameter block */
2654 SSVAL(params,0,dptr_num);
2655 SSVAL(params,2,numentries);
2656 SSVAL(params,4,finished);
2657 SSVAL(params,6,0); /* Never an EA error */
2658 SSVAL(params,8,last_entry_off);
2660 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2663 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2664 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2666 reply_nterror(req, NT_STATUS_NO_MEMORY);
2670 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2671 smb_fn_name(req->cmd),
2672 mask, directory, dirtype, numentries ) );
2675 * Force a name mangle here to ensure that the
2676 * mask as an 8.3 name is top of the mangled cache.
2677 * The reasons for this are subtle. Don't remove
2678 * this code unless you know what you are doing
2679 * (see PR#13758). JRA.
2682 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2683 char mangled_name[13];
2684 name_to_8_3(mask, mangled_name, True, conn->params);
2692 TALLOC_FREE(smb_dname);
2696 /****************************************************************************
2697 Reply to a TRANS2_FINDNEXT.
2698 ****************************************************************************/
2700 static void call_trans2findnext(connection_struct *conn,
2701 struct smb_request *req,
2702 char **pparams, int total_params,
2703 char **ppdata, int total_data,
2704 unsigned int max_data_bytes)
2706 /* We must be careful here that we don't return more than the
2707 allowed number of data bytes. If this means returning fewer than
2708 maxentries then so be it. We assume that the redirector has
2709 enough room for the fixed number of parameter bytes it has
2711 char *params = *pparams;
2712 char *pdata = *ppdata;
2718 uint16 findnext_flags;
2719 bool close_after_request;
2721 bool requires_resume_key;
2723 bool mask_contains_wcard = False;
2724 char *resume_name = NULL;
2725 const char *mask = NULL;
2726 const char *directory = NULL;
2730 int i, last_entry_off=0;
2731 bool finished = False;
2732 bool dont_descend = False;
2733 bool out_of_space = False;
2734 int space_remaining;
2735 struct ea_list *ea_list = NULL;
2736 NTSTATUS ntstatus = NT_STATUS_OK;
2737 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2738 TALLOC_CTX *ctx = talloc_tos();
2739 struct dptr_struct *dirptr;
2740 struct smbd_server_connection *sconn = req->sconn;
2741 bool backup_priv = false;
2742 bool as_root = false;
2744 if (total_params < 13) {
2745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2749 dptr_num = SVAL(params,0);
2750 maxentries = SVAL(params,2);
2751 info_level = SVAL(params,4);
2752 resume_key = IVAL(params,6);
2753 findnext_flags = SVAL(params,10);
2754 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2755 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2756 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2757 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2759 if (!continue_bit) {
2760 /* We only need resume_name if continue_bit is zero. */
2761 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2763 total_params - 12, STR_TERMINATE, &ntstatus,
2764 &mask_contains_wcard);
2765 if (!NT_STATUS_IS_OK(ntstatus)) {
2766 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2767 complain (it thinks we're asking for the directory above the shared
2768 path or an invalid name). Catch this as the resume name is only compared, never used in
2769 a file access. JRA. */
2770 srvstr_pull_talloc(ctx, params, req->flags2,
2771 &resume_name, params+12,
2775 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2776 reply_nterror(req, ntstatus);
2782 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2783 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2784 resume_key = %d resume name = %s continue=%d level = %d\n",
2785 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2786 requires_resume_key, resume_key,
2787 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2790 /* W2K3 seems to treat zero as 1. */
2794 switch (info_level) {
2795 case SMB_FIND_INFO_STANDARD:
2796 case SMB_FIND_EA_SIZE:
2797 case SMB_FIND_EA_LIST:
2798 case SMB_FIND_FILE_DIRECTORY_INFO:
2799 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2800 case SMB_FIND_FILE_NAMES_INFO:
2801 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2802 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2803 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2805 case SMB_FIND_FILE_UNIX:
2806 case SMB_FIND_FILE_UNIX_INFO2:
2807 /* Always use filesystem for UNIX mtime query. */
2808 ask_sharemode = false;
2809 if (!lp_unix_extensions()) {
2810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2815 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2819 if (info_level == SMB_FIND_EA_LIST) {
2822 if (total_data < 4) {
2823 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2827 ea_size = IVAL(pdata,0);
2828 if (ea_size != total_data) {
2829 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2830 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2835 if (!lp_ea_support(SNUM(conn))) {
2836 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2840 /* Pull out the list of names. */
2841 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2848 *ppdata = (char *)SMB_REALLOC(
2849 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2850 if(*ppdata == NULL) {
2851 reply_nterror(req, NT_STATUS_NO_MEMORY);
2856 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2858 /* Realloc the params space */
2859 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2860 if(*pparams == NULL ) {
2861 reply_nterror(req, NT_STATUS_NO_MEMORY);
2867 /* Check that the dptr is valid */
2868 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2869 reply_nterror(req, STATUS_NO_MORE_FILES);
2873 directory = dptr_path(sconn, dptr_num);
2875 /* Get the wildcard mask from the dptr */
2876 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2877 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2878 reply_nterror(req, STATUS_NO_MORE_FILES);
2882 /* Get the attr mask from the dptr */
2883 dirtype = dptr_attr(sconn, dptr_num);
2885 backup_priv = dptr_get_priv(dirptr);
2887 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2888 "backup_priv = %d\n",
2889 dptr_num, mask, dirtype,
2891 dptr_TellDir(dirptr),
2894 /* Initialize per TRANS2_FIND_NEXT operation data */
2895 dptr_init_search_op(dirptr);
2897 /* We don't need to check for VOL here as this is returned by
2898 a different TRANS2 call. */
2900 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2901 directory,lp_dontdescend(ctx, SNUM(conn))));
2902 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2903 dont_descend = True;
2906 space_remaining = max_data_bytes;
2907 out_of_space = False;
2915 * Seek to the correct position. We no longer use the resume key but
2916 * depend on the last file name instead.
2919 if(!continue_bit && resume_name && *resume_name) {
2922 long current_pos = 0;
2924 * Remember, name_to_8_3 is called by
2925 * get_lanman2_dir_entry(), so the resume name
2926 * could be mangled. Ensure we check the unmangled name.
2929 if (mangle_is_mangled(resume_name, conn->params)) {
2930 char *new_resume_name = NULL;
2931 mangle_lookup_name_from_8_3(ctx,
2935 if (new_resume_name) {
2936 resume_name = new_resume_name;
2941 * Fix for NT redirector problem triggered by resume key indexes
2942 * changing between directory scans. We now return a resume key of 0
2943 * and instead look for the filename to continue from (also given
2944 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2945 * findfirst/findnext (as is usual) then the directory pointer
2946 * should already be at the correct place.
2949 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2950 } /* end if resume_name && !continue_bit */
2952 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2953 bool got_exact_match = False;
2955 /* this is a heuristic to avoid seeking the dirptr except when
2956 absolutely necessary. It allows for a filename of about 40 chars */
2957 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2958 out_of_space = True;
2961 finished = !get_lanman2_dir_entry(ctx,
2965 mask,dirtype,info_level,
2966 requires_resume_key,dont_descend,
2969 space_remaining, &out_of_space,
2971 &last_entry_off, ea_list);
2974 if (finished && out_of_space)
2977 if (!finished && !out_of_space)
2981 * As an optimisation if we know we aren't looking
2982 * for a wildcard name (ie. the name matches the wildcard exactly)
2983 * then we can finish on any (first) match.
2984 * This speeds up large directory searches. JRA.
2990 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2993 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2994 smb_fn_name(req->cmd),
2995 mask, directory, dirtype, numentries ) );
2997 /* Check if we can close the dirptr */
2998 if(close_after_request || (finished && close_if_end)) {
2999 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3000 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3007 /* Set up the return parameter block */
3008 SSVAL(params,0,numentries);
3009 SSVAL(params,2,finished);
3010 SSVAL(params,4,0); /* Never an EA error */
3011 SSVAL(params,6,last_entry_off);
3013 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3019 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3021 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3025 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3027 SMB_ASSERT(extended_info != NULL);
3029 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3030 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3031 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3032 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3033 #ifdef SAMBA_VERSION_REVISION
3034 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3036 extended_info->samba_subversion = 0;
3037 #ifdef SAMBA_VERSION_RC_RELEASE
3038 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3040 #ifdef SAMBA_VERSION_PRE_RELEASE
3041 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3044 #ifdef SAMBA_VERSION_VENDOR_PATCH
3045 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3047 extended_info->samba_gitcommitdate = 0;
3048 #ifdef SAMBA_VERSION_COMMIT_TIME
3049 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3052 memset(extended_info->samba_version_string, 0,
3053 sizeof(extended_info->samba_version_string));
3055 snprintf (extended_info->samba_version_string,
3056 sizeof(extended_info->samba_version_string),
3057 "%s", samba_version_string());
3060 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3061 TALLOC_CTX *mem_ctx,
3062 uint16_t info_level,
3064 unsigned int max_data_bytes,
3065 size_t *fixed_portion,
3066 struct smb_filename *fname,
3070 char *pdata, *end_data;
3071 int data_len = 0, len;
3072 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3073 int snum = SNUM(conn);
3074 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3075 char *filename = NULL;
3076 uint32 additional_flags = 0;
3077 struct smb_filename smb_fname;
3079 NTSTATUS status = NT_STATUS_OK;
3081 if (fname == NULL || fname->base_name == NULL) {
3084 filename = fname->base_name;
3088 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3089 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3090 "info level (0x%x) on IPC$.\n",
3091 (unsigned int)info_level));
3092 return NT_STATUS_ACCESS_DENIED;
3096 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3098 ZERO_STRUCT(smb_fname);
3099 smb_fname.base_name = discard_const_p(char, filename);
3101 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3102 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3103 return map_nt_error_from_unix(errno);
3108 *ppdata = (char *)SMB_REALLOC(
3109 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3110 if (*ppdata == NULL) {
3111 return NT_STATUS_NO_MEMORY;
3115 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3116 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3120 switch (info_level) {
3121 case SMB_INFO_ALLOCATION:
3123 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3125 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3126 return map_nt_error_from_unix(errno);
3129 block_size = lp_block_size(snum);
3130 if (bsize < block_size) {
3131 uint64_t factor = block_size/bsize;
3136 if (bsize > block_size) {
3137 uint64_t factor = bsize/block_size;
3142 bytes_per_sector = 512;
3143 sectors_per_unit = bsize/bytes_per_sector;
3145 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3146 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3147 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3149 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3150 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3151 SIVAL(pdata,l1_cUnit,dsize);
3152 SIVAL(pdata,l1_cUnitAvail,dfree);
3153 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3157 case SMB_INFO_VOLUME:
3158 /* Return volume name */
3160 * Add volume serial number - hash of a combination of
3161 * the called hostname and the service name.
3163 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3165 * Win2k3 and previous mess this up by sending a name length
3166 * one byte short. I believe only older clients (OS/2 Win9x) use
3167 * this call so try fixing this by adding a terminating null to
3168 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3172 pdata+l2_vol_szVolLabel, vname,
3173 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3174 STR_NOALIGN|STR_TERMINATE);
3175 SCVAL(pdata,l2_vol_cch,len);
3176 data_len = l2_vol_szVolLabel + len;
3177 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3178 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3182 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3183 case SMB_FS_ATTRIBUTE_INFORMATION:
3185 additional_flags = 0;
3186 #if defined(HAVE_SYS_QUOTAS)
3187 additional_flags |= FILE_VOLUME_QUOTAS;
3190 if(lp_nt_acl_support(SNUM(conn))) {
3191 additional_flags |= FILE_PERSISTENT_ACLS;
3194 /* Capabilities are filled in at connection time through STATVFS call */
3195 additional_flags |= conn->fs_capabilities;
3196 additional_flags |= lp_parm_int(conn->params->service,
3197 "share", "fake_fscaps",
3200 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3201 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3202 additional_flags); /* FS ATTRIBUTES */
3204 SIVAL(pdata,4,255); /* Max filename component length */
3205 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3206 and will think we can't do long filenames */
3207 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3208 PTR_DIFF(end_data, pdata+12),
3211 data_len = 12 + len;
3212 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3213 /* the client only requested a portion of the
3215 data_len = max_data_bytes;
3216 status = STATUS_BUFFER_OVERFLOW;
3218 *fixed_portion = 16;
3221 case SMB_QUERY_FS_LABEL_INFO:
3222 case SMB_FS_LABEL_INFORMATION:
3223 len = srvstr_push(pdata, flags2, pdata+4, vname,
3224 PTR_DIFF(end_data, pdata+4), 0);
3229 case SMB_QUERY_FS_VOLUME_INFO:
3230 case SMB_FS_VOLUME_INFORMATION:
3233 * Add volume serial number - hash of a combination of
3234 * the called hostname and the service name.
3236 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3237 (str_checksum(get_local_machine_name())<<16));
3239 /* Max label len is 32 characters. */
3240 len = srvstr_push(pdata, flags2, pdata+18, vname,
3241 PTR_DIFF(end_data, pdata+18),
3243 SIVAL(pdata,12,len);
3246 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3247 (int)strlen(vname),vname,
3248 lp_servicename(talloc_tos(), snum)));
3249 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3250 /* the client only requested a portion of the
3252 data_len = max_data_bytes;
3253 status = STATUS_BUFFER_OVERFLOW;
3255 *fixed_portion = 24;
3258 case SMB_QUERY_FS_SIZE_INFO:
3259 case SMB_FS_SIZE_INFORMATION:
3261 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3263 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3264 return map_nt_error_from_unix(errno);
3266 block_size = lp_block_size(snum);
3267 if (bsize < block_size) {
3268 uint64_t factor = block_size/bsize;
3273 if (bsize > block_size) {
3274 uint64_t factor = bsize/block_size;
3279 bytes_per_sector = 512;
3280 sectors_per_unit = bsize/bytes_per_sector;
3281 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3282 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3283 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3284 SBIG_UINT(pdata,0,dsize);
3285 SBIG_UINT(pdata,8,dfree);
3286 SIVAL(pdata,16,sectors_per_unit);
3287 SIVAL(pdata,20,bytes_per_sector);
3288 *fixed_portion = 24;
3292 case SMB_FS_FULL_SIZE_INFORMATION:
3294 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3296 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3297 return map_nt_error_from_unix(errno);
3299 block_size = lp_block_size(snum);
3300 if (bsize < block_size) {
3301 uint64_t factor = block_size/bsize;
3306 if (bsize > block_size) {
3307 uint64_t factor = bsize/block_size;
3312 bytes_per_sector = 512;
3313 sectors_per_unit = bsize/bytes_per_sector;
3314 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3315 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3316 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3317 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3318 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3319 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3320 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3321 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3322 *fixed_portion = 32;
3326 case SMB_QUERY_FS_DEVICE_INFO:
3327 case SMB_FS_DEVICE_INFORMATION:
3329 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3331 if (!CAN_WRITE(conn)) {
3332 characteristics |= FILE_READ_ONLY_DEVICE;
3335 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3336 SIVAL(pdata,4,characteristics);
3341 #ifdef HAVE_SYS_QUOTAS
3342 case SMB_FS_QUOTA_INFORMATION:
3344 * what we have to send --metze:
3346 * Unknown1: 24 NULL bytes
3347 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3348 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3349 * Quota Flags: 2 byte :
3350 * Unknown3: 6 NULL bytes
3354 * details for Quota Flags:
3356 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3357 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3358 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3359 * 0x0001 Enable Quotas: enable quota for this fs
3363 /* we need to fake up a fsp here,
3364 * because its not send in this call
3367 SMB_NTQUOTA_STRUCT quotas;
3370 ZERO_STRUCT(quotas);
3373 fsp.fnum = FNUM_FIELD_INVALID;
3376 if (get_current_uid(conn) != 0) {
3377 DEBUG(0,("set_user_quota: access_denied "
3378 "service [%s] user [%s]\n",
3379 lp_servicename(talloc_tos(), SNUM(conn)),
3380 conn->session_info->unix_info->unix_name));
3381 return NT_STATUS_ACCESS_DENIED;
3384 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3385 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3386 return map_nt_error_from_unix(errno);
3391 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3392 lp_servicename(talloc_tos(), SNUM(conn))));
3394 /* Unknown1 24 NULL bytes*/
3395 SBIG_UINT(pdata,0,(uint64_t)0);
3396 SBIG_UINT(pdata,8,(uint64_t)0);
3397 SBIG_UINT(pdata,16,(uint64_t)0);
3399 /* Default Soft Quota 8 bytes */
3400 SBIG_UINT(pdata,24,quotas.softlim);
3402 /* Default Hard Quota 8 bytes */
3403 SBIG_UINT(pdata,32,quotas.hardlim);
3405 /* Quota flag 2 bytes */
3406 SSVAL(pdata,40,quotas.qflags);
3408 /* Unknown3 6 NULL bytes */
3414 #endif /* HAVE_SYS_QUOTAS */
3415 case SMB_FS_OBJECTID_INFORMATION:
3417 unsigned char objid[16];
3418 struct smb_extended_info extended_info;
3419 memcpy(pdata,create_volume_objectid(conn, objid),16);
3420 samba_extended_info_version (&extended_info);
3421 SIVAL(pdata,16,extended_info.samba_magic);
3422 SIVAL(pdata,20,extended_info.samba_version);
3423 SIVAL(pdata,24,extended_info.samba_subversion);
3424 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3425 memcpy(pdata+36,extended_info.samba_version_string,28);
3431 * Query the version and capabilities of the CIFS UNIX extensions
3435 case SMB_QUERY_CIFS_UNIX_INFO:
3437 bool large_write = lp_min_receive_file_size() &&
3438 !srv_is_signing_active(conn->sconn);
3439 bool large_read = !srv_is_signing_active(conn->sconn);
3440 int encrypt_caps = 0;
3442 if (!lp_unix_extensions()) {
3443 return NT_STATUS_INVALID_LEVEL;
3446 switch (conn->encrypt_level) {
3447 case SMB_SIGNING_OFF:
3450 case SMB_SIGNING_IF_REQUIRED:
3451 case SMB_SIGNING_DEFAULT:
3452 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3454 case SMB_SIGNING_REQUIRED:
3455 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3456 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3457 large_write = false;
3463 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3464 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3466 /* We have POSIX ACLs, pathname, encryption,
3467 * large read/write, and locking capability. */
3469 SBIG_UINT(pdata,4,((uint64_t)(
3470 CIFS_UNIX_POSIX_ACLS_CAP|
3471 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3472 CIFS_UNIX_FCNTL_LOCKS_CAP|
3473 CIFS_UNIX_EXTATTR_CAP|
3474 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3476 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3478 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3482 case SMB_QUERY_POSIX_FS_INFO:
3485 vfs_statvfs_struct svfs;
3487 if (!lp_unix_extensions()) {
3488 return NT_STATUS_INVALID_LEVEL;
3491 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3495 SIVAL(pdata,0,svfs.OptimalTransferSize);
3496 SIVAL(pdata,4,svfs.BlockSize);
3497 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3498 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3499 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3500 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3501 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3502 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3503 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3505 } else if (rc == EOPNOTSUPP) {
3506 return NT_STATUS_INVALID_LEVEL;
3507 #endif /* EOPNOTSUPP */
3509 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3510 return NT_STATUS_DOS(ERRSRV, ERRerror);
3515 case SMB_QUERY_POSIX_WHOAMI:
3521 if (!lp_unix_extensions()) {
3522 return NT_STATUS_INVALID_LEVEL;
3525 if (max_data_bytes < 40) {
3526 return NT_STATUS_BUFFER_TOO_SMALL;
3529 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3530 flags |= SMB_WHOAMI_GUEST;
3533 /* NOTE: 8 bytes for UID/GID, irrespective of native
3534 * platform size. This matches
3535 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3537 data_len = 4 /* flags */
3544 + 4 /* pad/reserved */
3545 + (conn->session_info->unix_token->ngroups * 8)
3547 + (conn->session_info->security_token->num_sids *
3551 SIVAL(pdata, 0, flags);
3552 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3554 (uint64_t)conn->session_info->unix_token->uid);
3555 SBIG_UINT(pdata, 16,
3556 (uint64_t)conn->session_info->unix_token->gid);
3559 if (data_len >= max_data_bytes) {
3560 /* Potential overflow, skip the GIDs and SIDs. */
3562 SIVAL(pdata, 24, 0); /* num_groups */
3563 SIVAL(pdata, 28, 0); /* num_sids */
3564 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3565 SIVAL(pdata, 36, 0); /* reserved */
3571 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3572 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3574 /* We walk the SID list twice, but this call is fairly
3575 * infrequent, and I don't expect that it's performance
3576 * sensitive -- jpeach
3578 for (i = 0, sid_bytes = 0;
3579 i < conn->session_info->security_token->num_sids; ++i) {
3580 sid_bytes += ndr_size_dom_sid(
3581 &conn->session_info->security_token->sids[i],
3585 /* SID list byte count */
3586 SIVAL(pdata, 32, sid_bytes);
3588 /* 4 bytes pad/reserved - must be zero */
3589 SIVAL(pdata, 36, 0);
3593 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3594 SBIG_UINT(pdata, data_len,
3595 (uint64_t)conn->session_info->unix_token->groups[i]);
3601 i < conn->session_info->security_token->num_sids; ++i) {
3602 int sid_len = ndr_size_dom_sid(
3603 &conn->session_info->security_token->sids[i],
3606 sid_linearize(pdata + data_len, sid_len,
3607 &conn->session_info->security_token->sids[i]);
3608 data_len += sid_len;
3614 case SMB_MAC_QUERY_FS_INFO:
3616 * Thursby MAC extension... ONLY on NTFS filesystems
3617 * once we do streams then we don't need this
3619 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3621 SIVAL(pdata,84,0x100); /* Don't support mac... */
3626 return NT_STATUS_INVALID_LEVEL;
3629 *ret_data_len = data_len;
3633 /****************************************************************************
3634 Reply to a TRANS2_QFSINFO (query filesystem info).
3635 ****************************************************************************/
3637 static void call_trans2qfsinfo(connection_struct *conn,
3638 struct smb_request *req,
3639 char **pparams, int total_params,
3640 char **ppdata, int total_data,
3641 unsigned int max_data_bytes)
3643 char *params = *pparams;
3644 uint16_t info_level;
3646 size_t fixed_portion;
3649 if (total_params < 2) {
3650 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3654 info_level = SVAL(params,0);
3656 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3657 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3658 DEBUG(0,("call_trans2qfsinfo: encryption required "
3659 "and info level 0x%x sent.\n",
3660 (unsigned int)info_level));
3661 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3666 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3668 status = smbd_do_qfsinfo(conn, req,
3675 if (!NT_STATUS_IS_OK(status)) {
3676 reply_nterror(req, status);
3680 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3683 DEBUG( 4, ( "%s info_level = %d\n",
3684 smb_fn_name(req->cmd), info_level) );
3689 /****************************************************************************
3690 Reply to a TRANS2_SETFSINFO (set filesystem info).
3691 ****************************************************************************/
3693 static void call_trans2setfsinfo(connection_struct *conn,
3694 struct smb_request *req,
3695 char **pparams, int total_params,
3696 char **ppdata, int total_data,
3697 unsigned int max_data_bytes)
3699 struct smbd_server_connection *sconn = req->sconn;
3700 char *pdata = *ppdata;
3701 char *params = *pparams;
3704 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3705 lp_servicename(talloc_tos(), SNUM(conn))));
3708 if (total_params < 4) {
3709 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3715 info_level = SVAL(params,2);
3718 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3719 info_level != SMB_SET_CIFS_UNIX_INFO) {
3720 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3721 "info level (0x%x) on IPC$.\n",
3722 (unsigned int)info_level));
3723 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3728 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3729 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3730 DEBUG(0,("call_trans2setfsinfo: encryption required "
3731 "and info level 0x%x sent.\n",
3732 (unsigned int)info_level));
3733 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3738 switch(info_level) {
3739 case SMB_SET_CIFS_UNIX_INFO:
3740 if (!lp_unix_extensions()) {
3741 DEBUG(2,("call_trans2setfsinfo: "
3742 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3743 "unix extensions off\n"));
3745 NT_STATUS_INVALID_LEVEL);
3749 /* There should be 12 bytes of capabilities set. */
3750 if (total_data < 12) {
3753 NT_STATUS_INVALID_PARAMETER);
3756 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3757 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3758 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3759 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3760 /* Just print these values for now. */
3761 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3762 "major = %u, minor = %u cap_low = 0x%x, "
3764 (unsigned int)sconn->
3765 smb1.unix_info.client_major,
3766 (unsigned int)sconn->
3767 smb1.unix_info.client_minor,
3768 (unsigned int)sconn->
3769 smb1.unix_info.client_cap_low,
3770 (unsigned int)sconn->
3771 smb1.unix_info.client_cap_high));
3773 /* Here is where we must switch to posix pathname processing... */
3774 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3775 lp_set_posix_pathnames();
3776 mangle_change_to_posix();
3779 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3780 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3781 /* Client that knows how to do posix locks,
3782 * but not posix open/mkdir operations. Set a
3783 * default type for read/write checks. */
3785 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3790 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3793 size_t param_len = 0;
3794 size_t data_len = total_data;
3796 if (!lp_unix_extensions()) {
3799 NT_STATUS_INVALID_LEVEL);
3803 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3806 NT_STATUS_NOT_SUPPORTED);
3810 if (req->sconn->smb1.echo_handler.trusted_fde) {
3811 DEBUG( 2,("call_trans2setfsinfo: "
3812 "request transport encryption disabled"
3813 "with 'fork echo handler = yes'\n"));
3816 NT_STATUS_NOT_SUPPORTED);
3820 DEBUG( 4,("call_trans2setfsinfo: "
3821 "request transport encryption.\n"));
3823 status = srv_request_encryption_setup(conn,
3824 (unsigned char **)ppdata,
3826 (unsigned char **)pparams,
3829 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3830 !NT_STATUS_IS_OK(status)) {
3831 reply_nterror(req, status);
3835 send_trans2_replies(conn, req,
3843 if (NT_STATUS_IS_OK(status)) {
3844 /* Server-side transport
3845 * encryption is now *on*. */
3846 status = srv_encryption_start(conn);
3847 if (!NT_STATUS_IS_OK(status)) {
3848 char *reason = talloc_asprintf(talloc_tos(),
3849 "Failure in setting "
3850 "up encrypted transport: %s",
3852 exit_server_cleanly(reason);
3858 case SMB_FS_QUOTA_INFORMATION:
3860 files_struct *fsp = NULL;
3861 SMB_NTQUOTA_STRUCT quotas;
3863 ZERO_STRUCT(quotas);
3866 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3867 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3868 lp_servicename(talloc_tos(), SNUM(conn)),
3869 conn->session_info->unix_info->unix_name));
3870 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3874 /* note: normaly there're 48 bytes,
3875 * but we didn't use the last 6 bytes for now
3878 fsp = file_fsp(req, SVAL(params,0));
3880 if (!check_fsp_ntquota_handle(conn, req,
3882 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3884 req, NT_STATUS_INVALID_HANDLE);
3888 if (total_data < 42) {
3889 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3893 NT_STATUS_INVALID_PARAMETER);
3897 /* unknown_1 24 NULL bytes in pdata*/
3899 /* the soft quotas 8 bytes (uint64_t)*/
3900 quotas.softlim = BVAL(pdata,24);
3902 /* the hard quotas 8 bytes (uint64_t)*/
3903 quotas.hardlim = BVAL(pdata,32);
3905 /* quota_flags 2 bytes **/
3906 quotas.qflags = SVAL(pdata,40);
3908 /* unknown_2 6 NULL bytes follow*/
3910 /* now set the quotas */
3911 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3912 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3913 reply_nterror(req, map_nt_error_from_unix(errno));
3920 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3922 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3928 * sending this reply works fine,
3929 * but I'm not sure it's the same
3930 * like windows do...
3933 reply_outbuf(req, 10, 0);
3936 #if defined(HAVE_POSIX_ACLS)
3937 /****************************************************************************
3938 Utility function to count the number of entries in a POSIX acl.
3939 ****************************************************************************/
3941 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3943 unsigned int ace_count = 0;
3944 int entry_id = SMB_ACL_FIRST_ENTRY;
3945 SMB_ACL_ENTRY_T entry;
3947 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3949 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3950 entry_id = SMB_ACL_NEXT_ENTRY;
3957 /****************************************************************************
3958 Utility function to marshall a POSIX acl into wire format.
3959 ****************************************************************************/
3961 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3963 int entry_id = SMB_ACL_FIRST_ENTRY;
3964 SMB_ACL_ENTRY_T entry;
3966 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3967 SMB_ACL_TAG_T tagtype;
3968 SMB_ACL_PERMSET_T permset;
3969 unsigned char perms = 0;
3970 unsigned int own_grp;
3973 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3974 entry_id = SMB_ACL_NEXT_ENTRY;
3977 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3978 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3982 if (sys_acl_get_permset(entry, &permset) == -1) {
3983 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3987 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3988 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3989 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3991 SCVAL(pdata,1,perms);
3994 case SMB_ACL_USER_OBJ:
3995 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3996 own_grp = (unsigned int)pst->st_ex_uid;
3997 SIVAL(pdata,2,own_grp);
4002 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4004 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4007 own_grp = (unsigned int)*puid;
4008 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4009 SIVAL(pdata,2,own_grp);
4013 case SMB_ACL_GROUP_OBJ:
4014 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4015 own_grp = (unsigned int)pst->st_ex_gid;
4016 SIVAL(pdata,2,own_grp);
4021 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4023 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4026 own_grp = (unsigned int)*pgid;
4027 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4028 SIVAL(pdata,2,own_grp);
4033 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4034 SIVAL(pdata,2,0xFFFFFFFF);
4035 SIVAL(pdata,6,0xFFFFFFFF);
4038 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4039 SIVAL(pdata,2,0xFFFFFFFF);
4040 SIVAL(pdata,6,0xFFFFFFFF);
4043 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4046 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4053 /****************************************************************************
4054 Store the FILE_UNIX_BASIC info.
4055 ****************************************************************************/
4057 static char *store_file_unix_basic(connection_struct *conn,
4060 const SMB_STRUCT_STAT *psbuf)
4062 uint64_t file_index = get_FileIndex(conn, psbuf);
4065 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4066 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4068 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4071 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4074 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4075 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4076 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4079 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4083 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4087 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4090 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4091 devno = psbuf->st_ex_rdev;
4093 devno = psbuf->st_ex_dev;
4096 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4100 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4104 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4107 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4111 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4118 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4119 * the chflags(2) (or equivalent) flags.
4121 * XXX: this really should be behind the VFS interface. To do this, we would
4122 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4123 * Each VFS module could then implement its own mapping as appropriate for the
4124 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4126 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4130 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4134 { UF_IMMUTABLE, EXT_IMMUTABLE },
4138 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4142 { UF_HIDDEN, EXT_HIDDEN },
4145 /* Do not remove. We need to guarantee that this array has at least one
4146 * entry to build on HP-UX.
4152 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4153 uint32 *smb_fflags, uint32 *smb_fmask)
4157 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4158 *smb_fmask |= info2_flags_map[i].smb_fflag;
4159 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4160 *smb_fflags |= info2_flags_map[i].smb_fflag;
4165 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4166 const uint32 smb_fflags,
4167 const uint32 smb_fmask,
4170 uint32 max_fmask = 0;
4173 *stat_fflags = psbuf->st_ex_flags;
4175 /* For each flags requested in smb_fmask, check the state of the
4176 * corresponding flag in smb_fflags and set or clear the matching
4180 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4181 max_fmask |= info2_flags_map[i].smb_fflag;
4182 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4183 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4184 *stat_fflags |= info2_flags_map[i].stat_fflag;
4186 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4191 /* If smb_fmask is asking to set any bits that are not supported by
4192 * our flag mappings, we should fail.
4194 if ((smb_fmask & max_fmask) != smb_fmask) {
4202 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4203 * of file flags and birth (create) time.
4205 static char *store_file_unix_basic_info2(connection_struct *conn,
4208 const SMB_STRUCT_STAT *psbuf)
4210 uint32 file_flags = 0;
4211 uint32 flags_mask = 0;
4213 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4215 /* Create (birth) time 64 bit */
4216 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4219 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4220 SIVAL(pdata, 0, file_flags); /* flags */
4221 SIVAL(pdata, 4, flags_mask); /* mask */
4227 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4228 const struct stream_struct *streams,
4230 unsigned int max_data_bytes,
4231 unsigned int *data_size)
4234 unsigned int ofs = 0;
4236 if (max_data_bytes < 32) {
4237 return NT_STATUS_INFO_LENGTH_MISMATCH;
4240 for (i = 0; i < num_streams; i++) {
4241 unsigned int next_offset;
4243 smb_ucs2_t *namebuf;
4245 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4246 streams[i].name, &namelen) ||
4249 return NT_STATUS_INVALID_PARAMETER;
4253 * name_buf is now null-terminated, we need to marshall as not
4260 * We cannot overflow ...
4262 if ((ofs + 24 + namelen) > max_data_bytes) {
4263 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4265 TALLOC_FREE(namebuf);
4266 return STATUS_BUFFER_OVERFLOW;
4269 SIVAL(data, ofs+4, namelen);
4270 SOFF_T(data, ofs+8, streams[i].size);
4271 SOFF_T(data, ofs+16, streams[i].alloc_size);
4272 memcpy(data+ofs+24, namebuf, namelen);
4273 TALLOC_FREE(namebuf);
4275 next_offset = ofs + 24 + namelen;
4277 if (i == num_streams-1) {
4278 SIVAL(data, ofs, 0);
4281 unsigned int align = ndr_align_size(next_offset, 8);
4283 if ((next_offset + align) > max_data_bytes) {
4284 DEBUG(10, ("refusing to overflow align "
4285 "reply at stream %u\n",
4287 TALLOC_FREE(namebuf);
4288 return STATUS_BUFFER_OVERFLOW;
4291 memset(data+next_offset, 0, align);
4292 next_offset += align;
4294 SIVAL(data, ofs, next_offset - ofs);
4301 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4305 return NT_STATUS_OK;
4308 /****************************************************************************
4309 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4310 ****************************************************************************/
4312 static void call_trans2qpipeinfo(connection_struct *conn,
4313 struct smb_request *req,
4314 unsigned int tran_call,
4315 char **pparams, int total_params,
4316 char **ppdata, int total_data,
4317 unsigned int max_data_bytes)
4319 char *params = *pparams;
4320 char *pdata = *ppdata;
4321 unsigned int data_size = 0;
4322 unsigned int param_size = 2;
4327 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4331 if (total_params < 4) {
4332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4336 fsp = file_fsp(req, SVAL(params,0));
4337 if (!fsp_is_np(fsp)) {
4338 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4342 info_level = SVAL(params,2);
4344 *pparams = (char *)SMB_REALLOC(*pparams,2);
4345 if (*pparams == NULL) {
4346 reply_nterror(req, NT_STATUS_NO_MEMORY);
4351 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4352 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4353 if (*ppdata == NULL ) {
4354 reply_nterror(req, NT_STATUS_NO_MEMORY);
4359 switch (info_level) {
4360 case SMB_FILE_STANDARD_INFORMATION:
4362 SOFF_T(pdata,0,4096LL);
4369 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4373 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4379 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4380 TALLOC_CTX *mem_ctx,
4381 uint16_t info_level,
4383 struct smb_filename *smb_fname,
4384 bool delete_pending,
4385 struct timespec write_time_ts,
4386 struct ea_list *ea_list,
4387 int lock_data_count,
4390 unsigned int max_data_bytes,
4391 size_t *fixed_portion,
4393 unsigned int *pdata_size)
4395 char *pdata = *ppdata;
4396 char *dstart, *dend;
4397 unsigned int data_size;
4398 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4399 time_t create_time, mtime, atime, c_time;
4400 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4407 uint64_t file_size = 0;
4409 uint64_t allocation_size = 0;
4410 uint64_t file_index = 0;
4411 uint32_t access_mask = 0;
4413 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4414 return NT_STATUS_INVALID_LEVEL;
4417 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4418 smb_fname_str_dbg(smb_fname),
4420 info_level, max_data_bytes));
4422 mode = dos_mode(conn, smb_fname);
4423 nlink = psbuf->st_ex_nlink;
4425 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4429 if ((nlink > 0) && delete_pending) {
4433 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4434 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4435 if (*ppdata == NULL) {
4436 return NT_STATUS_NO_MEMORY;
4440 dend = dstart + data_size - 1;
4442 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4443 update_stat_ex_mtime(psbuf, write_time_ts);
4446 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4447 mtime_ts = psbuf->st_ex_mtime;
4448 atime_ts = psbuf->st_ex_atime;
4449 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4451 if (lp_dos_filetime_resolution(SNUM(conn))) {
4452 dos_filetime_timespec(&create_time_ts);
4453 dos_filetime_timespec(&mtime_ts);
4454 dos_filetime_timespec(&atime_ts);
4455 dos_filetime_timespec(&ctime_ts);
4458 create_time = convert_timespec_to_time_t(create_time_ts);
4459 mtime = convert_timespec_to_time_t(mtime_ts);
4460 atime = convert_timespec_to_time_t(atime_ts);
4461 c_time = convert_timespec_to_time_t(ctime_ts);
4463 p = strrchr_m(smb_fname->base_name,'/');
4465 base_name = smb_fname->base_name;
4469 /* NT expects the name to be in an exact form of the *full*
4470 filename. See the trans2 torture test */
4471 if (ISDOT(base_name)) {
4472 dos_fname = talloc_strdup(mem_ctx, "\\");
4474 return NT_STATUS_NO_MEMORY;
4477 dos_fname = talloc_asprintf(mem_ctx,
4479 smb_fname->base_name);
4481 return NT_STATUS_NO_MEMORY;
4483 if (is_ntfs_stream_smb_fname(smb_fname)) {
4484 dos_fname = talloc_asprintf(dos_fname, "%s",
4485 smb_fname->stream_name);
4487 return NT_STATUS_NO_MEMORY;
4491 string_replace(dos_fname, '/', '\\');
4494 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4497 /* Do we have this path open ? */
4499 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4500 fsp1 = file_find_di_first(conn->sconn, fileid);
4501 if (fsp1 && fsp1->initial_allocation_size) {
4502 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4506 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4507 file_size = get_file_size_stat(psbuf);
4511 pos = fsp->fh->position_information;
4515 access_mask = fsp->access_mask;
4517 /* GENERIC_EXECUTE mapping from Windows */
4518 access_mask = 0x12019F;
4521 /* This should be an index number - looks like
4524 I think this causes us to fail the IFSKIT
4525 BasicFileInformationTest. -tpot */
4526 file_index = get_FileIndex(conn, psbuf);
4530 switch (info_level) {
4531 case SMB_INFO_STANDARD:
4532 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4534 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4535 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4536 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4537 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4538 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4539 SSVAL(pdata,l1_attrFile,mode);
4542 case SMB_INFO_QUERY_EA_SIZE:
4544 unsigned int ea_size =
4545 estimate_ea_size(conn, fsp,
4547 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4549 srv_put_dos_date2(pdata,0,create_time);
4550 srv_put_dos_date2(pdata,4,atime);
4551 srv_put_dos_date2(pdata,8,mtime); /* write time */
4552 SIVAL(pdata,12,(uint32)file_size);
4553 SIVAL(pdata,16,(uint32)allocation_size);
4554 SSVAL(pdata,20,mode);
4555 SIVAL(pdata,22,ea_size);
4559 case SMB_INFO_IS_NAME_VALID:
4560 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4562 /* os/2 needs this ? really ?*/
4563 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4565 /* This is only reached for qpathinfo */
4569 case SMB_INFO_QUERY_EAS_FROM_LIST:
4571 size_t total_ea_len = 0;
4572 struct ea_list *ea_file_list = NULL;
4573 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4576 get_ea_list_from_file(mem_ctx, conn, fsp,
4578 &total_ea_len, &ea_file_list);
4579 if (!NT_STATUS_IS_OK(status)) {
4583 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4585 if (!ea_list || (total_ea_len > data_size)) {
4587 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4591 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4595 case SMB_INFO_QUERY_ALL_EAS:
4597 /* We have data_size bytes to put EA's into. */
4598 size_t total_ea_len = 0;
4599 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4601 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4603 &total_ea_len, &ea_list);
4604 if (!NT_STATUS_IS_OK(status)) {
4608 if (!ea_list || (total_ea_len > data_size)) {
4610 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4614 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4618 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4620 /* This is FileFullEaInformation - 0xF which maps to
4621 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4623 /* We have data_size bytes to put EA's into. */
4624 size_t total_ea_len = 0;
4625 struct ea_list *ea_file_list = NULL;
4627 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4629 /*TODO: add filtering and index handling */
4632 get_ea_list_from_file(mem_ctx, conn, fsp,
4634 &total_ea_len, &ea_file_list);
4635 if (!NT_STATUS_IS_OK(status)) {
4638 if (!ea_file_list) {
4639 return NT_STATUS_NO_EAS_ON_FILE;
4642 status = fill_ea_chained_buffer(mem_ctx,
4646 conn, ea_file_list);
4647 if (!NT_STATUS_IS_OK(status)) {
4653 case SMB_FILE_BASIC_INFORMATION:
4654 case SMB_QUERY_FILE_BASIC_INFO:
4656 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4657 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4658 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4660 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4664 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4665 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4666 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4667 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4668 SIVAL(pdata,32,mode);
4670 DEBUG(5,("SMB_QFBI - "));
4671 DEBUG(5,("create: %s ", ctime(&create_time)));
4672 DEBUG(5,("access: %s ", ctime(&atime)));
4673 DEBUG(5,("write: %s ", ctime(&mtime)));
4674 DEBUG(5,("change: %s ", ctime(&c_time)));
4675 DEBUG(5,("mode: %x\n", mode));
4676 *fixed_portion = data_size;
4679 case SMB_FILE_STANDARD_INFORMATION:
4680 case SMB_QUERY_FILE_STANDARD_INFO:
4682 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4684 SOFF_T(pdata,0,allocation_size);
4685 SOFF_T(pdata,8,file_size);
4686 SIVAL(pdata,16,nlink);
4687 SCVAL(pdata,20,delete_pending?1:0);
4688 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4689 SSVAL(pdata,22,0); /* Padding. */
4690 *fixed_portion = 24;
4693 case SMB_FILE_EA_INFORMATION:
4694 case SMB_QUERY_FILE_EA_INFO:
4696 unsigned int ea_size =
4697 estimate_ea_size(conn, fsp, smb_fname);
4698 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4701 SIVAL(pdata,0,ea_size);
4705 /* Get the 8.3 name - used if NT SMB was negotiated. */
4706 case SMB_QUERY_FILE_ALT_NAME_INFO:
4707 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4710 char mangled_name[13];
4711 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4712 if (!name_to_8_3(base_name,mangled_name,
4713 True,conn->params)) {
4714 return NT_STATUS_NO_MEMORY;
4716 len = srvstr_push(dstart, flags2,
4717 pdata+4, mangled_name,
4718 PTR_DIFF(dend, pdata+4),
4720 data_size = 4 + len;
4726 case SMB_QUERY_FILE_NAME_INFO:
4730 this must be *exactly* right for ACLs on mapped drives to work
4732 len = srvstr_push(dstart, flags2,
4734 PTR_DIFF(dend, pdata+4),
4736 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4737 data_size = 4 + len;
4742 case SMB_FILE_ALLOCATION_INFORMATION:
4743 case SMB_QUERY_FILE_ALLOCATION_INFO:
4744 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4746 SOFF_T(pdata,0,allocation_size);
4749 case SMB_FILE_END_OF_FILE_INFORMATION:
4750 case SMB_QUERY_FILE_END_OF_FILEINFO:
4751 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4753 SOFF_T(pdata,0,file_size);
4756 case SMB_QUERY_FILE_ALL_INFO:
4757 case SMB_FILE_ALL_INFORMATION:
4760 unsigned int ea_size =
4761 estimate_ea_size(conn, fsp, smb_fname);
4762 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4763 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4764 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4765 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4766 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4767 SIVAL(pdata,32,mode);
4768 SIVAL(pdata,36,0); /* padding. */
4770 SOFF_T(pdata,0,allocation_size);
4771 SOFF_T(pdata,8,file_size);
4772 SIVAL(pdata,16,nlink);
4773 SCVAL(pdata,20,delete_pending);
4774 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4777 SIVAL(pdata,0,ea_size);
4778 pdata += 4; /* EA info */
4779 len = srvstr_push(dstart, flags2,
4781 PTR_DIFF(dend, pdata+4),
4785 data_size = PTR_DIFF(pdata,(*ppdata));
4786 *fixed_portion = 10;
4790 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4793 unsigned int ea_size =
4794 estimate_ea_size(conn, fsp, smb_fname);
4795 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4796 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4797 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4798 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4799 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4800 SIVAL(pdata, 0x20, mode);
4801 SIVAL(pdata, 0x24, 0); /* padding. */
4802 SBVAL(pdata, 0x28, allocation_size);
4803 SBVAL(pdata, 0x30, file_size);
4804 SIVAL(pdata, 0x38, nlink);
4805 SCVAL(pdata, 0x3C, delete_pending);
4806 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4807 SSVAL(pdata, 0x3E, 0); /* padding */
4808 SBVAL(pdata, 0x40, file_index);
4809 SIVAL(pdata, 0x48, ea_size);
4810 SIVAL(pdata, 0x4C, access_mask);
4811 SBVAL(pdata, 0x50, pos);
4812 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4813 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4817 len = srvstr_push(dstart, flags2,
4819 PTR_DIFF(dend, pdata+4),
4823 data_size = PTR_DIFF(pdata,(*ppdata));
4824 *fixed_portion = 104;
4827 case SMB_FILE_INTERNAL_INFORMATION:
4829 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4830 SBVAL(pdata, 0, file_index);
4835 case SMB_FILE_ACCESS_INFORMATION:
4836 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4837 SIVAL(pdata, 0, access_mask);
4842 case SMB_FILE_NAME_INFORMATION:
4843 /* Pathname with leading '\'. */
4846 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4847 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4848 SIVAL(pdata,0,byte_len);
4849 data_size = 4 + byte_len;
4853 case SMB_FILE_DISPOSITION_INFORMATION:
4854 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4856 SCVAL(pdata,0,delete_pending);
4860 case SMB_FILE_POSITION_INFORMATION:
4861 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4863 SOFF_T(pdata,0,pos);
4867 case SMB_FILE_MODE_INFORMATION:
4868 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4869 SIVAL(pdata,0,mode);
4874 case SMB_FILE_ALIGNMENT_INFORMATION:
4875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4876 SIVAL(pdata,0,0); /* No alignment needed. */
4882 * NT4 server just returns "invalid query" to this - if we try
4883 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4886 /* The first statement above is false - verified using Thursby
4887 * client against NT4 -- gcolley.
4889 case SMB_QUERY_FILE_STREAM_INFO:
4890 case SMB_FILE_STREAM_INFORMATION: {
4891 unsigned int num_streams = 0;
4892 struct stream_struct *streams = NULL;
4894 DEBUG(10,("smbd_do_qfilepathinfo: "
4895 "SMB_FILE_STREAM_INFORMATION\n"));
4897 if (is_ntfs_stream_smb_fname(smb_fname)) {
4898 return NT_STATUS_INVALID_PARAMETER;
4901 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4902 talloc_tos(), &num_streams, &streams);
4904 if (!NT_STATUS_IS_OK(status)) {
4905 DEBUG(10, ("could not get stream info: %s\n",
4906 nt_errstr(status)));
4910 status = marshall_stream_info(num_streams, streams,
4911 pdata, max_data_bytes,
4914 if (!NT_STATUS_IS_OK(status)) {
4915 DEBUG(10, ("marshall_stream_info failed: %s\n",
4916 nt_errstr(status)));
4917 TALLOC_FREE(streams);
4921 TALLOC_FREE(streams);
4923 *fixed_portion = 32;
4927 case SMB_QUERY_COMPRESSION_INFO:
4928 case SMB_FILE_COMPRESSION_INFORMATION:
4929 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4930 SOFF_T(pdata,0,file_size);
4931 SIVAL(pdata,8,0); /* ??? */
4932 SIVAL(pdata,12,0); /* ??? */
4934 *fixed_portion = 16;
4937 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4938 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4939 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4940 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4941 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4942 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4943 SOFF_T(pdata,32,allocation_size);
4944 SOFF_T(pdata,40,file_size);
4945 SIVAL(pdata,48,mode);
4946 SIVAL(pdata,52,0); /* ??? */
4948 *fixed_portion = 56;
4951 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4952 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4953 SIVAL(pdata,0,mode);
4960 * CIFS UNIX Extensions.
4963 case SMB_QUERY_FILE_UNIX_BASIC:
4965 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4966 data_size = PTR_DIFF(pdata,(*ppdata));
4968 DEBUG(4,("smbd_do_qfilepathinfo: "
4969 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4970 dump_data(4, (uint8_t *)(*ppdata), data_size);
4974 case SMB_QUERY_FILE_UNIX_INFO2:
4976 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4977 data_size = PTR_DIFF(pdata,(*ppdata));
4981 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4983 for (i=0; i<100; i++)
4984 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4990 case SMB_QUERY_FILE_UNIX_LINK:
4993 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4996 return NT_STATUS_NO_MEMORY;
4999 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5001 if(!S_ISLNK(psbuf->st_ex_mode)) {
5002 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5005 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5007 len = SMB_VFS_READLINK(conn,
5008 smb_fname->base_name,
5011 return map_nt_error_from_unix(errno);
5014 len = srvstr_push(dstart, flags2,
5016 PTR_DIFF(dend, pdata),
5019 data_size = PTR_DIFF(pdata,(*ppdata));
5024 #if defined(HAVE_POSIX_ACLS)
5025 case SMB_QUERY_POSIX_ACL:
5027 SMB_ACL_T file_acl = NULL;
5028 SMB_ACL_T def_acl = NULL;
5029 uint16 num_file_acls = 0;
5030 uint16 num_def_acls = 0;
5032 if (fsp && fsp->fh->fd != -1) {
5033 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5037 SMB_VFS_SYS_ACL_GET_FILE(conn,
5038 smb_fname->base_name,
5039 SMB_ACL_TYPE_ACCESS,
5043 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5044 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5045 "not implemented on "
5046 "filesystem containing %s\n",
5047 smb_fname->base_name));
5048 return NT_STATUS_NOT_IMPLEMENTED;
5051 if (S_ISDIR(psbuf->st_ex_mode)) {
5052 if (fsp && fsp->is_directory) {
5054 SMB_VFS_SYS_ACL_GET_FILE(
5056 fsp->fsp_name->base_name,
5057 SMB_ACL_TYPE_DEFAULT,
5061 SMB_VFS_SYS_ACL_GET_FILE(
5063 smb_fname->base_name,
5064 SMB_ACL_TYPE_DEFAULT,
5067 def_acl = free_empty_sys_acl(conn, def_acl);
5070 num_file_acls = count_acl_entries(conn, file_acl);
5071 num_def_acls = count_acl_entries(conn, def_acl);
5073 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5074 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5076 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5077 SMB_POSIX_ACL_HEADER_SIZE) ));
5079 TALLOC_FREE(file_acl);
5082 TALLOC_FREE(def_acl);
5084 return NT_STATUS_BUFFER_TOO_SMALL;
5087 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5088 SSVAL(pdata,2,num_file_acls);
5089 SSVAL(pdata,4,num_def_acls);
5090 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5092 TALLOC_FREE(file_acl);
5095 TALLOC_FREE(def_acl);
5097 return NT_STATUS_INTERNAL_ERROR;
5099 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5101 TALLOC_FREE(file_acl);
5104 TALLOC_FREE(def_acl);
5106 return NT_STATUS_INTERNAL_ERROR;
5110 TALLOC_FREE(file_acl);
5113 TALLOC_FREE(def_acl);
5115 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5121 case SMB_QUERY_POSIX_LOCK:
5126 enum brl_type lock_type;
5128 /* We need an open file with a real fd for this. */
5129 if (!fsp || fsp->fh->fd == -1) {
5130 return NT_STATUS_INVALID_LEVEL;
5133 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5134 return NT_STATUS_INVALID_PARAMETER;
5137 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5138 case POSIX_LOCK_TYPE_READ:
5139 lock_type = READ_LOCK;
5141 case POSIX_LOCK_TYPE_WRITE:
5142 lock_type = WRITE_LOCK;
5144 case POSIX_LOCK_TYPE_UNLOCK:
5146 /* There's no point in asking for an unlock... */
5147 return NT_STATUS_INVALID_PARAMETER;
5150 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5151 #if defined(HAVE_LONGLONG)
5152 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5153 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5154 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5155 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5156 #else /* HAVE_LONGLONG */
5157 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5158 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5159 #endif /* HAVE_LONGLONG */
5161 status = query_lock(fsp,
5168 if (ERROR_WAS_LOCK_DENIED(status)) {
5169 /* Here we need to report who has it locked... */
5170 data_size = POSIX_LOCK_DATA_SIZE;
5172 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5173 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5174 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5175 #if defined(HAVE_LONGLONG)
5176 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5177 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5178 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5179 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5180 #else /* HAVE_LONGLONG */
5181 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5182 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5183 #endif /* HAVE_LONGLONG */
5185 } else if (NT_STATUS_IS_OK(status)) {
5186 /* For success we just return a copy of what we sent
5187 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5188 data_size = POSIX_LOCK_DATA_SIZE;
5189 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5190 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5198 return NT_STATUS_INVALID_LEVEL;
5201 *pdata_size = data_size;
5202 return NT_STATUS_OK;
5205 /****************************************************************************
5206 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5207 file name or file id).
5208 ****************************************************************************/
5210 static void call_trans2qfilepathinfo(connection_struct *conn,
5211 struct smb_request *req,
5212 unsigned int tran_call,
5213 char **pparams, int total_params,
5214 char **ppdata, int total_data,
5215 unsigned int max_data_bytes)
5217 char *params = *pparams;
5218 char *pdata = *ppdata;
5220 unsigned int data_size = 0;
5221 unsigned int param_size = 2;
5222 struct smb_filename *smb_fname = NULL;
5223 bool delete_pending = False;
5224 struct timespec write_time_ts;
5225 files_struct *fsp = NULL;
5226 struct file_id fileid;
5227 struct ea_list *ea_list = NULL;
5228 int lock_data_count = 0;
5229 char *lock_data = NULL;
5230 size_t fixed_portion;
5231 NTSTATUS status = NT_STATUS_OK;
5234 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5238 ZERO_STRUCT(write_time_ts);
5240 if (tran_call == TRANSACT2_QFILEINFO) {
5241 if (total_params < 4) {
5242 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5247 call_trans2qpipeinfo(conn, req, tran_call,
5248 pparams, total_params,
5254 fsp = file_fsp(req, SVAL(params,0));
5255 info_level = SVAL(params,2);
5257 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5259 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5260 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5264 /* Initial check for valid fsp ptr. */
5265 if (!check_fsp_open(conn, req, fsp)) {
5269 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5270 if (smb_fname == NULL) {
5271 reply_nterror(req, NT_STATUS_NO_MEMORY);
5275 if(fsp->fake_file_handle) {
5277 * This is actually for the QUOTA_FAKE_FILE --metze
5280 /* We know this name is ok, it's already passed the checks. */
5282 } else if(fsp->fh->fd == -1) {
5284 * This is actually a QFILEINFO on a directory
5285 * handle (returned from an NT SMB). NT5.0 seems
5286 * to do this call. JRA.
5289 if (INFO_LEVEL_IS_UNIX(info_level)) {
5290 /* Always do lstat for UNIX calls. */
5291 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5292 DEBUG(3,("call_trans2qfilepathinfo: "
5293 "SMB_VFS_LSTAT of %s failed "
5295 smb_fname_str_dbg(smb_fname),
5298 map_nt_error_from_unix(errno));
5301 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5302 DEBUG(3,("call_trans2qfilepathinfo: "
5303 "SMB_VFS_STAT of %s failed (%s)\n",
5304 smb_fname_str_dbg(smb_fname),
5307 map_nt_error_from_unix(errno));
5311 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5312 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5315 * Original code - this is an open file.
5317 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5318 DEBUG(3, ("fstat of %s failed (%s)\n",
5319 fsp_fnum_dbg(fsp), strerror(errno)));
5321 map_nt_error_from_unix(errno));
5324 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5325 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5331 uint32_t ucf_flags = 0;
5334 if (total_params < 7) {
5335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5339 info_level = SVAL(params,0);
5341 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5343 if (INFO_LEVEL_IS_UNIX(info_level)) {
5344 if (!lp_unix_extensions()) {
5345 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5348 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5349 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5350 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5351 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5355 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5357 STR_TERMINATE, &status);
5358 if (!NT_STATUS_IS_OK(status)) {
5359 reply_nterror(req, status);
5363 status = filename_convert(req,
5365 req->flags2 & FLAGS2_DFS_PATHNAMES,
5370 if (!NT_STATUS_IS_OK(status)) {
5371 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5372 reply_botherror(req,
5373 NT_STATUS_PATH_NOT_COVERED,
5374 ERRSRV, ERRbadpath);
5377 reply_nterror(req, status);
5381 /* If this is a stream, check if there is a delete_pending. */
5382 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5383 && is_ntfs_stream_smb_fname(smb_fname)) {
5384 struct smb_filename *smb_fname_base;
5386 /* Create an smb_filename with stream_name == NULL. */
5387 smb_fname_base = synthetic_smb_fname(
5388 talloc_tos(), smb_fname->base_name,
5390 if (smb_fname_base == NULL) {
5391 reply_nterror(req, NT_STATUS_NO_MEMORY);
5395 if (INFO_LEVEL_IS_UNIX(info_level)) {
5396 /* Always do lstat for UNIX calls. */
5397 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5398 DEBUG(3,("call_trans2qfilepathinfo: "
5399 "SMB_VFS_LSTAT of %s failed "
5401 smb_fname_str_dbg(smb_fname_base),
5403 TALLOC_FREE(smb_fname_base);
5405 map_nt_error_from_unix(errno));
5409 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5410 DEBUG(3,("call_trans2qfilepathinfo: "
5411 "fileinfo of %s failed "
5413 smb_fname_str_dbg(smb_fname_base),
5415 TALLOC_FREE(smb_fname_base);
5417 map_nt_error_from_unix(errno));
5422 status = file_name_hash(conn,
5423 smb_fname_str_dbg(smb_fname_base),
5425 if (!NT_STATUS_IS_OK(status)) {
5426 TALLOC_FREE(smb_fname_base);
5427 reply_nterror(req, status);
5431 fileid = vfs_file_id_from_sbuf(conn,
5432 &smb_fname_base->st);
5433 TALLOC_FREE(smb_fname_base);
5434 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5435 if (delete_pending) {
5436 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5441 if (INFO_LEVEL_IS_UNIX(info_level)) {
5442 /* Always do lstat for UNIX calls. */
5443 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5444 DEBUG(3,("call_trans2qfilepathinfo: "
5445 "SMB_VFS_LSTAT of %s failed (%s)\n",
5446 smb_fname_str_dbg(smb_fname),
5449 map_nt_error_from_unix(errno));
5454 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5455 DEBUG(3,("call_trans2qfilepathinfo: "
5456 "SMB_VFS_STAT of %s failed (%s)\n",
5457 smb_fname_str_dbg(smb_fname),
5460 map_nt_error_from_unix(errno));
5465 status = file_name_hash(conn,
5466 smb_fname_str_dbg(smb_fname),
5468 if (!NT_STATUS_IS_OK(status)) {
5469 reply_nterror(req, status);
5473 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5474 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5475 if (delete_pending) {
5476 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5481 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5482 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5484 info_level,tran_call,total_data));
5486 /* Pull out any data sent here before we realloc. */
5487 switch (info_level) {
5488 case SMB_INFO_QUERY_EAS_FROM_LIST:
5490 /* Pull any EA list from the data portion. */
5493 if (total_data < 4) {
5495 req, NT_STATUS_INVALID_PARAMETER);
5498 ea_size = IVAL(pdata,0);
5500 if (total_data > 0 && ea_size != total_data) {
5501 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5502 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5504 req, NT_STATUS_INVALID_PARAMETER);
5508 if (!lp_ea_support(SNUM(conn))) {
5509 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5513 /* Pull out the list of names. */
5514 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5517 req, NT_STATUS_INVALID_PARAMETER);
5523 case SMB_QUERY_POSIX_LOCK:
5525 if (fsp == NULL || fsp->fh->fd == -1) {
5526 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5530 if (total_data != POSIX_LOCK_DATA_SIZE) {
5532 req, NT_STATUS_INVALID_PARAMETER);
5536 /* Copy the lock range data. */
5537 lock_data = (char *)talloc_memdup(
5538 req, pdata, total_data);
5540 reply_nterror(req, NT_STATUS_NO_MEMORY);
5543 lock_data_count = total_data;
5549 *pparams = (char *)SMB_REALLOC(*pparams,2);
5550 if (*pparams == NULL) {
5551 reply_nterror(req, NT_STATUS_NO_MEMORY);
5558 * draft-leach-cifs-v1-spec-02.txt
5559 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5562 * The requested information is placed in the Data portion of the
5563 * transaction response. For the information levels greater than 0x100,
5564 * the transaction response has 1 parameter word which should be
5565 * ignored by the client.
5567 * However Windows only follows this rule for the IS_NAME_VALID call.
5569 switch (info_level) {
5570 case SMB_INFO_IS_NAME_VALID:
5575 if ((info_level & 0xFF00) == 0xFF00) {
5577 * We use levels that start with 0xFF00
5578 * internally to represent SMB2 specific levels
5580 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5584 status = smbd_do_qfilepathinfo(conn, req, info_level,
5586 delete_pending, write_time_ts,
5588 lock_data_count, lock_data,
5589 req->flags2, max_data_bytes,
5591 ppdata, &data_size);
5592 if (!NT_STATUS_IS_OK(status)) {
5593 reply_nterror(req, status);
5596 if (fixed_portion > max_data_bytes) {
5597 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
5601 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5607 /****************************************************************************
5608 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5610 ****************************************************************************/
5612 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5613 connection_struct *conn,
5614 struct smb_request *req,
5615 bool overwrite_if_exists,
5616 const struct smb_filename *smb_fname_old,
5617 struct smb_filename *smb_fname_new)
5619 NTSTATUS status = NT_STATUS_OK;
5621 /* source must already exist. */
5622 if (!VALID_STAT(smb_fname_old->st)) {
5623 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5626 if (VALID_STAT(smb_fname_new->st)) {
5627 if (overwrite_if_exists) {
5628 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5629 return NT_STATUS_FILE_IS_A_DIRECTORY;
5631 status = unlink_internals(conn,
5633 FILE_ATTRIBUTE_NORMAL,
5636 if (!NT_STATUS_IS_OK(status)) {
5640 /* Disallow if newname already exists. */
5641 return NT_STATUS_OBJECT_NAME_COLLISION;
5645 /* No links from a directory. */
5646 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5647 return NT_STATUS_FILE_IS_A_DIRECTORY;
5650 /* Setting a hardlink to/from a stream isn't currently supported. */
5651 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5652 is_ntfs_stream_smb_fname(smb_fname_new)) {
5653 return NT_STATUS_INVALID_PARAMETER;
5656 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5657 smb_fname_old->base_name, smb_fname_new->base_name));
5659 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5660 smb_fname_new->base_name) != 0) {
5661 status = map_nt_error_from_unix(errno);
5662 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5663 nt_errstr(status), smb_fname_old->base_name,
5664 smb_fname_new->base_name));
5669 /****************************************************************************
5670 Deal with setting the time from any of the setfilepathinfo functions.
5671 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5672 calling this function.
5673 ****************************************************************************/
5675 NTSTATUS smb_set_file_time(connection_struct *conn,
5677 const struct smb_filename *smb_fname,
5678 struct smb_file_time *ft,
5679 bool setting_write_time)
5681 struct smb_filename smb_fname_base;
5683 FILE_NOTIFY_CHANGE_LAST_ACCESS
5684 |FILE_NOTIFY_CHANGE_LAST_WRITE
5685 |FILE_NOTIFY_CHANGE_CREATION;
5687 if (!VALID_STAT(smb_fname->st)) {
5688 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5691 /* get some defaults (no modifications) if any info is zero or -1. */
5692 if (null_timespec(ft->create_time)) {
5693 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5696 if (null_timespec(ft->atime)) {
5697 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5700 if (null_timespec(ft->mtime)) {
5701 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5704 if (!setting_write_time) {
5705 /* ft->mtime comes from change time, not write time. */
5706 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5709 /* Ensure the resolution is the correct for
5710 * what we can store on this filesystem. */
5712 round_timespec(conn->ts_res, &ft->create_time);
5713 round_timespec(conn->ts_res, &ft->ctime);
5714 round_timespec(conn->ts_res, &ft->atime);
5715 round_timespec(conn->ts_res, &ft->mtime);
5717 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5718 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5719 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5720 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5721 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5722 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5723 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5724 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5726 if (setting_write_time) {
5728 * This was a Windows setfileinfo on an open file.
5729 * NT does this a lot. We also need to
5730 * set the time here, as it can be read by
5731 * FindFirst/FindNext and with the patch for bug #2045
5732 * in smbd/fileio.c it ensures that this timestamp is
5733 * kept sticky even after a write. We save the request
5734 * away and will set it on file close and after a write. JRA.
5737 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5738 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5741 if (fsp->base_fsp) {
5742 set_sticky_write_time_fsp(fsp->base_fsp,
5745 set_sticky_write_time_fsp(fsp, ft->mtime);
5748 set_sticky_write_time_path(
5749 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5754 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5756 /* Always call ntimes on the base, even if a stream was passed in. */
5757 smb_fname_base = *smb_fname;
5758 smb_fname_base.stream_name = NULL;
5760 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5761 return map_nt_error_from_unix(errno);
5764 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5765 smb_fname->base_name);
5766 return NT_STATUS_OK;
5769 /****************************************************************************
5770 Deal with setting the dosmode from any of the setfilepathinfo functions.
5771 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5772 done before calling this function.
5773 ****************************************************************************/
5775 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5776 const struct smb_filename *smb_fname,
5779 struct smb_filename *smb_fname_base;
5782 if (!VALID_STAT(smb_fname->st)) {
5783 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5786 /* Always operate on the base_name, even if a stream was passed in. */
5787 smb_fname_base = synthetic_smb_fname(
5788 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5789 if (smb_fname_base == NULL) {
5790 return NT_STATUS_NO_MEMORY;
5794 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5795 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5797 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5801 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5803 /* check the mode isn't different, before changing it */
5804 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5805 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5806 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5807 (unsigned int)dosmode));
5809 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5811 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5813 smb_fname_str_dbg(smb_fname_base),
5815 status = map_nt_error_from_unix(errno);
5819 status = NT_STATUS_OK;
5821 TALLOC_FREE(smb_fname_base);
5825 /****************************************************************************
5826 Deal with setting the size from any of the setfilepathinfo functions.
5827 ****************************************************************************/
5829 static NTSTATUS smb_set_file_size(connection_struct *conn,
5830 struct smb_request *req,
5832 const struct smb_filename *smb_fname,
5833 const SMB_STRUCT_STAT *psbuf,
5835 bool fail_after_createfile)
5837 NTSTATUS status = NT_STATUS_OK;
5838 struct smb_filename *smb_fname_tmp = NULL;
5839 files_struct *new_fsp = NULL;
5841 if (!VALID_STAT(*psbuf)) {
5842 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5845 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5847 if (size == get_file_size_stat(psbuf)) {
5848 return NT_STATUS_OK;
5851 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5852 smb_fname_str_dbg(smb_fname), (double)size));
5854 if (fsp && fsp->fh->fd != -1) {
5855 /* Handle based call. */
5856 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5857 return NT_STATUS_ACCESS_DENIED;
5860 if (vfs_set_filelen(fsp, size) == -1) {
5861 return map_nt_error_from_unix(errno);
5863 trigger_write_time_update_immediate(fsp);
5864 return NT_STATUS_OK;
5867 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5868 if (smb_fname_tmp == NULL) {
5869 return NT_STATUS_NO_MEMORY;
5872 smb_fname_tmp->st = *psbuf;
5874 status = SMB_VFS_CREATE_FILE(
5877 0, /* root_dir_fid */
5878 smb_fname_tmp, /* fname */
5879 FILE_WRITE_DATA, /* access_mask */
5880 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5882 FILE_OPEN, /* create_disposition*/
5883 0, /* create_options */
5884 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5885 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5886 0, /* allocation_size */
5887 0, /* private_flags */
5890 &new_fsp, /* result */
5893 TALLOC_FREE(smb_fname_tmp);
5895 if (!NT_STATUS_IS_OK(status)) {
5896 /* NB. We check for open_was_deferred in the caller. */
5900 /* See RAW-SFILEINFO-END-OF-FILE */
5901 if (fail_after_createfile) {
5902 close_file(req, new_fsp,NORMAL_CLOSE);
5903 return NT_STATUS_INVALID_LEVEL;
5906 if (vfs_set_filelen(new_fsp, size) == -1) {
5907 status = map_nt_error_from_unix(errno);
5908 close_file(req, new_fsp,NORMAL_CLOSE);
5912 trigger_write_time_update_immediate(new_fsp);
5913 close_file(req, new_fsp,NORMAL_CLOSE);
5914 return NT_STATUS_OK;
5917 /****************************************************************************
5918 Deal with SMB_INFO_SET_EA.
5919 ****************************************************************************/
5921 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5925 const struct smb_filename *smb_fname)
5927 struct ea_list *ea_list = NULL;
5928 TALLOC_CTX *ctx = NULL;
5929 NTSTATUS status = NT_STATUS_OK;
5931 if (total_data < 10) {
5933 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5934 length. They seem to have no effect. Bug #3212. JRA */
5936 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5937 /* We're done. We only get EA info in this call. */
5938 return NT_STATUS_OK;
5941 return NT_STATUS_INVALID_PARAMETER;
5944 if (IVAL(pdata,0) > total_data) {
5945 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5946 IVAL(pdata,0), (unsigned int)total_data));
5947 return NT_STATUS_INVALID_PARAMETER;
5951 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5953 return NT_STATUS_INVALID_PARAMETER;
5956 status = set_ea(conn, fsp, smb_fname, ea_list);
5961 /****************************************************************************
5962 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5963 ****************************************************************************/
5965 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5970 struct ea_list *ea_list = NULL;
5974 return NT_STATUS_INVALID_HANDLE;
5977 if (!lp_ea_support(SNUM(conn))) {
5978 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5979 "EA's not supported.\n",
5980 (unsigned int)total_data));
5981 return NT_STATUS_EAS_NOT_SUPPORTED;
5984 if (total_data < 10) {
5985 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5987 (unsigned int)total_data));
5988 return NT_STATUS_INVALID_PARAMETER;
5991 ea_list = read_nttrans_ea_list(talloc_tos(),
5996 return NT_STATUS_INVALID_PARAMETER;
5999 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6001 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6002 smb_fname_str_dbg(fsp->fsp_name),
6003 nt_errstr(status) ));
6009 /****************************************************************************
6010 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6011 ****************************************************************************/
6013 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6017 struct smb_filename *smb_fname)
6019 NTSTATUS status = NT_STATUS_OK;
6020 bool delete_on_close;
6023 if (total_data < 1) {
6024 return NT_STATUS_INVALID_PARAMETER;
6028 return NT_STATUS_INVALID_HANDLE;
6031 delete_on_close = (CVAL(pdata,0) ? True : False);
6032 dosmode = dos_mode(conn, smb_fname);
6034 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6035 "delete_on_close = %u\n",
6036 smb_fname_str_dbg(smb_fname),
6037 (unsigned int)dosmode,
6038 (unsigned int)delete_on_close ));
6040 if (delete_on_close) {
6041 status = can_set_delete_on_close(fsp, dosmode);
6042 if (!NT_STATUS_IS_OK(status)) {
6047 /* The set is across all open files on this dev/inode pair. */
6048 if (!set_delete_on_close(fsp, delete_on_close,
6049 conn->session_info->security_token,
6050 conn->session_info->unix_token)) {
6051 return NT_STATUS_ACCESS_DENIED;
6053 return NT_STATUS_OK;
6056 /****************************************************************************
6057 Deal with SMB_FILE_POSITION_INFORMATION.
6058 ****************************************************************************/
6060 static NTSTATUS smb_file_position_information(connection_struct *conn,
6065 uint64_t position_information;
6067 if (total_data < 8) {
6068 return NT_STATUS_INVALID_PARAMETER;
6072 /* Ignore on pathname based set. */
6073 return NT_STATUS_OK;
6076 position_information = (uint64_t)IVAL(pdata,0);
6077 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6079 DEBUG(10,("smb_file_position_information: Set file position "
6080 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6081 (double)position_information));
6082 fsp->fh->position_information = position_information;
6083 return NT_STATUS_OK;
6086 /****************************************************************************
6087 Deal with SMB_FILE_MODE_INFORMATION.
6088 ****************************************************************************/
6090 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6096 if (total_data < 4) {
6097 return NT_STATUS_INVALID_PARAMETER;
6099 mode = IVAL(pdata,0);
6100 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6101 return NT_STATUS_INVALID_PARAMETER;
6103 return NT_STATUS_OK;
6106 /****************************************************************************
6107 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6108 ****************************************************************************/
6110 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6111 struct smb_request *req,
6114 const struct smb_filename *smb_fname)
6116 char *link_target = NULL;
6117 const char *newname = smb_fname->base_name;
6118 TALLOC_CTX *ctx = talloc_tos();
6120 /* Set a symbolic link. */
6121 /* Don't allow this if follow links is false. */
6123 if (total_data == 0) {
6124 return NT_STATUS_INVALID_PARAMETER;
6127 if (!lp_symlinks(SNUM(conn))) {
6128 return NT_STATUS_ACCESS_DENIED;
6131 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6132 total_data, STR_TERMINATE);
6135 return NT_STATUS_INVALID_PARAMETER;
6138 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6139 newname, link_target ));
6141 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6142 return map_nt_error_from_unix(errno);
6145 return NT_STATUS_OK;
6148 /****************************************************************************
6149 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6150 ****************************************************************************/
6152 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6153 struct smb_request *req,
6154 const char *pdata, int total_data,
6155 struct smb_filename *smb_fname_new)
6157 char *oldname = NULL;
6158 struct smb_filename *smb_fname_old = NULL;
6159 TALLOC_CTX *ctx = talloc_tos();
6160 NTSTATUS status = NT_STATUS_OK;
6162 /* Set a hard link. */
6163 if (total_data == 0) {
6164 return NT_STATUS_INVALID_PARAMETER;
6167 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6168 total_data, STR_TERMINATE, &status);
6169 if (!NT_STATUS_IS_OK(status)) {
6173 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6174 smb_fname_str_dbg(smb_fname_new), oldname));
6176 status = filename_convert(ctx,
6178 req->flags2 & FLAGS2_DFS_PATHNAMES,
6183 if (!NT_STATUS_IS_OK(status)) {
6187 return hardlink_internals(ctx, conn, req, false,
6188 smb_fname_old, smb_fname_new);
6191 /****************************************************************************
6192 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6193 ****************************************************************************/
6195 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6196 struct smb_request *req,
6200 struct smb_filename *smb_fname_src)
6204 char *newname = NULL;
6205 struct smb_filename *smb_fname_dst = NULL;
6206 NTSTATUS status = NT_STATUS_OK;
6207 TALLOC_CTX *ctx = talloc_tos();
6210 return NT_STATUS_INVALID_HANDLE;
6213 if (total_data < 20) {
6214 return NT_STATUS_INVALID_PARAMETER;
6217 overwrite = (CVAL(pdata,0) ? True : False);
6218 len = IVAL(pdata,16);
6220 if (len > (total_data - 20) || (len == 0)) {
6221 return NT_STATUS_INVALID_PARAMETER;
6224 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6225 &pdata[20], len, STR_TERMINATE,
6227 if (!NT_STATUS_IS_OK(status)) {
6231 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6234 status = filename_convert(ctx,
6236 req->flags2 & FLAGS2_DFS_PATHNAMES,
6241 if (!NT_STATUS_IS_OK(status)) {
6245 if (fsp->base_fsp) {
6246 /* newname must be a stream name. */
6247 if (newname[0] != ':') {
6248 return NT_STATUS_NOT_SUPPORTED;
6251 /* Create an smb_fname to call rename_internals_fsp() with. */
6252 smb_fname_dst = synthetic_smb_fname(
6253 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6255 if (smb_fname_dst == NULL) {
6256 status = NT_STATUS_NO_MEMORY;
6261 * Set the original last component, since
6262 * rename_internals_fsp() requires it.
6264 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6266 if (smb_fname_dst->original_lcomp == NULL) {
6267 status = NT_STATUS_NO_MEMORY;
6273 DEBUG(10,("smb2_file_rename_information: "
6274 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6275 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6276 smb_fname_str_dbg(smb_fname_dst)));
6277 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6278 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6282 TALLOC_FREE(smb_fname_dst);
6286 static NTSTATUS smb_file_link_information(connection_struct *conn,
6287 struct smb_request *req,
6291 struct smb_filename *smb_fname_src)
6295 char *newname = NULL;
6296 struct smb_filename *smb_fname_dst = NULL;
6297 NTSTATUS status = NT_STATUS_OK;
6298 TALLOC_CTX *ctx = talloc_tos();
6301 return NT_STATUS_INVALID_HANDLE;
6304 if (total_data < 20) {
6305 return NT_STATUS_INVALID_PARAMETER;
6308 overwrite = (CVAL(pdata,0) ? true : false);
6309 len = IVAL(pdata,16);
6311 if (len > (total_data - 20) || (len == 0)) {
6312 return NT_STATUS_INVALID_PARAMETER;
6315 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6316 &pdata[20], len, STR_TERMINATE,
6318 if (!NT_STATUS_IS_OK(status)) {
6322 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6325 status = filename_convert(ctx,
6327 req->flags2 & FLAGS2_DFS_PATHNAMES,
6332 if (!NT_STATUS_IS_OK(status)) {
6336 if (fsp->base_fsp) {
6337 /* No stream names. */
6338 return NT_STATUS_NOT_SUPPORTED;
6341 DEBUG(10,("smb_file_link_information: "
6342 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6343 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6344 smb_fname_str_dbg(smb_fname_dst)));
6345 status = hardlink_internals(ctx,
6352 TALLOC_FREE(smb_fname_dst);
6356 /****************************************************************************
6357 Deal with SMB_FILE_RENAME_INFORMATION.
6358 ****************************************************************************/
6360 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6361 struct smb_request *req,
6365 struct smb_filename *smb_fname_src)
6370 char *newname = NULL;
6371 struct smb_filename *smb_fname_dst = NULL;
6372 bool dest_has_wcard = False;
6373 NTSTATUS status = NT_STATUS_OK;
6375 TALLOC_CTX *ctx = talloc_tos();
6377 if (total_data < 13) {
6378 return NT_STATUS_INVALID_PARAMETER;
6381 overwrite = (CVAL(pdata,0) ? True : False);
6382 root_fid = IVAL(pdata,4);
6383 len = IVAL(pdata,8);
6385 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6386 return NT_STATUS_INVALID_PARAMETER;
6389 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6392 if (!NT_STATUS_IS_OK(status)) {
6396 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6399 status = resolve_dfspath_wcard(ctx, conn,
6400 req->flags2 & FLAGS2_DFS_PATHNAMES,
6403 !conn->sconn->using_smb2,
6406 if (!NT_STATUS_IS_OK(status)) {
6410 /* Check the new name has no '/' characters. */
6411 if (strchr_m(newname, '/')) {
6412 return NT_STATUS_NOT_SUPPORTED;
6415 if (fsp && fsp->base_fsp) {
6416 /* newname must be a stream name. */
6417 if (newname[0] != ':') {
6418 return NT_STATUS_NOT_SUPPORTED;
6421 /* Create an smb_fname to call rename_internals_fsp() with. */
6422 smb_fname_dst = synthetic_smb_fname(
6423 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6425 if (smb_fname_dst == NULL) {
6426 status = NT_STATUS_NO_MEMORY;
6431 * Set the original last component, since
6432 * rename_internals_fsp() requires it.
6434 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6436 if (smb_fname_dst->original_lcomp == NULL) {
6437 status = NT_STATUS_NO_MEMORY;
6443 * Build up an smb_fname_dst based on the filename passed in.
6444 * We basically just strip off the last component, and put on
6445 * the newname instead.
6447 char *base_name = NULL;
6449 /* newname must *not* be a stream name. */
6450 if (newname[0] == ':') {
6451 return NT_STATUS_NOT_SUPPORTED;
6455 * Strip off the last component (filename) of the path passed
6458 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6460 return NT_STATUS_NO_MEMORY;
6462 p = strrchr_m(base_name, '/');
6466 base_name = talloc_strdup(ctx, "");
6468 return NT_STATUS_NO_MEMORY;
6471 /* Append the new name. */
6472 base_name = talloc_asprintf_append(base_name,
6476 return NT_STATUS_NO_MEMORY;
6479 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6482 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6485 /* If an error we expect this to be
6486 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6488 if (!NT_STATUS_IS_OK(status)) {
6489 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6493 /* Create an smb_fname to call rename_internals_fsp() */
6494 smb_fname_dst = synthetic_smb_fname(
6495 ctx, base_name, NULL, NULL);
6496 if (smb_fname_dst == NULL) {
6497 status = NT_STATUS_NO_MEMORY;
6504 DEBUG(10,("smb_file_rename_information: "
6505 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6506 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6507 smb_fname_str_dbg(smb_fname_dst)));
6508 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6511 DEBUG(10,("smb_file_rename_information: "
6512 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6513 smb_fname_str_dbg(smb_fname_src),
6514 smb_fname_str_dbg(smb_fname_dst)));
6515 status = rename_internals(ctx, conn, req, smb_fname_src,
6516 smb_fname_dst, 0, overwrite, false,
6518 FILE_WRITE_ATTRIBUTES);
6521 TALLOC_FREE(smb_fname_dst);
6525 /****************************************************************************
6526 Deal with SMB_SET_POSIX_ACL.
6527 ****************************************************************************/
6529 #if defined(HAVE_POSIX_ACLS)
6530 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6534 const struct smb_filename *smb_fname)
6536 uint16 posix_acl_version;
6537 uint16 num_file_acls;
6538 uint16 num_def_acls;
6539 bool valid_file_acls = True;
6540 bool valid_def_acls = True;
6542 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6543 return NT_STATUS_INVALID_PARAMETER;
6545 posix_acl_version = SVAL(pdata,0);
6546 num_file_acls = SVAL(pdata,2);
6547 num_def_acls = SVAL(pdata,4);
6549 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6550 valid_file_acls = False;
6554 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6555 valid_def_acls = False;
6559 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6560 return NT_STATUS_INVALID_PARAMETER;
6563 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6564 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6565 return NT_STATUS_INVALID_PARAMETER;
6568 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6569 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6570 (unsigned int)num_file_acls,
6571 (unsigned int)num_def_acls));
6573 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6574 smb_fname->base_name, num_file_acls,
6575 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6576 return map_nt_error_from_unix(errno);
6579 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6580 smb_fname->base_name, &smb_fname->st, num_def_acls,
6581 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6582 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6583 return map_nt_error_from_unix(errno);
6585 return NT_STATUS_OK;
6589 /****************************************************************************
6590 Deal with SMB_SET_POSIX_LOCK.
6591 ****************************************************************************/
6593 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6594 struct smb_request *req,
6602 bool blocking_lock = False;
6603 enum brl_type lock_type;
6605 NTSTATUS status = NT_STATUS_OK;
6607 if (fsp == NULL || fsp->fh->fd == -1) {
6608 return NT_STATUS_INVALID_HANDLE;
6611 if (total_data != POSIX_LOCK_DATA_SIZE) {
6612 return NT_STATUS_INVALID_PARAMETER;
6615 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6616 case POSIX_LOCK_TYPE_READ:
6617 lock_type = READ_LOCK;
6619 case POSIX_LOCK_TYPE_WRITE:
6620 /* Return the right POSIX-mappable error code for files opened read-only. */
6621 if (!fsp->can_write) {
6622 return NT_STATUS_INVALID_HANDLE;
6624 lock_type = WRITE_LOCK;
6626 case POSIX_LOCK_TYPE_UNLOCK:
6627 lock_type = UNLOCK_LOCK;
6630 return NT_STATUS_INVALID_PARAMETER;
6633 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6634 blocking_lock = False;
6635 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6636 blocking_lock = True;
6638 return NT_STATUS_INVALID_PARAMETER;
6641 if (!lp_blocking_locks(SNUM(conn))) {
6642 blocking_lock = False;
6645 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6646 #if defined(HAVE_LONGLONG)
6647 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6648 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6649 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6650 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6651 #else /* HAVE_LONGLONG */
6652 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6653 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6654 #endif /* HAVE_LONGLONG */
6656 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6657 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6659 (unsigned int)lock_type,
6660 (unsigned long long)smblctx,
6664 if (lock_type == UNLOCK_LOCK) {
6665 status = do_unlock(req->sconn->msg_ctx,
6672 uint64_t block_smblctx;
6674 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6686 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6688 * A blocking lock was requested. Package up
6689 * this smb into a queued request and push it
6690 * onto the blocking lock queue.
6692 if(push_blocking_lock_request(br_lck,
6695 -1, /* infinite timeout. */
6703 TALLOC_FREE(br_lck);
6707 TALLOC_FREE(br_lck);
6713 /****************************************************************************
6714 Deal with SMB_SET_FILE_BASIC_INFO.
6715 ****************************************************************************/
6717 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6721 const struct smb_filename *smb_fname)
6723 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6724 struct smb_file_time ft;
6726 NTSTATUS status = NT_STATUS_OK;
6730 if (total_data < 36) {
6731 return NT_STATUS_INVALID_PARAMETER;
6734 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6735 if (!NT_STATUS_IS_OK(status)) {
6739 /* Set the attributes */
6740 dosmode = IVAL(pdata,32);
6741 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6742 if (!NT_STATUS_IS_OK(status)) {
6747 ft.create_time = interpret_long_date(pdata);
6750 ft.atime = interpret_long_date(pdata+8);
6753 ft.mtime = interpret_long_date(pdata+16);
6756 ft.ctime = interpret_long_date(pdata+24);
6758 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6759 smb_fname_str_dbg(smb_fname)));
6761 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6765 /****************************************************************************
6766 Deal with SMB_INFO_STANDARD.
6767 ****************************************************************************/
6769 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6773 const struct smb_filename *smb_fname)
6776 struct smb_file_time ft;
6780 if (total_data < 12) {
6781 return NT_STATUS_INVALID_PARAMETER;
6785 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6787 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6789 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6791 DEBUG(10,("smb_set_info_standard: file %s\n",
6792 smb_fname_str_dbg(smb_fname)));
6794 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6795 if (!NT_STATUS_IS_OK(status)) {
6799 return smb_set_file_time(conn,
6806 /****************************************************************************
6807 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6808 ****************************************************************************/
6810 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6811 struct smb_request *req,
6815 struct smb_filename *smb_fname)
6817 uint64_t allocation_size = 0;
6818 NTSTATUS status = NT_STATUS_OK;
6819 files_struct *new_fsp = NULL;
6821 if (!VALID_STAT(smb_fname->st)) {
6822 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6825 if (total_data < 8) {
6826 return NT_STATUS_INVALID_PARAMETER;
6829 allocation_size = (uint64_t)IVAL(pdata,0);
6830 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6831 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6832 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6833 (double)allocation_size));
6835 if (allocation_size) {
6836 allocation_size = smb_roundup(conn, allocation_size);
6839 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6840 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6841 (double)allocation_size));
6843 if (fsp && fsp->fh->fd != -1) {
6844 /* Open file handle. */
6845 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6846 return NT_STATUS_ACCESS_DENIED;
6849 /* Only change if needed. */
6850 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6851 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6852 return map_nt_error_from_unix(errno);
6855 /* But always update the time. */
6857 * This is equivalent to a write. Ensure it's seen immediately
6858 * if there are no pending writes.
6860 trigger_write_time_update_immediate(fsp);
6861 return NT_STATUS_OK;
6864 /* Pathname or stat or directory file. */
6865 status = SMB_VFS_CREATE_FILE(
6868 0, /* root_dir_fid */
6869 smb_fname, /* fname */
6870 FILE_WRITE_DATA, /* access_mask */
6871 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6873 FILE_OPEN, /* create_disposition*/
6874 0, /* create_options */
6875 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6876 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6877 0, /* allocation_size */
6878 0, /* private_flags */
6881 &new_fsp, /* result */
6884 if (!NT_STATUS_IS_OK(status)) {
6885 /* NB. We check for open_was_deferred in the caller. */
6889 /* Only change if needed. */
6890 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6891 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6892 status = map_nt_error_from_unix(errno);
6893 close_file(req, new_fsp, NORMAL_CLOSE);
6898 /* Changing the allocation size should set the last mod time. */
6900 * This is equivalent to a write. Ensure it's seen immediately
6901 * if there are no pending writes.
6903 trigger_write_time_update_immediate(new_fsp);
6905 close_file(req, new_fsp, NORMAL_CLOSE);
6906 return NT_STATUS_OK;
6909 /****************************************************************************
6910 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6911 ****************************************************************************/
6913 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6914 struct smb_request *req,
6918 const struct smb_filename *smb_fname,
6919 bool fail_after_createfile)
6923 if (total_data < 8) {
6924 return NT_STATUS_INVALID_PARAMETER;
6927 size = IVAL(pdata,0);
6928 size |= (((off_t)IVAL(pdata,4)) << 32);
6929 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6930 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6933 return smb_set_file_size(conn, req,
6938 fail_after_createfile);
6941 /****************************************************************************
6942 Allow a UNIX info mknod.
6943 ****************************************************************************/
6945 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6948 const struct smb_filename *smb_fname)
6950 uint32 file_type = IVAL(pdata,56);
6951 #if defined(HAVE_MAKEDEV)
6952 uint32 dev_major = IVAL(pdata,60);
6953 uint32 dev_minor = IVAL(pdata,68);
6955 SMB_DEV_T dev = (SMB_DEV_T)0;
6956 uint32 raw_unixmode = IVAL(pdata,84);
6960 if (total_data < 100) {
6961 return NT_STATUS_INVALID_PARAMETER;
6964 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6965 PERM_NEW_FILE, &unixmode);
6966 if (!NT_STATUS_IS_OK(status)) {
6970 #if defined(HAVE_MAKEDEV)
6971 dev = makedev(dev_major, dev_minor);
6974 switch (file_type) {
6975 #if defined(S_IFIFO)
6976 case UNIX_TYPE_FIFO:
6977 unixmode |= S_IFIFO;
6980 #if defined(S_IFSOCK)
6981 case UNIX_TYPE_SOCKET:
6982 unixmode |= S_IFSOCK;
6985 #if defined(S_IFCHR)
6986 case UNIX_TYPE_CHARDEV:
6987 unixmode |= S_IFCHR;
6990 #if defined(S_IFBLK)
6991 case UNIX_TYPE_BLKDEV:
6992 unixmode |= S_IFBLK;
6996 return NT_STATUS_INVALID_PARAMETER;
6999 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7000 "%.0f mode 0%o for file %s\n", (double)dev,
7001 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7003 /* Ok - do the mknod. */
7004 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7005 return map_nt_error_from_unix(errno);
7008 /* If any of the other "set" calls fail we
7009 * don't want to end up with a half-constructed mknod.
7012 if (lp_inherit_perms(SNUM(conn))) {
7014 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7016 return NT_STATUS_NO_MEMORY;
7018 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7020 TALLOC_FREE(parent);
7023 return NT_STATUS_OK;
7026 /****************************************************************************
7027 Deal with SMB_SET_FILE_UNIX_BASIC.
7028 ****************************************************************************/
7030 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7031 struct smb_request *req,
7035 const struct smb_filename *smb_fname)
7037 struct smb_file_time ft;
7038 uint32 raw_unixmode;
7041 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7042 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7043 NTSTATUS status = NT_STATUS_OK;
7044 bool delete_on_fail = False;
7045 enum perm_type ptype;
7046 files_struct *all_fsps = NULL;
7047 bool modify_mtime = true;
7049 struct smb_filename *smb_fname_tmp = NULL;
7050 SMB_STRUCT_STAT sbuf;
7054 if (total_data < 100) {
7055 return NT_STATUS_INVALID_PARAMETER;
7058 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7059 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7060 size=IVAL(pdata,0); /* first 8 Bytes are size */
7061 size |= (((off_t)IVAL(pdata,4)) << 32);
7064 ft.atime = interpret_long_date(pdata+24); /* access_time */
7065 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7066 set_owner = (uid_t)IVAL(pdata,40);
7067 set_grp = (gid_t)IVAL(pdata,48);
7068 raw_unixmode = IVAL(pdata,84);
7070 if (VALID_STAT(smb_fname->st)) {
7071 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7072 ptype = PERM_EXISTING_DIR;
7074 ptype = PERM_EXISTING_FILE;
7077 ptype = PERM_NEW_FILE;
7080 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7082 if (!NT_STATUS_IS_OK(status)) {
7086 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7087 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7088 smb_fname_str_dbg(smb_fname), (double)size,
7089 (unsigned int)set_owner, (unsigned int)set_grp,
7090 (int)raw_unixmode));
7092 sbuf = smb_fname->st;
7094 if (!VALID_STAT(sbuf)) {
7096 * The only valid use of this is to create character and block
7097 * devices, and named pipes. This is deprecated (IMHO) and
7098 * a new info level should be used for mknod. JRA.
7101 status = smb_unix_mknod(conn,
7105 if (!NT_STATUS_IS_OK(status)) {
7109 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7110 if (smb_fname_tmp == NULL) {
7111 return NT_STATUS_NO_MEMORY;
7114 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7115 status = map_nt_error_from_unix(errno);
7116 TALLOC_FREE(smb_fname_tmp);
7117 SMB_VFS_UNLINK(conn, smb_fname);
7121 sbuf = smb_fname_tmp->st;
7122 smb_fname = smb_fname_tmp;
7124 /* Ensure we don't try and change anything else. */
7125 raw_unixmode = SMB_MODE_NO_CHANGE;
7126 size = get_file_size_stat(&sbuf);
7127 ft.atime = sbuf.st_ex_atime;
7128 ft.mtime = sbuf.st_ex_mtime;
7130 * We continue here as we might want to change the
7133 delete_on_fail = True;
7137 /* Horrible backwards compatibility hack as an old server bug
7138 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7142 size = get_file_size_stat(&sbuf);
7147 * Deal with the UNIX specific mode set.
7150 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7153 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7154 "setting mode 0%o for file %s\n",
7155 (unsigned int)unixmode,
7156 smb_fname_str_dbg(smb_fname)));
7157 if (fsp && fsp->fh->fd != -1) {
7158 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7160 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7163 return map_nt_error_from_unix(errno);
7168 * Deal with the UNIX specific uid set.
7171 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7172 (sbuf.st_ex_uid != set_owner)) {
7175 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7176 "changing owner %u for path %s\n",
7177 (unsigned int)set_owner,
7178 smb_fname_str_dbg(smb_fname)));
7180 if (fsp && fsp->fh->fd != -1) {
7181 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7184 * UNIX extensions calls must always operate
7187 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7188 set_owner, (gid_t)-1);
7192 status = map_nt_error_from_unix(errno);
7193 if (delete_on_fail) {
7194 SMB_VFS_UNLINK(conn, smb_fname);
7201 * Deal with the UNIX specific gid set.
7204 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7205 (sbuf.st_ex_gid != set_grp)) {
7208 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7209 "changing group %u for file %s\n",
7210 (unsigned int)set_owner,
7211 smb_fname_str_dbg(smb_fname)));
7212 if (fsp && fsp->fh->fd != -1) {
7213 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7216 * UNIX extensions calls must always operate
7219 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name, (uid_t)-1,
7223 status = map_nt_error_from_unix(errno);
7224 if (delete_on_fail) {
7225 SMB_VFS_UNLINK(conn, smb_fname);
7231 /* Deal with any size changes. */
7233 status = smb_set_file_size(conn, req,
7239 if (!NT_STATUS_IS_OK(status)) {
7243 /* Deal with any time changes. */
7244 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7245 /* No change, don't cancel anything. */
7249 id = vfs_file_id_from_sbuf(conn, &sbuf);
7250 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7251 all_fsps = file_find_di_next(all_fsps)) {
7253 * We're setting the time explicitly for UNIX.
7254 * Cancel any pending changes over all handles.
7256 all_fsps->update_write_time_on_close = false;
7257 TALLOC_FREE(all_fsps->update_write_time_event);
7261 * Override the "setting_write_time"
7262 * parameter here as it almost does what
7263 * we need. Just remember if we modified
7264 * mtime and send the notify ourselves.
7266 if (null_timespec(ft.mtime)) {
7267 modify_mtime = false;
7270 status = smb_set_file_time(conn,
7276 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7277 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7282 /****************************************************************************
7283 Deal with SMB_SET_FILE_UNIX_INFO2.
7284 ****************************************************************************/
7286 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7287 struct smb_request *req,
7291 const struct smb_filename *smb_fname)
7297 if (total_data < 116) {
7298 return NT_STATUS_INVALID_PARAMETER;
7301 /* Start by setting all the fields that are common between UNIX_BASIC
7304 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7306 if (!NT_STATUS_IS_OK(status)) {
7310 smb_fflags = IVAL(pdata, 108);
7311 smb_fmask = IVAL(pdata, 112);
7313 /* NB: We should only attempt to alter the file flags if the client
7314 * sends a non-zero mask.
7316 if (smb_fmask != 0) {
7317 int stat_fflags = 0;
7319 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7320 smb_fmask, &stat_fflags)) {
7321 /* Client asked to alter a flag we don't understand. */
7322 return NT_STATUS_INVALID_PARAMETER;
7325 if (fsp && fsp->fh->fd != -1) {
7326 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7327 return NT_STATUS_NOT_SUPPORTED;
7329 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7330 stat_fflags) != 0) {
7331 return map_nt_error_from_unix(errno);
7336 /* XXX: need to add support for changing the create_time here. You
7337 * can do this for paths on Darwin with setattrlist(2). The right way
7338 * to hook this up is probably by extending the VFS utimes interface.
7341 return NT_STATUS_OK;
7344 /****************************************************************************
7345 Create a directory with POSIX semantics.
7346 ****************************************************************************/
7348 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7349 struct smb_request *req,
7352 struct smb_filename *smb_fname,
7353 int *pdata_return_size)
7355 NTSTATUS status = NT_STATUS_OK;
7356 uint32 raw_unixmode = 0;
7357 uint32 mod_unixmode = 0;
7358 mode_t unixmode = (mode_t)0;
7359 files_struct *fsp = NULL;
7360 uint16 info_level_return = 0;
7362 char *pdata = *ppdata;
7364 if (total_data < 18) {
7365 return NT_STATUS_INVALID_PARAMETER;
7368 raw_unixmode = IVAL(pdata,8);
7369 /* Next 4 bytes are not yet defined. */
7371 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7372 PERM_NEW_DIR, &unixmode);
7373 if (!NT_STATUS_IS_OK(status)) {
7377 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7379 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7380 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7382 status = SMB_VFS_CREATE_FILE(
7385 0, /* root_dir_fid */
7386 smb_fname, /* fname */
7387 FILE_READ_ATTRIBUTES, /* access_mask */
7388 FILE_SHARE_NONE, /* share_access */
7389 FILE_CREATE, /* create_disposition*/
7390 FILE_DIRECTORY_FILE, /* create_options */
7391 mod_unixmode, /* file_attributes */
7392 0, /* oplock_request */
7393 0, /* allocation_size */
7394 0, /* private_flags */
7400 if (NT_STATUS_IS_OK(status)) {
7401 close_file(req, fsp, NORMAL_CLOSE);
7404 info_level_return = SVAL(pdata,16);
7406 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7407 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7408 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7409 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7411 *pdata_return_size = 12;
7414 /* Realloc the data size */
7415 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7416 if (*ppdata == NULL) {
7417 *pdata_return_size = 0;
7418 return NT_STATUS_NO_MEMORY;
7422 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7423 SSVAL(pdata,2,0); /* No fnum. */
7424 SIVAL(pdata,4,info); /* Was directory created. */
7426 switch (info_level_return) {
7427 case SMB_QUERY_FILE_UNIX_BASIC:
7428 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7429 SSVAL(pdata,10,0); /* Padding. */
7430 store_file_unix_basic(conn, pdata + 12, fsp,
7433 case SMB_QUERY_FILE_UNIX_INFO2:
7434 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7435 SSVAL(pdata,10,0); /* Padding. */
7436 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7440 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7441 SSVAL(pdata,10,0); /* Padding. */
7448 /****************************************************************************
7449 Open/Create a file with POSIX semantics.
7450 ****************************************************************************/
7452 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7453 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7455 static NTSTATUS smb_posix_open(connection_struct *conn,
7456 struct smb_request *req,
7459 struct smb_filename *smb_fname,
7460 int *pdata_return_size)
7462 bool extended_oplock_granted = False;
7463 char *pdata = *ppdata;
7465 uint32 wire_open_mode = 0;
7466 uint32 raw_unixmode = 0;
7467 uint32 mod_unixmode = 0;
7468 uint32 create_disp = 0;
7469 uint32 access_mask = 0;
7470 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7471 NTSTATUS status = NT_STATUS_OK;
7472 mode_t unixmode = (mode_t)0;
7473 files_struct *fsp = NULL;
7474 int oplock_request = 0;
7476 uint16 info_level_return = 0;
7478 if (total_data < 18) {
7479 return NT_STATUS_INVALID_PARAMETER;
7482 flags = IVAL(pdata,0);
7483 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7484 if (oplock_request) {
7485 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7488 wire_open_mode = IVAL(pdata,4);
7490 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7491 return smb_posix_mkdir(conn, req,
7498 switch (wire_open_mode & SMB_ACCMODE) {
7500 access_mask = SMB_O_RDONLY_MAPPING;
7503 access_mask = SMB_O_WRONLY_MAPPING;
7506 access_mask = (SMB_O_RDONLY_MAPPING|
7507 SMB_O_WRONLY_MAPPING);
7510 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7511 (unsigned int)wire_open_mode ));
7512 return NT_STATUS_INVALID_PARAMETER;
7515 wire_open_mode &= ~SMB_ACCMODE;
7517 /* First take care of O_CREAT|O_EXCL interactions. */
7518 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7519 case (SMB_O_CREAT | SMB_O_EXCL):
7520 /* File exists fail. File not exist create. */
7521 create_disp = FILE_CREATE;
7524 /* File exists open. File not exist create. */
7525 create_disp = FILE_OPEN_IF;
7528 /* O_EXCL on its own without O_CREAT is undefined.
7529 We deliberately ignore it as some versions of
7530 Linux CIFSFS can send a bare O_EXCL on the
7531 wire which other filesystems in the kernel
7532 ignore. See bug 9519 for details. */
7537 /* File exists open. File not exist fail. */
7538 create_disp = FILE_OPEN;
7541 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7542 (unsigned int)wire_open_mode ));
7543 return NT_STATUS_INVALID_PARAMETER;
7546 /* Next factor in the effects of O_TRUNC. */
7547 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7549 if (wire_open_mode & SMB_O_TRUNC) {
7550 switch (create_disp) {
7552 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7553 /* Leave create_disp alone as
7554 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7556 /* File exists fail. File not exist create. */
7559 /* SMB_O_CREAT | SMB_O_TRUNC */
7560 /* File exists overwrite. File not exist create. */
7561 create_disp = FILE_OVERWRITE_IF;
7565 /* File exists overwrite. File not exist fail. */
7566 create_disp = FILE_OVERWRITE;
7569 /* Cannot get here. */
7570 smb_panic("smb_posix_open: logic error");
7571 return NT_STATUS_INVALID_PARAMETER;
7575 raw_unixmode = IVAL(pdata,8);
7576 /* Next 4 bytes are not yet defined. */
7578 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7579 (VALID_STAT(smb_fname->st) ?
7580 PERM_EXISTING_FILE : PERM_NEW_FILE),
7583 if (!NT_STATUS_IS_OK(status)) {
7587 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7589 if (wire_open_mode & SMB_O_SYNC) {
7590 create_options |= FILE_WRITE_THROUGH;
7592 if (wire_open_mode & SMB_O_APPEND) {
7593 access_mask |= FILE_APPEND_DATA;
7595 if (wire_open_mode & SMB_O_DIRECT) {
7596 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7599 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7600 VALID_STAT_OF_DIR(smb_fname->st)) {
7601 if (access_mask != SMB_O_RDONLY_MAPPING) {
7602 return NT_STATUS_FILE_IS_A_DIRECTORY;
7604 create_options &= ~FILE_NON_DIRECTORY_FILE;
7605 create_options |= FILE_DIRECTORY_FILE;
7608 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7609 smb_fname_str_dbg(smb_fname),
7610 (unsigned int)wire_open_mode,
7611 (unsigned int)unixmode ));
7613 status = SMB_VFS_CREATE_FILE(
7616 0, /* root_dir_fid */
7617 smb_fname, /* fname */
7618 access_mask, /* access_mask */
7619 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7621 create_disp, /* create_disposition*/
7622 create_options, /* create_options */
7623 mod_unixmode, /* file_attributes */
7624 oplock_request, /* oplock_request */
7625 0, /* allocation_size */
7626 0, /* private_flags */
7632 if (!NT_STATUS_IS_OK(status)) {
7636 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7637 extended_oplock_granted = True;
7640 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7641 extended_oplock_granted = True;
7644 info_level_return = SVAL(pdata,16);
7646 /* Allocate the correct return size. */
7648 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7649 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7650 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7651 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7653 *pdata_return_size = 12;
7656 /* Realloc the data size */
7657 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7658 if (*ppdata == NULL) {
7659 close_file(req, fsp, ERROR_CLOSE);
7660 *pdata_return_size = 0;
7661 return NT_STATUS_NO_MEMORY;
7665 if (extended_oplock_granted) {
7666 if (flags & REQUEST_BATCH_OPLOCK) {
7667 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7669 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7671 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7672 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7674 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7677 SSVAL(pdata,2,fsp->fnum);
7678 SIVAL(pdata,4,info); /* Was file created etc. */
7680 switch (info_level_return) {
7681 case SMB_QUERY_FILE_UNIX_BASIC:
7682 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7683 SSVAL(pdata,10,0); /* padding. */
7684 store_file_unix_basic(conn, pdata + 12, fsp,
7687 case SMB_QUERY_FILE_UNIX_INFO2:
7688 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7689 SSVAL(pdata,10,0); /* padding. */
7690 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7694 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7695 SSVAL(pdata,10,0); /* padding. */
7698 return NT_STATUS_OK;
7701 /****************************************************************************
7702 Delete a file with POSIX semantics.
7703 ****************************************************************************/
7705 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7706 struct smb_request *req,
7709 struct smb_filename *smb_fname)
7711 NTSTATUS status = NT_STATUS_OK;
7712 files_struct *fsp = NULL;
7716 int create_options = 0;
7718 struct share_mode_lock *lck = NULL;
7720 if (total_data < 2) {
7721 return NT_STATUS_INVALID_PARAMETER;
7724 flags = SVAL(pdata,0);
7726 if (!VALID_STAT(smb_fname->st)) {
7727 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7730 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7731 !VALID_STAT_OF_DIR(smb_fname->st)) {
7732 return NT_STATUS_NOT_A_DIRECTORY;
7735 DEBUG(10,("smb_posix_unlink: %s %s\n",
7736 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7737 smb_fname_str_dbg(smb_fname)));
7739 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7740 create_options |= FILE_DIRECTORY_FILE;
7743 status = SMB_VFS_CREATE_FILE(
7746 0, /* root_dir_fid */
7747 smb_fname, /* fname */
7748 DELETE_ACCESS, /* access_mask */
7749 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7751 FILE_OPEN, /* create_disposition*/
7752 create_options, /* create_options */
7753 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7754 0, /* oplock_request */
7755 0, /* allocation_size */
7756 0, /* private_flags */
7762 if (!NT_STATUS_IS_OK(status)) {
7767 * Don't lie to client. If we can't really delete due to
7768 * non-POSIX opens return SHARING_VIOLATION.
7771 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7773 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7774 "lock for file %s\n", fsp_str_dbg(fsp)));
7775 close_file(req, fsp, NORMAL_CLOSE);
7776 return NT_STATUS_INVALID_PARAMETER;
7780 * See if others still have the file open. If this is the case, then
7781 * don't delete. If all opens are POSIX delete we can set the delete
7782 * on close disposition.
7784 for (i=0; i<lck->data->num_share_modes; i++) {
7785 struct share_mode_entry *e = &lck->data->share_modes[i];
7786 if (is_valid_share_mode_entry(e)) {
7787 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7790 if (share_mode_stale_pid(lck->data, i)) {
7793 /* Fail with sharing violation. */
7795 close_file(req, fsp, NORMAL_CLOSE);
7796 return NT_STATUS_SHARING_VIOLATION;
7801 * Set the delete on close.
7803 status = smb_set_file_disposition_info(conn,
7811 if (!NT_STATUS_IS_OK(status)) {
7812 close_file(req, fsp, NORMAL_CLOSE);
7815 return close_file(req, fsp, NORMAL_CLOSE);
7818 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7819 struct smb_request *req,
7820 TALLOC_CTX *mem_ctx,
7821 uint16_t info_level,
7823 struct smb_filename *smb_fname,
7824 char **ppdata, int total_data,
7827 char *pdata = *ppdata;
7828 NTSTATUS status = NT_STATUS_OK;
7829 int data_return_size = 0;
7833 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7834 return NT_STATUS_INVALID_LEVEL;
7837 if (!CAN_WRITE(conn)) {
7838 /* Allow POSIX opens. The open path will deny
7839 * any non-readonly opens. */
7840 if (info_level != SMB_POSIX_PATH_OPEN) {
7841 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7845 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7846 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7848 info_level, total_data));
7850 switch (info_level) {
7852 case SMB_INFO_STANDARD:
7854 status = smb_set_info_standard(conn,
7862 case SMB_INFO_SET_EA:
7864 status = smb_info_set_ea(conn,
7872 case SMB_SET_FILE_BASIC_INFO:
7873 case SMB_FILE_BASIC_INFORMATION:
7875 status = smb_set_file_basic_info(conn,
7883 case SMB_FILE_ALLOCATION_INFORMATION:
7884 case SMB_SET_FILE_ALLOCATION_INFO:
7886 status = smb_set_file_allocation_info(conn, req,
7894 case SMB_FILE_END_OF_FILE_INFORMATION:
7895 case SMB_SET_FILE_END_OF_FILE_INFO:
7898 * XP/Win7 both fail after the createfile with
7899 * SMB_SET_FILE_END_OF_FILE_INFO but not
7900 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7901 * The level is known here, so pass it down
7905 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7907 status = smb_set_file_end_of_file_info(conn, req,
7916 case SMB_FILE_DISPOSITION_INFORMATION:
7917 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7920 /* JRA - We used to just ignore this on a path ?
7921 * Shouldn't this be invalid level on a pathname
7924 if (tran_call != TRANSACT2_SETFILEINFO) {
7925 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7928 status = smb_set_file_disposition_info(conn,
7936 case SMB_FILE_POSITION_INFORMATION:
7938 status = smb_file_position_information(conn,
7945 case SMB_FILE_FULL_EA_INFORMATION:
7947 status = smb_set_file_full_ea_info(conn,
7954 /* From tridge Samba4 :
7955 * MODE_INFORMATION in setfileinfo (I have no
7956 * idea what "mode information" on a file is - it takes a value of 0,
7957 * 2, 4 or 6. What could it be?).
7960 case SMB_FILE_MODE_INFORMATION:
7962 status = smb_file_mode_information(conn,
7969 * CIFS UNIX extensions.
7972 case SMB_SET_FILE_UNIX_BASIC:
7974 status = smb_set_file_unix_basic(conn, req,
7982 case SMB_SET_FILE_UNIX_INFO2:
7984 status = smb_set_file_unix_info2(conn, req,
7992 case SMB_SET_FILE_UNIX_LINK:
7995 /* We must have a pathname for this. */
7996 return NT_STATUS_INVALID_LEVEL;
7998 status = smb_set_file_unix_link(conn, req, pdata,
7999 total_data, smb_fname);
8003 case SMB_SET_FILE_UNIX_HLINK:
8006 /* We must have a pathname for this. */
8007 return NT_STATUS_INVALID_LEVEL;
8009 status = smb_set_file_unix_hlink(conn, req,
8015 case SMB_FILE_RENAME_INFORMATION:
8017 status = smb_file_rename_information(conn, req,
8023 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8025 /* SMB2 rename information. */
8026 status = smb2_file_rename_information(conn, req,
8032 case SMB_FILE_LINK_INFORMATION:
8034 status = smb_file_link_information(conn, req,
8040 #if defined(HAVE_POSIX_ACLS)
8041 case SMB_SET_POSIX_ACL:
8043 status = smb_set_posix_acl(conn,
8052 case SMB_SET_POSIX_LOCK:
8055 return NT_STATUS_INVALID_LEVEL;
8057 status = smb_set_posix_lock(conn, req,
8058 pdata, total_data, fsp);
8062 case SMB_POSIX_PATH_OPEN:
8065 /* We must have a pathname for this. */
8066 return NT_STATUS_INVALID_LEVEL;
8069 status = smb_posix_open(conn, req,
8077 case SMB_POSIX_PATH_UNLINK:
8080 /* We must have a pathname for this. */
8081 return NT_STATUS_INVALID_LEVEL;
8084 status = smb_posix_unlink(conn, req,
8092 return NT_STATUS_INVALID_LEVEL;
8095 if (!NT_STATUS_IS_OK(status)) {
8099 *ret_data_size = data_return_size;
8100 return NT_STATUS_OK;
8103 /****************************************************************************
8104 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8105 ****************************************************************************/
8107 static void call_trans2setfilepathinfo(connection_struct *conn,
8108 struct smb_request *req,
8109 unsigned int tran_call,
8110 char **pparams, int total_params,
8111 char **ppdata, int total_data,
8112 unsigned int max_data_bytes)
8114 char *params = *pparams;
8115 char *pdata = *ppdata;
8117 struct smb_filename *smb_fname = NULL;
8118 files_struct *fsp = NULL;
8119 NTSTATUS status = NT_STATUS_OK;
8120 int data_return_size = 0;
8123 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8127 if (tran_call == TRANSACT2_SETFILEINFO) {
8128 if (total_params < 4) {
8129 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8133 fsp = file_fsp(req, SVAL(params,0));
8134 /* Basic check for non-null fsp. */
8135 if (!check_fsp_open(conn, req, fsp)) {
8138 info_level = SVAL(params,2);
8140 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8141 if (smb_fname == NULL) {
8142 reply_nterror(req, NT_STATUS_NO_MEMORY);
8146 if(fsp->fh->fd == -1) {
8148 * This is actually a SETFILEINFO on a directory
8149 * handle (returned from an NT SMB). NT5.0 seems
8150 * to do this call. JRA.
8152 if (INFO_LEVEL_IS_UNIX(info_level)) {
8153 /* Always do lstat for UNIX calls. */
8154 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8155 DEBUG(3,("call_trans2setfilepathinfo: "
8156 "SMB_VFS_LSTAT of %s failed "
8158 smb_fname_str_dbg(smb_fname),
8160 reply_nterror(req, map_nt_error_from_unix(errno));
8164 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8165 DEBUG(3,("call_trans2setfilepathinfo: "
8166 "fileinfo of %s failed (%s)\n",
8167 smb_fname_str_dbg(smb_fname),
8169 reply_nterror(req, map_nt_error_from_unix(errno));
8173 } else if (fsp->print_file) {
8175 * Doing a DELETE_ON_CLOSE should cancel a print job.
8177 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8178 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8180 DEBUG(3,("call_trans2setfilepathinfo: "
8181 "Cancelling print job (%s)\n",
8185 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8191 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8196 * Original code - this is an open file.
8198 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8199 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8200 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8202 reply_nterror(req, map_nt_error_from_unix(errno));
8208 uint32_t ucf_flags = 0;
8211 if (total_params < 7) {
8212 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8216 info_level = SVAL(params,0);
8217 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8218 total_params - 6, STR_TERMINATE,
8220 if (!NT_STATUS_IS_OK(status)) {
8221 reply_nterror(req, status);
8225 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8226 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8227 info_level == SMB_FILE_RENAME_INFORMATION ||
8228 info_level == SMB_POSIX_PATH_UNLINK) {
8229 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8232 status = filename_convert(req, conn,
8233 req->flags2 & FLAGS2_DFS_PATHNAMES,
8238 if (!NT_STATUS_IS_OK(status)) {
8239 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8240 reply_botherror(req,
8241 NT_STATUS_PATH_NOT_COVERED,
8242 ERRSRV, ERRbadpath);
8245 reply_nterror(req, status);
8249 if (INFO_LEVEL_IS_UNIX(info_level)) {
8251 * For CIFS UNIX extensions the target name may not exist.
8254 /* Always do lstat for UNIX calls. */
8255 SMB_VFS_LSTAT(conn, smb_fname);
8257 } else if (!VALID_STAT(smb_fname->st) &&
8258 SMB_VFS_STAT(conn, smb_fname)) {
8259 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8261 smb_fname_str_dbg(smb_fname),
8263 reply_nterror(req, map_nt_error_from_unix(errno));
8268 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8269 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8271 info_level,total_data));
8273 /* Realloc the parameter size */
8274 *pparams = (char *)SMB_REALLOC(*pparams,2);
8275 if (*pparams == NULL) {
8276 reply_nterror(req, NT_STATUS_NO_MEMORY);
8283 status = smbd_do_setfilepathinfo(conn, req, req,
8289 if (!NT_STATUS_IS_OK(status)) {
8290 if (open_was_deferred(req->sconn, req->mid)) {
8291 /* We have re-scheduled this call. */
8294 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8295 /* We have re-scheduled this call. */
8298 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8299 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8300 ERRSRV, ERRbadpath);
8303 if (info_level == SMB_POSIX_PATH_OPEN) {
8304 reply_openerror(req, status);
8309 * Invalid EA name needs to return 2 param bytes,
8310 * not a zero-length error packet.
8312 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8313 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8316 reply_nterror(req, status);
8321 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8327 /****************************************************************************
8328 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8329 ****************************************************************************/
8331 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8332 char **pparams, int total_params,
8333 char **ppdata, int total_data,
8334 unsigned int max_data_bytes)
8336 struct smb_filename *smb_dname = NULL;
8337 char *params = *pparams;
8338 char *pdata = *ppdata;
8339 char *directory = NULL;
8340 NTSTATUS status = NT_STATUS_OK;
8341 struct ea_list *ea_list = NULL;
8342 TALLOC_CTX *ctx = talloc_tos();
8344 if (!CAN_WRITE(conn)) {
8345 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8349 if (total_params < 5) {
8350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8354 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8355 total_params - 4, STR_TERMINATE,
8357 if (!NT_STATUS_IS_OK(status)) {
8358 reply_nterror(req, status);
8362 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8364 status = filename_convert(ctx,
8366 req->flags2 & FLAGS2_DFS_PATHNAMES,
8372 if (!NT_STATUS_IS_OK(status)) {
8373 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8374 reply_botherror(req,
8375 NT_STATUS_PATH_NOT_COVERED,
8376 ERRSRV, ERRbadpath);
8379 reply_nterror(req, status);
8384 * OS/2 workplace shell seems to send SET_EA requests of "null"
8385 * length (4 bytes containing IVAL 4).
8386 * They seem to have no effect. Bug #3212. JRA.
8389 if (total_data && (total_data != 4)) {
8390 /* Any data in this call is an EA list. */
8391 if (total_data < 10) {
8392 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8396 if (IVAL(pdata,0) > total_data) {
8397 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8398 IVAL(pdata,0), (unsigned int)total_data));
8399 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8403 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8406 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8410 if (!lp_ea_support(SNUM(conn))) {
8411 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8415 /* If total_data == 4 Windows doesn't care what values
8416 * are placed in that field, it just ignores them.
8417 * The System i QNTC IBM SMB client puts bad values here,
8418 * so ignore them. */
8420 status = create_directory(conn, req, smb_dname);
8422 if (!NT_STATUS_IS_OK(status)) {
8423 reply_nterror(req, status);
8427 /* Try and set any given EA. */
8429 status = set_ea(conn, NULL, smb_dname, ea_list);
8430 if (!NT_STATUS_IS_OK(status)) {
8431 reply_nterror(req, status);
8436 /* Realloc the parameter and data sizes */
8437 *pparams = (char *)SMB_REALLOC(*pparams,2);
8438 if(*pparams == NULL) {
8439 reply_nterror(req, NT_STATUS_NO_MEMORY);
8446 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8449 TALLOC_FREE(smb_dname);
8453 /****************************************************************************
8454 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8455 We don't actually do this - we just send a null response.
8456 ****************************************************************************/
8458 static void call_trans2findnotifyfirst(connection_struct *conn,
8459 struct smb_request *req,
8460 char **pparams, int total_params,
8461 char **ppdata, int total_data,
8462 unsigned int max_data_bytes)
8464 char *params = *pparams;
8467 if (total_params < 6) {
8468 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8472 info_level = SVAL(params,4);
8473 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8475 switch (info_level) {
8480 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8484 /* Realloc the parameter and data sizes */
8485 *pparams = (char *)SMB_REALLOC(*pparams,6);
8486 if (*pparams == NULL) {
8487 reply_nterror(req, NT_STATUS_NO_MEMORY);
8492 SSVAL(params,0,fnf_handle);
8493 SSVAL(params,2,0); /* No changes */
8494 SSVAL(params,4,0); /* No EA errors */
8501 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8506 /****************************************************************************
8507 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8508 changes). Currently this does nothing.
8509 ****************************************************************************/
8511 static void call_trans2findnotifynext(connection_struct *conn,
8512 struct smb_request *req,
8513 char **pparams, int total_params,
8514 char **ppdata, int total_data,
8515 unsigned int max_data_bytes)
8517 char *params = *pparams;
8519 DEBUG(3,("call_trans2findnotifynext\n"));
8521 /* Realloc the parameter and data sizes */
8522 *pparams = (char *)SMB_REALLOC(*pparams,4);
8523 if (*pparams == NULL) {
8524 reply_nterror(req, NT_STATUS_NO_MEMORY);
8529 SSVAL(params,0,0); /* No changes */
8530 SSVAL(params,2,0); /* No EA errors */
8532 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8537 /****************************************************************************
8538 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8539 ****************************************************************************/
8541 static void call_trans2getdfsreferral(connection_struct *conn,
8542 struct smb_request *req,
8543 char **pparams, int total_params,
8544 char **ppdata, int total_data,
8545 unsigned int max_data_bytes)
8547 char *params = *pparams;
8548 char *pathname = NULL;
8550 int max_referral_level;
8551 NTSTATUS status = NT_STATUS_OK;
8552 TALLOC_CTX *ctx = talloc_tos();
8554 DEBUG(10,("call_trans2getdfsreferral\n"));
8556 if (total_params < 3) {
8557 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8561 max_referral_level = SVAL(params,0);
8563 if(!lp_host_msdfs()) {
8564 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8568 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8569 total_params - 2, STR_TERMINATE);
8571 reply_nterror(req, NT_STATUS_NOT_FOUND);
8574 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8575 ppdata,&status)) < 0) {
8576 reply_nterror(req, status);
8580 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8581 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8582 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8587 #define LMCAT_SPL 0x53
8588 #define LMFUNC_GETJOBID 0x60
8590 /****************************************************************************
8591 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8592 ****************************************************************************/
8594 static void call_trans2ioctl(connection_struct *conn,
8595 struct smb_request *req,
8596 char **pparams, int total_params,
8597 char **ppdata, int total_data,
8598 unsigned int max_data_bytes)
8600 char *pdata = *ppdata;
8601 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8603 /* check for an invalid fid before proceeding */
8606 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8610 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8611 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8612 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8613 if (*ppdata == NULL) {
8614 reply_nterror(req, NT_STATUS_NO_MEMORY);
8619 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8620 CAN ACCEPT THIS IN UNICODE. JRA. */
8623 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8625 srvstr_push(pdata, req->flags2, pdata + 2,
8626 lp_netbios_name(), 15,
8627 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8628 srvstr_push(pdata, req->flags2, pdata+18,
8629 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8630 STR_ASCII|STR_TERMINATE); /* Service name */
8631 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8636 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8637 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8640 /****************************************************************************
8641 Reply to a SMBfindclose (stop trans2 directory search).
8642 ****************************************************************************/
8644 void reply_findclose(struct smb_request *req)
8647 struct smbd_server_connection *sconn = req->sconn;
8649 START_PROFILE(SMBfindclose);
8652 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8653 END_PROFILE(SMBfindclose);
8657 dptr_num = SVALS(req->vwv+0, 0);
8659 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8661 dptr_close(sconn, &dptr_num);
8663 reply_outbuf(req, 0, 0);
8665 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8667 END_PROFILE(SMBfindclose);
8671 /****************************************************************************
8672 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8673 ****************************************************************************/
8675 void reply_findnclose(struct smb_request *req)
8679 START_PROFILE(SMBfindnclose);
8682 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8683 END_PROFILE(SMBfindnclose);
8687 dptr_num = SVAL(req->vwv+0, 0);
8689 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8691 /* We never give out valid handles for a
8692 findnotifyfirst - so any dptr_num is ok here.
8695 reply_outbuf(req, 0, 0);
8697 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8699 END_PROFILE(SMBfindnclose);
8703 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8704 struct trans_state *state)
8706 if (get_Protocol() >= PROTOCOL_NT1) {
8707 req->flags2 |= 0x40; /* IS_LONG_NAME */
8708 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8711 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8712 if (state->call != TRANSACT2_QFSINFO &&
8713 state->call != TRANSACT2_SETFSINFO) {
8714 DEBUG(0,("handle_trans2: encryption required "
8716 (unsigned int)state->call));
8717 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8722 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8724 /* Now we must call the relevant TRANS2 function */
8725 switch(state->call) {
8726 case TRANSACT2_OPEN:
8728 START_PROFILE(Trans2_open);
8729 call_trans2open(conn, req,
8730 &state->param, state->total_param,
8731 &state->data, state->total_data,
8732 state->max_data_return);
8733 END_PROFILE(Trans2_open);
8737 case TRANSACT2_FINDFIRST:
8739 START_PROFILE(Trans2_findfirst);
8740 call_trans2findfirst(conn, req,
8741 &state->param, state->total_param,
8742 &state->data, state->total_data,
8743 state->max_data_return);
8744 END_PROFILE(Trans2_findfirst);
8748 case TRANSACT2_FINDNEXT:
8750 START_PROFILE(Trans2_findnext);
8751 call_trans2findnext(conn, req,
8752 &state->param, state->total_param,
8753 &state->data, state->total_data,
8754 state->max_data_return);
8755 END_PROFILE(Trans2_findnext);
8759 case TRANSACT2_QFSINFO:
8761 START_PROFILE(Trans2_qfsinfo);
8762 call_trans2qfsinfo(conn, req,
8763 &state->param, state->total_param,
8764 &state->data, state->total_data,
8765 state->max_data_return);
8766 END_PROFILE(Trans2_qfsinfo);
8770 case TRANSACT2_SETFSINFO:
8772 START_PROFILE(Trans2_setfsinfo);
8773 call_trans2setfsinfo(conn, req,
8774 &state->param, state->total_param,
8775 &state->data, state->total_data,
8776 state->max_data_return);
8777 END_PROFILE(Trans2_setfsinfo);
8781 case TRANSACT2_QPATHINFO:
8782 case TRANSACT2_QFILEINFO:
8784 START_PROFILE(Trans2_qpathinfo);
8785 call_trans2qfilepathinfo(conn, req, state->call,
8786 &state->param, state->total_param,
8787 &state->data, state->total_data,
8788 state->max_data_return);
8789 END_PROFILE(Trans2_qpathinfo);
8793 case TRANSACT2_SETPATHINFO:
8794 case TRANSACT2_SETFILEINFO:
8796 START_PROFILE(Trans2_setpathinfo);
8797 call_trans2setfilepathinfo(conn, req, state->call,
8798 &state->param, state->total_param,
8799 &state->data, state->total_data,
8800 state->max_data_return);
8801 END_PROFILE(Trans2_setpathinfo);
8805 case TRANSACT2_FINDNOTIFYFIRST:
8807 START_PROFILE(Trans2_findnotifyfirst);
8808 call_trans2findnotifyfirst(conn, req,
8809 &state->param, state->total_param,
8810 &state->data, state->total_data,
8811 state->max_data_return);
8812 END_PROFILE(Trans2_findnotifyfirst);
8816 case TRANSACT2_FINDNOTIFYNEXT:
8818 START_PROFILE(Trans2_findnotifynext);
8819 call_trans2findnotifynext(conn, req,
8820 &state->param, state->total_param,
8821 &state->data, state->total_data,
8822 state->max_data_return);
8823 END_PROFILE(Trans2_findnotifynext);
8827 case TRANSACT2_MKDIR:
8829 START_PROFILE(Trans2_mkdir);
8830 call_trans2mkdir(conn, req,
8831 &state->param, state->total_param,
8832 &state->data, state->total_data,
8833 state->max_data_return);
8834 END_PROFILE(Trans2_mkdir);
8838 case TRANSACT2_GET_DFS_REFERRAL:
8840 START_PROFILE(Trans2_get_dfs_referral);
8841 call_trans2getdfsreferral(conn, req,
8842 &state->param, state->total_param,
8843 &state->data, state->total_data,
8844 state->max_data_return);
8845 END_PROFILE(Trans2_get_dfs_referral);
8849 case TRANSACT2_IOCTL:
8851 START_PROFILE(Trans2_ioctl);
8852 call_trans2ioctl(conn, req,
8853 &state->param, state->total_param,
8854 &state->data, state->total_data,
8855 state->max_data_return);
8856 END_PROFILE(Trans2_ioctl);
8861 /* Error in request */
8862 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8863 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8867 /****************************************************************************
8868 Reply to a SMBtrans2.
8869 ****************************************************************************/
8871 void reply_trans2(struct smb_request *req)
8873 connection_struct *conn = req->conn;
8878 unsigned int tran_call;
8879 struct trans_state *state;
8882 START_PROFILE(SMBtrans2);
8884 if (req->wct < 14) {
8885 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8886 END_PROFILE(SMBtrans2);
8890 dsoff = SVAL(req->vwv+12, 0);
8891 dscnt = SVAL(req->vwv+11, 0);
8892 psoff = SVAL(req->vwv+10, 0);
8893 pscnt = SVAL(req->vwv+9, 0);
8894 tran_call = SVAL(req->vwv+14, 0);
8896 result = allow_new_trans(conn->pending_trans, req->mid);
8897 if (!NT_STATUS_IS_OK(result)) {
8898 DEBUG(2, ("Got invalid trans2 request: %s\n",
8899 nt_errstr(result)));
8900 reply_nterror(req, result);
8901 END_PROFILE(SMBtrans2);
8906 switch (tran_call) {
8907 /* List the allowed trans2 calls on IPC$ */
8908 case TRANSACT2_OPEN:
8909 case TRANSACT2_GET_DFS_REFERRAL:
8910 case TRANSACT2_QFILEINFO:
8911 case TRANSACT2_QFSINFO:
8912 case TRANSACT2_SETFSINFO:
8915 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8916 END_PROFILE(SMBtrans2);
8921 if ((state = talloc(conn, struct trans_state)) == NULL) {
8922 DEBUG(0, ("talloc failed\n"));
8923 reply_nterror(req, NT_STATUS_NO_MEMORY);
8924 END_PROFILE(SMBtrans2);
8928 state->cmd = SMBtrans2;
8930 state->mid = req->mid;
8931 state->vuid = req->vuid;
8932 state->setup_count = SVAL(req->vwv+13, 0);
8933 state->setup = NULL;
8934 state->total_param = SVAL(req->vwv+0, 0);
8935 state->param = NULL;
8936 state->total_data = SVAL(req->vwv+1, 0);
8938 state->max_param_return = SVAL(req->vwv+2, 0);
8939 state->max_data_return = SVAL(req->vwv+3, 0);
8940 state->max_setup_return = SVAL(req->vwv+4, 0);
8941 state->close_on_completion = BITSETW(req->vwv+5, 0);
8942 state->one_way = BITSETW(req->vwv+5, 1);
8944 state->call = tran_call;
8946 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8947 is so as a sanity check */
8948 if (state->setup_count != 1) {
8950 * Need to have rc=0 for ioctl to get job id for OS/2.
8951 * Network printing will fail if function is not successful.
8952 * Similar function in reply.c will be used if protocol
8953 * is LANMAN1.0 instead of LM1.2X002.
8954 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8955 * outbuf doesn't have to be set(only job id is used).
8957 if ( (state->setup_count == 4)
8958 && (tran_call == TRANSACT2_IOCTL)
8959 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8960 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8961 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8963 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8964 DEBUG(2,("Transaction is %d\n",tran_call));
8966 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8967 END_PROFILE(SMBtrans2);
8972 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8975 if (state->total_data) {
8977 if (trans_oob(state->total_data, 0, dscnt)
8978 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8982 /* Can't use talloc here, the core routines do realloc on the
8983 * params and data. */
8984 state->data = (char *)SMB_MALLOC(state->total_data);
8985 if (state->data == NULL) {
8986 DEBUG(0,("reply_trans2: data malloc fail for %u "
8987 "bytes !\n", (unsigned int)state->total_data));
8989 reply_nterror(req, NT_STATUS_NO_MEMORY);
8990 END_PROFILE(SMBtrans2);
8994 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8997 if (state->total_param) {
8999 if (trans_oob(state->total_param, 0, pscnt)
9000 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9004 /* Can't use talloc here, the core routines do realloc on the
9005 * params and data. */
9006 state->param = (char *)SMB_MALLOC(state->total_param);
9007 if (state->param == NULL) {
9008 DEBUG(0,("reply_trans: param malloc fail for %u "
9009 "bytes !\n", (unsigned int)state->total_param));
9010 SAFE_FREE(state->data);
9012 reply_nterror(req, NT_STATUS_NO_MEMORY);
9013 END_PROFILE(SMBtrans2);
9017 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9020 state->received_data = dscnt;
9021 state->received_param = pscnt;
9023 if ((state->received_param == state->total_param) &&
9024 (state->received_data == state->total_data)) {
9026 handle_trans2(conn, req, state);
9028 SAFE_FREE(state->data);
9029 SAFE_FREE(state->param);
9031 END_PROFILE(SMBtrans2);
9035 DLIST_ADD(conn->pending_trans, state);
9037 /* We need to send an interim response then receive the rest
9038 of the parameter/data bytes */
9039 reply_outbuf(req, 0, 0);
9040 show_msg((char *)req->outbuf);
9041 END_PROFILE(SMBtrans2);
9046 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9047 SAFE_FREE(state->data);
9048 SAFE_FREE(state->param);
9050 END_PROFILE(SMBtrans2);
9051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9055 /****************************************************************************
9056 Reply to a SMBtranss2
9057 ****************************************************************************/
9059 void reply_transs2(struct smb_request *req)
9061 connection_struct *conn = req->conn;
9062 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9063 struct trans_state *state;
9065 START_PROFILE(SMBtranss2);
9067 show_msg((const char *)req->inbuf);
9069 /* Windows clients expect all replies to
9070 a transact secondary (SMBtranss2 0x33)
9071 to have a command code of transact
9072 (SMBtrans2 0x32). See bug #8989
9073 and also [MS-CIFS] section 2.2.4.47.2
9076 req->cmd = SMBtrans2;
9079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9080 END_PROFILE(SMBtranss2);
9084 for (state = conn->pending_trans; state != NULL;
9085 state = state->next) {
9086 if (state->mid == req->mid) {
9091 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9092 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9093 END_PROFILE(SMBtranss2);
9097 /* Revise state->total_param and state->total_data in case they have
9098 changed downwards */
9100 if (SVAL(req->vwv+0, 0) < state->total_param)
9101 state->total_param = SVAL(req->vwv+0, 0);
9102 if (SVAL(req->vwv+1, 0) < state->total_data)
9103 state->total_data = SVAL(req->vwv+1, 0);
9105 pcnt = SVAL(req->vwv+2, 0);
9106 poff = SVAL(req->vwv+3, 0);
9107 pdisp = SVAL(req->vwv+4, 0);
9109 dcnt = SVAL(req->vwv+5, 0);
9110 doff = SVAL(req->vwv+6, 0);
9111 ddisp = SVAL(req->vwv+7, 0);
9113 state->received_param += pcnt;
9114 state->received_data += dcnt;
9116 if ((state->received_data > state->total_data) ||
9117 (state->received_param > state->total_param))
9121 if (trans_oob(state->total_param, pdisp, pcnt)
9122 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9125 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9129 if (trans_oob(state->total_data, ddisp, dcnt)
9130 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9133 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9136 if ((state->received_param < state->total_param) ||
9137 (state->received_data < state->total_data)) {
9138 END_PROFILE(SMBtranss2);
9142 handle_trans2(conn, req, state);
9144 DLIST_REMOVE(conn->pending_trans, state);
9145 SAFE_FREE(state->data);
9146 SAFE_FREE(state->param);
9149 END_PROFILE(SMBtranss2);
9154 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9155 DLIST_REMOVE(conn->pending_trans, state);
9156 SAFE_FREE(state->data);
9157 SAFE_FREE(state->param);
9159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9160 END_PROFILE(SMBtranss2);