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) {
1396 /* Apply mode mask */
1397 ret &= lp_create_mask(SNUM(conn));
1398 /* Add in force bits */
1399 ret |= lp_force_create_mode(SNUM(conn));
1400 } else if (ptype == PERM_NEW_DIR) {
1401 ret &= lp_dir_mask(SNUM(conn));
1402 /* Add in force bits */
1403 ret |= lp_force_dir_mode(SNUM(conn));
1407 return NT_STATUS_OK;
1410 /****************************************************************************
1411 Needed to show the msdfs symlinks as directories. Modifies psbuf
1412 to be a directory if it's a msdfs link.
1413 ****************************************************************************/
1415 static bool check_msdfs_link(connection_struct *conn,
1416 const char *pathname,
1417 SMB_STRUCT_STAT *psbuf)
1419 int saved_errno = errno;
1420 if(lp_host_msdfs() &&
1421 lp_msdfs_root(SNUM(conn)) &&
1422 is_msdfs_link(conn, pathname, psbuf)) {
1424 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1427 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1428 errno = saved_errno;
1431 errno = saved_errno;
1436 /****************************************************************************
1437 Get a level dependent lanman2 dir entry.
1438 ****************************************************************************/
1440 struct smbd_dirptr_lanman2_state {
1441 connection_struct *conn;
1442 uint32_t info_level;
1443 bool check_mangled_names;
1445 bool got_exact_match;
1448 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1454 struct smbd_dirptr_lanman2_state *state =
1455 (struct smbd_dirptr_lanman2_state *)private_data;
1457 char mangled_name[13]; /* mangled 8.3 name. */
1461 /* Mangle fname if it's an illegal name. */
1462 if (mangle_must_mangle(dname, state->conn->params)) {
1463 ok = name_to_8_3(dname, mangled_name,
1464 true, state->conn->params);
1468 fname = mangled_name;
1473 got_match = exact_match(state->has_wild,
1474 state->conn->case_sensitive,
1476 state->got_exact_match = got_match;
1478 got_match = mask_match(fname, mask,
1479 state->conn->case_sensitive);
1482 if(!got_match && state->check_mangled_names &&
1483 !mangle_is_8_3(fname, false, state->conn->params)) {
1485 * It turns out that NT matches wildcards against
1486 * both long *and* short names. This may explain some
1487 * of the wildcard wierdness from old DOS clients
1488 * that some people have been seeing.... JRA.
1490 /* Force the mangling into 8.3. */
1491 ok = name_to_8_3(fname, mangled_name,
1492 false, state->conn->params);
1497 got_match = exact_match(state->has_wild,
1498 state->conn->case_sensitive,
1499 mangled_name, mask);
1500 state->got_exact_match = got_match;
1502 got_match = mask_match(mangled_name, mask,
1503 state->conn->case_sensitive);
1511 *_fname = talloc_strdup(ctx, fname);
1512 if (*_fname == NULL) {
1519 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1521 struct smb_filename *smb_fname,
1524 struct smbd_dirptr_lanman2_state *state =
1525 (struct smbd_dirptr_lanman2_state *)private_data;
1526 bool ms_dfs_link = false;
1529 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1530 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1531 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1532 "Couldn't lstat [%s] (%s)\n",
1533 smb_fname_str_dbg(smb_fname),
1537 } else if (!VALID_STAT(smb_fname->st) &&
1538 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1539 /* Needed to show the msdfs symlinks as
1542 ms_dfs_link = check_msdfs_link(state->conn,
1543 smb_fname->base_name,
1546 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1547 "Couldn't stat [%s] (%s)\n",
1548 smb_fname_str_dbg(smb_fname),
1555 mode = dos_mode_msdfs(state->conn, smb_fname);
1557 mode = dos_mode(state->conn, smb_fname);
1564 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1565 connection_struct *conn,
1567 uint32_t info_level,
1568 struct ea_list *name_list,
1569 bool check_mangled_names,
1570 bool requires_resume_key,
1573 const struct smb_filename *smb_fname,
1574 int space_remaining,
1581 uint64_t *last_entry_off)
1583 char *p, *q, *pdata = *ppdata;
1585 uint64_t file_size = 0;
1586 uint64_t allocation_size = 0;
1587 uint64_t file_index = 0;
1589 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1590 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1592 char *last_entry_ptr;
1597 *out_of_space = false;
1599 ZERO_STRUCT(mdate_ts);
1600 ZERO_STRUCT(adate_ts);
1601 ZERO_STRUCT(create_date_ts);
1602 ZERO_STRUCT(cdate_ts);
1604 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1605 file_size = get_file_size_stat(&smb_fname->st);
1607 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1609 file_index = get_FileIndex(conn, &smb_fname->st);
1611 mdate_ts = smb_fname->st.st_ex_mtime;
1612 adate_ts = smb_fname->st.st_ex_atime;
1613 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1614 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1616 if (lp_dos_filetime_resolution(SNUM(conn))) {
1617 dos_filetime_timespec(&create_date_ts);
1618 dos_filetime_timespec(&mdate_ts);
1619 dos_filetime_timespec(&adate_ts);
1620 dos_filetime_timespec(&cdate_ts);
1623 create_date = convert_timespec_to_time_t(create_date_ts);
1624 mdate = convert_timespec_to_time_t(mdate_ts);
1625 adate = convert_timespec_to_time_t(adate_ts);
1627 /* align the record */
1628 SMB_ASSERT(align >= 1);
1630 off = (int)PTR_DIFF(pdata, base_data);
1631 pad = (off + (align-1)) & ~(align-1);
1634 if (pad && pad > space_remaining) {
1635 *out_of_space = true;
1636 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1637 "for padding (wanted %u, had %d)\n",
1640 return false; /* Not finished - just out of space */
1644 /* initialize padding to 0 */
1646 memset(pdata, 0, pad);
1648 space_remaining -= pad;
1650 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1660 switch (info_level) {
1661 case SMB_FIND_INFO_STANDARD:
1662 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1663 if(requires_resume_key) {
1667 srv_put_dos_date2(p,0,create_date);
1668 srv_put_dos_date2(p,4,adate);
1669 srv_put_dos_date2(p,8,mdate);
1670 SIVAL(p,12,(uint32)file_size);
1671 SIVAL(p,16,(uint32)allocation_size);
1675 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1676 p += ucs2_align(base_data, p, 0);
1678 len = srvstr_push(base_data, flags2, p,
1679 fname, PTR_DIFF(end_data, p),
1681 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1683 SCVAL(nameptr, -1, len - 2);
1685 SCVAL(nameptr, -1, 0);
1689 SCVAL(nameptr, -1, len - 1);
1691 SCVAL(nameptr, -1, 0);
1697 case SMB_FIND_EA_SIZE:
1698 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1699 if (requires_resume_key) {
1703 srv_put_dos_date2(p,0,create_date);
1704 srv_put_dos_date2(p,4,adate);
1705 srv_put_dos_date2(p,8,mdate);
1706 SIVAL(p,12,(uint32)file_size);
1707 SIVAL(p,16,(uint32)allocation_size);
1710 unsigned int ea_size = estimate_ea_size(conn, NULL,
1712 SIVAL(p,22,ea_size); /* Extended attributes */
1716 len = srvstr_push(base_data, flags2,
1717 p, fname, PTR_DIFF(end_data, p),
1718 STR_TERMINATE | STR_NOALIGN);
1719 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1732 SCVAL(nameptr,0,len);
1734 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1737 case SMB_FIND_EA_LIST:
1739 struct ea_list *file_list = NULL;
1743 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1747 if (requires_resume_key) {
1751 srv_put_dos_date2(p,0,create_date);
1752 srv_put_dos_date2(p,4,adate);
1753 srv_put_dos_date2(p,8,mdate);
1754 SIVAL(p,12,(uint32)file_size);
1755 SIVAL(p,16,(uint32)allocation_size);
1757 p += 22; /* p now points to the EA area. */
1759 status = get_ea_list_from_file(ctx, conn, NULL,
1761 &ea_len, &file_list);
1762 if (!NT_STATUS_IS_OK(status)) {
1765 name_list = ea_list_union(name_list, file_list, &ea_len);
1767 /* We need to determine if this entry will fit in the space available. */
1768 /* Max string size is 255 bytes. */
1769 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1770 *out_of_space = true;
1771 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1772 "(wanted %u, had %d)\n",
1773 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1775 return False; /* Not finished - just out of space */
1778 /* Push the ea_data followed by the name. */
1779 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1781 len = srvstr_push(base_data, flags2,
1782 p + 1, fname, PTR_DIFF(end_data, p+1),
1783 STR_TERMINATE | STR_NOALIGN);
1784 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1797 SCVAL(nameptr,0,len);
1799 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1803 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1804 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1805 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1807 SIVAL(p,0,reskey); p += 4;
1808 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1809 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1810 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1811 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1812 SOFF_T(p,0,file_size); p += 8;
1813 SOFF_T(p,0,allocation_size); p += 8;
1814 SIVAL(p,0,mode); p += 4;
1815 q = p; p += 4; /* q is placeholder for name length. */
1816 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1817 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1819 unsigned int ea_size = estimate_ea_size(conn, NULL,
1821 SIVAL(p,0,ea_size); /* Extended attributes */
1824 /* Clear the short name buffer. This is
1825 * IMPORTANT as not doing so will trigger
1826 * a Win2k client bug. JRA.
1828 if (!was_8_3 && check_mangled_names) {
1829 char mangled_name[13]; /* mangled 8.3 name. */
1830 if (!name_to_8_3(fname,mangled_name,True,
1832 /* Error - mangle failed ! */
1833 memset(mangled_name,'\0',12);
1835 mangled_name[12] = 0;
1836 len = srvstr_push(base_data, flags2,
1837 p+2, mangled_name, 24,
1838 STR_UPPER|STR_UNICODE);
1840 memset(p + 2 + len,'\0',24 - len);
1847 len = srvstr_push(base_data, flags2, p,
1848 fname, PTR_DIFF(end_data, p),
1849 STR_TERMINATE_ASCII);
1853 len = PTR_DIFF(p, pdata);
1854 pad = (len + (align-1)) & ~(align-1);
1856 * offset to the next entry, the caller
1857 * will overwrite it for the last entry
1858 * that's why we always include the padding
1862 * set padding to zero
1865 memset(p, 0, pad - len);
1872 case SMB_FIND_FILE_DIRECTORY_INFO:
1873 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1875 SIVAL(p,0,reskey); p += 4;
1876 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1877 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1878 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1879 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1880 SOFF_T(p,0,file_size); p += 8;
1881 SOFF_T(p,0,allocation_size); p += 8;
1882 SIVAL(p,0,mode); p += 4;
1883 len = srvstr_push(base_data, flags2,
1884 p + 4, fname, PTR_DIFF(end_data, p+4),
1885 STR_TERMINATE_ASCII);
1889 len = PTR_DIFF(p, pdata);
1890 pad = (len + (align-1)) & ~(align-1);
1892 * offset to the next entry, the caller
1893 * will overwrite it for the last entry
1894 * that's why we always include the padding
1898 * set padding to zero
1901 memset(p, 0, pad - len);
1908 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1909 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1911 SIVAL(p,0,reskey); p += 4;
1912 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1913 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1914 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1915 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1916 SOFF_T(p,0,file_size); p += 8;
1917 SOFF_T(p,0,allocation_size); p += 8;
1918 SIVAL(p,0,mode); p += 4;
1919 q = p; p += 4; /* q is placeholder for name length. */
1921 unsigned int ea_size = estimate_ea_size(conn, NULL,
1923 SIVAL(p,0,ea_size); /* Extended attributes */
1926 len = srvstr_push(base_data, flags2, p,
1927 fname, PTR_DIFF(end_data, p),
1928 STR_TERMINATE_ASCII);
1932 len = PTR_DIFF(p, pdata);
1933 pad = (len + (align-1)) & ~(align-1);
1935 * offset to the next entry, the caller
1936 * will overwrite it for the last entry
1937 * that's why we always include the padding
1941 * set padding to zero
1944 memset(p, 0, pad - len);
1951 case SMB_FIND_FILE_NAMES_INFO:
1952 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1954 SIVAL(p,0,reskey); p += 4;
1956 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1957 acl on a dir (tridge) */
1958 len = srvstr_push(base_data, flags2, p,
1959 fname, PTR_DIFF(end_data, p),
1960 STR_TERMINATE_ASCII);
1964 len = PTR_DIFF(p, pdata);
1965 pad = (len + (align-1)) & ~(align-1);
1967 * offset to the next entry, the caller
1968 * will overwrite it for the last entry
1969 * that's why we always include the padding
1973 * set padding to zero
1976 memset(p, 0, pad - len);
1983 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1984 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1986 SIVAL(p,0,reskey); p += 4;
1987 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1988 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1989 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1990 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1991 SOFF_T(p,0,file_size); p += 8;
1992 SOFF_T(p,0,allocation_size); p += 8;
1993 SIVAL(p,0,mode); p += 4;
1994 q = p; p += 4; /* q is placeholder for name length. */
1995 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1996 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1998 unsigned int ea_size = estimate_ea_size(conn, NULL,
2000 SIVAL(p,0,ea_size); /* Extended attributes */
2003 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2004 SBVAL(p,0,file_index); p += 8;
2005 len = srvstr_push(base_data, flags2, p,
2006 fname, PTR_DIFF(end_data, p),
2007 STR_TERMINATE_ASCII);
2011 len = PTR_DIFF(p, pdata);
2012 pad = (len + (align-1)) & ~(align-1);
2014 * offset to the next entry, the caller
2015 * will overwrite it for the last entry
2016 * that's why we always include the padding
2020 * set padding to zero
2023 memset(p, 0, pad - len);
2030 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2031 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2032 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2034 SIVAL(p,0,reskey); p += 4;
2035 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2036 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2037 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2038 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2039 SOFF_T(p,0,file_size); p += 8;
2040 SOFF_T(p,0,allocation_size); p += 8;
2041 SIVAL(p,0,mode); p += 4;
2042 q = p; p += 4; /* q is placeholder for name length */
2043 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2044 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2046 unsigned int ea_size = estimate_ea_size(conn, NULL,
2048 SIVAL(p,0,ea_size); /* Extended attributes */
2051 /* Clear the short name buffer. This is
2052 * IMPORTANT as not doing so will trigger
2053 * a Win2k client bug. JRA.
2055 if (!was_8_3 && check_mangled_names) {
2056 char mangled_name[13]; /* mangled 8.3 name. */
2057 if (!name_to_8_3(fname,mangled_name,True,
2059 /* Error - mangle failed ! */
2060 memset(mangled_name,'\0',12);
2062 mangled_name[12] = 0;
2063 len = srvstr_push(base_data, flags2,
2064 p+2, mangled_name, 24,
2065 STR_UPPER|STR_UNICODE);
2068 memset(p + 2 + len,'\0',24 - len);
2075 SSVAL(p,0,0); p += 2; /* Reserved ? */
2076 SBVAL(p,0,file_index); p += 8;
2077 len = srvstr_push(base_data, flags2, p,
2078 fname, PTR_DIFF(end_data, p),
2079 STR_TERMINATE_ASCII);
2083 len = PTR_DIFF(p, pdata);
2084 pad = (len + (align-1)) & ~(align-1);
2086 * offset to the next entry, the caller
2087 * will overwrite it for the last entry
2088 * that's why we always include the padding
2092 * set padding to zero
2095 memset(p, 0, pad - len);
2102 /* CIFS UNIX Extension. */
2104 case SMB_FIND_FILE_UNIX:
2105 case SMB_FIND_FILE_UNIX_INFO2:
2107 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2109 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2111 if (info_level == SMB_FIND_FILE_UNIX) {
2112 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2113 p = store_file_unix_basic(conn, p,
2114 NULL, &smb_fname->st);
2115 len = srvstr_push(base_data, flags2, p,
2116 fname, PTR_DIFF(end_data, p),
2119 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2120 p = store_file_unix_basic_info2(conn, p,
2121 NULL, &smb_fname->st);
2124 len = srvstr_push(base_data, flags2, p, fname,
2125 PTR_DIFF(end_data, p), 0);
2126 SIVAL(nameptr, 0, len);
2131 len = PTR_DIFF(p, pdata);
2132 pad = (len + (align-1)) & ~(align-1);
2134 * offset to the next entry, the caller
2135 * will overwrite it for the last entry
2136 * that's why we always include the padding
2140 * set padding to zero
2143 memset(p, 0, pad - len);
2148 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2156 if (PTR_DIFF(p,pdata) > space_remaining) {
2157 *out_of_space = true;
2158 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2159 "(wanted %u, had %d)\n",
2160 (unsigned int)PTR_DIFF(p,pdata),
2162 return false; /* Not finished - just out of space */
2165 /* Setup the last entry pointer, as an offset from base_data */
2166 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2167 /* Advance the data pointer to the next slot */
2173 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2174 connection_struct *conn,
2175 struct dptr_struct *dirptr,
2177 const char *path_mask,
2180 int requires_resume_key,
2188 int space_remaining,
2190 bool *got_exact_match,
2191 int *_last_entry_off,
2192 struct ea_list *name_list)
2195 const char *mask = NULL;
2196 long prev_dirpos = 0;
2199 struct smb_filename *smb_fname = NULL;
2200 struct smbd_dirptr_lanman2_state state;
2202 uint64_t last_entry_off = 0;
2206 state.info_level = info_level;
2207 state.check_mangled_names = lp_manglednames(conn->params);
2208 state.has_wild = dptr_has_wild(dirptr);
2209 state.got_exact_match = false;
2211 *out_of_space = false;
2212 *got_exact_match = false;
2214 p = strrchr_m(path_mask,'/');
2225 ok = smbd_dirptr_get_entry(ctx,
2231 smbd_dirptr_lanman2_match_fn,
2232 smbd_dirptr_lanman2_mode_fn,
2242 *got_exact_match = state.got_exact_match;
2244 ok = smbd_marshall_dir_entry(ctx,
2249 state.check_mangled_names,
2250 requires_resume_key,
2263 TALLOC_FREE(smb_fname);
2264 if (*out_of_space) {
2265 dptr_SeekDir(dirptr, prev_dirpos);
2272 *_last_entry_off = last_entry_off;
2276 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2277 connection_struct *conn,
2278 struct dptr_struct *dirptr,
2280 const char *path_mask,
2283 bool requires_resume_key,
2289 int space_remaining,
2291 bool *got_exact_match,
2292 int *last_entry_off,
2293 struct ea_list *name_list)
2296 const bool do_pad = true;
2298 if (info_level >= 1 && info_level <= 3) {
2299 /* No alignment on earlier info levels. */
2303 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2304 path_mask, dirtype, info_level,
2305 requires_resume_key, dont_descend, ask_sharemode,
2307 ppdata, base_data, end_data,
2309 out_of_space, got_exact_match,
2310 last_entry_off, name_list);
2313 /****************************************************************************
2314 Reply to a TRANS2_FINDFIRST.
2315 ****************************************************************************/
2317 static void call_trans2findfirst(connection_struct *conn,
2318 struct smb_request *req,
2319 char **pparams, int total_params,
2320 char **ppdata, int total_data,
2321 unsigned int max_data_bytes)
2323 /* We must be careful here that we don't return more than the
2324 allowed number of data bytes. If this means returning fewer than
2325 maxentries then so be it. We assume that the redirector has
2326 enough room for the fixed number of parameter bytes it has
2328 struct smb_filename *smb_dname = NULL;
2329 char *params = *pparams;
2330 char *pdata = *ppdata;
2334 uint16 findfirst_flags;
2335 bool close_after_first;
2337 bool requires_resume_key;
2339 char *directory = NULL;
2342 int last_entry_off=0;
2346 bool finished = False;
2347 bool dont_descend = False;
2348 bool out_of_space = False;
2349 int space_remaining;
2350 bool mask_contains_wcard = False;
2351 struct ea_list *ea_list = NULL;
2352 NTSTATUS ntstatus = NT_STATUS_OK;
2353 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2354 TALLOC_CTX *ctx = talloc_tos();
2355 struct dptr_struct *dirptr = NULL;
2356 struct smbd_server_connection *sconn = req->sconn;
2357 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2358 bool backup_priv = false;
2360 if (total_params < 13) {
2361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2365 dirtype = SVAL(params,0);
2366 maxentries = SVAL(params,2);
2367 findfirst_flags = SVAL(params,4);
2368 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2369 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2370 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2371 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2372 security_token_has_privilege(get_current_nttok(conn),
2375 info_level = SVAL(params,6);
2377 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2378 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2379 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2381 info_level, max_data_bytes));
2384 /* W2K3 seems to treat zero as 1. */
2388 switch (info_level) {
2389 case SMB_FIND_INFO_STANDARD:
2390 case SMB_FIND_EA_SIZE:
2391 case SMB_FIND_EA_LIST:
2392 case SMB_FIND_FILE_DIRECTORY_INFO:
2393 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2394 case SMB_FIND_FILE_NAMES_INFO:
2395 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2396 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2397 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2399 case SMB_FIND_FILE_UNIX:
2400 case SMB_FIND_FILE_UNIX_INFO2:
2401 /* Always use filesystem for UNIX mtime query. */
2402 ask_sharemode = false;
2403 if (!lp_unix_extensions()) {
2404 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2407 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2410 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2414 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2415 params+12, total_params - 12,
2416 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2417 if (!NT_STATUS_IS_OK(ntstatus)) {
2418 reply_nterror(req, ntstatus);
2424 ntstatus = filename_convert_with_privilege(ctx,
2429 &mask_contains_wcard,
2432 ntstatus = filename_convert(ctx, conn,
2433 req->flags2 & FLAGS2_DFS_PATHNAMES,
2436 &mask_contains_wcard,
2440 if (!NT_STATUS_IS_OK(ntstatus)) {
2441 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2442 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2443 ERRSRV, ERRbadpath);
2446 reply_nterror(req, ntstatus);
2450 mask = smb_dname->original_lcomp;
2452 directory = smb_dname->base_name;
2454 p = strrchr_m(directory,'/');
2456 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2457 if((directory[0] == '.') && (directory[1] == '\0')) {
2458 mask = talloc_strdup(ctx,"*");
2460 reply_nterror(req, NT_STATUS_NO_MEMORY);
2463 mask_contains_wcard = True;
2469 if (p == NULL || p == directory) {
2470 /* Ensure we don't have a directory name of "". */
2471 directory = talloc_strdup(talloc_tos(), ".");
2473 reply_nterror(req, NT_STATUS_NO_MEMORY);
2478 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2480 if (info_level == SMB_FIND_EA_LIST) {
2483 if (total_data < 4) {
2484 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2488 ea_size = IVAL(pdata,0);
2489 if (ea_size != total_data) {
2490 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2491 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2492 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2496 if (!lp_ea_support(SNUM(conn))) {
2497 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2501 /* Pull out the list of names. */
2502 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2504 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2509 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2510 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2514 *ppdata = (char *)SMB_REALLOC(
2515 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2516 if(*ppdata == NULL ) {
2517 reply_nterror(req, NT_STATUS_NO_MEMORY);
2521 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2523 /* Realloc the params space */
2524 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2525 if (*pparams == NULL) {
2526 reply_nterror(req, NT_STATUS_NO_MEMORY);
2531 /* Save the wildcard match and attribs we are using on this directory -
2532 needed as lanman2 assumes these are being saved between calls */
2534 ntstatus = dptr_create(conn,
2542 mask_contains_wcard,
2546 if (!NT_STATUS_IS_OK(ntstatus)) {
2547 reply_nterror(req, ntstatus);
2552 /* Remember this in case we have
2553 to do a findnext. */
2554 dptr_set_priv(dirptr);
2557 dptr_num = dptr_dnum(dirptr);
2558 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2560 /* Initialize per TRANS2_FIND_FIRST operation data */
2561 dptr_init_search_op(dirptr);
2563 /* We don't need to check for VOL here as this is returned by
2564 a different TRANS2 call. */
2566 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2567 directory,lp_dontdescend(ctx, SNUM(conn))));
2568 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2569 dont_descend = True;
2572 space_remaining = max_data_bytes;
2573 out_of_space = False;
2575 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2576 bool got_exact_match = False;
2578 /* this is a heuristic to avoid seeking the dirptr except when
2579 absolutely necessary. It allows for a filename of about 40 chars */
2580 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2581 out_of_space = True;
2584 finished = !get_lanman2_dir_entry(ctx,
2588 mask,dirtype,info_level,
2589 requires_resume_key,dont_descend,
2592 space_remaining, &out_of_space,
2594 &last_entry_off, ea_list);
2597 if (finished && out_of_space)
2600 if (!finished && !out_of_space)
2604 * As an optimisation if we know we aren't looking
2605 * for a wildcard name (ie. the name matches the wildcard exactly)
2606 * then we can finish on any (first) match.
2607 * This speeds up large directory searches. JRA.
2613 /* Ensure space_remaining never goes -ve. */
2614 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2615 space_remaining = 0;
2616 out_of_space = true;
2618 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2622 /* Check if we can close the dirptr */
2623 if(close_after_first || (finished && close_if_end)) {
2624 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2625 dptr_close(sconn, &dptr_num);
2629 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2630 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2631 * the protocol level is less than NT1. Tested with smbclient. JRA.
2632 * This should fix the OS/2 client bug #2335.
2635 if(numentries == 0) {
2636 dptr_close(sconn, &dptr_num);
2637 if (get_Protocol() < PROTOCOL_NT1) {
2638 reply_force_doserror(req, ERRDOS, ERRnofiles);
2641 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2642 ERRDOS, ERRbadfile);
2647 /* At this point pdata points to numentries directory entries. */
2649 /* Set up the return parameter block */
2650 SSVAL(params,0,dptr_num);
2651 SSVAL(params,2,numentries);
2652 SSVAL(params,4,finished);
2653 SSVAL(params,6,0); /* Never an EA error */
2654 SSVAL(params,8,last_entry_off);
2656 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2659 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2660 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2662 reply_nterror(req, NT_STATUS_NO_MEMORY);
2666 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2667 smb_fn_name(req->cmd),
2668 mask, directory, dirtype, numentries ) );
2671 * Force a name mangle here to ensure that the
2672 * mask as an 8.3 name is top of the mangled cache.
2673 * The reasons for this are subtle. Don't remove
2674 * this code unless you know what you are doing
2675 * (see PR#13758). JRA.
2678 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2679 char mangled_name[13];
2680 name_to_8_3(mask, mangled_name, True, conn->params);
2688 TALLOC_FREE(smb_dname);
2692 /****************************************************************************
2693 Reply to a TRANS2_FINDNEXT.
2694 ****************************************************************************/
2696 static void call_trans2findnext(connection_struct *conn,
2697 struct smb_request *req,
2698 char **pparams, int total_params,
2699 char **ppdata, int total_data,
2700 unsigned int max_data_bytes)
2702 /* We must be careful here that we don't return more than the
2703 allowed number of data bytes. If this means returning fewer than
2704 maxentries then so be it. We assume that the redirector has
2705 enough room for the fixed number of parameter bytes it has
2707 char *params = *pparams;
2708 char *pdata = *ppdata;
2714 uint16 findnext_flags;
2715 bool close_after_request;
2717 bool requires_resume_key;
2719 bool mask_contains_wcard = False;
2720 char *resume_name = NULL;
2721 const char *mask = NULL;
2722 const char *directory = NULL;
2726 int i, last_entry_off=0;
2727 bool finished = False;
2728 bool dont_descend = False;
2729 bool out_of_space = False;
2730 int space_remaining;
2731 struct ea_list *ea_list = NULL;
2732 NTSTATUS ntstatus = NT_STATUS_OK;
2733 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2734 TALLOC_CTX *ctx = talloc_tos();
2735 struct dptr_struct *dirptr;
2736 struct smbd_server_connection *sconn = req->sconn;
2737 bool backup_priv = false;
2739 if (total_params < 13) {
2740 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2744 dptr_num = SVAL(params,0);
2745 maxentries = SVAL(params,2);
2746 info_level = SVAL(params,4);
2747 resume_key = IVAL(params,6);
2748 findnext_flags = SVAL(params,10);
2749 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2750 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2751 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2752 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2754 if (!continue_bit) {
2755 /* We only need resume_name if continue_bit is zero. */
2756 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2758 total_params - 12, STR_TERMINATE, &ntstatus,
2759 &mask_contains_wcard);
2760 if (!NT_STATUS_IS_OK(ntstatus)) {
2761 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2762 complain (it thinks we're asking for the directory above the shared
2763 path or an invalid name). Catch this as the resume name is only compared, never used in
2764 a file access. JRA. */
2765 srvstr_pull_talloc(ctx, params, req->flags2,
2766 &resume_name, params+12,
2770 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2771 reply_nterror(req, ntstatus);
2777 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2778 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2779 resume_key = %d resume name = %s continue=%d level = %d\n",
2780 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2781 requires_resume_key, resume_key,
2782 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2785 /* W2K3 seems to treat zero as 1. */
2789 switch (info_level) {
2790 case SMB_FIND_INFO_STANDARD:
2791 case SMB_FIND_EA_SIZE:
2792 case SMB_FIND_EA_LIST:
2793 case SMB_FIND_FILE_DIRECTORY_INFO:
2794 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2795 case SMB_FIND_FILE_NAMES_INFO:
2796 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2797 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2798 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2800 case SMB_FIND_FILE_UNIX:
2801 case SMB_FIND_FILE_UNIX_INFO2:
2802 /* Always use filesystem for UNIX mtime query. */
2803 ask_sharemode = false;
2804 if (!lp_unix_extensions()) {
2805 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2814 if (info_level == SMB_FIND_EA_LIST) {
2817 if (total_data < 4) {
2818 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2822 ea_size = IVAL(pdata,0);
2823 if (ea_size != total_data) {
2824 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2825 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2826 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2830 if (!lp_ea_support(SNUM(conn))) {
2831 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2835 /* Pull out the list of names. */
2836 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2838 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2843 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2844 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;
2914 * Seek to the correct position. We no longer use the resume key but
2915 * depend on the last file name instead.
2918 if(!continue_bit && resume_name && *resume_name) {
2921 long current_pos = 0;
2923 * Remember, name_to_8_3 is called by
2924 * get_lanman2_dir_entry(), so the resume name
2925 * could be mangled. Ensure we check the unmangled name.
2928 if (mangle_is_mangled(resume_name, conn->params)) {
2929 char *new_resume_name = NULL;
2930 mangle_lookup_name_from_8_3(ctx,
2934 if (new_resume_name) {
2935 resume_name = new_resume_name;
2940 * Fix for NT redirector problem triggered by resume key indexes
2941 * changing between directory scans. We now return a resume key of 0
2942 * and instead look for the filename to continue from (also given
2943 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2944 * findfirst/findnext (as is usual) then the directory pointer
2945 * should already be at the correct place.
2948 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2949 } /* end if resume_name && !continue_bit */
2951 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2952 bool got_exact_match = False;
2954 /* this is a heuristic to avoid seeking the dirptr except when
2955 absolutely necessary. It allows for a filename of about 40 chars */
2956 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2957 out_of_space = True;
2960 finished = !get_lanman2_dir_entry(ctx,
2964 mask,dirtype,info_level,
2965 requires_resume_key,dont_descend,
2968 space_remaining, &out_of_space,
2970 &last_entry_off, ea_list);
2973 if (finished && out_of_space)
2976 if (!finished && !out_of_space)
2980 * As an optimisation if we know we aren't looking
2981 * for a wildcard name (ie. the name matches the wildcard exactly)
2982 * then we can finish on any (first) match.
2983 * This speeds up large directory searches. JRA.
2989 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2992 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2993 smb_fn_name(req->cmd),
2994 mask, directory, dirtype, numentries ) );
2996 /* Check if we can close the dirptr */
2997 if(close_after_request || (finished && close_if_end)) {
2998 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2999 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3006 /* Set up the return parameter block */
3007 SSVAL(params,0,numentries);
3008 SSVAL(params,2,finished);
3009 SSVAL(params,4,0); /* Never an EA error */
3010 SSVAL(params,6,last_entry_off);
3012 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3018 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3020 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3024 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3026 SMB_ASSERT(extended_info != NULL);
3028 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3029 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3030 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3031 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3032 #ifdef SAMBA_VERSION_REVISION
3033 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3035 extended_info->samba_subversion = 0;
3036 #ifdef SAMBA_VERSION_RC_RELEASE
3037 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3039 #ifdef SAMBA_VERSION_PRE_RELEASE
3040 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3043 #ifdef SAMBA_VERSION_VENDOR_PATCH
3044 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3046 extended_info->samba_gitcommitdate = 0;
3047 #ifdef SAMBA_VERSION_COMMIT_TIME
3048 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3051 memset(extended_info->samba_version_string, 0,
3052 sizeof(extended_info->samba_version_string));
3054 snprintf (extended_info->samba_version_string,
3055 sizeof(extended_info->samba_version_string),
3056 "%s", samba_version_string());
3059 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3060 TALLOC_CTX *mem_ctx,
3061 uint16_t info_level,
3063 unsigned int max_data_bytes,
3064 struct smb_filename *fname,
3068 char *pdata, *end_data;
3069 int data_len = 0, len;
3070 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3071 int snum = SNUM(conn);
3072 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3073 char *filename = NULL;
3074 uint32 additional_flags = 0;
3075 struct smb_filename smb_fname;
3077 NTSTATUS status = NT_STATUS_OK;
3079 if (fname == NULL || fname->base_name == NULL) {
3082 filename = fname->base_name;
3086 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3087 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3088 "info level (0x%x) on IPC$.\n",
3089 (unsigned int)info_level));
3090 return NT_STATUS_ACCESS_DENIED;
3094 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3096 ZERO_STRUCT(smb_fname);
3097 smb_fname.base_name = discard_const_p(char, filename);
3099 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3100 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3101 return map_nt_error_from_unix(errno);
3106 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3107 return NT_STATUS_INVALID_PARAMETER;
3110 *ppdata = (char *)SMB_REALLOC(
3111 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3112 if (*ppdata == NULL) {
3113 return NT_STATUS_NO_MEMORY;
3117 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3118 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;
3220 case SMB_QUERY_FS_LABEL_INFO:
3221 case SMB_FS_LABEL_INFORMATION:
3222 len = srvstr_push(pdata, flags2, pdata+4, vname,
3223 PTR_DIFF(end_data, pdata+4), 0);
3228 case SMB_QUERY_FS_VOLUME_INFO:
3229 case SMB_FS_VOLUME_INFORMATION:
3232 * Add volume serial number - hash of a combination of
3233 * the called hostname and the service name.
3235 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3236 (str_checksum(get_local_machine_name())<<16));
3238 /* Max label len is 32 characters. */
3239 len = srvstr_push(pdata, flags2, pdata+18, vname,
3240 PTR_DIFF(end_data, pdata+18),
3242 SIVAL(pdata,12,len);
3245 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3246 (int)strlen(vname),vname,
3247 lp_servicename(talloc_tos(), snum)));
3248 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3249 /* the client only requested a portion of the
3251 data_len = max_data_bytes;
3252 status = STATUS_BUFFER_OVERFLOW;
3256 case SMB_QUERY_FS_SIZE_INFO:
3257 case SMB_FS_SIZE_INFORMATION:
3259 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3261 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3262 return map_nt_error_from_unix(errno);
3264 block_size = lp_block_size(snum);
3265 if (bsize < block_size) {
3266 uint64_t factor = block_size/bsize;
3271 if (bsize > block_size) {
3272 uint64_t factor = bsize/block_size;
3277 bytes_per_sector = 512;
3278 sectors_per_unit = bsize/bytes_per_sector;
3279 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3280 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3281 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3282 SBIG_UINT(pdata,0,dsize);
3283 SBIG_UINT(pdata,8,dfree);
3284 SIVAL(pdata,16,sectors_per_unit);
3285 SIVAL(pdata,20,bytes_per_sector);
3289 case SMB_FS_FULL_SIZE_INFORMATION:
3291 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3293 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3294 return map_nt_error_from_unix(errno);
3296 block_size = lp_block_size(snum);
3297 if (bsize < block_size) {
3298 uint64_t factor = block_size/bsize;
3303 if (bsize > block_size) {
3304 uint64_t factor = bsize/block_size;
3309 bytes_per_sector = 512;
3310 sectors_per_unit = bsize/bytes_per_sector;
3311 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3312 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3313 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3314 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3315 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3316 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3317 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3318 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3322 case SMB_QUERY_FS_DEVICE_INFO:
3323 case SMB_FS_DEVICE_INFORMATION:
3325 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3327 if (!CAN_WRITE(conn)) {
3328 characteristics |= FILE_READ_ONLY_DEVICE;
3331 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3332 SIVAL(pdata,4,characteristics);
3336 #ifdef HAVE_SYS_QUOTAS
3337 case SMB_FS_QUOTA_INFORMATION:
3339 * what we have to send --metze:
3341 * Unknown1: 24 NULL bytes
3342 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3343 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3344 * Quota Flags: 2 byte :
3345 * Unknown3: 6 NULL bytes
3349 * details for Quota Flags:
3351 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3352 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3353 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3354 * 0x0001 Enable Quotas: enable quota for this fs
3358 /* we need to fake up a fsp here,
3359 * because its not send in this call
3362 SMB_NTQUOTA_STRUCT quotas;
3365 ZERO_STRUCT(quotas);
3368 fsp.fnum = FNUM_FIELD_INVALID;
3371 if (get_current_uid(conn) != 0) {
3372 DEBUG(0,("get_user_quota: access_denied "
3373 "service [%s] user [%s]\n",
3374 lp_servicename(talloc_tos(), SNUM(conn)),
3375 conn->session_info->unix_info->unix_name));
3376 return NT_STATUS_ACCESS_DENIED;
3379 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3380 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3381 return map_nt_error_from_unix(errno);
3386 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3387 lp_servicename(talloc_tos(), SNUM(conn))));
3389 /* Unknown1 24 NULL bytes*/
3390 SBIG_UINT(pdata,0,(uint64_t)0);
3391 SBIG_UINT(pdata,8,(uint64_t)0);
3392 SBIG_UINT(pdata,16,(uint64_t)0);
3394 /* Default Soft Quota 8 bytes */
3395 SBIG_UINT(pdata,24,quotas.softlim);
3397 /* Default Hard Quota 8 bytes */
3398 SBIG_UINT(pdata,32,quotas.hardlim);
3400 /* Quota flag 2 bytes */
3401 SSVAL(pdata,40,quotas.qflags);
3403 /* Unknown3 6 NULL bytes */
3409 #endif /* HAVE_SYS_QUOTAS */
3410 case SMB_FS_OBJECTID_INFORMATION:
3412 unsigned char objid[16];
3413 struct smb_extended_info extended_info;
3414 memcpy(pdata,create_volume_objectid(conn, objid),16);
3415 samba_extended_info_version (&extended_info);
3416 SIVAL(pdata,16,extended_info.samba_magic);
3417 SIVAL(pdata,20,extended_info.samba_version);
3418 SIVAL(pdata,24,extended_info.samba_subversion);
3419 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3420 memcpy(pdata+36,extended_info.samba_version_string,28);
3426 * Query the version and capabilities of the CIFS UNIX extensions
3430 case SMB_QUERY_CIFS_UNIX_INFO:
3432 bool large_write = lp_min_receive_file_size() &&
3433 !srv_is_signing_active(conn->sconn);
3434 bool large_read = !srv_is_signing_active(conn->sconn);
3435 int encrypt_caps = 0;
3437 if (!lp_unix_extensions()) {
3438 return NT_STATUS_INVALID_LEVEL;
3441 switch (conn->encrypt_level) {
3442 case SMB_SIGNING_OFF:
3445 case SMB_SIGNING_IF_REQUIRED:
3446 case SMB_SIGNING_DEFAULT:
3447 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3449 case SMB_SIGNING_REQUIRED:
3450 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3451 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3452 large_write = false;
3458 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3459 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3461 /* We have POSIX ACLs, pathname, encryption,
3462 * large read/write, and locking capability. */
3464 SBIG_UINT(pdata,4,((uint64_t)(
3465 CIFS_UNIX_POSIX_ACLS_CAP|
3466 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3467 CIFS_UNIX_FCNTL_LOCKS_CAP|
3468 CIFS_UNIX_EXTATTR_CAP|
3469 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3471 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3473 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3477 case SMB_QUERY_POSIX_FS_INFO:
3480 vfs_statvfs_struct svfs;
3482 if (!lp_unix_extensions()) {
3483 return NT_STATUS_INVALID_LEVEL;
3486 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3490 SIVAL(pdata,0,svfs.OptimalTransferSize);
3491 SIVAL(pdata,4,svfs.BlockSize);
3492 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3493 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3494 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3495 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3496 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3497 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3498 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3500 } else if (rc == EOPNOTSUPP) {
3501 return NT_STATUS_INVALID_LEVEL;
3502 #endif /* EOPNOTSUPP */
3504 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3505 return NT_STATUS_DOS(ERRSRV, ERRerror);
3510 case SMB_QUERY_POSIX_WHOAMI:
3516 if (!lp_unix_extensions()) {
3517 return NT_STATUS_INVALID_LEVEL;
3520 if (max_data_bytes < 40) {
3521 return NT_STATUS_BUFFER_TOO_SMALL;
3524 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3525 flags |= SMB_WHOAMI_GUEST;
3528 /* NOTE: 8 bytes for UID/GID, irrespective of native
3529 * platform size. This matches
3530 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3532 data_len = 4 /* flags */
3539 + 4 /* pad/reserved */
3540 + (conn->session_info->unix_token->ngroups * 8)
3542 + (conn->session_info->security_token->num_sids *
3546 SIVAL(pdata, 0, flags);
3547 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3549 (uint64_t)conn->session_info->unix_token->uid);
3550 SBIG_UINT(pdata, 16,
3551 (uint64_t)conn->session_info->unix_token->gid);
3554 if (data_len >= max_data_bytes) {
3555 /* Potential overflow, skip the GIDs and SIDs. */
3557 SIVAL(pdata, 24, 0); /* num_groups */
3558 SIVAL(pdata, 28, 0); /* num_sids */
3559 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3560 SIVAL(pdata, 36, 0); /* reserved */
3566 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3567 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3569 /* We walk the SID list twice, but this call is fairly
3570 * infrequent, and I don't expect that it's performance
3571 * sensitive -- jpeach
3573 for (i = 0, sid_bytes = 0;
3574 i < conn->session_info->security_token->num_sids; ++i) {
3575 sid_bytes += ndr_size_dom_sid(
3576 &conn->session_info->security_token->sids[i],
3580 /* SID list byte count */
3581 SIVAL(pdata, 32, sid_bytes);
3583 /* 4 bytes pad/reserved - must be zero */
3584 SIVAL(pdata, 36, 0);
3588 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3589 SBIG_UINT(pdata, data_len,
3590 (uint64_t)conn->session_info->unix_token->groups[i]);
3596 i < conn->session_info->security_token->num_sids; ++i) {
3597 int sid_len = ndr_size_dom_sid(
3598 &conn->session_info->security_token->sids[i],
3601 sid_linearize(pdata + data_len, sid_len,
3602 &conn->session_info->security_token->sids[i]);
3603 data_len += sid_len;
3609 case SMB_MAC_QUERY_FS_INFO:
3611 * Thursby MAC extension... ONLY on NTFS filesystems
3612 * once we do streams then we don't need this
3614 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3616 SIVAL(pdata,84,0x100); /* Don't support mac... */
3621 return NT_STATUS_INVALID_LEVEL;
3624 *ret_data_len = data_len;
3628 /****************************************************************************
3629 Reply to a TRANS2_QFSINFO (query filesystem info).
3630 ****************************************************************************/
3632 static void call_trans2qfsinfo(connection_struct *conn,
3633 struct smb_request *req,
3634 char **pparams, int total_params,
3635 char **ppdata, int total_data,
3636 unsigned int max_data_bytes)
3638 char *params = *pparams;
3639 uint16_t info_level;
3643 if (total_params < 2) {
3644 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3648 info_level = SVAL(params,0);
3650 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3651 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3652 DEBUG(0,("call_trans2qfsinfo: encryption required "
3653 "and info level 0x%x sent.\n",
3654 (unsigned int)info_level));
3655 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3660 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3662 status = smbd_do_qfsinfo(conn, req,
3668 if (!NT_STATUS_IS_OK(status)) {
3669 reply_nterror(req, status);
3673 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3676 DEBUG( 4, ( "%s info_level = %d\n",
3677 smb_fn_name(req->cmd), info_level) );
3682 /****************************************************************************
3683 Reply to a TRANS2_SETFSINFO (set filesystem info).
3684 ****************************************************************************/
3686 static void call_trans2setfsinfo(connection_struct *conn,
3687 struct smb_request *req,
3688 char **pparams, int total_params,
3689 char **ppdata, int total_data,
3690 unsigned int max_data_bytes)
3692 struct smbd_server_connection *sconn = req->sconn;
3693 char *pdata = *ppdata;
3694 char *params = *pparams;
3697 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3698 lp_servicename(talloc_tos(), SNUM(conn))));
3701 if (total_params < 4) {
3702 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3708 info_level = SVAL(params,2);
3711 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3712 info_level != SMB_SET_CIFS_UNIX_INFO) {
3713 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3714 "info level (0x%x) on IPC$.\n",
3715 (unsigned int)info_level));
3716 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3721 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3722 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3723 DEBUG(0,("call_trans2setfsinfo: encryption required "
3724 "and info level 0x%x sent.\n",
3725 (unsigned int)info_level));
3726 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3731 switch(info_level) {
3732 case SMB_SET_CIFS_UNIX_INFO:
3733 if (!lp_unix_extensions()) {
3734 DEBUG(2,("call_trans2setfsinfo: "
3735 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3736 "unix extensions off\n"));
3738 NT_STATUS_INVALID_LEVEL);
3742 /* There should be 12 bytes of capabilities set. */
3743 if (total_data < 12) {
3746 NT_STATUS_INVALID_PARAMETER);
3749 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3750 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3751 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3752 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3753 /* Just print these values for now. */
3754 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3755 "major = %u, minor = %u cap_low = 0x%x, "
3757 (unsigned int)sconn->
3758 smb1.unix_info.client_major,
3759 (unsigned int)sconn->
3760 smb1.unix_info.client_minor,
3761 (unsigned int)sconn->
3762 smb1.unix_info.client_cap_low,
3763 (unsigned int)sconn->
3764 smb1.unix_info.client_cap_high));
3766 /* Here is where we must switch to posix pathname processing... */
3767 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3768 lp_set_posix_pathnames();
3769 mangle_change_to_posix();
3772 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3773 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3774 /* Client that knows how to do posix locks,
3775 * but not posix open/mkdir operations. Set a
3776 * default type for read/write checks. */
3778 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3783 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3786 size_t param_len = 0;
3787 size_t data_len = total_data;
3789 if (!lp_unix_extensions()) {
3792 NT_STATUS_INVALID_LEVEL);
3796 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3799 NT_STATUS_NOT_SUPPORTED);
3803 if (req->sconn->smb1.echo_handler.trusted_fde) {
3804 DEBUG( 2,("call_trans2setfsinfo: "
3805 "request transport encryption disabled"
3806 "with 'fork echo handler = yes'\n"));
3809 NT_STATUS_NOT_SUPPORTED);
3813 DEBUG( 4,("call_trans2setfsinfo: "
3814 "request transport encryption.\n"));
3816 status = srv_request_encryption_setup(conn,
3817 (unsigned char **)ppdata,
3819 (unsigned char **)pparams,
3822 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3823 !NT_STATUS_IS_OK(status)) {
3824 reply_nterror(req, status);
3828 send_trans2_replies(conn, req,
3836 if (NT_STATUS_IS_OK(status)) {
3837 /* Server-side transport
3838 * encryption is now *on*. */
3839 status = srv_encryption_start(conn);
3840 if (!NT_STATUS_IS_OK(status)) {
3841 char *reason = talloc_asprintf(talloc_tos(),
3842 "Failure in setting "
3843 "up encrypted transport: %s",
3845 exit_server_cleanly(reason);
3851 case SMB_FS_QUOTA_INFORMATION:
3853 files_struct *fsp = NULL;
3854 SMB_NTQUOTA_STRUCT quotas;
3856 ZERO_STRUCT(quotas);
3859 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3860 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3861 lp_servicename(talloc_tos(), SNUM(conn)),
3862 conn->session_info->unix_info->unix_name));
3863 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3867 /* note: normaly there're 48 bytes,
3868 * but we didn't use the last 6 bytes for now
3871 fsp = file_fsp(req, SVAL(params,0));
3873 if (!check_fsp_ntquota_handle(conn, req,
3875 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3877 req, NT_STATUS_INVALID_HANDLE);
3881 if (total_data < 42) {
3882 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3886 NT_STATUS_INVALID_PARAMETER);
3890 /* unknown_1 24 NULL bytes in pdata*/
3892 /* the soft quotas 8 bytes (uint64_t)*/
3893 quotas.softlim = BVAL(pdata,24);
3895 /* the hard quotas 8 bytes (uint64_t)*/
3896 quotas.hardlim = BVAL(pdata,32);
3898 /* quota_flags 2 bytes **/
3899 quotas.qflags = SVAL(pdata,40);
3901 /* unknown_2 6 NULL bytes follow*/
3903 /* now set the quotas */
3904 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3905 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3906 reply_nterror(req, map_nt_error_from_unix(errno));
3913 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3915 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3921 * sending this reply works fine,
3922 * but I'm not sure it's the same
3923 * like windows do...
3926 reply_outbuf(req, 10, 0);
3929 #if defined(HAVE_POSIX_ACLS)
3930 /****************************************************************************
3931 Utility function to count the number of entries in a POSIX acl.
3932 ****************************************************************************/
3934 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3936 unsigned int ace_count = 0;
3937 int entry_id = SMB_ACL_FIRST_ENTRY;
3938 SMB_ACL_ENTRY_T entry;
3940 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3942 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3943 entry_id = SMB_ACL_NEXT_ENTRY;
3950 /****************************************************************************
3951 Utility function to marshall a POSIX acl into wire format.
3952 ****************************************************************************/
3954 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3956 int entry_id = SMB_ACL_FIRST_ENTRY;
3957 SMB_ACL_ENTRY_T entry;
3959 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3960 SMB_ACL_TAG_T tagtype;
3961 SMB_ACL_PERMSET_T permset;
3962 unsigned char perms = 0;
3963 unsigned int own_grp;
3966 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3967 entry_id = SMB_ACL_NEXT_ENTRY;
3970 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3971 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3975 if (sys_acl_get_permset(entry, &permset) == -1) {
3976 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3980 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3981 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3982 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3984 SCVAL(pdata,1,perms);
3987 case SMB_ACL_USER_OBJ:
3988 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3989 own_grp = (unsigned int)pst->st_ex_uid;
3990 SIVAL(pdata,2,own_grp);
3995 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3997 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4000 own_grp = (unsigned int)*puid;
4001 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4002 SIVAL(pdata,2,own_grp);
4006 case SMB_ACL_GROUP_OBJ:
4007 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4008 own_grp = (unsigned int)pst->st_ex_gid;
4009 SIVAL(pdata,2,own_grp);
4014 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4016 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4019 own_grp = (unsigned int)*pgid;
4020 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4021 SIVAL(pdata,2,own_grp);
4026 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4027 SIVAL(pdata,2,0xFFFFFFFF);
4028 SIVAL(pdata,6,0xFFFFFFFF);
4031 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4032 SIVAL(pdata,2,0xFFFFFFFF);
4033 SIVAL(pdata,6,0xFFFFFFFF);
4036 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4039 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4046 /****************************************************************************
4047 Store the FILE_UNIX_BASIC info.
4048 ****************************************************************************/
4050 static char *store_file_unix_basic(connection_struct *conn,
4053 const SMB_STRUCT_STAT *psbuf)
4055 uint64_t file_index = get_FileIndex(conn, psbuf);
4058 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4059 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4061 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4064 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4067 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4068 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4069 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4072 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4076 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4080 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4083 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4084 devno = psbuf->st_ex_rdev;
4086 devno = psbuf->st_ex_dev;
4089 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4093 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4097 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4100 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4104 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4111 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4112 * the chflags(2) (or equivalent) flags.
4114 * XXX: this really should be behind the VFS interface. To do this, we would
4115 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4116 * Each VFS module could then implement its own mapping as appropriate for the
4117 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4119 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4123 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4127 { UF_IMMUTABLE, EXT_IMMUTABLE },
4131 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4135 { UF_HIDDEN, EXT_HIDDEN },
4138 /* Do not remove. We need to guarantee that this array has at least one
4139 * entry to build on HP-UX.
4145 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4146 uint32 *smb_fflags, uint32 *smb_fmask)
4150 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4151 *smb_fmask |= info2_flags_map[i].smb_fflag;
4152 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4153 *smb_fflags |= info2_flags_map[i].smb_fflag;
4158 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4159 const uint32 smb_fflags,
4160 const uint32 smb_fmask,
4163 uint32 max_fmask = 0;
4166 *stat_fflags = psbuf->st_ex_flags;
4168 /* For each flags requested in smb_fmask, check the state of the
4169 * corresponding flag in smb_fflags and set or clear the matching
4173 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4174 max_fmask |= info2_flags_map[i].smb_fflag;
4175 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4176 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4177 *stat_fflags |= info2_flags_map[i].stat_fflag;
4179 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4184 /* If smb_fmask is asking to set any bits that are not supported by
4185 * our flag mappings, we should fail.
4187 if ((smb_fmask & max_fmask) != smb_fmask) {
4195 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4196 * of file flags and birth (create) time.
4198 static char *store_file_unix_basic_info2(connection_struct *conn,
4201 const SMB_STRUCT_STAT *psbuf)
4203 uint32 file_flags = 0;
4204 uint32 flags_mask = 0;
4206 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4208 /* Create (birth) time 64 bit */
4209 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4212 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4213 SIVAL(pdata, 0, file_flags); /* flags */
4214 SIVAL(pdata, 4, flags_mask); /* mask */
4220 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4221 const struct stream_struct *streams,
4223 unsigned int max_data_bytes,
4224 unsigned int *data_size)
4227 unsigned int ofs = 0;
4229 for (i = 0; i < num_streams; i++) {
4230 unsigned int next_offset;
4232 smb_ucs2_t *namebuf;
4234 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4235 streams[i].name, &namelen) ||
4238 return NT_STATUS_INVALID_PARAMETER;
4242 * name_buf is now null-terminated, we need to marshall as not
4249 * We cannot overflow ...
4251 if ((ofs + 24 + namelen) > max_data_bytes) {
4252 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4254 TALLOC_FREE(namebuf);
4255 return STATUS_BUFFER_OVERFLOW;
4258 SIVAL(data, ofs+4, namelen);
4259 SOFF_T(data, ofs+8, streams[i].size);
4260 SOFF_T(data, ofs+16, streams[i].alloc_size);
4261 memcpy(data+ofs+24, namebuf, namelen);
4262 TALLOC_FREE(namebuf);
4264 next_offset = ofs + 24 + namelen;
4266 if (i == num_streams-1) {
4267 SIVAL(data, ofs, 0);
4270 unsigned int align = ndr_align_size(next_offset, 8);
4272 if ((next_offset + align) > max_data_bytes) {
4273 DEBUG(10, ("refusing to overflow align "
4274 "reply at stream %u\n",
4276 TALLOC_FREE(namebuf);
4277 return STATUS_BUFFER_OVERFLOW;
4280 memset(data+next_offset, 0, align);
4281 next_offset += align;
4283 SIVAL(data, ofs, next_offset - ofs);
4290 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4294 return NT_STATUS_OK;
4297 /****************************************************************************
4298 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4299 ****************************************************************************/
4301 static void call_trans2qpipeinfo(connection_struct *conn,
4302 struct smb_request *req,
4303 unsigned int tran_call,
4304 char **pparams, int total_params,
4305 char **ppdata, int total_data,
4306 unsigned int max_data_bytes)
4308 char *params = *pparams;
4309 char *pdata = *ppdata;
4310 unsigned int data_size = 0;
4311 unsigned int param_size = 2;
4316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4320 if (total_params < 4) {
4321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4325 fsp = file_fsp(req, SVAL(params,0));
4326 if (!fsp_is_np(fsp)) {
4327 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4331 info_level = SVAL(params,2);
4333 *pparams = (char *)SMB_REALLOC(*pparams,2);
4334 if (*pparams == NULL) {
4335 reply_nterror(req, NT_STATUS_NO_MEMORY);
4340 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4341 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4344 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4345 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4346 if (*ppdata == NULL ) {
4347 reply_nterror(req, NT_STATUS_NO_MEMORY);
4352 switch (info_level) {
4353 case SMB_FILE_STANDARD_INFORMATION:
4355 SOFF_T(pdata,0,4096LL);
4362 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4366 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4372 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4373 TALLOC_CTX *mem_ctx,
4374 uint16_t info_level,
4376 struct smb_filename *smb_fname,
4377 bool delete_pending,
4378 struct timespec write_time_ts,
4379 struct ea_list *ea_list,
4380 int lock_data_count,
4383 unsigned int max_data_bytes,
4385 unsigned int *pdata_size)
4387 char *pdata = *ppdata;
4388 char *dstart, *dend;
4389 unsigned int data_size;
4390 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4391 time_t create_time, mtime, atime, c_time;
4392 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4399 uint64_t file_size = 0;
4401 uint64_t allocation_size = 0;
4402 uint64_t file_index = 0;
4403 uint32_t access_mask = 0;
4405 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4406 return NT_STATUS_INVALID_LEVEL;
4409 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4410 smb_fname_str_dbg(smb_fname),
4412 info_level, max_data_bytes));
4414 mode = dos_mode(conn, smb_fname);
4415 nlink = psbuf->st_ex_nlink;
4417 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4421 if ((nlink > 0) && delete_pending) {
4425 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4426 return NT_STATUS_INVALID_PARAMETER;
4429 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4430 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4431 if (*ppdata == NULL) {
4432 return NT_STATUS_NO_MEMORY;
4436 dend = dstart + data_size - 1;
4438 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4439 update_stat_ex_mtime(psbuf, write_time_ts);
4442 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4443 mtime_ts = psbuf->st_ex_mtime;
4444 atime_ts = psbuf->st_ex_atime;
4445 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4447 if (lp_dos_filetime_resolution(SNUM(conn))) {
4448 dos_filetime_timespec(&create_time_ts);
4449 dos_filetime_timespec(&mtime_ts);
4450 dos_filetime_timespec(&atime_ts);
4451 dos_filetime_timespec(&ctime_ts);
4454 create_time = convert_timespec_to_time_t(create_time_ts);
4455 mtime = convert_timespec_to_time_t(mtime_ts);
4456 atime = convert_timespec_to_time_t(atime_ts);
4457 c_time = convert_timespec_to_time_t(ctime_ts);
4459 p = strrchr_m(smb_fname->base_name,'/');
4461 base_name = smb_fname->base_name;
4465 /* NT expects the name to be in an exact form of the *full*
4466 filename. See the trans2 torture test */
4467 if (ISDOT(base_name)) {
4468 dos_fname = talloc_strdup(mem_ctx, "\\");
4470 return NT_STATUS_NO_MEMORY;
4473 dos_fname = talloc_asprintf(mem_ctx,
4475 smb_fname->base_name);
4477 return NT_STATUS_NO_MEMORY;
4479 if (is_ntfs_stream_smb_fname(smb_fname)) {
4480 dos_fname = talloc_asprintf(dos_fname, "%s",
4481 smb_fname->stream_name);
4483 return NT_STATUS_NO_MEMORY;
4487 string_replace(dos_fname, '/', '\\');
4490 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4493 /* Do we have this path open ? */
4495 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4496 fsp1 = file_find_di_first(conn->sconn, fileid);
4497 if (fsp1 && fsp1->initial_allocation_size) {
4498 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4502 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4503 file_size = get_file_size_stat(psbuf);
4507 pos = fsp->fh->position_information;
4511 access_mask = fsp->access_mask;
4513 /* GENERIC_EXECUTE mapping from Windows */
4514 access_mask = 0x12019F;
4517 /* This should be an index number - looks like
4520 I think this causes us to fail the IFSKIT
4521 BasicFileInformationTest. -tpot */
4522 file_index = get_FileIndex(conn, psbuf);
4524 switch (info_level) {
4525 case SMB_INFO_STANDARD:
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4528 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4529 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4530 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4531 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4532 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4533 SSVAL(pdata,l1_attrFile,mode);
4536 case SMB_INFO_QUERY_EA_SIZE:
4538 unsigned int ea_size =
4539 estimate_ea_size(conn, fsp,
4541 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4543 srv_put_dos_date2(pdata,0,create_time);
4544 srv_put_dos_date2(pdata,4,atime);
4545 srv_put_dos_date2(pdata,8,mtime); /* write time */
4546 SIVAL(pdata,12,(uint32)file_size);
4547 SIVAL(pdata,16,(uint32)allocation_size);
4548 SSVAL(pdata,20,mode);
4549 SIVAL(pdata,22,ea_size);
4553 case SMB_INFO_IS_NAME_VALID:
4554 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4556 /* os/2 needs this ? really ?*/
4557 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4559 /* This is only reached for qpathinfo */
4563 case SMB_INFO_QUERY_EAS_FROM_LIST:
4565 size_t total_ea_len = 0;
4566 struct ea_list *ea_file_list = NULL;
4567 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4570 get_ea_list_from_file(mem_ctx, conn, fsp,
4572 &total_ea_len, &ea_file_list);
4573 if (!NT_STATUS_IS_OK(status)) {
4577 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4579 if (!ea_list || (total_ea_len > data_size)) {
4581 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4585 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4589 case SMB_INFO_QUERY_ALL_EAS:
4591 /* We have data_size bytes to put EA's into. */
4592 size_t total_ea_len = 0;
4593 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4595 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4597 &total_ea_len, &ea_list);
4598 if (!NT_STATUS_IS_OK(status)) {
4602 if (!ea_list || (total_ea_len > data_size)) {
4604 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4608 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4612 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4614 /* This is FileFullEaInformation - 0xF which maps to
4615 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4617 /* We have data_size bytes to put EA's into. */
4618 size_t total_ea_len = 0;
4619 struct ea_list *ea_file_list = NULL;
4621 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4623 /*TODO: add filtering and index handling */
4626 get_ea_list_from_file(mem_ctx, conn, fsp,
4628 &total_ea_len, &ea_file_list);
4629 if (!NT_STATUS_IS_OK(status)) {
4632 if (!ea_file_list) {
4633 return NT_STATUS_NO_EAS_ON_FILE;
4636 status = fill_ea_chained_buffer(mem_ctx,
4640 conn, ea_file_list);
4641 if (!NT_STATUS_IS_OK(status)) {
4647 case SMB_FILE_BASIC_INFORMATION:
4648 case SMB_QUERY_FILE_BASIC_INFO:
4650 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4652 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4654 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4658 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4659 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4660 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4661 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4662 SIVAL(pdata,32,mode);
4664 DEBUG(5,("SMB_QFBI - "));
4665 DEBUG(5,("create: %s ", ctime(&create_time)));
4666 DEBUG(5,("access: %s ", ctime(&atime)));
4667 DEBUG(5,("write: %s ", ctime(&mtime)));
4668 DEBUG(5,("change: %s ", ctime(&c_time)));
4669 DEBUG(5,("mode: %x\n", mode));
4672 case SMB_FILE_STANDARD_INFORMATION:
4673 case SMB_QUERY_FILE_STANDARD_INFO:
4675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4677 SOFF_T(pdata,0,allocation_size);
4678 SOFF_T(pdata,8,file_size);
4679 SIVAL(pdata,16,nlink);
4680 SCVAL(pdata,20,delete_pending?1:0);
4681 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4682 SSVAL(pdata,22,0); /* Padding. */
4685 case SMB_FILE_EA_INFORMATION:
4686 case SMB_QUERY_FILE_EA_INFO:
4688 unsigned int ea_size =
4689 estimate_ea_size(conn, fsp, smb_fname);
4690 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4692 SIVAL(pdata,0,ea_size);
4696 /* Get the 8.3 name - used if NT SMB was negotiated. */
4697 case SMB_QUERY_FILE_ALT_NAME_INFO:
4698 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4701 char mangled_name[13];
4702 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4703 if (!name_to_8_3(base_name,mangled_name,
4704 True,conn->params)) {
4705 return NT_STATUS_NO_MEMORY;
4707 len = srvstr_push(dstart, flags2,
4708 pdata+4, mangled_name,
4709 PTR_DIFF(dend, pdata+4),
4711 data_size = 4 + len;
4716 case SMB_QUERY_FILE_NAME_INFO:
4720 this must be *exactly* right for ACLs on mapped drives to work
4722 len = srvstr_push(dstart, flags2,
4724 PTR_DIFF(dend, pdata+4),
4726 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4727 data_size = 4 + len;
4732 case SMB_FILE_ALLOCATION_INFORMATION:
4733 case SMB_QUERY_FILE_ALLOCATION_INFO:
4734 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4736 SOFF_T(pdata,0,allocation_size);
4739 case SMB_FILE_END_OF_FILE_INFORMATION:
4740 case SMB_QUERY_FILE_END_OF_FILEINFO:
4741 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4743 SOFF_T(pdata,0,file_size);
4746 case SMB_QUERY_FILE_ALL_INFO:
4747 case SMB_FILE_ALL_INFORMATION:
4750 unsigned int ea_size =
4751 estimate_ea_size(conn, fsp, smb_fname);
4752 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4753 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4754 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4755 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4756 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4757 SIVAL(pdata,32,mode);
4758 SIVAL(pdata,36,0); /* padding. */
4760 SOFF_T(pdata,0,allocation_size);
4761 SOFF_T(pdata,8,file_size);
4762 SIVAL(pdata,16,nlink);
4763 SCVAL(pdata,20,delete_pending);
4764 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4767 SIVAL(pdata,0,ea_size);
4768 pdata += 4; /* EA info */
4769 len = srvstr_push(dstart, flags2,
4771 PTR_DIFF(dend, pdata+4),
4775 data_size = PTR_DIFF(pdata,(*ppdata));
4779 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4782 unsigned int ea_size =
4783 estimate_ea_size(conn, fsp, smb_fname);
4784 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4785 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4786 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4787 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4788 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4789 SIVAL(pdata, 0x20, mode);
4790 SIVAL(pdata, 0x24, 0); /* padding. */
4791 SBVAL(pdata, 0x28, allocation_size);
4792 SBVAL(pdata, 0x30, file_size);
4793 SIVAL(pdata, 0x38, nlink);
4794 SCVAL(pdata, 0x3C, delete_pending);
4795 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4796 SSVAL(pdata, 0x3E, 0); /* padding */
4797 SBVAL(pdata, 0x40, file_index);
4798 SIVAL(pdata, 0x48, ea_size);
4799 SIVAL(pdata, 0x4C, access_mask);
4800 SBVAL(pdata, 0x50, pos);
4801 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4802 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4806 len = srvstr_push(dstart, flags2,
4808 PTR_DIFF(dend, pdata+4),
4812 data_size = PTR_DIFF(pdata,(*ppdata));
4815 case SMB_FILE_INTERNAL_INFORMATION:
4817 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4818 SBVAL(pdata, 0, file_index);
4822 case SMB_FILE_ACCESS_INFORMATION:
4823 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4824 SIVAL(pdata, 0, access_mask);
4828 case SMB_FILE_NAME_INFORMATION:
4829 /* Pathname with leading '\'. */
4832 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4833 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4834 SIVAL(pdata,0,byte_len);
4835 data_size = 4 + byte_len;
4839 case SMB_FILE_DISPOSITION_INFORMATION:
4840 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4842 SCVAL(pdata,0,delete_pending);
4845 case SMB_FILE_POSITION_INFORMATION:
4846 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4848 SOFF_T(pdata,0,pos);
4851 case SMB_FILE_MODE_INFORMATION:
4852 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4853 SIVAL(pdata,0,mode);
4857 case SMB_FILE_ALIGNMENT_INFORMATION:
4858 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4859 SIVAL(pdata,0,0); /* No alignment needed. */
4864 * NT4 server just returns "invalid query" to this - if we try
4865 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4868 /* The first statement above is false - verified using Thursby
4869 * client against NT4 -- gcolley.
4871 case SMB_QUERY_FILE_STREAM_INFO:
4872 case SMB_FILE_STREAM_INFORMATION: {
4873 unsigned int num_streams = 0;
4874 struct stream_struct *streams = NULL;
4876 DEBUG(10,("smbd_do_qfilepathinfo: "
4877 "SMB_FILE_STREAM_INFORMATION\n"));
4879 if (is_ntfs_stream_smb_fname(smb_fname)) {
4880 return NT_STATUS_INVALID_PARAMETER;
4883 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4884 talloc_tos(), &num_streams, &streams);
4886 if (!NT_STATUS_IS_OK(status)) {
4887 DEBUG(10, ("could not get stream info: %s\n",
4888 nt_errstr(status)));
4892 status = marshall_stream_info(num_streams, streams,
4893 pdata, max_data_bytes,
4896 if (!NT_STATUS_IS_OK(status)) {
4897 DEBUG(10, ("marshall_stream_info failed: %s\n",
4898 nt_errstr(status)));
4899 TALLOC_FREE(streams);
4903 TALLOC_FREE(streams);
4907 case SMB_QUERY_COMPRESSION_INFO:
4908 case SMB_FILE_COMPRESSION_INFORMATION:
4909 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4910 SOFF_T(pdata,0,file_size);
4911 SIVAL(pdata,8,0); /* ??? */
4912 SIVAL(pdata,12,0); /* ??? */
4916 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4917 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4918 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4919 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4920 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4921 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4922 SOFF_T(pdata,32,allocation_size);
4923 SOFF_T(pdata,40,file_size);
4924 SIVAL(pdata,48,mode);
4925 SIVAL(pdata,52,0); /* ??? */
4929 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4930 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4931 SIVAL(pdata,0,mode);
4937 * CIFS UNIX Extensions.
4940 case SMB_QUERY_FILE_UNIX_BASIC:
4942 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4943 data_size = PTR_DIFF(pdata,(*ppdata));
4945 DEBUG(4,("smbd_do_qfilepathinfo: "
4946 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4947 dump_data(4, (uint8_t *)(*ppdata), data_size);
4951 case SMB_QUERY_FILE_UNIX_INFO2:
4953 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4954 data_size = PTR_DIFF(pdata,(*ppdata));
4958 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4960 for (i=0; i<100; i++)
4961 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4967 case SMB_QUERY_FILE_UNIX_LINK:
4970 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4973 return NT_STATUS_NO_MEMORY;
4976 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4978 if(!S_ISLNK(psbuf->st_ex_mode)) {
4979 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4982 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4984 len = SMB_VFS_READLINK(conn,
4985 smb_fname->base_name,
4988 return map_nt_error_from_unix(errno);
4991 len = srvstr_push(dstart, flags2,
4993 PTR_DIFF(dend, pdata),
4996 data_size = PTR_DIFF(pdata,(*ppdata));
5001 #if defined(HAVE_POSIX_ACLS)
5002 case SMB_QUERY_POSIX_ACL:
5004 SMB_ACL_T file_acl = NULL;
5005 SMB_ACL_T def_acl = NULL;
5006 uint16 num_file_acls = 0;
5007 uint16 num_def_acls = 0;
5009 if (fsp && fsp->fh->fd != -1) {
5010 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5014 SMB_VFS_SYS_ACL_GET_FILE(conn,
5015 smb_fname->base_name,
5016 SMB_ACL_TYPE_ACCESS,
5020 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5021 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5022 "not implemented on "
5023 "filesystem containing %s\n",
5024 smb_fname->base_name));
5025 return NT_STATUS_NOT_IMPLEMENTED;
5028 if (S_ISDIR(psbuf->st_ex_mode)) {
5029 if (fsp && fsp->is_directory) {
5031 SMB_VFS_SYS_ACL_GET_FILE(
5033 fsp->fsp_name->base_name,
5034 SMB_ACL_TYPE_DEFAULT,
5038 SMB_VFS_SYS_ACL_GET_FILE(
5040 smb_fname->base_name,
5041 SMB_ACL_TYPE_DEFAULT,
5044 def_acl = free_empty_sys_acl(conn, def_acl);
5047 num_file_acls = count_acl_entries(conn, file_acl);
5048 num_def_acls = count_acl_entries(conn, def_acl);
5050 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5051 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5053 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5054 SMB_POSIX_ACL_HEADER_SIZE) ));
5056 TALLOC_FREE(file_acl);
5059 TALLOC_FREE(def_acl);
5061 return NT_STATUS_BUFFER_TOO_SMALL;
5064 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5065 SSVAL(pdata,2,num_file_acls);
5066 SSVAL(pdata,4,num_def_acls);
5067 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5069 TALLOC_FREE(file_acl);
5072 TALLOC_FREE(def_acl);
5074 return NT_STATUS_INTERNAL_ERROR;
5076 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5078 TALLOC_FREE(file_acl);
5081 TALLOC_FREE(def_acl);
5083 return NT_STATUS_INTERNAL_ERROR;
5087 TALLOC_FREE(file_acl);
5090 TALLOC_FREE(def_acl);
5092 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5098 case SMB_QUERY_POSIX_LOCK:
5103 enum brl_type lock_type;
5105 /* We need an open file with a real fd for this. */
5106 if (!fsp || fsp->fh->fd == -1) {
5107 return NT_STATUS_INVALID_LEVEL;
5110 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5111 return NT_STATUS_INVALID_PARAMETER;
5114 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5115 case POSIX_LOCK_TYPE_READ:
5116 lock_type = READ_LOCK;
5118 case POSIX_LOCK_TYPE_WRITE:
5119 lock_type = WRITE_LOCK;
5121 case POSIX_LOCK_TYPE_UNLOCK:
5123 /* There's no point in asking for an unlock... */
5124 return NT_STATUS_INVALID_PARAMETER;
5127 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5128 #if defined(HAVE_LONGLONG)
5129 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5130 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5131 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5132 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5133 #else /* HAVE_LONGLONG */
5134 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5135 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5136 #endif /* HAVE_LONGLONG */
5138 status = query_lock(fsp,
5145 if (ERROR_WAS_LOCK_DENIED(status)) {
5146 /* Here we need to report who has it locked... */
5147 data_size = POSIX_LOCK_DATA_SIZE;
5149 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5150 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5151 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5152 #if defined(HAVE_LONGLONG)
5153 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5154 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5155 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5156 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5157 #else /* HAVE_LONGLONG */
5158 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5159 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5160 #endif /* HAVE_LONGLONG */
5162 } else if (NT_STATUS_IS_OK(status)) {
5163 /* For success we just return a copy of what we sent
5164 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5165 data_size = POSIX_LOCK_DATA_SIZE;
5166 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5167 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5175 return NT_STATUS_INVALID_LEVEL;
5178 *pdata_size = data_size;
5179 return NT_STATUS_OK;
5182 /****************************************************************************
5183 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5184 file name or file id).
5185 ****************************************************************************/
5187 static void call_trans2qfilepathinfo(connection_struct *conn,
5188 struct smb_request *req,
5189 unsigned int tran_call,
5190 char **pparams, int total_params,
5191 char **ppdata, int total_data,
5192 unsigned int max_data_bytes)
5194 char *params = *pparams;
5195 char *pdata = *ppdata;
5197 unsigned int data_size = 0;
5198 unsigned int param_size = 2;
5199 struct smb_filename *smb_fname = NULL;
5200 bool delete_pending = False;
5201 struct timespec write_time_ts;
5202 files_struct *fsp = NULL;
5203 struct file_id fileid;
5204 struct ea_list *ea_list = NULL;
5205 int lock_data_count = 0;
5206 char *lock_data = NULL;
5207 NTSTATUS status = NT_STATUS_OK;
5210 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5214 ZERO_STRUCT(write_time_ts);
5216 if (tran_call == TRANSACT2_QFILEINFO) {
5217 if (total_params < 4) {
5218 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5223 call_trans2qpipeinfo(conn, req, tran_call,
5224 pparams, total_params,
5230 fsp = file_fsp(req, SVAL(params,0));
5231 info_level = SVAL(params,2);
5233 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5235 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5236 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5240 /* Initial check for valid fsp ptr. */
5241 if (!check_fsp_open(conn, req, fsp)) {
5245 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5246 if (smb_fname == NULL) {
5247 reply_nterror(req, NT_STATUS_NO_MEMORY);
5251 if(fsp->fake_file_handle) {
5253 * This is actually for the QUOTA_FAKE_FILE --metze
5256 /* We know this name is ok, it's already passed the checks. */
5258 } else if(fsp->fh->fd == -1) {
5260 * This is actually a QFILEINFO on a directory
5261 * handle (returned from an NT SMB). NT5.0 seems
5262 * to do this call. JRA.
5265 if (INFO_LEVEL_IS_UNIX(info_level)) {
5266 /* Always do lstat for UNIX calls. */
5267 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5268 DEBUG(3,("call_trans2qfilepathinfo: "
5269 "SMB_VFS_LSTAT of %s failed "
5271 smb_fname_str_dbg(smb_fname),
5274 map_nt_error_from_unix(errno));
5277 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5278 DEBUG(3,("call_trans2qfilepathinfo: "
5279 "SMB_VFS_STAT of %s failed (%s)\n",
5280 smb_fname_str_dbg(smb_fname),
5283 map_nt_error_from_unix(errno));
5287 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5288 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5291 * Original code - this is an open file.
5293 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5294 DEBUG(3, ("fstat of %s failed (%s)\n",
5295 fsp_fnum_dbg(fsp), strerror(errno)));
5297 map_nt_error_from_unix(errno));
5300 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5301 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5307 uint32_t ucf_flags = 0;
5310 if (total_params < 7) {
5311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5315 info_level = SVAL(params,0);
5317 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5319 if (INFO_LEVEL_IS_UNIX(info_level)) {
5320 if (!lp_unix_extensions()) {
5321 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5324 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5325 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5326 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5327 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5331 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5333 STR_TERMINATE, &status);
5334 if (!NT_STATUS_IS_OK(status)) {
5335 reply_nterror(req, status);
5339 status = filename_convert(req,
5341 req->flags2 & FLAGS2_DFS_PATHNAMES,
5346 if (!NT_STATUS_IS_OK(status)) {
5347 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5348 reply_botherror(req,
5349 NT_STATUS_PATH_NOT_COVERED,
5350 ERRSRV, ERRbadpath);
5353 reply_nterror(req, status);
5357 /* If this is a stream, check if there is a delete_pending. */
5358 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5359 && is_ntfs_stream_smb_fname(smb_fname)) {
5360 struct smb_filename *smb_fname_base;
5362 /* Create an smb_filename with stream_name == NULL. */
5363 smb_fname_base = synthetic_smb_fname(
5364 talloc_tos(), smb_fname->base_name,
5366 if (smb_fname_base == NULL) {
5367 reply_nterror(req, NT_STATUS_NO_MEMORY);
5371 if (INFO_LEVEL_IS_UNIX(info_level)) {
5372 /* Always do lstat for UNIX calls. */
5373 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5374 DEBUG(3,("call_trans2qfilepathinfo: "
5375 "SMB_VFS_LSTAT of %s failed "
5377 smb_fname_str_dbg(smb_fname_base),
5379 TALLOC_FREE(smb_fname_base);
5381 map_nt_error_from_unix(errno));
5385 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5386 DEBUG(3,("call_trans2qfilepathinfo: "
5387 "fileinfo of %s failed "
5389 smb_fname_str_dbg(smb_fname_base),
5391 TALLOC_FREE(smb_fname_base);
5393 map_nt_error_from_unix(errno));
5398 status = file_name_hash(conn,
5399 smb_fname_str_dbg(smb_fname_base),
5401 if (!NT_STATUS_IS_OK(status)) {
5402 TALLOC_FREE(smb_fname_base);
5403 reply_nterror(req, status);
5407 fileid = vfs_file_id_from_sbuf(conn,
5408 &smb_fname_base->st);
5409 TALLOC_FREE(smb_fname_base);
5410 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5411 if (delete_pending) {
5412 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5417 if (INFO_LEVEL_IS_UNIX(info_level)) {
5418 /* Always do lstat for UNIX calls. */
5419 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5420 DEBUG(3,("call_trans2qfilepathinfo: "
5421 "SMB_VFS_LSTAT of %s failed (%s)\n",
5422 smb_fname_str_dbg(smb_fname),
5425 map_nt_error_from_unix(errno));
5430 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5431 DEBUG(3,("call_trans2qfilepathinfo: "
5432 "SMB_VFS_STAT of %s failed (%s)\n",
5433 smb_fname_str_dbg(smb_fname),
5436 map_nt_error_from_unix(errno));
5441 status = file_name_hash(conn,
5442 smb_fname_str_dbg(smb_fname),
5444 if (!NT_STATUS_IS_OK(status)) {
5445 reply_nterror(req, status);
5449 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5450 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5451 if (delete_pending) {
5452 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5457 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5458 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5460 info_level,tran_call,total_data));
5462 /* Pull out any data sent here before we realloc. */
5463 switch (info_level) {
5464 case SMB_INFO_QUERY_EAS_FROM_LIST:
5466 /* Pull any EA list from the data portion. */
5469 if (total_data < 4) {
5471 req, NT_STATUS_INVALID_PARAMETER);
5474 ea_size = IVAL(pdata,0);
5476 if (total_data > 0 && ea_size != total_data) {
5477 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5478 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5480 req, NT_STATUS_INVALID_PARAMETER);
5484 if (!lp_ea_support(SNUM(conn))) {
5485 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5489 /* Pull out the list of names. */
5490 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5493 req, NT_STATUS_INVALID_PARAMETER);
5499 case SMB_QUERY_POSIX_LOCK:
5501 if (fsp == NULL || fsp->fh->fd == -1) {
5502 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5506 if (total_data != POSIX_LOCK_DATA_SIZE) {
5508 req, NT_STATUS_INVALID_PARAMETER);
5512 /* Copy the lock range data. */
5513 lock_data = (char *)talloc_memdup(
5514 req, pdata, total_data);
5516 reply_nterror(req, NT_STATUS_NO_MEMORY);
5519 lock_data_count = total_data;
5525 *pparams = (char *)SMB_REALLOC(*pparams,2);
5526 if (*pparams == NULL) {
5527 reply_nterror(req, NT_STATUS_NO_MEMORY);
5534 * draft-leach-cifs-v1-spec-02.txt
5535 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5538 * The requested information is placed in the Data portion of the
5539 * transaction response. For the information levels greater than 0x100,
5540 * the transaction response has 1 parameter word which should be
5541 * ignored by the client.
5543 * However Windows only follows this rule for the IS_NAME_VALID call.
5545 switch (info_level) {
5546 case SMB_INFO_IS_NAME_VALID:
5551 if ((info_level & 0xFF00) == 0xFF00) {
5553 * We use levels that start with 0xFF00
5554 * internally to represent SMB2 specific levels
5556 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5560 status = smbd_do_qfilepathinfo(conn, req, info_level,
5562 delete_pending, write_time_ts,
5564 lock_data_count, lock_data,
5565 req->flags2, max_data_bytes,
5566 ppdata, &data_size);
5567 if (!NT_STATUS_IS_OK(status)) {
5568 reply_nterror(req, status);
5572 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5578 /****************************************************************************
5579 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5581 ****************************************************************************/
5583 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5584 connection_struct *conn,
5585 struct smb_request *req,
5586 bool overwrite_if_exists,
5587 const struct smb_filename *smb_fname_old,
5588 struct smb_filename *smb_fname_new)
5590 NTSTATUS status = NT_STATUS_OK;
5592 /* source must already exist. */
5593 if (!VALID_STAT(smb_fname_old->st)) {
5594 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5597 if (VALID_STAT(smb_fname_new->st)) {
5598 if (overwrite_if_exists) {
5599 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5600 return NT_STATUS_FILE_IS_A_DIRECTORY;
5602 status = unlink_internals(conn,
5604 FILE_ATTRIBUTE_NORMAL,
5607 if (!NT_STATUS_IS_OK(status)) {
5611 /* Disallow if newname already exists. */
5612 return NT_STATUS_OBJECT_NAME_COLLISION;
5616 /* No links from a directory. */
5617 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5618 return NT_STATUS_FILE_IS_A_DIRECTORY;
5621 /* Setting a hardlink to/from a stream isn't currently supported. */
5622 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5623 is_ntfs_stream_smb_fname(smb_fname_new)) {
5624 return NT_STATUS_INVALID_PARAMETER;
5627 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5628 smb_fname_old->base_name, smb_fname_new->base_name));
5630 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5631 smb_fname_new->base_name) != 0) {
5632 status = map_nt_error_from_unix(errno);
5633 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5634 nt_errstr(status), smb_fname_old->base_name,
5635 smb_fname_new->base_name));
5640 /****************************************************************************
5641 Deal with setting the time from any of the setfilepathinfo functions.
5642 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5643 calling this function.
5644 ****************************************************************************/
5646 NTSTATUS smb_set_file_time(connection_struct *conn,
5648 const struct smb_filename *smb_fname,
5649 struct smb_file_time *ft,
5650 bool setting_write_time)
5652 struct smb_filename smb_fname_base;
5654 FILE_NOTIFY_CHANGE_LAST_ACCESS
5655 |FILE_NOTIFY_CHANGE_LAST_WRITE
5656 |FILE_NOTIFY_CHANGE_CREATION;
5658 if (!VALID_STAT(smb_fname->st)) {
5659 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5662 /* get some defaults (no modifications) if any info is zero or -1. */
5663 if (null_timespec(ft->create_time)) {
5664 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5667 if (null_timespec(ft->atime)) {
5668 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5671 if (null_timespec(ft->mtime)) {
5672 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5675 if (!setting_write_time) {
5676 /* ft->mtime comes from change time, not write time. */
5677 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5680 /* Ensure the resolution is the correct for
5681 * what we can store on this filesystem. */
5683 round_timespec(conn->ts_res, &ft->create_time);
5684 round_timespec(conn->ts_res, &ft->ctime);
5685 round_timespec(conn->ts_res, &ft->atime);
5686 round_timespec(conn->ts_res, &ft->mtime);
5688 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5689 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5690 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5691 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5692 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5693 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5694 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5695 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5697 if (setting_write_time) {
5699 * This was a Windows setfileinfo on an open file.
5700 * NT does this a lot. We also need to
5701 * set the time here, as it can be read by
5702 * FindFirst/FindNext and with the patch for bug #2045
5703 * in smbd/fileio.c it ensures that this timestamp is
5704 * kept sticky even after a write. We save the request
5705 * away and will set it on file close and after a write. JRA.
5708 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5709 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5712 if (fsp->base_fsp) {
5713 set_sticky_write_time_fsp(fsp->base_fsp,
5716 set_sticky_write_time_fsp(fsp, ft->mtime);
5719 set_sticky_write_time_path(
5720 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5725 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5727 /* Always call ntimes on the base, even if a stream was passed in. */
5728 smb_fname_base = *smb_fname;
5729 smb_fname_base.stream_name = NULL;
5731 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5732 return map_nt_error_from_unix(errno);
5735 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5736 smb_fname->base_name);
5737 return NT_STATUS_OK;
5740 /****************************************************************************
5741 Deal with setting the dosmode from any of the setfilepathinfo functions.
5742 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5743 done before calling this function.
5744 ****************************************************************************/
5746 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5747 const struct smb_filename *smb_fname,
5750 struct smb_filename *smb_fname_base;
5753 if (!VALID_STAT(smb_fname->st)) {
5754 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5757 /* Always operate on the base_name, even if a stream was passed in. */
5758 smb_fname_base = synthetic_smb_fname(
5759 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5760 if (smb_fname_base == NULL) {
5761 return NT_STATUS_NO_MEMORY;
5765 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5766 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5768 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5772 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5774 /* check the mode isn't different, before changing it */
5775 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5776 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5777 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5778 (unsigned int)dosmode));
5780 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5782 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5784 smb_fname_str_dbg(smb_fname_base),
5786 status = map_nt_error_from_unix(errno);
5790 status = NT_STATUS_OK;
5792 TALLOC_FREE(smb_fname_base);
5796 /****************************************************************************
5797 Deal with setting the size from any of the setfilepathinfo functions.
5798 ****************************************************************************/
5800 static NTSTATUS smb_set_file_size(connection_struct *conn,
5801 struct smb_request *req,
5803 const struct smb_filename *smb_fname,
5804 const SMB_STRUCT_STAT *psbuf,
5806 bool fail_after_createfile)
5808 NTSTATUS status = NT_STATUS_OK;
5809 struct smb_filename *smb_fname_tmp = NULL;
5810 files_struct *new_fsp = NULL;
5812 if (!VALID_STAT(*psbuf)) {
5813 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5816 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5818 if (size == get_file_size_stat(psbuf)) {
5819 return NT_STATUS_OK;
5822 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5823 smb_fname_str_dbg(smb_fname), (double)size));
5825 if (fsp && fsp->fh->fd != -1) {
5826 /* Handle based call. */
5827 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5828 return NT_STATUS_ACCESS_DENIED;
5831 if (vfs_set_filelen(fsp, size) == -1) {
5832 return map_nt_error_from_unix(errno);
5834 trigger_write_time_update_immediate(fsp);
5835 return NT_STATUS_OK;
5838 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5839 if (smb_fname_tmp == NULL) {
5840 return NT_STATUS_NO_MEMORY;
5843 smb_fname_tmp->st = *psbuf;
5845 status = SMB_VFS_CREATE_FILE(
5848 0, /* root_dir_fid */
5849 smb_fname_tmp, /* fname */
5850 FILE_WRITE_DATA, /* access_mask */
5851 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5853 FILE_OPEN, /* create_disposition*/
5854 0, /* create_options */
5855 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5856 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5857 0, /* allocation_size */
5858 0, /* private_flags */
5861 &new_fsp, /* result */
5864 TALLOC_FREE(smb_fname_tmp);
5866 if (!NT_STATUS_IS_OK(status)) {
5867 /* NB. We check for open_was_deferred in the caller. */
5871 /* See RAW-SFILEINFO-END-OF-FILE */
5872 if (fail_after_createfile) {
5873 close_file(req, new_fsp,NORMAL_CLOSE);
5874 return NT_STATUS_INVALID_LEVEL;
5877 if (vfs_set_filelen(new_fsp, size) == -1) {
5878 status = map_nt_error_from_unix(errno);
5879 close_file(req, new_fsp,NORMAL_CLOSE);
5883 trigger_write_time_update_immediate(new_fsp);
5884 close_file(req, new_fsp,NORMAL_CLOSE);
5885 return NT_STATUS_OK;
5888 /****************************************************************************
5889 Deal with SMB_INFO_SET_EA.
5890 ****************************************************************************/
5892 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5896 const struct smb_filename *smb_fname)
5898 struct ea_list *ea_list = NULL;
5899 TALLOC_CTX *ctx = NULL;
5900 NTSTATUS status = NT_STATUS_OK;
5902 if (total_data < 10) {
5904 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5905 length. They seem to have no effect. Bug #3212. JRA */
5907 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5908 /* We're done. We only get EA info in this call. */
5909 return NT_STATUS_OK;
5912 return NT_STATUS_INVALID_PARAMETER;
5915 if (IVAL(pdata,0) > total_data) {
5916 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5917 IVAL(pdata,0), (unsigned int)total_data));
5918 return NT_STATUS_INVALID_PARAMETER;
5922 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5924 return NT_STATUS_INVALID_PARAMETER;
5927 status = set_ea(conn, fsp, smb_fname, ea_list);
5932 /****************************************************************************
5933 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5934 ****************************************************************************/
5936 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5941 struct ea_list *ea_list = NULL;
5945 return NT_STATUS_INVALID_HANDLE;
5948 if (!lp_ea_support(SNUM(conn))) {
5949 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5950 "EA's not supported.\n",
5951 (unsigned int)total_data));
5952 return NT_STATUS_EAS_NOT_SUPPORTED;
5955 if (total_data < 10) {
5956 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5958 (unsigned int)total_data));
5959 return NT_STATUS_INVALID_PARAMETER;
5962 ea_list = read_nttrans_ea_list(talloc_tos(),
5967 return NT_STATUS_INVALID_PARAMETER;
5970 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5972 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5973 smb_fname_str_dbg(fsp->fsp_name),
5974 nt_errstr(status) ));
5980 /****************************************************************************
5981 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5982 ****************************************************************************/
5984 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5988 struct smb_filename *smb_fname)
5990 NTSTATUS status = NT_STATUS_OK;
5991 bool delete_on_close;
5994 if (total_data < 1) {
5995 return NT_STATUS_INVALID_PARAMETER;
5999 return NT_STATUS_INVALID_HANDLE;
6002 delete_on_close = (CVAL(pdata,0) ? True : False);
6003 dosmode = dos_mode(conn, smb_fname);
6005 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6006 "delete_on_close = %u\n",
6007 smb_fname_str_dbg(smb_fname),
6008 (unsigned int)dosmode,
6009 (unsigned int)delete_on_close ));
6011 if (delete_on_close) {
6012 status = can_set_delete_on_close(fsp, dosmode);
6013 if (!NT_STATUS_IS_OK(status)) {
6018 /* The set is across all open files on this dev/inode pair. */
6019 if (!set_delete_on_close(fsp, delete_on_close,
6020 conn->session_info->security_token,
6021 conn->session_info->unix_token)) {
6022 return NT_STATUS_ACCESS_DENIED;
6024 return NT_STATUS_OK;
6027 /****************************************************************************
6028 Deal with SMB_FILE_POSITION_INFORMATION.
6029 ****************************************************************************/
6031 static NTSTATUS smb_file_position_information(connection_struct *conn,
6036 uint64_t position_information;
6038 if (total_data < 8) {
6039 return NT_STATUS_INVALID_PARAMETER;
6043 /* Ignore on pathname based set. */
6044 return NT_STATUS_OK;
6047 position_information = (uint64_t)IVAL(pdata,0);
6048 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6050 DEBUG(10,("smb_file_position_information: Set file position "
6051 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6052 (double)position_information));
6053 fsp->fh->position_information = position_information;
6054 return NT_STATUS_OK;
6057 /****************************************************************************
6058 Deal with SMB_FILE_MODE_INFORMATION.
6059 ****************************************************************************/
6061 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6067 if (total_data < 4) {
6068 return NT_STATUS_INVALID_PARAMETER;
6070 mode = IVAL(pdata,0);
6071 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6072 return NT_STATUS_INVALID_PARAMETER;
6074 return NT_STATUS_OK;
6077 /****************************************************************************
6078 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6079 ****************************************************************************/
6081 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6082 struct smb_request *req,
6085 const struct smb_filename *smb_fname)
6087 char *link_target = NULL;
6088 const char *newname = smb_fname->base_name;
6089 TALLOC_CTX *ctx = talloc_tos();
6091 /* Set a symbolic link. */
6092 /* Don't allow this if follow links is false. */
6094 if (total_data == 0) {
6095 return NT_STATUS_INVALID_PARAMETER;
6098 if (!lp_symlinks(SNUM(conn))) {
6099 return NT_STATUS_ACCESS_DENIED;
6102 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6103 total_data, STR_TERMINATE);
6106 return NT_STATUS_INVALID_PARAMETER;
6109 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6110 newname, link_target ));
6112 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6113 return map_nt_error_from_unix(errno);
6116 return NT_STATUS_OK;
6119 /****************************************************************************
6120 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6121 ****************************************************************************/
6123 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6124 struct smb_request *req,
6125 const char *pdata, int total_data,
6126 struct smb_filename *smb_fname_new)
6128 char *oldname = NULL;
6129 struct smb_filename *smb_fname_old = NULL;
6130 TALLOC_CTX *ctx = talloc_tos();
6131 NTSTATUS status = NT_STATUS_OK;
6133 /* Set a hard link. */
6134 if (total_data == 0) {
6135 return NT_STATUS_INVALID_PARAMETER;
6138 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6139 total_data, STR_TERMINATE, &status);
6140 if (!NT_STATUS_IS_OK(status)) {
6144 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6145 smb_fname_str_dbg(smb_fname_new), oldname));
6147 status = filename_convert(ctx,
6149 req->flags2 & FLAGS2_DFS_PATHNAMES,
6154 if (!NT_STATUS_IS_OK(status)) {
6158 return hardlink_internals(ctx, conn, req, false,
6159 smb_fname_old, smb_fname_new);
6162 /****************************************************************************
6163 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6164 ****************************************************************************/
6166 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6167 struct smb_request *req,
6171 struct smb_filename *smb_fname_src)
6175 char *newname = NULL;
6176 struct smb_filename *smb_fname_dst = NULL;
6177 NTSTATUS status = NT_STATUS_OK;
6178 TALLOC_CTX *ctx = talloc_tos();
6181 return NT_STATUS_INVALID_HANDLE;
6184 if (total_data < 20) {
6185 return NT_STATUS_INVALID_PARAMETER;
6188 overwrite = (CVAL(pdata,0) ? True : False);
6189 len = IVAL(pdata,16);
6191 if (len > (total_data - 20) || (len == 0)) {
6192 return NT_STATUS_INVALID_PARAMETER;
6195 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6196 &pdata[20], len, STR_TERMINATE,
6198 if (!NT_STATUS_IS_OK(status)) {
6202 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6205 status = filename_convert(ctx,
6207 req->flags2 & FLAGS2_DFS_PATHNAMES,
6212 if (!NT_STATUS_IS_OK(status)) {
6216 if (fsp->base_fsp) {
6217 /* newname must be a stream name. */
6218 if (newname[0] != ':') {
6219 return NT_STATUS_NOT_SUPPORTED;
6222 /* Create an smb_fname to call rename_internals_fsp() with. */
6223 smb_fname_dst = synthetic_smb_fname(
6224 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6226 if (smb_fname_dst == NULL) {
6227 status = NT_STATUS_NO_MEMORY;
6232 * Set the original last component, since
6233 * rename_internals_fsp() requires it.
6235 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6237 if (smb_fname_dst->original_lcomp == NULL) {
6238 status = NT_STATUS_NO_MEMORY;
6244 DEBUG(10,("smb2_file_rename_information: "
6245 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6246 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6247 smb_fname_str_dbg(smb_fname_dst)));
6248 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6249 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6253 TALLOC_FREE(smb_fname_dst);
6257 static NTSTATUS smb_file_link_information(connection_struct *conn,
6258 struct smb_request *req,
6262 struct smb_filename *smb_fname_src)
6266 char *newname = NULL;
6267 struct smb_filename *smb_fname_dst = NULL;
6268 NTSTATUS status = NT_STATUS_OK;
6269 TALLOC_CTX *ctx = talloc_tos();
6272 return NT_STATUS_INVALID_HANDLE;
6275 if (total_data < 20) {
6276 return NT_STATUS_INVALID_PARAMETER;
6279 overwrite = (CVAL(pdata,0) ? true : false);
6280 len = IVAL(pdata,16);
6282 if (len > (total_data - 20) || (len == 0)) {
6283 return NT_STATUS_INVALID_PARAMETER;
6286 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6287 &pdata[20], len, STR_TERMINATE,
6289 if (!NT_STATUS_IS_OK(status)) {
6293 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6296 status = filename_convert(ctx,
6298 req->flags2 & FLAGS2_DFS_PATHNAMES,
6303 if (!NT_STATUS_IS_OK(status)) {
6307 if (fsp->base_fsp) {
6308 /* No stream names. */
6309 return NT_STATUS_NOT_SUPPORTED;
6312 DEBUG(10,("smb_file_link_information: "
6313 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6314 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6315 smb_fname_str_dbg(smb_fname_dst)));
6316 status = hardlink_internals(ctx,
6323 TALLOC_FREE(smb_fname_dst);
6327 /****************************************************************************
6328 Deal with SMB_FILE_RENAME_INFORMATION.
6329 ****************************************************************************/
6331 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6332 struct smb_request *req,
6336 struct smb_filename *smb_fname_src)
6341 char *newname = NULL;
6342 struct smb_filename *smb_fname_dst = NULL;
6343 bool dest_has_wcard = False;
6344 NTSTATUS status = NT_STATUS_OK;
6346 TALLOC_CTX *ctx = talloc_tos();
6348 if (total_data < 13) {
6349 return NT_STATUS_INVALID_PARAMETER;
6352 overwrite = (CVAL(pdata,0) ? True : False);
6353 root_fid = IVAL(pdata,4);
6354 len = IVAL(pdata,8);
6356 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6357 return NT_STATUS_INVALID_PARAMETER;
6360 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6363 if (!NT_STATUS_IS_OK(status)) {
6367 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6370 status = resolve_dfspath_wcard(ctx, conn,
6371 req->flags2 & FLAGS2_DFS_PATHNAMES,
6374 !conn->sconn->using_smb2,
6377 if (!NT_STATUS_IS_OK(status)) {
6381 /* Check the new name has no '/' characters. */
6382 if (strchr_m(newname, '/')) {
6383 return NT_STATUS_NOT_SUPPORTED;
6386 if (fsp && fsp->base_fsp) {
6387 /* newname must be a stream name. */
6388 if (newname[0] != ':') {
6389 return NT_STATUS_NOT_SUPPORTED;
6392 /* Create an smb_fname to call rename_internals_fsp() with. */
6393 smb_fname_dst = synthetic_smb_fname(
6394 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6396 if (smb_fname_dst == NULL) {
6397 status = NT_STATUS_NO_MEMORY;
6402 * Set the original last component, since
6403 * rename_internals_fsp() requires it.
6405 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6407 if (smb_fname_dst->original_lcomp == NULL) {
6408 status = NT_STATUS_NO_MEMORY;
6414 * Build up an smb_fname_dst based on the filename passed in.
6415 * We basically just strip off the last component, and put on
6416 * the newname instead.
6418 char *base_name = NULL;
6420 /* newname must *not* be a stream name. */
6421 if (newname[0] == ':') {
6422 return NT_STATUS_NOT_SUPPORTED;
6426 * Strip off the last component (filename) of the path passed
6429 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6431 return NT_STATUS_NO_MEMORY;
6433 p = strrchr_m(base_name, '/');
6437 base_name = talloc_strdup(ctx, "");
6439 return NT_STATUS_NO_MEMORY;
6442 /* Append the new name. */
6443 base_name = talloc_asprintf_append(base_name,
6447 return NT_STATUS_NO_MEMORY;
6450 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6453 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6456 /* If an error we expect this to be
6457 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6459 if (!NT_STATUS_IS_OK(status)) {
6460 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6464 /* Create an smb_fname to call rename_internals_fsp() */
6465 smb_fname_dst = synthetic_smb_fname(
6466 ctx, base_name, NULL, NULL);
6467 if (smb_fname_dst == NULL) {
6468 status = NT_STATUS_NO_MEMORY;
6475 DEBUG(10,("smb_file_rename_information: "
6476 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6477 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6478 smb_fname_str_dbg(smb_fname_dst)));
6479 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6482 DEBUG(10,("smb_file_rename_information: "
6483 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6484 smb_fname_str_dbg(smb_fname_src),
6485 smb_fname_str_dbg(smb_fname_dst)));
6486 status = rename_internals(ctx, conn, req, smb_fname_src,
6487 smb_fname_dst, 0, overwrite, false,
6489 FILE_WRITE_ATTRIBUTES);
6492 TALLOC_FREE(smb_fname_dst);
6496 /****************************************************************************
6497 Deal with SMB_SET_POSIX_ACL.
6498 ****************************************************************************/
6500 #if defined(HAVE_POSIX_ACLS)
6501 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6505 const struct smb_filename *smb_fname)
6507 uint16 posix_acl_version;
6508 uint16 num_file_acls;
6509 uint16 num_def_acls;
6510 bool valid_file_acls = True;
6511 bool valid_def_acls = True;
6513 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6514 return NT_STATUS_INVALID_PARAMETER;
6516 posix_acl_version = SVAL(pdata,0);
6517 num_file_acls = SVAL(pdata,2);
6518 num_def_acls = SVAL(pdata,4);
6520 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6521 valid_file_acls = False;
6525 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6526 valid_def_acls = False;
6530 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6531 return NT_STATUS_INVALID_PARAMETER;
6534 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6535 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6536 return NT_STATUS_INVALID_PARAMETER;
6539 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6540 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6541 (unsigned int)num_file_acls,
6542 (unsigned int)num_def_acls));
6544 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6545 smb_fname->base_name, num_file_acls,
6546 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6547 return map_nt_error_from_unix(errno);
6550 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6551 smb_fname->base_name, &smb_fname->st, num_def_acls,
6552 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6553 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6554 return map_nt_error_from_unix(errno);
6556 return NT_STATUS_OK;
6560 /****************************************************************************
6561 Deal with SMB_SET_POSIX_LOCK.
6562 ****************************************************************************/
6564 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6565 struct smb_request *req,
6573 bool blocking_lock = False;
6574 enum brl_type lock_type;
6576 NTSTATUS status = NT_STATUS_OK;
6578 if (fsp == NULL || fsp->fh->fd == -1) {
6579 return NT_STATUS_INVALID_HANDLE;
6582 if (total_data != POSIX_LOCK_DATA_SIZE) {
6583 return NT_STATUS_INVALID_PARAMETER;
6586 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6587 case POSIX_LOCK_TYPE_READ:
6588 lock_type = READ_LOCK;
6590 case POSIX_LOCK_TYPE_WRITE:
6591 /* Return the right POSIX-mappable error code for files opened read-only. */
6592 if (!fsp->can_write) {
6593 return NT_STATUS_INVALID_HANDLE;
6595 lock_type = WRITE_LOCK;
6597 case POSIX_LOCK_TYPE_UNLOCK:
6598 lock_type = UNLOCK_LOCK;
6601 return NT_STATUS_INVALID_PARAMETER;
6604 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6605 blocking_lock = False;
6606 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6607 blocking_lock = True;
6609 return NT_STATUS_INVALID_PARAMETER;
6612 if (!lp_blocking_locks(SNUM(conn))) {
6613 blocking_lock = False;
6616 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6617 #if defined(HAVE_LONGLONG)
6618 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6619 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6620 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6621 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6622 #else /* HAVE_LONGLONG */
6623 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6624 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6625 #endif /* HAVE_LONGLONG */
6627 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6628 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6630 (unsigned int)lock_type,
6631 (unsigned long long)smblctx,
6635 if (lock_type == UNLOCK_LOCK) {
6636 status = do_unlock(req->sconn->msg_ctx,
6643 uint64_t block_smblctx;
6645 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6657 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6659 * A blocking lock was requested. Package up
6660 * this smb into a queued request and push it
6661 * onto the blocking lock queue.
6663 if(push_blocking_lock_request(br_lck,
6666 -1, /* infinite timeout. */
6674 TALLOC_FREE(br_lck);
6678 TALLOC_FREE(br_lck);
6684 /****************************************************************************
6685 Deal with SMB_SET_FILE_BASIC_INFO.
6686 ****************************************************************************/
6688 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6692 const struct smb_filename *smb_fname)
6694 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6695 struct smb_file_time ft;
6697 NTSTATUS status = NT_STATUS_OK;
6701 if (total_data < 36) {
6702 return NT_STATUS_INVALID_PARAMETER;
6705 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6706 if (!NT_STATUS_IS_OK(status)) {
6710 /* Set the attributes */
6711 dosmode = IVAL(pdata,32);
6712 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6713 if (!NT_STATUS_IS_OK(status)) {
6718 ft.create_time = interpret_long_date(pdata);
6721 ft.atime = interpret_long_date(pdata+8);
6724 ft.mtime = interpret_long_date(pdata+16);
6727 ft.ctime = interpret_long_date(pdata+24);
6729 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6730 smb_fname_str_dbg(smb_fname)));
6732 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6736 /****************************************************************************
6737 Deal with SMB_INFO_STANDARD.
6738 ****************************************************************************/
6740 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6744 const struct smb_filename *smb_fname)
6747 struct smb_file_time ft;
6751 if (total_data < 12) {
6752 return NT_STATUS_INVALID_PARAMETER;
6756 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6758 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6760 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6762 DEBUG(10,("smb_set_info_standard: file %s\n",
6763 smb_fname_str_dbg(smb_fname)));
6765 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6766 if (!NT_STATUS_IS_OK(status)) {
6770 return smb_set_file_time(conn,
6777 /****************************************************************************
6778 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6779 ****************************************************************************/
6781 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6782 struct smb_request *req,
6786 struct smb_filename *smb_fname)
6788 uint64_t allocation_size = 0;
6789 NTSTATUS status = NT_STATUS_OK;
6790 files_struct *new_fsp = NULL;
6792 if (!VALID_STAT(smb_fname->st)) {
6793 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6796 if (total_data < 8) {
6797 return NT_STATUS_INVALID_PARAMETER;
6800 allocation_size = (uint64_t)IVAL(pdata,0);
6801 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6802 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6803 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6804 (double)allocation_size));
6806 if (allocation_size) {
6807 allocation_size = smb_roundup(conn, allocation_size);
6810 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6811 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6812 (double)allocation_size));
6814 if (fsp && fsp->fh->fd != -1) {
6815 /* Open file handle. */
6816 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6817 return NT_STATUS_ACCESS_DENIED;
6820 /* Only change if needed. */
6821 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6822 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6823 return map_nt_error_from_unix(errno);
6826 /* But always update the time. */
6828 * This is equivalent to a write. Ensure it's seen immediately
6829 * if there are no pending writes.
6831 trigger_write_time_update_immediate(fsp);
6832 return NT_STATUS_OK;
6835 /* Pathname or stat or directory file. */
6836 status = SMB_VFS_CREATE_FILE(
6839 0, /* root_dir_fid */
6840 smb_fname, /* fname */
6841 FILE_WRITE_DATA, /* access_mask */
6842 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6844 FILE_OPEN, /* create_disposition*/
6845 0, /* create_options */
6846 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6847 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6848 0, /* allocation_size */
6849 0, /* private_flags */
6852 &new_fsp, /* result */
6855 if (!NT_STATUS_IS_OK(status)) {
6856 /* NB. We check for open_was_deferred in the caller. */
6860 /* Only change if needed. */
6861 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6862 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6863 status = map_nt_error_from_unix(errno);
6864 close_file(req, new_fsp, NORMAL_CLOSE);
6869 /* Changing the allocation size should set the last mod time. */
6871 * This is equivalent to a write. Ensure it's seen immediately
6872 * if there are no pending writes.
6874 trigger_write_time_update_immediate(new_fsp);
6876 close_file(req, new_fsp, NORMAL_CLOSE);
6877 return NT_STATUS_OK;
6880 /****************************************************************************
6881 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6882 ****************************************************************************/
6884 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6885 struct smb_request *req,
6889 const struct smb_filename *smb_fname,
6890 bool fail_after_createfile)
6894 if (total_data < 8) {
6895 return NT_STATUS_INVALID_PARAMETER;
6898 size = IVAL(pdata,0);
6899 size |= (((off_t)IVAL(pdata,4)) << 32);
6900 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6901 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6904 return smb_set_file_size(conn, req,
6909 fail_after_createfile);
6912 /****************************************************************************
6913 Allow a UNIX info mknod.
6914 ****************************************************************************/
6916 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6919 const struct smb_filename *smb_fname)
6921 uint32 file_type = IVAL(pdata,56);
6922 #if defined(HAVE_MAKEDEV)
6923 uint32 dev_major = IVAL(pdata,60);
6924 uint32 dev_minor = IVAL(pdata,68);
6926 SMB_DEV_T dev = (SMB_DEV_T)0;
6927 uint32 raw_unixmode = IVAL(pdata,84);
6931 if (total_data < 100) {
6932 return NT_STATUS_INVALID_PARAMETER;
6935 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6936 PERM_NEW_FILE, &unixmode);
6937 if (!NT_STATUS_IS_OK(status)) {
6941 #if defined(HAVE_MAKEDEV)
6942 dev = makedev(dev_major, dev_minor);
6945 switch (file_type) {
6946 #if defined(S_IFIFO)
6947 case UNIX_TYPE_FIFO:
6948 unixmode |= S_IFIFO;
6951 #if defined(S_IFSOCK)
6952 case UNIX_TYPE_SOCKET:
6953 unixmode |= S_IFSOCK;
6956 #if defined(S_IFCHR)
6957 case UNIX_TYPE_CHARDEV:
6958 unixmode |= S_IFCHR;
6961 #if defined(S_IFBLK)
6962 case UNIX_TYPE_BLKDEV:
6963 unixmode |= S_IFBLK;
6967 return NT_STATUS_INVALID_PARAMETER;
6970 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6971 "%.0f mode 0%o for file %s\n", (double)dev,
6972 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6974 /* Ok - do the mknod. */
6975 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6976 return map_nt_error_from_unix(errno);
6979 /* If any of the other "set" calls fail we
6980 * don't want to end up with a half-constructed mknod.
6983 if (lp_inherit_perms(SNUM(conn))) {
6985 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6987 return NT_STATUS_NO_MEMORY;
6989 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6991 TALLOC_FREE(parent);
6994 return NT_STATUS_OK;
6997 /****************************************************************************
6998 Deal with SMB_SET_FILE_UNIX_BASIC.
6999 ****************************************************************************/
7001 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7002 struct smb_request *req,
7006 const struct smb_filename *smb_fname)
7008 struct smb_file_time ft;
7009 uint32 raw_unixmode;
7012 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7013 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7014 NTSTATUS status = NT_STATUS_OK;
7015 bool delete_on_fail = False;
7016 enum perm_type ptype;
7017 files_struct *all_fsps = NULL;
7018 bool modify_mtime = true;
7020 struct smb_filename *smb_fname_tmp = NULL;
7021 SMB_STRUCT_STAT sbuf;
7025 if (total_data < 100) {
7026 return NT_STATUS_INVALID_PARAMETER;
7029 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7030 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7031 size=IVAL(pdata,0); /* first 8 Bytes are size */
7032 size |= (((off_t)IVAL(pdata,4)) << 32);
7035 ft.atime = interpret_long_date(pdata+24); /* access_time */
7036 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7037 set_owner = (uid_t)IVAL(pdata,40);
7038 set_grp = (gid_t)IVAL(pdata,48);
7039 raw_unixmode = IVAL(pdata,84);
7041 if (VALID_STAT(smb_fname->st)) {
7042 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7043 ptype = PERM_EXISTING_DIR;
7045 ptype = PERM_EXISTING_FILE;
7048 ptype = PERM_NEW_FILE;
7051 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7053 if (!NT_STATUS_IS_OK(status)) {
7057 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7058 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7059 smb_fname_str_dbg(smb_fname), (double)size,
7060 (unsigned int)set_owner, (unsigned int)set_grp,
7061 (int)raw_unixmode));
7063 sbuf = smb_fname->st;
7065 if (!VALID_STAT(sbuf)) {
7067 * The only valid use of this is to create character and block
7068 * devices, and named pipes. This is deprecated (IMHO) and
7069 * a new info level should be used for mknod. JRA.
7072 status = smb_unix_mknod(conn,
7076 if (!NT_STATUS_IS_OK(status)) {
7080 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7081 if (smb_fname_tmp == NULL) {
7082 return NT_STATUS_NO_MEMORY;
7085 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7086 status = map_nt_error_from_unix(errno);
7087 TALLOC_FREE(smb_fname_tmp);
7088 SMB_VFS_UNLINK(conn, smb_fname);
7092 sbuf = smb_fname_tmp->st;
7093 smb_fname = smb_fname_tmp;
7095 /* Ensure we don't try and change anything else. */
7096 raw_unixmode = SMB_MODE_NO_CHANGE;
7097 size = get_file_size_stat(&sbuf);
7098 ft.atime = sbuf.st_ex_atime;
7099 ft.mtime = sbuf.st_ex_mtime;
7101 * We continue here as we might want to change the
7104 delete_on_fail = True;
7108 /* Horrible backwards compatibility hack as an old server bug
7109 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7113 size = get_file_size_stat(&sbuf);
7118 * Deal with the UNIX specific mode set.
7121 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7124 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7125 "setting mode 0%o for file %s\n",
7126 (unsigned int)unixmode,
7127 smb_fname_str_dbg(smb_fname)));
7128 if (fsp && fsp->fh->fd != -1) {
7129 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7131 ret = SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode);
7134 return map_nt_error_from_unix(errno);
7139 * Deal with the UNIX specific uid set.
7142 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7143 (sbuf.st_ex_uid != set_owner)) {
7146 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7147 "changing owner %u for path %s\n",
7148 (unsigned int)set_owner,
7149 smb_fname_str_dbg(smb_fname)));
7151 if (S_ISLNK(sbuf.st_ex_mode)) {
7152 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7153 set_owner, (gid_t)-1);
7155 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7156 set_owner, (gid_t)-1);
7160 status = map_nt_error_from_unix(errno);
7161 if (delete_on_fail) {
7162 SMB_VFS_UNLINK(conn, smb_fname);
7169 * Deal with the UNIX specific gid set.
7172 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7173 (sbuf.st_ex_gid != set_grp)) {
7174 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7175 "changing group %u for file %s\n",
7176 (unsigned int)set_owner,
7177 smb_fname_str_dbg(smb_fname)));
7178 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7180 status = map_nt_error_from_unix(errno);
7181 if (delete_on_fail) {
7182 SMB_VFS_UNLINK(conn, smb_fname);
7188 /* Deal with any size changes. */
7190 status = smb_set_file_size(conn, req,
7196 if (!NT_STATUS_IS_OK(status)) {
7200 /* Deal with any time changes. */
7201 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7202 /* No change, don't cancel anything. */
7206 id = vfs_file_id_from_sbuf(conn, &sbuf);
7207 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7208 all_fsps = file_find_di_next(all_fsps)) {
7210 * We're setting the time explicitly for UNIX.
7211 * Cancel any pending changes over all handles.
7213 all_fsps->update_write_time_on_close = false;
7214 TALLOC_FREE(all_fsps->update_write_time_event);
7218 * Override the "setting_write_time"
7219 * parameter here as it almost does what
7220 * we need. Just remember if we modified
7221 * mtime and send the notify ourselves.
7223 if (null_timespec(ft.mtime)) {
7224 modify_mtime = false;
7227 status = smb_set_file_time(conn,
7233 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7234 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7239 /****************************************************************************
7240 Deal with SMB_SET_FILE_UNIX_INFO2.
7241 ****************************************************************************/
7243 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7244 struct smb_request *req,
7248 const struct smb_filename *smb_fname)
7254 if (total_data < 116) {
7255 return NT_STATUS_INVALID_PARAMETER;
7258 /* Start by setting all the fields that are common between UNIX_BASIC
7261 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7263 if (!NT_STATUS_IS_OK(status)) {
7267 smb_fflags = IVAL(pdata, 108);
7268 smb_fmask = IVAL(pdata, 112);
7270 /* NB: We should only attempt to alter the file flags if the client
7271 * sends a non-zero mask.
7273 if (smb_fmask != 0) {
7274 int stat_fflags = 0;
7276 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7277 smb_fmask, &stat_fflags)) {
7278 /* Client asked to alter a flag we don't understand. */
7279 return NT_STATUS_INVALID_PARAMETER;
7282 if (fsp && fsp->fh->fd != -1) {
7283 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7284 return NT_STATUS_NOT_SUPPORTED;
7286 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7287 stat_fflags) != 0) {
7288 return map_nt_error_from_unix(errno);
7293 /* XXX: need to add support for changing the create_time here. You
7294 * can do this for paths on Darwin with setattrlist(2). The right way
7295 * to hook this up is probably by extending the VFS utimes interface.
7298 return NT_STATUS_OK;
7301 /****************************************************************************
7302 Create a directory with POSIX semantics.
7303 ****************************************************************************/
7305 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7306 struct smb_request *req,
7309 struct smb_filename *smb_fname,
7310 int *pdata_return_size)
7312 NTSTATUS status = NT_STATUS_OK;
7313 uint32 raw_unixmode = 0;
7314 uint32 mod_unixmode = 0;
7315 mode_t unixmode = (mode_t)0;
7316 files_struct *fsp = NULL;
7317 uint16 info_level_return = 0;
7319 char *pdata = *ppdata;
7321 if (total_data < 18) {
7322 return NT_STATUS_INVALID_PARAMETER;
7325 raw_unixmode = IVAL(pdata,8);
7326 /* Next 4 bytes are not yet defined. */
7328 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7329 PERM_NEW_DIR, &unixmode);
7330 if (!NT_STATUS_IS_OK(status)) {
7334 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7336 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7337 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7339 status = SMB_VFS_CREATE_FILE(
7342 0, /* root_dir_fid */
7343 smb_fname, /* fname */
7344 FILE_READ_ATTRIBUTES, /* access_mask */
7345 FILE_SHARE_NONE, /* share_access */
7346 FILE_CREATE, /* create_disposition*/
7347 FILE_DIRECTORY_FILE, /* create_options */
7348 mod_unixmode, /* file_attributes */
7349 0, /* oplock_request */
7350 0, /* allocation_size */
7351 0, /* private_flags */
7357 if (NT_STATUS_IS_OK(status)) {
7358 close_file(req, fsp, NORMAL_CLOSE);
7361 info_level_return = SVAL(pdata,16);
7363 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7364 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7365 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7366 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7368 *pdata_return_size = 12;
7371 /* Realloc the data size */
7372 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7373 if (*ppdata == NULL) {
7374 *pdata_return_size = 0;
7375 return NT_STATUS_NO_MEMORY;
7379 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7380 SSVAL(pdata,2,0); /* No fnum. */
7381 SIVAL(pdata,4,info); /* Was directory created. */
7383 switch (info_level_return) {
7384 case SMB_QUERY_FILE_UNIX_BASIC:
7385 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7386 SSVAL(pdata,10,0); /* Padding. */
7387 store_file_unix_basic(conn, pdata + 12, fsp,
7390 case SMB_QUERY_FILE_UNIX_INFO2:
7391 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7392 SSVAL(pdata,10,0); /* Padding. */
7393 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7397 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7398 SSVAL(pdata,10,0); /* Padding. */
7405 /****************************************************************************
7406 Open/Create a file with POSIX semantics.
7407 ****************************************************************************/
7409 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7410 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7412 static NTSTATUS smb_posix_open(connection_struct *conn,
7413 struct smb_request *req,
7416 struct smb_filename *smb_fname,
7417 int *pdata_return_size)
7419 bool extended_oplock_granted = False;
7420 char *pdata = *ppdata;
7422 uint32 wire_open_mode = 0;
7423 uint32 raw_unixmode = 0;
7424 uint32 mod_unixmode = 0;
7425 uint32 create_disp = 0;
7426 uint32 access_mask = 0;
7427 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7428 NTSTATUS status = NT_STATUS_OK;
7429 mode_t unixmode = (mode_t)0;
7430 files_struct *fsp = NULL;
7431 int oplock_request = 0;
7433 uint16 info_level_return = 0;
7435 if (total_data < 18) {
7436 return NT_STATUS_INVALID_PARAMETER;
7439 flags = IVAL(pdata,0);
7440 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7441 if (oplock_request) {
7442 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7445 wire_open_mode = IVAL(pdata,4);
7447 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7448 return smb_posix_mkdir(conn, req,
7455 switch (wire_open_mode & SMB_ACCMODE) {
7457 access_mask = SMB_O_RDONLY_MAPPING;
7460 access_mask = SMB_O_WRONLY_MAPPING;
7463 access_mask = (SMB_O_RDONLY_MAPPING|
7464 SMB_O_WRONLY_MAPPING);
7467 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7468 (unsigned int)wire_open_mode ));
7469 return NT_STATUS_INVALID_PARAMETER;
7472 wire_open_mode &= ~SMB_ACCMODE;
7474 /* First take care of O_CREAT|O_EXCL interactions. */
7475 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7476 case (SMB_O_CREAT | SMB_O_EXCL):
7477 /* File exists fail. File not exist create. */
7478 create_disp = FILE_CREATE;
7481 /* File exists open. File not exist create. */
7482 create_disp = FILE_OPEN_IF;
7485 /* O_EXCL on its own without O_CREAT is undefined.
7486 We deliberately ignore it as some versions of
7487 Linux CIFSFS can send a bare O_EXCL on the
7488 wire which other filesystems in the kernel
7489 ignore. See bug 9519 for details. */
7494 /* File exists open. File not exist fail. */
7495 create_disp = FILE_OPEN;
7498 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7499 (unsigned int)wire_open_mode ));
7500 return NT_STATUS_INVALID_PARAMETER;
7503 /* Next factor in the effects of O_TRUNC. */
7504 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7506 if (wire_open_mode & SMB_O_TRUNC) {
7507 switch (create_disp) {
7509 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7510 /* Leave create_disp alone as
7511 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7513 /* File exists fail. File not exist create. */
7516 /* SMB_O_CREAT | SMB_O_TRUNC */
7517 /* File exists overwrite. File not exist create. */
7518 create_disp = FILE_OVERWRITE_IF;
7522 /* File exists overwrite. File not exist fail. */
7523 create_disp = FILE_OVERWRITE;
7526 /* Cannot get here. */
7527 smb_panic("smb_posix_open: logic error");
7528 return NT_STATUS_INVALID_PARAMETER;
7532 raw_unixmode = IVAL(pdata,8);
7533 /* Next 4 bytes are not yet defined. */
7535 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7536 (VALID_STAT(smb_fname->st) ?
7537 PERM_EXISTING_FILE : PERM_NEW_FILE),
7540 if (!NT_STATUS_IS_OK(status)) {
7544 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7546 if (wire_open_mode & SMB_O_SYNC) {
7547 create_options |= FILE_WRITE_THROUGH;
7549 if (wire_open_mode & SMB_O_APPEND) {
7550 access_mask |= FILE_APPEND_DATA;
7552 if (wire_open_mode & SMB_O_DIRECT) {
7553 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7556 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7557 VALID_STAT_OF_DIR(smb_fname->st)) {
7558 if (access_mask != SMB_O_RDONLY_MAPPING) {
7559 return NT_STATUS_FILE_IS_A_DIRECTORY;
7561 create_options &= ~FILE_NON_DIRECTORY_FILE;
7562 create_options |= FILE_DIRECTORY_FILE;
7565 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7566 smb_fname_str_dbg(smb_fname),
7567 (unsigned int)wire_open_mode,
7568 (unsigned int)unixmode ));
7570 status = SMB_VFS_CREATE_FILE(
7573 0, /* root_dir_fid */
7574 smb_fname, /* fname */
7575 access_mask, /* access_mask */
7576 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7578 create_disp, /* create_disposition*/
7579 create_options, /* create_options */
7580 mod_unixmode, /* file_attributes */
7581 oplock_request, /* oplock_request */
7582 0, /* allocation_size */
7583 0, /* private_flags */
7589 if (!NT_STATUS_IS_OK(status)) {
7593 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7594 extended_oplock_granted = True;
7597 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7598 extended_oplock_granted = True;
7601 info_level_return = SVAL(pdata,16);
7603 /* Allocate the correct return size. */
7605 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7606 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7607 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7608 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7610 *pdata_return_size = 12;
7613 /* Realloc the data size */
7614 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7615 if (*ppdata == NULL) {
7616 close_file(req, fsp, ERROR_CLOSE);
7617 *pdata_return_size = 0;
7618 return NT_STATUS_NO_MEMORY;
7622 if (extended_oplock_granted) {
7623 if (flags & REQUEST_BATCH_OPLOCK) {
7624 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7626 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7628 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7629 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7631 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7634 SSVAL(pdata,2,fsp->fnum);
7635 SIVAL(pdata,4,info); /* Was file created etc. */
7637 switch (info_level_return) {
7638 case SMB_QUERY_FILE_UNIX_BASIC:
7639 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7640 SSVAL(pdata,10,0); /* padding. */
7641 store_file_unix_basic(conn, pdata + 12, fsp,
7644 case SMB_QUERY_FILE_UNIX_INFO2:
7645 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7646 SSVAL(pdata,10,0); /* padding. */
7647 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7651 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7652 SSVAL(pdata,10,0); /* padding. */
7655 return NT_STATUS_OK;
7658 /****************************************************************************
7659 Delete a file with POSIX semantics.
7660 ****************************************************************************/
7662 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7663 struct smb_request *req,
7666 struct smb_filename *smb_fname)
7668 NTSTATUS status = NT_STATUS_OK;
7669 files_struct *fsp = NULL;
7673 int create_options = 0;
7675 struct share_mode_lock *lck = NULL;
7677 if (total_data < 2) {
7678 return NT_STATUS_INVALID_PARAMETER;
7681 flags = SVAL(pdata,0);
7683 if (!VALID_STAT(smb_fname->st)) {
7684 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7687 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7688 !VALID_STAT_OF_DIR(smb_fname->st)) {
7689 return NT_STATUS_NOT_A_DIRECTORY;
7692 DEBUG(10,("smb_posix_unlink: %s %s\n",
7693 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7694 smb_fname_str_dbg(smb_fname)));
7696 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7697 create_options |= FILE_DIRECTORY_FILE;
7700 status = SMB_VFS_CREATE_FILE(
7703 0, /* root_dir_fid */
7704 smb_fname, /* fname */
7705 DELETE_ACCESS, /* access_mask */
7706 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7708 FILE_OPEN, /* create_disposition*/
7709 create_options, /* create_options */
7710 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7711 0, /* oplock_request */
7712 0, /* allocation_size */
7713 0, /* private_flags */
7719 if (!NT_STATUS_IS_OK(status)) {
7724 * Don't lie to client. If we can't really delete due to
7725 * non-POSIX opens return SHARING_VIOLATION.
7728 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7730 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7731 "lock for file %s\n", fsp_str_dbg(fsp)));
7732 close_file(req, fsp, NORMAL_CLOSE);
7733 return NT_STATUS_INVALID_PARAMETER;
7737 * See if others still have the file open. If this is the case, then
7738 * don't delete. If all opens are POSIX delete we can set the delete
7739 * on close disposition.
7741 for (i=0; i<lck->data->num_share_modes; i++) {
7742 struct share_mode_entry *e = &lck->data->share_modes[i];
7743 if (is_valid_share_mode_entry(e)) {
7744 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7747 if (share_mode_stale_pid(lck->data, i)) {
7750 /* Fail with sharing violation. */
7752 close_file(req, fsp, NORMAL_CLOSE);
7753 return NT_STATUS_SHARING_VIOLATION;
7758 * Set the delete on close.
7760 status = smb_set_file_disposition_info(conn,
7768 if (!NT_STATUS_IS_OK(status)) {
7769 close_file(req, fsp, NORMAL_CLOSE);
7772 return close_file(req, fsp, NORMAL_CLOSE);
7775 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7776 struct smb_request *req,
7777 TALLOC_CTX *mem_ctx,
7778 uint16_t info_level,
7780 struct smb_filename *smb_fname,
7781 char **ppdata, int total_data,
7784 char *pdata = *ppdata;
7785 NTSTATUS status = NT_STATUS_OK;
7786 int data_return_size = 0;
7790 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7791 return NT_STATUS_INVALID_LEVEL;
7794 if (!CAN_WRITE(conn)) {
7795 /* Allow POSIX opens. The open path will deny
7796 * any non-readonly opens. */
7797 if (info_level != SMB_POSIX_PATH_OPEN) {
7798 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7802 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7803 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7805 info_level, total_data));
7807 switch (info_level) {
7809 case SMB_INFO_STANDARD:
7811 status = smb_set_info_standard(conn,
7819 case SMB_INFO_SET_EA:
7821 status = smb_info_set_ea(conn,
7829 case SMB_SET_FILE_BASIC_INFO:
7830 case SMB_FILE_BASIC_INFORMATION:
7832 status = smb_set_file_basic_info(conn,
7840 case SMB_FILE_ALLOCATION_INFORMATION:
7841 case SMB_SET_FILE_ALLOCATION_INFO:
7843 status = smb_set_file_allocation_info(conn, req,
7851 case SMB_FILE_END_OF_FILE_INFORMATION:
7852 case SMB_SET_FILE_END_OF_FILE_INFO:
7855 * XP/Win7 both fail after the createfile with
7856 * SMB_SET_FILE_END_OF_FILE_INFO but not
7857 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7858 * The level is known here, so pass it down
7862 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7864 status = smb_set_file_end_of_file_info(conn, req,
7873 case SMB_FILE_DISPOSITION_INFORMATION:
7874 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7877 /* JRA - We used to just ignore this on a path ?
7878 * Shouldn't this be invalid level on a pathname
7881 if (tran_call != TRANSACT2_SETFILEINFO) {
7882 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7885 status = smb_set_file_disposition_info(conn,
7893 case SMB_FILE_POSITION_INFORMATION:
7895 status = smb_file_position_information(conn,
7902 case SMB_FILE_FULL_EA_INFORMATION:
7904 status = smb_set_file_full_ea_info(conn,
7911 /* From tridge Samba4 :
7912 * MODE_INFORMATION in setfileinfo (I have no
7913 * idea what "mode information" on a file is - it takes a value of 0,
7914 * 2, 4 or 6. What could it be?).
7917 case SMB_FILE_MODE_INFORMATION:
7919 status = smb_file_mode_information(conn,
7926 * CIFS UNIX extensions.
7929 case SMB_SET_FILE_UNIX_BASIC:
7931 status = smb_set_file_unix_basic(conn, req,
7939 case SMB_SET_FILE_UNIX_INFO2:
7941 status = smb_set_file_unix_info2(conn, req,
7949 case SMB_SET_FILE_UNIX_LINK:
7952 /* We must have a pathname for this. */
7953 return NT_STATUS_INVALID_LEVEL;
7955 status = smb_set_file_unix_link(conn, req, pdata,
7956 total_data, smb_fname);
7960 case SMB_SET_FILE_UNIX_HLINK:
7963 /* We must have a pathname for this. */
7964 return NT_STATUS_INVALID_LEVEL;
7966 status = smb_set_file_unix_hlink(conn, req,
7972 case SMB_FILE_RENAME_INFORMATION:
7974 status = smb_file_rename_information(conn, req,
7980 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7982 /* SMB2 rename information. */
7983 status = smb2_file_rename_information(conn, req,
7989 case SMB_FILE_LINK_INFORMATION:
7991 status = smb_file_link_information(conn, req,
7997 #if defined(HAVE_POSIX_ACLS)
7998 case SMB_SET_POSIX_ACL:
8000 status = smb_set_posix_acl(conn,
8009 case SMB_SET_POSIX_LOCK:
8012 return NT_STATUS_INVALID_LEVEL;
8014 status = smb_set_posix_lock(conn, req,
8015 pdata, total_data, fsp);
8019 case SMB_POSIX_PATH_OPEN:
8022 /* We must have a pathname for this. */
8023 return NT_STATUS_INVALID_LEVEL;
8026 status = smb_posix_open(conn, req,
8034 case SMB_POSIX_PATH_UNLINK:
8037 /* We must have a pathname for this. */
8038 return NT_STATUS_INVALID_LEVEL;
8041 status = smb_posix_unlink(conn, req,
8049 return NT_STATUS_INVALID_LEVEL;
8052 if (!NT_STATUS_IS_OK(status)) {
8056 *ret_data_size = data_return_size;
8057 return NT_STATUS_OK;
8060 /****************************************************************************
8061 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8062 ****************************************************************************/
8064 static void call_trans2setfilepathinfo(connection_struct *conn,
8065 struct smb_request *req,
8066 unsigned int tran_call,
8067 char **pparams, int total_params,
8068 char **ppdata, int total_data,
8069 unsigned int max_data_bytes)
8071 char *params = *pparams;
8072 char *pdata = *ppdata;
8074 struct smb_filename *smb_fname = NULL;
8075 files_struct *fsp = NULL;
8076 NTSTATUS status = NT_STATUS_OK;
8077 int data_return_size = 0;
8080 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8084 if (tran_call == TRANSACT2_SETFILEINFO) {
8085 if (total_params < 4) {
8086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8090 fsp = file_fsp(req, SVAL(params,0));
8091 /* Basic check for non-null fsp. */
8092 if (!check_fsp_open(conn, req, fsp)) {
8095 info_level = SVAL(params,2);
8097 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8098 if (smb_fname == NULL) {
8099 reply_nterror(req, NT_STATUS_NO_MEMORY);
8103 if(fsp->fh->fd == -1) {
8105 * This is actually a SETFILEINFO on a directory
8106 * handle (returned from an NT SMB). NT5.0 seems
8107 * to do this call. JRA.
8109 if (INFO_LEVEL_IS_UNIX(info_level)) {
8110 /* Always do lstat for UNIX calls. */
8111 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8112 DEBUG(3,("call_trans2setfilepathinfo: "
8113 "SMB_VFS_LSTAT of %s failed "
8115 smb_fname_str_dbg(smb_fname),
8117 reply_nterror(req, map_nt_error_from_unix(errno));
8121 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8122 DEBUG(3,("call_trans2setfilepathinfo: "
8123 "fileinfo of %s failed (%s)\n",
8124 smb_fname_str_dbg(smb_fname),
8126 reply_nterror(req, map_nt_error_from_unix(errno));
8130 } else if (fsp->print_file) {
8132 * Doing a DELETE_ON_CLOSE should cancel a print job.
8134 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8135 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8137 DEBUG(3,("call_trans2setfilepathinfo: "
8138 "Cancelling print job (%s)\n",
8142 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8148 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8153 * Original code - this is an open file.
8155 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8156 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8157 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8159 reply_nterror(req, map_nt_error_from_unix(errno));
8165 uint32_t ucf_flags = 0;
8168 if (total_params < 7) {
8169 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8173 info_level = SVAL(params,0);
8174 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8175 total_params - 6, STR_TERMINATE,
8177 if (!NT_STATUS_IS_OK(status)) {
8178 reply_nterror(req, status);
8182 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8183 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8184 info_level == SMB_FILE_RENAME_INFORMATION ||
8185 info_level == SMB_POSIX_PATH_UNLINK) {
8186 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8189 status = filename_convert(req, conn,
8190 req->flags2 & FLAGS2_DFS_PATHNAMES,
8195 if (!NT_STATUS_IS_OK(status)) {
8196 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8197 reply_botherror(req,
8198 NT_STATUS_PATH_NOT_COVERED,
8199 ERRSRV, ERRbadpath);
8202 reply_nterror(req, status);
8206 if (INFO_LEVEL_IS_UNIX(info_level)) {
8208 * For CIFS UNIX extensions the target name may not exist.
8211 /* Always do lstat for UNIX calls. */
8212 SMB_VFS_LSTAT(conn, smb_fname);
8214 } else if (!VALID_STAT(smb_fname->st) &&
8215 SMB_VFS_STAT(conn, smb_fname)) {
8216 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8218 smb_fname_str_dbg(smb_fname),
8220 reply_nterror(req, map_nt_error_from_unix(errno));
8225 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8226 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8228 info_level,total_data));
8230 /* Realloc the parameter size */
8231 *pparams = (char *)SMB_REALLOC(*pparams,2);
8232 if (*pparams == NULL) {
8233 reply_nterror(req, NT_STATUS_NO_MEMORY);
8240 status = smbd_do_setfilepathinfo(conn, req, req,
8246 if (!NT_STATUS_IS_OK(status)) {
8247 if (open_was_deferred(req->sconn, req->mid)) {
8248 /* We have re-scheduled this call. */
8251 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8252 /* We have re-scheduled this call. */
8255 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8256 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8257 ERRSRV, ERRbadpath);
8260 if (info_level == SMB_POSIX_PATH_OPEN) {
8261 reply_openerror(req, status);
8266 * Invalid EA name needs to return 2 param bytes,
8267 * not a zero-length error packet.
8269 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8270 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8273 reply_nterror(req, status);
8278 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8284 /****************************************************************************
8285 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8286 ****************************************************************************/
8288 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8289 char **pparams, int total_params,
8290 char **ppdata, int total_data,
8291 unsigned int max_data_bytes)
8293 struct smb_filename *smb_dname = NULL;
8294 char *params = *pparams;
8295 char *pdata = *ppdata;
8296 char *directory = NULL;
8297 NTSTATUS status = NT_STATUS_OK;
8298 struct ea_list *ea_list = NULL;
8299 TALLOC_CTX *ctx = talloc_tos();
8301 if (!CAN_WRITE(conn)) {
8302 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8306 if (total_params < 5) {
8307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8311 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8312 total_params - 4, STR_TERMINATE,
8314 if (!NT_STATUS_IS_OK(status)) {
8315 reply_nterror(req, status);
8319 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8321 status = filename_convert(ctx,
8323 req->flags2 & FLAGS2_DFS_PATHNAMES,
8329 if (!NT_STATUS_IS_OK(status)) {
8330 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8331 reply_botherror(req,
8332 NT_STATUS_PATH_NOT_COVERED,
8333 ERRSRV, ERRbadpath);
8336 reply_nterror(req, status);
8341 * OS/2 workplace shell seems to send SET_EA requests of "null"
8342 * length (4 bytes containing IVAL 4).
8343 * They seem to have no effect. Bug #3212. JRA.
8346 if (total_data && (total_data != 4)) {
8347 /* Any data in this call is an EA list. */
8348 if (total_data < 10) {
8349 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8353 if (IVAL(pdata,0) > total_data) {
8354 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8355 IVAL(pdata,0), (unsigned int)total_data));
8356 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8360 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8363 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8367 if (!lp_ea_support(SNUM(conn))) {
8368 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8372 /* If total_data == 4 Windows doesn't care what values
8373 * are placed in that field, it just ignores them.
8374 * The System i QNTC IBM SMB client puts bad values here,
8375 * so ignore them. */
8377 status = create_directory(conn, req, smb_dname);
8379 if (!NT_STATUS_IS_OK(status)) {
8380 reply_nterror(req, status);
8384 /* Try and set any given EA. */
8386 status = set_ea(conn, NULL, smb_dname, ea_list);
8387 if (!NT_STATUS_IS_OK(status)) {
8388 reply_nterror(req, status);
8393 /* Realloc the parameter and data sizes */
8394 *pparams = (char *)SMB_REALLOC(*pparams,2);
8395 if(*pparams == NULL) {
8396 reply_nterror(req, NT_STATUS_NO_MEMORY);
8403 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8406 TALLOC_FREE(smb_dname);
8410 /****************************************************************************
8411 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8412 We don't actually do this - we just send a null response.
8413 ****************************************************************************/
8415 static void call_trans2findnotifyfirst(connection_struct *conn,
8416 struct smb_request *req,
8417 char **pparams, int total_params,
8418 char **ppdata, int total_data,
8419 unsigned int max_data_bytes)
8421 char *params = *pparams;
8424 if (total_params < 6) {
8425 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8429 info_level = SVAL(params,4);
8430 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8432 switch (info_level) {
8437 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8441 /* Realloc the parameter and data sizes */
8442 *pparams = (char *)SMB_REALLOC(*pparams,6);
8443 if (*pparams == NULL) {
8444 reply_nterror(req, NT_STATUS_NO_MEMORY);
8449 SSVAL(params,0,fnf_handle);
8450 SSVAL(params,2,0); /* No changes */
8451 SSVAL(params,4,0); /* No EA errors */
8458 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8463 /****************************************************************************
8464 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8465 changes). Currently this does nothing.
8466 ****************************************************************************/
8468 static void call_trans2findnotifynext(connection_struct *conn,
8469 struct smb_request *req,
8470 char **pparams, int total_params,
8471 char **ppdata, int total_data,
8472 unsigned int max_data_bytes)
8474 char *params = *pparams;
8476 DEBUG(3,("call_trans2findnotifynext\n"));
8478 /* Realloc the parameter and data sizes */
8479 *pparams = (char *)SMB_REALLOC(*pparams,4);
8480 if (*pparams == NULL) {
8481 reply_nterror(req, NT_STATUS_NO_MEMORY);
8486 SSVAL(params,0,0); /* No changes */
8487 SSVAL(params,2,0); /* No EA errors */
8489 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8494 /****************************************************************************
8495 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8496 ****************************************************************************/
8498 static void call_trans2getdfsreferral(connection_struct *conn,
8499 struct smb_request *req,
8500 char **pparams, int total_params,
8501 char **ppdata, int total_data,
8502 unsigned int max_data_bytes)
8504 char *params = *pparams;
8505 char *pathname = NULL;
8507 int max_referral_level;
8508 NTSTATUS status = NT_STATUS_OK;
8509 TALLOC_CTX *ctx = talloc_tos();
8511 DEBUG(10,("call_trans2getdfsreferral\n"));
8513 if (total_params < 3) {
8514 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8518 max_referral_level = SVAL(params,0);
8520 if(!lp_host_msdfs()) {
8521 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8525 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8526 total_params - 2, STR_TERMINATE);
8528 reply_nterror(req, NT_STATUS_NOT_FOUND);
8531 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8532 ppdata,&status)) < 0) {
8533 reply_nterror(req, status);
8537 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8538 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8539 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8544 #define LMCAT_SPL 0x53
8545 #define LMFUNC_GETJOBID 0x60
8547 /****************************************************************************
8548 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8549 ****************************************************************************/
8551 static void call_trans2ioctl(connection_struct *conn,
8552 struct smb_request *req,
8553 char **pparams, int total_params,
8554 char **ppdata, int total_data,
8555 unsigned int max_data_bytes)
8557 char *pdata = *ppdata;
8558 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8560 /* check for an invalid fid before proceeding */
8563 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8567 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8568 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8569 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8570 if (*ppdata == NULL) {
8571 reply_nterror(req, NT_STATUS_NO_MEMORY);
8576 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8577 CAN ACCEPT THIS IN UNICODE. JRA. */
8580 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8582 srvstr_push(pdata, req->flags2, pdata + 2,
8583 lp_netbios_name(), 15,
8584 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8585 srvstr_push(pdata, req->flags2, pdata+18,
8586 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8587 STR_ASCII|STR_TERMINATE); /* Service name */
8588 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8593 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8594 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8597 /****************************************************************************
8598 Reply to a SMBfindclose (stop trans2 directory search).
8599 ****************************************************************************/
8601 void reply_findclose(struct smb_request *req)
8604 struct smbd_server_connection *sconn = req->sconn;
8606 START_PROFILE(SMBfindclose);
8609 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8610 END_PROFILE(SMBfindclose);
8614 dptr_num = SVALS(req->vwv+0, 0);
8616 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8618 dptr_close(sconn, &dptr_num);
8620 reply_outbuf(req, 0, 0);
8622 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8624 END_PROFILE(SMBfindclose);
8628 /****************************************************************************
8629 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8630 ****************************************************************************/
8632 void reply_findnclose(struct smb_request *req)
8636 START_PROFILE(SMBfindnclose);
8639 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8640 END_PROFILE(SMBfindnclose);
8644 dptr_num = SVAL(req->vwv+0, 0);
8646 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8648 /* We never give out valid handles for a
8649 findnotifyfirst - so any dptr_num is ok here.
8652 reply_outbuf(req, 0, 0);
8654 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8656 END_PROFILE(SMBfindnclose);
8660 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8661 struct trans_state *state)
8663 if (get_Protocol() >= PROTOCOL_NT1) {
8664 req->flags2 |= 0x40; /* IS_LONG_NAME */
8665 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8668 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8669 if (state->call != TRANSACT2_QFSINFO &&
8670 state->call != TRANSACT2_SETFSINFO) {
8671 DEBUG(0,("handle_trans2: encryption required "
8673 (unsigned int)state->call));
8674 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8679 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8681 /* Now we must call the relevant TRANS2 function */
8682 switch(state->call) {
8683 case TRANSACT2_OPEN:
8685 START_PROFILE(Trans2_open);
8686 call_trans2open(conn, req,
8687 &state->param, state->total_param,
8688 &state->data, state->total_data,
8689 state->max_data_return);
8690 END_PROFILE(Trans2_open);
8694 case TRANSACT2_FINDFIRST:
8696 START_PROFILE(Trans2_findfirst);
8697 call_trans2findfirst(conn, req,
8698 &state->param, state->total_param,
8699 &state->data, state->total_data,
8700 state->max_data_return);
8701 END_PROFILE(Trans2_findfirst);
8705 case TRANSACT2_FINDNEXT:
8707 START_PROFILE(Trans2_findnext);
8708 call_trans2findnext(conn, req,
8709 &state->param, state->total_param,
8710 &state->data, state->total_data,
8711 state->max_data_return);
8712 END_PROFILE(Trans2_findnext);
8716 case TRANSACT2_QFSINFO:
8718 START_PROFILE(Trans2_qfsinfo);
8719 call_trans2qfsinfo(conn, req,
8720 &state->param, state->total_param,
8721 &state->data, state->total_data,
8722 state->max_data_return);
8723 END_PROFILE(Trans2_qfsinfo);
8727 case TRANSACT2_SETFSINFO:
8729 START_PROFILE(Trans2_setfsinfo);
8730 call_trans2setfsinfo(conn, req,
8731 &state->param, state->total_param,
8732 &state->data, state->total_data,
8733 state->max_data_return);
8734 END_PROFILE(Trans2_setfsinfo);
8738 case TRANSACT2_QPATHINFO:
8739 case TRANSACT2_QFILEINFO:
8741 START_PROFILE(Trans2_qpathinfo);
8742 call_trans2qfilepathinfo(conn, req, state->call,
8743 &state->param, state->total_param,
8744 &state->data, state->total_data,
8745 state->max_data_return);
8746 END_PROFILE(Trans2_qpathinfo);
8750 case TRANSACT2_SETPATHINFO:
8751 case TRANSACT2_SETFILEINFO:
8753 START_PROFILE(Trans2_setpathinfo);
8754 call_trans2setfilepathinfo(conn, req, state->call,
8755 &state->param, state->total_param,
8756 &state->data, state->total_data,
8757 state->max_data_return);
8758 END_PROFILE(Trans2_setpathinfo);
8762 case TRANSACT2_FINDNOTIFYFIRST:
8764 START_PROFILE(Trans2_findnotifyfirst);
8765 call_trans2findnotifyfirst(conn, req,
8766 &state->param, state->total_param,
8767 &state->data, state->total_data,
8768 state->max_data_return);
8769 END_PROFILE(Trans2_findnotifyfirst);
8773 case TRANSACT2_FINDNOTIFYNEXT:
8775 START_PROFILE(Trans2_findnotifynext);
8776 call_trans2findnotifynext(conn, req,
8777 &state->param, state->total_param,
8778 &state->data, state->total_data,
8779 state->max_data_return);
8780 END_PROFILE(Trans2_findnotifynext);
8784 case TRANSACT2_MKDIR:
8786 START_PROFILE(Trans2_mkdir);
8787 call_trans2mkdir(conn, req,
8788 &state->param, state->total_param,
8789 &state->data, state->total_data,
8790 state->max_data_return);
8791 END_PROFILE(Trans2_mkdir);
8795 case TRANSACT2_GET_DFS_REFERRAL:
8797 START_PROFILE(Trans2_get_dfs_referral);
8798 call_trans2getdfsreferral(conn, req,
8799 &state->param, state->total_param,
8800 &state->data, state->total_data,
8801 state->max_data_return);
8802 END_PROFILE(Trans2_get_dfs_referral);
8806 case TRANSACT2_IOCTL:
8808 START_PROFILE(Trans2_ioctl);
8809 call_trans2ioctl(conn, req,
8810 &state->param, state->total_param,
8811 &state->data, state->total_data,
8812 state->max_data_return);
8813 END_PROFILE(Trans2_ioctl);
8818 /* Error in request */
8819 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8820 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8824 /****************************************************************************
8825 Reply to a SMBtrans2.
8826 ****************************************************************************/
8828 void reply_trans2(struct smb_request *req)
8830 connection_struct *conn = req->conn;
8835 unsigned int tran_call;
8836 struct trans_state *state;
8839 START_PROFILE(SMBtrans2);
8841 if (req->wct < 14) {
8842 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8843 END_PROFILE(SMBtrans2);
8847 dsoff = SVAL(req->vwv+12, 0);
8848 dscnt = SVAL(req->vwv+11, 0);
8849 psoff = SVAL(req->vwv+10, 0);
8850 pscnt = SVAL(req->vwv+9, 0);
8851 tran_call = SVAL(req->vwv+14, 0);
8853 result = allow_new_trans(conn->pending_trans, req->mid);
8854 if (!NT_STATUS_IS_OK(result)) {
8855 DEBUG(2, ("Got invalid trans2 request: %s\n",
8856 nt_errstr(result)));
8857 reply_nterror(req, result);
8858 END_PROFILE(SMBtrans2);
8863 switch (tran_call) {
8864 /* List the allowed trans2 calls on IPC$ */
8865 case TRANSACT2_OPEN:
8866 case TRANSACT2_GET_DFS_REFERRAL:
8867 case TRANSACT2_QFILEINFO:
8868 case TRANSACT2_QFSINFO:
8869 case TRANSACT2_SETFSINFO:
8872 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8873 END_PROFILE(SMBtrans2);
8878 if ((state = talloc(conn, struct trans_state)) == NULL) {
8879 DEBUG(0, ("talloc failed\n"));
8880 reply_nterror(req, NT_STATUS_NO_MEMORY);
8881 END_PROFILE(SMBtrans2);
8885 state->cmd = SMBtrans2;
8887 state->mid = req->mid;
8888 state->vuid = req->vuid;
8889 state->setup_count = SVAL(req->vwv+13, 0);
8890 state->setup = NULL;
8891 state->total_param = SVAL(req->vwv+0, 0);
8892 state->param = NULL;
8893 state->total_data = SVAL(req->vwv+1, 0);
8895 state->max_param_return = SVAL(req->vwv+2, 0);
8896 state->max_data_return = SVAL(req->vwv+3, 0);
8897 state->max_setup_return = SVAL(req->vwv+4, 0);
8898 state->close_on_completion = BITSETW(req->vwv+5, 0);
8899 state->one_way = BITSETW(req->vwv+5, 1);
8901 state->call = tran_call;
8903 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8904 is so as a sanity check */
8905 if (state->setup_count != 1) {
8907 * Need to have rc=0 for ioctl to get job id for OS/2.
8908 * Network printing will fail if function is not successful.
8909 * Similar function in reply.c will be used if protocol
8910 * is LANMAN1.0 instead of LM1.2X002.
8911 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8912 * outbuf doesn't have to be set(only job id is used).
8914 if ( (state->setup_count == 4)
8915 && (tran_call == TRANSACT2_IOCTL)
8916 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8917 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8918 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8920 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8921 DEBUG(2,("Transaction is %d\n",tran_call));
8923 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8924 END_PROFILE(SMBtrans2);
8929 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8932 if (state->total_data) {
8934 if (trans_oob(state->total_data, 0, dscnt)
8935 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8939 /* Can't use talloc here, the core routines do realloc on the
8940 * params and data. */
8941 state->data = (char *)SMB_MALLOC(state->total_data);
8942 if (state->data == NULL) {
8943 DEBUG(0,("reply_trans2: data malloc fail for %u "
8944 "bytes !\n", (unsigned int)state->total_data));
8946 reply_nterror(req, NT_STATUS_NO_MEMORY);
8947 END_PROFILE(SMBtrans2);
8951 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8954 if (state->total_param) {
8956 if (trans_oob(state->total_param, 0, pscnt)
8957 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8961 /* Can't use talloc here, the core routines do realloc on the
8962 * params and data. */
8963 state->param = (char *)SMB_MALLOC(state->total_param);
8964 if (state->param == NULL) {
8965 DEBUG(0,("reply_trans: param malloc fail for %u "
8966 "bytes !\n", (unsigned int)state->total_param));
8967 SAFE_FREE(state->data);
8969 reply_nterror(req, NT_STATUS_NO_MEMORY);
8970 END_PROFILE(SMBtrans2);
8974 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8977 state->received_data = dscnt;
8978 state->received_param = pscnt;
8980 if ((state->received_param == state->total_param) &&
8981 (state->received_data == state->total_data)) {
8983 handle_trans2(conn, req, state);
8985 SAFE_FREE(state->data);
8986 SAFE_FREE(state->param);
8988 END_PROFILE(SMBtrans2);
8992 DLIST_ADD(conn->pending_trans, state);
8994 /* We need to send an interim response then receive the rest
8995 of the parameter/data bytes */
8996 reply_outbuf(req, 0, 0);
8997 show_msg((char *)req->outbuf);
8998 END_PROFILE(SMBtrans2);
9003 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9004 SAFE_FREE(state->data);
9005 SAFE_FREE(state->param);
9007 END_PROFILE(SMBtrans2);
9008 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9012 /****************************************************************************
9013 Reply to a SMBtranss2
9014 ****************************************************************************/
9016 void reply_transs2(struct smb_request *req)
9018 connection_struct *conn = req->conn;
9019 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9020 struct trans_state *state;
9022 START_PROFILE(SMBtranss2);
9024 show_msg((const char *)req->inbuf);
9026 /* Windows clients expect all replies to
9027 a transact secondary (SMBtranss2 0x33)
9028 to have a command code of transact
9029 (SMBtrans2 0x32). See bug #8989
9030 and also [MS-CIFS] section 2.2.4.47.2
9033 req->cmd = SMBtrans2;
9036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9037 END_PROFILE(SMBtranss2);
9041 for (state = conn->pending_trans; state != NULL;
9042 state = state->next) {
9043 if (state->mid == req->mid) {
9048 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9050 END_PROFILE(SMBtranss2);
9054 /* Revise state->total_param and state->total_data in case they have
9055 changed downwards */
9057 if (SVAL(req->vwv+0, 0) < state->total_param)
9058 state->total_param = SVAL(req->vwv+0, 0);
9059 if (SVAL(req->vwv+1, 0) < state->total_data)
9060 state->total_data = SVAL(req->vwv+1, 0);
9062 pcnt = SVAL(req->vwv+2, 0);
9063 poff = SVAL(req->vwv+3, 0);
9064 pdisp = SVAL(req->vwv+4, 0);
9066 dcnt = SVAL(req->vwv+5, 0);
9067 doff = SVAL(req->vwv+6, 0);
9068 ddisp = SVAL(req->vwv+7, 0);
9070 state->received_param += pcnt;
9071 state->received_data += dcnt;
9073 if ((state->received_data > state->total_data) ||
9074 (state->received_param > state->total_param))
9078 if (trans_oob(state->total_param, pdisp, pcnt)
9079 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9082 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9086 if (trans_oob(state->total_data, ddisp, dcnt)
9087 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9090 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9093 if ((state->received_param < state->total_param) ||
9094 (state->received_data < state->total_data)) {
9095 END_PROFILE(SMBtranss2);
9099 handle_trans2(conn, req, state);
9101 DLIST_REMOVE(conn->pending_trans, state);
9102 SAFE_FREE(state->data);
9103 SAFE_FREE(state->param);
9106 END_PROFILE(SMBtranss2);
9111 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9112 DLIST_REMOVE(conn->pending_trans, state);
9113 SAFE_FREE(state->data);
9114 SAFE_FREE(state->param);
9116 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9117 END_PROFILE(SMBtranss2);