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);
1397 case PERM_EXISTING_FILE:
1398 /* Apply mode mask */
1399 ret &= lp_create_mask(SNUM(conn));
1400 /* Add in force bits */
1401 ret |= lp_force_create_mode(SNUM(conn));
1404 case PERM_EXISTING_DIR:
1405 ret &= lp_dir_mask(SNUM(conn));
1406 /* Add in force bits */
1407 ret |= lp_force_dir_mode(SNUM(conn));
1412 return NT_STATUS_OK;
1415 /****************************************************************************
1416 Needed to show the msdfs symlinks as directories. Modifies psbuf
1417 to be a directory if it's a msdfs link.
1418 ****************************************************************************/
1420 static bool check_msdfs_link(connection_struct *conn,
1421 const char *pathname,
1422 SMB_STRUCT_STAT *psbuf)
1424 int saved_errno = errno;
1425 if(lp_host_msdfs() &&
1426 lp_msdfs_root(SNUM(conn)) &&
1427 is_msdfs_link(conn, pathname, psbuf)) {
1429 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1432 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1433 errno = saved_errno;
1436 errno = saved_errno;
1441 /****************************************************************************
1442 Get a level dependent lanman2 dir entry.
1443 ****************************************************************************/
1445 struct smbd_dirptr_lanman2_state {
1446 connection_struct *conn;
1447 uint32_t info_level;
1448 bool check_mangled_names;
1450 bool got_exact_match;
1453 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1459 struct smbd_dirptr_lanman2_state *state =
1460 (struct smbd_dirptr_lanman2_state *)private_data;
1462 char mangled_name[13]; /* mangled 8.3 name. */
1466 /* Mangle fname if it's an illegal name. */
1467 if (mangle_must_mangle(dname, state->conn->params)) {
1468 ok = name_to_8_3(dname, mangled_name,
1469 true, state->conn->params);
1473 fname = mangled_name;
1478 got_match = exact_match(state->has_wild,
1479 state->conn->case_sensitive,
1481 state->got_exact_match = got_match;
1483 got_match = mask_match(fname, mask,
1484 state->conn->case_sensitive);
1487 if(!got_match && state->check_mangled_names &&
1488 !mangle_is_8_3(fname, false, state->conn->params)) {
1490 * It turns out that NT matches wildcards against
1491 * both long *and* short names. This may explain some
1492 * of the wildcard wierdness from old DOS clients
1493 * that some people have been seeing.... JRA.
1495 /* Force the mangling into 8.3. */
1496 ok = name_to_8_3(fname, mangled_name,
1497 false, state->conn->params);
1502 got_match = exact_match(state->has_wild,
1503 state->conn->case_sensitive,
1504 mangled_name, mask);
1505 state->got_exact_match = got_match;
1507 got_match = mask_match(mangled_name, mask,
1508 state->conn->case_sensitive);
1516 *_fname = talloc_strdup(ctx, fname);
1517 if (*_fname == NULL) {
1524 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1526 struct smb_filename *smb_fname,
1529 struct smbd_dirptr_lanman2_state *state =
1530 (struct smbd_dirptr_lanman2_state *)private_data;
1531 bool ms_dfs_link = false;
1534 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1535 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1536 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1537 "Couldn't lstat [%s] (%s)\n",
1538 smb_fname_str_dbg(smb_fname),
1542 } else if (!VALID_STAT(smb_fname->st) &&
1543 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1544 /* Needed to show the msdfs symlinks as
1547 ms_dfs_link = check_msdfs_link(state->conn,
1548 smb_fname->base_name,
1551 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1552 "Couldn't stat [%s] (%s)\n",
1553 smb_fname_str_dbg(smb_fname),
1560 mode = dos_mode_msdfs(state->conn, smb_fname);
1562 mode = dos_mode(state->conn, smb_fname);
1569 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1570 connection_struct *conn,
1572 uint32_t info_level,
1573 struct ea_list *name_list,
1574 bool check_mangled_names,
1575 bool requires_resume_key,
1578 const struct smb_filename *smb_fname,
1579 int space_remaining,
1586 uint64_t *last_entry_off)
1588 char *p, *q, *pdata = *ppdata;
1590 uint64_t file_size = 0;
1591 uint64_t allocation_size = 0;
1592 uint64_t file_index = 0;
1594 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1595 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1597 char *last_entry_ptr;
1602 *out_of_space = false;
1604 ZERO_STRUCT(mdate_ts);
1605 ZERO_STRUCT(adate_ts);
1606 ZERO_STRUCT(create_date_ts);
1607 ZERO_STRUCT(cdate_ts);
1609 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1610 file_size = get_file_size_stat(&smb_fname->st);
1612 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1614 file_index = get_FileIndex(conn, &smb_fname->st);
1616 mdate_ts = smb_fname->st.st_ex_mtime;
1617 adate_ts = smb_fname->st.st_ex_atime;
1618 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1619 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1621 if (lp_dos_filetime_resolution(SNUM(conn))) {
1622 dos_filetime_timespec(&create_date_ts);
1623 dos_filetime_timespec(&mdate_ts);
1624 dos_filetime_timespec(&adate_ts);
1625 dos_filetime_timespec(&cdate_ts);
1628 create_date = convert_timespec_to_time_t(create_date_ts);
1629 mdate = convert_timespec_to_time_t(mdate_ts);
1630 adate = convert_timespec_to_time_t(adate_ts);
1632 /* align the record */
1633 SMB_ASSERT(align >= 1);
1635 off = (int)PTR_DIFF(pdata, base_data);
1636 pad = (off + (align-1)) & ~(align-1);
1639 if (pad && pad > space_remaining) {
1640 *out_of_space = true;
1641 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1642 "for padding (wanted %u, had %d)\n",
1645 return false; /* Not finished - just out of space */
1649 /* initialize padding to 0 */
1651 memset(pdata, 0, pad);
1653 space_remaining -= pad;
1655 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1665 switch (info_level) {
1666 case SMB_FIND_INFO_STANDARD:
1667 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1668 if(requires_resume_key) {
1672 srv_put_dos_date2(p,0,create_date);
1673 srv_put_dos_date2(p,4,adate);
1674 srv_put_dos_date2(p,8,mdate);
1675 SIVAL(p,12,(uint32)file_size);
1676 SIVAL(p,16,(uint32)allocation_size);
1680 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1681 p += ucs2_align(base_data, p, 0);
1683 len = srvstr_push(base_data, flags2, p,
1684 fname, PTR_DIFF(end_data, p),
1686 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1688 SCVAL(nameptr, -1, len - 2);
1690 SCVAL(nameptr, -1, 0);
1694 SCVAL(nameptr, -1, len - 1);
1696 SCVAL(nameptr, -1, 0);
1702 case SMB_FIND_EA_SIZE:
1703 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1704 if (requires_resume_key) {
1708 srv_put_dos_date2(p,0,create_date);
1709 srv_put_dos_date2(p,4,adate);
1710 srv_put_dos_date2(p,8,mdate);
1711 SIVAL(p,12,(uint32)file_size);
1712 SIVAL(p,16,(uint32)allocation_size);
1715 unsigned int ea_size = estimate_ea_size(conn, NULL,
1717 SIVAL(p,22,ea_size); /* Extended attributes */
1721 len = srvstr_push(base_data, flags2,
1722 p, fname, PTR_DIFF(end_data, p),
1723 STR_TERMINATE | STR_NOALIGN);
1724 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1737 SCVAL(nameptr,0,len);
1739 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1742 case SMB_FIND_EA_LIST:
1744 struct ea_list *file_list = NULL;
1748 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1752 if (requires_resume_key) {
1756 srv_put_dos_date2(p,0,create_date);
1757 srv_put_dos_date2(p,4,adate);
1758 srv_put_dos_date2(p,8,mdate);
1759 SIVAL(p,12,(uint32)file_size);
1760 SIVAL(p,16,(uint32)allocation_size);
1762 p += 22; /* p now points to the EA area. */
1764 status = get_ea_list_from_file(ctx, conn, NULL,
1766 &ea_len, &file_list);
1767 if (!NT_STATUS_IS_OK(status)) {
1770 name_list = ea_list_union(name_list, file_list, &ea_len);
1772 /* We need to determine if this entry will fit in the space available. */
1773 /* Max string size is 255 bytes. */
1774 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1775 *out_of_space = true;
1776 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1777 "(wanted %u, had %d)\n",
1778 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1780 return False; /* Not finished - just out of space */
1783 /* Push the ea_data followed by the name. */
1784 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1786 len = srvstr_push(base_data, flags2,
1787 p + 1, fname, PTR_DIFF(end_data, p+1),
1788 STR_TERMINATE | STR_NOALIGN);
1789 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1802 SCVAL(nameptr,0,len);
1804 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1808 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1809 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1810 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1812 SIVAL(p,0,reskey); p += 4;
1813 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1814 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1815 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1816 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1817 SOFF_T(p,0,file_size); p += 8;
1818 SOFF_T(p,0,allocation_size); p += 8;
1819 SIVAL(p,0,mode); p += 4;
1820 q = p; p += 4; /* q is placeholder for name length. */
1821 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1822 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1824 unsigned int ea_size = estimate_ea_size(conn, NULL,
1826 SIVAL(p,0,ea_size); /* Extended attributes */
1829 /* Clear the short name buffer. This is
1830 * IMPORTANT as not doing so will trigger
1831 * a Win2k client bug. JRA.
1833 if (!was_8_3 && check_mangled_names) {
1834 char mangled_name[13]; /* mangled 8.3 name. */
1835 if (!name_to_8_3(fname,mangled_name,True,
1837 /* Error - mangle failed ! */
1838 memset(mangled_name,'\0',12);
1840 mangled_name[12] = 0;
1841 len = srvstr_push(base_data, flags2,
1842 p+2, mangled_name, 24,
1843 STR_UPPER|STR_UNICODE);
1845 memset(p + 2 + len,'\0',24 - len);
1852 len = srvstr_push(base_data, flags2, p,
1853 fname, PTR_DIFF(end_data, p),
1854 STR_TERMINATE_ASCII);
1858 len = PTR_DIFF(p, pdata);
1859 pad = (len + (align-1)) & ~(align-1);
1861 * offset to the next entry, the caller
1862 * will overwrite it for the last entry
1863 * that's why we always include the padding
1867 * set padding to zero
1870 memset(p, 0, pad - len);
1877 case SMB_FIND_FILE_DIRECTORY_INFO:
1878 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1880 SIVAL(p,0,reskey); p += 4;
1881 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1882 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1883 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1884 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1885 SOFF_T(p,0,file_size); p += 8;
1886 SOFF_T(p,0,allocation_size); p += 8;
1887 SIVAL(p,0,mode); p += 4;
1888 len = srvstr_push(base_data, flags2,
1889 p + 4, fname, PTR_DIFF(end_data, p+4),
1890 STR_TERMINATE_ASCII);
1894 len = PTR_DIFF(p, pdata);
1895 pad = (len + (align-1)) & ~(align-1);
1897 * offset to the next entry, the caller
1898 * will overwrite it for the last entry
1899 * that's why we always include the padding
1903 * set padding to zero
1906 memset(p, 0, pad - len);
1913 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1914 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1916 SIVAL(p,0,reskey); p += 4;
1917 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1918 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1919 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1920 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1921 SOFF_T(p,0,file_size); p += 8;
1922 SOFF_T(p,0,allocation_size); p += 8;
1923 SIVAL(p,0,mode); p += 4;
1924 q = p; p += 4; /* q is placeholder for name length. */
1926 unsigned int ea_size = estimate_ea_size(conn, NULL,
1928 SIVAL(p,0,ea_size); /* Extended attributes */
1931 len = srvstr_push(base_data, flags2, p,
1932 fname, PTR_DIFF(end_data, p),
1933 STR_TERMINATE_ASCII);
1937 len = PTR_DIFF(p, pdata);
1938 pad = (len + (align-1)) & ~(align-1);
1940 * offset to the next entry, the caller
1941 * will overwrite it for the last entry
1942 * that's why we always include the padding
1946 * set padding to zero
1949 memset(p, 0, pad - len);
1956 case SMB_FIND_FILE_NAMES_INFO:
1957 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1959 SIVAL(p,0,reskey); p += 4;
1961 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1962 acl on a dir (tridge) */
1963 len = srvstr_push(base_data, flags2, p,
1964 fname, PTR_DIFF(end_data, p),
1965 STR_TERMINATE_ASCII);
1969 len = PTR_DIFF(p, pdata);
1970 pad = (len + (align-1)) & ~(align-1);
1972 * offset to the next entry, the caller
1973 * will overwrite it for the last entry
1974 * that's why we always include the padding
1978 * set padding to zero
1981 memset(p, 0, pad - len);
1988 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1989 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1991 SIVAL(p,0,reskey); p += 4;
1992 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1993 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1994 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1995 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1996 SOFF_T(p,0,file_size); p += 8;
1997 SOFF_T(p,0,allocation_size); p += 8;
1998 SIVAL(p,0,mode); p += 4;
1999 q = p; p += 4; /* q is placeholder for name length. */
2000 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2001 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2003 unsigned int ea_size = estimate_ea_size(conn, NULL,
2005 SIVAL(p,0,ea_size); /* Extended attributes */
2008 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2009 SBVAL(p,0,file_index); p += 8;
2010 len = srvstr_push(base_data, flags2, p,
2011 fname, PTR_DIFF(end_data, p),
2012 STR_TERMINATE_ASCII);
2016 len = PTR_DIFF(p, pdata);
2017 pad = (len + (align-1)) & ~(align-1);
2019 * offset to the next entry, the caller
2020 * will overwrite it for the last entry
2021 * that's why we always include the padding
2025 * set padding to zero
2028 memset(p, 0, pad - len);
2035 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2036 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2037 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2039 SIVAL(p,0,reskey); p += 4;
2040 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2041 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2042 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2043 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2044 SOFF_T(p,0,file_size); p += 8;
2045 SOFF_T(p,0,allocation_size); p += 8;
2046 SIVAL(p,0,mode); p += 4;
2047 q = p; p += 4; /* q is placeholder for name length */
2048 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2049 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2051 unsigned int ea_size = estimate_ea_size(conn, NULL,
2053 SIVAL(p,0,ea_size); /* Extended attributes */
2056 /* Clear the short name buffer. This is
2057 * IMPORTANT as not doing so will trigger
2058 * a Win2k client bug. JRA.
2060 if (!was_8_3 && check_mangled_names) {
2061 char mangled_name[13]; /* mangled 8.3 name. */
2062 if (!name_to_8_3(fname,mangled_name,True,
2064 /* Error - mangle failed ! */
2065 memset(mangled_name,'\0',12);
2067 mangled_name[12] = 0;
2068 len = srvstr_push(base_data, flags2,
2069 p+2, mangled_name, 24,
2070 STR_UPPER|STR_UNICODE);
2073 memset(p + 2 + len,'\0',24 - len);
2080 SSVAL(p,0,0); p += 2; /* Reserved ? */
2081 SBVAL(p,0,file_index); p += 8;
2082 len = srvstr_push(base_data, flags2, p,
2083 fname, PTR_DIFF(end_data, p),
2084 STR_TERMINATE_ASCII);
2088 len = PTR_DIFF(p, pdata);
2089 pad = (len + (align-1)) & ~(align-1);
2091 * offset to the next entry, the caller
2092 * will overwrite it for the last entry
2093 * that's why we always include the padding
2097 * set padding to zero
2100 memset(p, 0, pad - len);
2107 /* CIFS UNIX Extension. */
2109 case SMB_FIND_FILE_UNIX:
2110 case SMB_FIND_FILE_UNIX_INFO2:
2112 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2114 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2116 if (info_level == SMB_FIND_FILE_UNIX) {
2117 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2118 p = store_file_unix_basic(conn, p,
2119 NULL, &smb_fname->st);
2120 len = srvstr_push(base_data, flags2, p,
2121 fname, PTR_DIFF(end_data, p),
2124 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2125 p = store_file_unix_basic_info2(conn, p,
2126 NULL, &smb_fname->st);
2129 len = srvstr_push(base_data, flags2, p, fname,
2130 PTR_DIFF(end_data, p), 0);
2131 SIVAL(nameptr, 0, len);
2136 len = PTR_DIFF(p, pdata);
2137 pad = (len + (align-1)) & ~(align-1);
2139 * offset to the next entry, the caller
2140 * will overwrite it for the last entry
2141 * that's why we always include the padding
2145 * set padding to zero
2148 memset(p, 0, pad - len);
2153 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2161 if (PTR_DIFF(p,pdata) > space_remaining) {
2162 *out_of_space = true;
2163 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2164 "(wanted %u, had %d)\n",
2165 (unsigned int)PTR_DIFF(p,pdata),
2167 return false; /* Not finished - just out of space */
2170 /* Setup the last entry pointer, as an offset from base_data */
2171 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2172 /* Advance the data pointer to the next slot */
2178 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2179 connection_struct *conn,
2180 struct dptr_struct *dirptr,
2182 const char *path_mask,
2185 int requires_resume_key,
2193 int space_remaining,
2195 bool *got_exact_match,
2196 int *_last_entry_off,
2197 struct ea_list *name_list)
2200 const char *mask = NULL;
2201 long prev_dirpos = 0;
2204 struct smb_filename *smb_fname = NULL;
2205 struct smbd_dirptr_lanman2_state state;
2207 uint64_t last_entry_off = 0;
2211 state.info_level = info_level;
2212 state.check_mangled_names = lp_manglednames(conn->params);
2213 state.has_wild = dptr_has_wild(dirptr);
2214 state.got_exact_match = false;
2216 *out_of_space = false;
2217 *got_exact_match = false;
2219 p = strrchr_m(path_mask,'/');
2230 ok = smbd_dirptr_get_entry(ctx,
2236 smbd_dirptr_lanman2_match_fn,
2237 smbd_dirptr_lanman2_mode_fn,
2247 *got_exact_match = state.got_exact_match;
2249 ok = smbd_marshall_dir_entry(ctx,
2254 state.check_mangled_names,
2255 requires_resume_key,
2268 TALLOC_FREE(smb_fname);
2269 if (*out_of_space) {
2270 dptr_SeekDir(dirptr, prev_dirpos);
2277 *_last_entry_off = last_entry_off;
2281 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2282 connection_struct *conn,
2283 struct dptr_struct *dirptr,
2285 const char *path_mask,
2288 bool requires_resume_key,
2294 int space_remaining,
2296 bool *got_exact_match,
2297 int *last_entry_off,
2298 struct ea_list *name_list)
2301 const bool do_pad = true;
2303 if (info_level >= 1 && info_level <= 3) {
2304 /* No alignment on earlier info levels. */
2308 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2309 path_mask, dirtype, info_level,
2310 requires_resume_key, dont_descend, ask_sharemode,
2312 ppdata, base_data, end_data,
2314 out_of_space, got_exact_match,
2315 last_entry_off, name_list);
2318 /****************************************************************************
2319 Reply to a TRANS2_FINDFIRST.
2320 ****************************************************************************/
2322 static void call_trans2findfirst(connection_struct *conn,
2323 struct smb_request *req,
2324 char **pparams, int total_params,
2325 char **ppdata, int total_data,
2326 unsigned int max_data_bytes)
2328 /* We must be careful here that we don't return more than the
2329 allowed number of data bytes. If this means returning fewer than
2330 maxentries then so be it. We assume that the redirector has
2331 enough room for the fixed number of parameter bytes it has
2333 struct smb_filename *smb_dname = NULL;
2334 char *params = *pparams;
2335 char *pdata = *ppdata;
2339 uint16 findfirst_flags;
2340 bool close_after_first;
2342 bool requires_resume_key;
2344 char *directory = NULL;
2347 int last_entry_off=0;
2351 bool finished = False;
2352 bool dont_descend = False;
2353 bool out_of_space = False;
2354 int space_remaining;
2355 bool mask_contains_wcard = False;
2356 struct ea_list *ea_list = NULL;
2357 NTSTATUS ntstatus = NT_STATUS_OK;
2358 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2359 TALLOC_CTX *ctx = talloc_tos();
2360 struct dptr_struct *dirptr = NULL;
2361 struct smbd_server_connection *sconn = req->sconn;
2362 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2363 bool backup_priv = false;
2365 if (total_params < 13) {
2366 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2370 dirtype = SVAL(params,0);
2371 maxentries = SVAL(params,2);
2372 findfirst_flags = SVAL(params,4);
2373 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2374 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2375 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2376 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2377 security_token_has_privilege(get_current_nttok(conn),
2380 info_level = SVAL(params,6);
2382 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2383 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2384 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2386 info_level, max_data_bytes));
2389 /* W2K3 seems to treat zero as 1. */
2393 switch (info_level) {
2394 case SMB_FIND_INFO_STANDARD:
2395 case SMB_FIND_EA_SIZE:
2396 case SMB_FIND_EA_LIST:
2397 case SMB_FIND_FILE_DIRECTORY_INFO:
2398 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2399 case SMB_FIND_FILE_NAMES_INFO:
2400 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2401 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2402 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2404 case SMB_FIND_FILE_UNIX:
2405 case SMB_FIND_FILE_UNIX_INFO2:
2406 /* Always use filesystem for UNIX mtime query. */
2407 ask_sharemode = false;
2408 if (!lp_unix_extensions()) {
2409 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2412 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2415 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2419 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2420 params+12, total_params - 12,
2421 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2422 if (!NT_STATUS_IS_OK(ntstatus)) {
2423 reply_nterror(req, ntstatus);
2429 ntstatus = filename_convert_with_privilege(ctx,
2434 &mask_contains_wcard,
2437 ntstatus = filename_convert(ctx, conn,
2438 req->flags2 & FLAGS2_DFS_PATHNAMES,
2441 &mask_contains_wcard,
2445 if (!NT_STATUS_IS_OK(ntstatus)) {
2446 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2447 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2448 ERRSRV, ERRbadpath);
2451 reply_nterror(req, ntstatus);
2455 mask = smb_dname->original_lcomp;
2457 directory = smb_dname->base_name;
2459 p = strrchr_m(directory,'/');
2461 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2462 if((directory[0] == '.') && (directory[1] == '\0')) {
2463 mask = talloc_strdup(ctx,"*");
2465 reply_nterror(req, NT_STATUS_NO_MEMORY);
2468 mask_contains_wcard = True;
2474 if (p == NULL || p == directory) {
2475 /* Ensure we don't have a directory name of "". */
2476 directory = talloc_strdup(talloc_tos(), ".");
2478 reply_nterror(req, NT_STATUS_NO_MEMORY);
2483 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2485 if (info_level == SMB_FIND_EA_LIST) {
2488 if (total_data < 4) {
2489 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2493 ea_size = IVAL(pdata,0);
2494 if (ea_size != total_data) {
2495 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2496 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2497 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2501 if (!lp_ea_support(SNUM(conn))) {
2502 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2506 /* Pull out the list of names. */
2507 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2509 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2514 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2515 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2519 *ppdata = (char *)SMB_REALLOC(
2520 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2521 if(*ppdata == NULL ) {
2522 reply_nterror(req, NT_STATUS_NO_MEMORY);
2526 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2528 /* Realloc the params space */
2529 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2530 if (*pparams == NULL) {
2531 reply_nterror(req, NT_STATUS_NO_MEMORY);
2536 /* Save the wildcard match and attribs we are using on this directory -
2537 needed as lanman2 assumes these are being saved between calls */
2539 ntstatus = dptr_create(conn,
2547 mask_contains_wcard,
2551 if (!NT_STATUS_IS_OK(ntstatus)) {
2552 reply_nterror(req, ntstatus);
2557 /* Remember this in case we have
2558 to do a findnext. */
2559 dptr_set_priv(dirptr);
2562 dptr_num = dptr_dnum(dirptr);
2563 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2565 /* Initialize per TRANS2_FIND_FIRST operation data */
2566 dptr_init_search_op(dirptr);
2568 /* We don't need to check for VOL here as this is returned by
2569 a different TRANS2 call. */
2571 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2572 directory,lp_dontdescend(ctx, SNUM(conn))));
2573 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2574 dont_descend = True;
2577 space_remaining = max_data_bytes;
2578 out_of_space = False;
2580 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2581 bool got_exact_match = False;
2583 /* this is a heuristic to avoid seeking the dirptr except when
2584 absolutely necessary. It allows for a filename of about 40 chars */
2585 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2586 out_of_space = True;
2589 finished = !get_lanman2_dir_entry(ctx,
2593 mask,dirtype,info_level,
2594 requires_resume_key,dont_descend,
2597 space_remaining, &out_of_space,
2599 &last_entry_off, ea_list);
2602 if (finished && out_of_space)
2605 if (!finished && !out_of_space)
2609 * As an optimisation if we know we aren't looking
2610 * for a wildcard name (ie. the name matches the wildcard exactly)
2611 * then we can finish on any (first) match.
2612 * This speeds up large directory searches. JRA.
2618 /* Ensure space_remaining never goes -ve. */
2619 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2620 space_remaining = 0;
2621 out_of_space = true;
2623 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2627 /* Check if we can close the dirptr */
2628 if(close_after_first || (finished && close_if_end)) {
2629 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2630 dptr_close(sconn, &dptr_num);
2634 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2635 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2636 * the protocol level is less than NT1. Tested with smbclient. JRA.
2637 * This should fix the OS/2 client bug #2335.
2640 if(numentries == 0) {
2641 dptr_close(sconn, &dptr_num);
2642 if (get_Protocol() < PROTOCOL_NT1) {
2643 reply_force_doserror(req, ERRDOS, ERRnofiles);
2646 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2647 ERRDOS, ERRbadfile);
2652 /* At this point pdata points to numentries directory entries. */
2654 /* Set up the return parameter block */
2655 SSVAL(params,0,dptr_num);
2656 SSVAL(params,2,numentries);
2657 SSVAL(params,4,finished);
2658 SSVAL(params,6,0); /* Never an EA error */
2659 SSVAL(params,8,last_entry_off);
2661 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2664 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2665 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2667 reply_nterror(req, NT_STATUS_NO_MEMORY);
2671 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2672 smb_fn_name(req->cmd),
2673 mask, directory, dirtype, numentries ) );
2676 * Force a name mangle here to ensure that the
2677 * mask as an 8.3 name is top of the mangled cache.
2678 * The reasons for this are subtle. Don't remove
2679 * this code unless you know what you are doing
2680 * (see PR#13758). JRA.
2683 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2684 char mangled_name[13];
2685 name_to_8_3(mask, mangled_name, True, conn->params);
2693 TALLOC_FREE(smb_dname);
2697 /****************************************************************************
2698 Reply to a TRANS2_FINDNEXT.
2699 ****************************************************************************/
2701 static void call_trans2findnext(connection_struct *conn,
2702 struct smb_request *req,
2703 char **pparams, int total_params,
2704 char **ppdata, int total_data,
2705 unsigned int max_data_bytes)
2707 /* We must be careful here that we don't return more than the
2708 allowed number of data bytes. If this means returning fewer than
2709 maxentries then so be it. We assume that the redirector has
2710 enough room for the fixed number of parameter bytes it has
2712 char *params = *pparams;
2713 char *pdata = *ppdata;
2719 uint16 findnext_flags;
2720 bool close_after_request;
2722 bool requires_resume_key;
2724 bool mask_contains_wcard = False;
2725 char *resume_name = NULL;
2726 const char *mask = NULL;
2727 const char *directory = NULL;
2731 int i, last_entry_off=0;
2732 bool finished = False;
2733 bool dont_descend = False;
2734 bool out_of_space = False;
2735 int space_remaining;
2736 struct ea_list *ea_list = NULL;
2737 NTSTATUS ntstatus = NT_STATUS_OK;
2738 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2739 TALLOC_CTX *ctx = talloc_tos();
2740 struct dptr_struct *dirptr;
2741 struct smbd_server_connection *sconn = req->sconn;
2742 bool backup_priv = false;
2744 if (total_params < 13) {
2745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2749 dptr_num = SVAL(params,0);
2750 maxentries = SVAL(params,2);
2751 info_level = SVAL(params,4);
2752 resume_key = IVAL(params,6);
2753 findnext_flags = SVAL(params,10);
2754 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2755 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2756 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2757 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2759 if (!continue_bit) {
2760 /* We only need resume_name if continue_bit is zero. */
2761 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2763 total_params - 12, STR_TERMINATE, &ntstatus,
2764 &mask_contains_wcard);
2765 if (!NT_STATUS_IS_OK(ntstatus)) {
2766 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2767 complain (it thinks we're asking for the directory above the shared
2768 path or an invalid name). Catch this as the resume name is only compared, never used in
2769 a file access. JRA. */
2770 srvstr_pull_talloc(ctx, params, req->flags2,
2771 &resume_name, params+12,
2775 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2776 reply_nterror(req, ntstatus);
2782 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2783 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2784 resume_key = %d resume name = %s continue=%d level = %d\n",
2785 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2786 requires_resume_key, resume_key,
2787 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2790 /* W2K3 seems to treat zero as 1. */
2794 switch (info_level) {
2795 case SMB_FIND_INFO_STANDARD:
2796 case SMB_FIND_EA_SIZE:
2797 case SMB_FIND_EA_LIST:
2798 case SMB_FIND_FILE_DIRECTORY_INFO:
2799 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2800 case SMB_FIND_FILE_NAMES_INFO:
2801 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2802 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2803 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2805 case SMB_FIND_FILE_UNIX:
2806 case SMB_FIND_FILE_UNIX_INFO2:
2807 /* Always use filesystem for UNIX mtime query. */
2808 ask_sharemode = false;
2809 if (!lp_unix_extensions()) {
2810 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2815 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2819 if (info_level == SMB_FIND_EA_LIST) {
2822 if (total_data < 4) {
2823 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2827 ea_size = IVAL(pdata,0);
2828 if (ea_size != total_data) {
2829 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2830 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2831 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2835 if (!lp_ea_support(SNUM(conn))) {
2836 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2840 /* Pull out the list of names. */
2841 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2843 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2848 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2849 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2853 *ppdata = (char *)SMB_REALLOC(
2854 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2855 if(*ppdata == NULL) {
2856 reply_nterror(req, NT_STATUS_NO_MEMORY);
2861 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2863 /* Realloc the params space */
2864 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2865 if(*pparams == NULL ) {
2866 reply_nterror(req, NT_STATUS_NO_MEMORY);
2872 /* Check that the dptr is valid */
2873 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2874 reply_nterror(req, STATUS_NO_MORE_FILES);
2878 directory = dptr_path(sconn, dptr_num);
2880 /* Get the wildcard mask from the dptr */
2881 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2882 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2883 reply_nterror(req, STATUS_NO_MORE_FILES);
2887 /* Get the attr mask from the dptr */
2888 dirtype = dptr_attr(sconn, dptr_num);
2890 backup_priv = dptr_get_priv(dirptr);
2892 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2893 "backup_priv = %d\n",
2894 dptr_num, mask, dirtype,
2896 dptr_TellDir(dirptr),
2899 /* Initialize per TRANS2_FIND_NEXT operation data */
2900 dptr_init_search_op(dirptr);
2902 /* We don't need to check for VOL here as this is returned by
2903 a different TRANS2 call. */
2905 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2906 directory,lp_dontdescend(ctx, SNUM(conn))));
2907 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2908 dont_descend = True;
2911 space_remaining = max_data_bytes;
2912 out_of_space = False;
2919 * Seek to the correct position. We no longer use the resume key but
2920 * depend on the last file name instead.
2923 if(!continue_bit && resume_name && *resume_name) {
2926 long current_pos = 0;
2928 * Remember, name_to_8_3 is called by
2929 * get_lanman2_dir_entry(), so the resume name
2930 * could be mangled. Ensure we check the unmangled name.
2933 if (mangle_is_mangled(resume_name, conn->params)) {
2934 char *new_resume_name = NULL;
2935 mangle_lookup_name_from_8_3(ctx,
2939 if (new_resume_name) {
2940 resume_name = new_resume_name;
2945 * Fix for NT redirector problem triggered by resume key indexes
2946 * changing between directory scans. We now return a resume key of 0
2947 * and instead look for the filename to continue from (also given
2948 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2949 * findfirst/findnext (as is usual) then the directory pointer
2950 * should already be at the correct place.
2953 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2954 } /* end if resume_name && !continue_bit */
2956 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2957 bool got_exact_match = False;
2959 /* this is a heuristic to avoid seeking the dirptr except when
2960 absolutely necessary. It allows for a filename of about 40 chars */
2961 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2962 out_of_space = True;
2965 finished = !get_lanman2_dir_entry(ctx,
2969 mask,dirtype,info_level,
2970 requires_resume_key,dont_descend,
2973 space_remaining, &out_of_space,
2975 &last_entry_off, ea_list);
2978 if (finished && out_of_space)
2981 if (!finished && !out_of_space)
2985 * As an optimisation if we know we aren't looking
2986 * for a wildcard name (ie. the name matches the wildcard exactly)
2987 * then we can finish on any (first) match.
2988 * This speeds up large directory searches. JRA.
2994 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2997 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2998 smb_fn_name(req->cmd),
2999 mask, directory, dirtype, numentries ) );
3001 /* Check if we can close the dirptr */
3002 if(close_after_request || (finished && close_if_end)) {
3003 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3004 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3011 /* Set up the return parameter block */
3012 SSVAL(params,0,numentries);
3013 SSVAL(params,2,finished);
3014 SSVAL(params,4,0); /* Never an EA error */
3015 SSVAL(params,6,last_entry_off);
3017 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3023 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3025 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3029 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3031 SMB_ASSERT(extended_info != NULL);
3033 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3034 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3035 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3036 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3037 #ifdef SAMBA_VERSION_REVISION
3038 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3040 extended_info->samba_subversion = 0;
3041 #ifdef SAMBA_VERSION_RC_RELEASE
3042 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3044 #ifdef SAMBA_VERSION_PRE_RELEASE
3045 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3048 #ifdef SAMBA_VERSION_VENDOR_PATCH
3049 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3051 extended_info->samba_gitcommitdate = 0;
3052 #ifdef SAMBA_VERSION_COMMIT_TIME
3053 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3056 memset(extended_info->samba_version_string, 0,
3057 sizeof(extended_info->samba_version_string));
3059 snprintf (extended_info->samba_version_string,
3060 sizeof(extended_info->samba_version_string),
3061 "%s", samba_version_string());
3064 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3065 TALLOC_CTX *mem_ctx,
3066 uint16_t info_level,
3068 unsigned int max_data_bytes,
3069 struct smb_filename *fname,
3073 char *pdata, *end_data;
3074 int data_len = 0, len;
3075 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3076 int snum = SNUM(conn);
3077 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3078 char *filename = NULL;
3079 uint32 additional_flags = 0;
3080 struct smb_filename smb_fname;
3082 NTSTATUS status = NT_STATUS_OK;
3084 if (fname == NULL || fname->base_name == NULL) {
3087 filename = fname->base_name;
3091 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3092 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3093 "info level (0x%x) on IPC$.\n",
3094 (unsigned int)info_level));
3095 return NT_STATUS_ACCESS_DENIED;
3099 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3101 ZERO_STRUCT(smb_fname);
3102 smb_fname.base_name = discard_const_p(char, filename);
3104 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3105 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3106 return map_nt_error_from_unix(errno);
3111 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3112 return NT_STATUS_INVALID_PARAMETER;
3115 *ppdata = (char *)SMB_REALLOC(
3116 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3117 if (*ppdata == NULL) {
3118 return NT_STATUS_NO_MEMORY;
3122 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3123 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3125 switch (info_level) {
3126 case SMB_INFO_ALLOCATION:
3128 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3130 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3131 return map_nt_error_from_unix(errno);
3134 block_size = lp_block_size(snum);
3135 if (bsize < block_size) {
3136 uint64_t factor = block_size/bsize;
3141 if (bsize > block_size) {
3142 uint64_t factor = bsize/block_size;
3147 bytes_per_sector = 512;
3148 sectors_per_unit = bsize/bytes_per_sector;
3150 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3151 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3152 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3154 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3155 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3156 SIVAL(pdata,l1_cUnit,dsize);
3157 SIVAL(pdata,l1_cUnitAvail,dfree);
3158 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3162 case SMB_INFO_VOLUME:
3163 /* Return volume name */
3165 * Add volume serial number - hash of a combination of
3166 * the called hostname and the service name.
3168 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3170 * Win2k3 and previous mess this up by sending a name length
3171 * one byte short. I believe only older clients (OS/2 Win9x) use
3172 * this call so try fixing this by adding a terminating null to
3173 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3177 pdata+l2_vol_szVolLabel, vname,
3178 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3179 STR_NOALIGN|STR_TERMINATE);
3180 SCVAL(pdata,l2_vol_cch,len);
3181 data_len = l2_vol_szVolLabel + len;
3182 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3183 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3187 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3188 case SMB_FS_ATTRIBUTE_INFORMATION:
3190 additional_flags = 0;
3191 #if defined(HAVE_SYS_QUOTAS)
3192 additional_flags |= FILE_VOLUME_QUOTAS;
3195 if(lp_nt_acl_support(SNUM(conn))) {
3196 additional_flags |= FILE_PERSISTENT_ACLS;
3199 /* Capabilities are filled in at connection time through STATVFS call */
3200 additional_flags |= conn->fs_capabilities;
3201 additional_flags |= lp_parm_int(conn->params->service,
3202 "share", "fake_fscaps",
3205 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3206 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3207 additional_flags); /* FS ATTRIBUTES */
3209 SIVAL(pdata,4,255); /* Max filename component length */
3210 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3211 and will think we can't do long filenames */
3212 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3213 PTR_DIFF(end_data, pdata+12),
3216 data_len = 12 + len;
3217 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3218 /* the client only requested a portion of the
3220 data_len = max_data_bytes;
3221 status = STATUS_BUFFER_OVERFLOW;
3225 case SMB_QUERY_FS_LABEL_INFO:
3226 case SMB_FS_LABEL_INFORMATION:
3227 len = srvstr_push(pdata, flags2, pdata+4, vname,
3228 PTR_DIFF(end_data, pdata+4), 0);
3233 case SMB_QUERY_FS_VOLUME_INFO:
3234 case SMB_FS_VOLUME_INFORMATION:
3237 * Add volume serial number - hash of a combination of
3238 * the called hostname and the service name.
3240 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3241 (str_checksum(get_local_machine_name())<<16));
3243 /* Max label len is 32 characters. */
3244 len = srvstr_push(pdata, flags2, pdata+18, vname,
3245 PTR_DIFF(end_data, pdata+18),
3247 SIVAL(pdata,12,len);
3250 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3251 (int)strlen(vname),vname,
3252 lp_servicename(talloc_tos(), snum)));
3253 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3254 /* the client only requested a portion of the
3256 data_len = max_data_bytes;
3257 status = STATUS_BUFFER_OVERFLOW;
3261 case SMB_QUERY_FS_SIZE_INFO:
3262 case SMB_FS_SIZE_INFORMATION:
3264 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3266 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3267 return map_nt_error_from_unix(errno);
3269 block_size = lp_block_size(snum);
3270 if (bsize < block_size) {
3271 uint64_t factor = block_size/bsize;
3276 if (bsize > block_size) {
3277 uint64_t factor = bsize/block_size;
3282 bytes_per_sector = 512;
3283 sectors_per_unit = bsize/bytes_per_sector;
3284 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3285 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3286 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3287 SBIG_UINT(pdata,0,dsize);
3288 SBIG_UINT(pdata,8,dfree);
3289 SIVAL(pdata,16,sectors_per_unit);
3290 SIVAL(pdata,20,bytes_per_sector);
3294 case SMB_FS_FULL_SIZE_INFORMATION:
3296 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3298 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3299 return map_nt_error_from_unix(errno);
3301 block_size = lp_block_size(snum);
3302 if (bsize < block_size) {
3303 uint64_t factor = block_size/bsize;
3308 if (bsize > block_size) {
3309 uint64_t factor = bsize/block_size;
3314 bytes_per_sector = 512;
3315 sectors_per_unit = bsize/bytes_per_sector;
3316 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3317 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3318 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3319 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3320 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3321 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3322 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3323 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3327 case SMB_QUERY_FS_DEVICE_INFO:
3328 case SMB_FS_DEVICE_INFORMATION:
3330 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3332 if (!CAN_WRITE(conn)) {
3333 characteristics |= FILE_READ_ONLY_DEVICE;
3336 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3337 SIVAL(pdata,4,characteristics);
3341 #ifdef HAVE_SYS_QUOTAS
3342 case SMB_FS_QUOTA_INFORMATION:
3344 * what we have to send --metze:
3346 * Unknown1: 24 NULL bytes
3347 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3348 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3349 * Quota Flags: 2 byte :
3350 * Unknown3: 6 NULL bytes
3354 * details for Quota Flags:
3356 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3357 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3358 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3359 * 0x0001 Enable Quotas: enable quota for this fs
3363 /* we need to fake up a fsp here,
3364 * because its not send in this call
3367 SMB_NTQUOTA_STRUCT quotas;
3370 ZERO_STRUCT(quotas);
3373 fsp.fnum = FNUM_FIELD_INVALID;
3376 if (get_current_uid(conn) != 0) {
3377 DEBUG(0,("get_user_quota: access_denied "
3378 "service [%s] user [%s]\n",
3379 lp_servicename(talloc_tos(), SNUM(conn)),
3380 conn->session_info->unix_info->unix_name));
3381 return NT_STATUS_ACCESS_DENIED;
3384 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3385 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3386 return map_nt_error_from_unix(errno);
3391 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3392 lp_servicename(talloc_tos(), SNUM(conn))));
3394 /* Unknown1 24 NULL bytes*/
3395 SBIG_UINT(pdata,0,(uint64_t)0);
3396 SBIG_UINT(pdata,8,(uint64_t)0);
3397 SBIG_UINT(pdata,16,(uint64_t)0);
3399 /* Default Soft Quota 8 bytes */
3400 SBIG_UINT(pdata,24,quotas.softlim);
3402 /* Default Hard Quota 8 bytes */
3403 SBIG_UINT(pdata,32,quotas.hardlim);
3405 /* Quota flag 2 bytes */
3406 SSVAL(pdata,40,quotas.qflags);
3408 /* Unknown3 6 NULL bytes */
3414 #endif /* HAVE_SYS_QUOTAS */
3415 case SMB_FS_OBJECTID_INFORMATION:
3417 unsigned char objid[16];
3418 struct smb_extended_info extended_info;
3419 memcpy(pdata,create_volume_objectid(conn, objid),16);
3420 samba_extended_info_version (&extended_info);
3421 SIVAL(pdata,16,extended_info.samba_magic);
3422 SIVAL(pdata,20,extended_info.samba_version);
3423 SIVAL(pdata,24,extended_info.samba_subversion);
3424 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3425 memcpy(pdata+36,extended_info.samba_version_string,28);
3431 * Query the version and capabilities of the CIFS UNIX extensions
3435 case SMB_QUERY_CIFS_UNIX_INFO:
3437 bool large_write = lp_min_receive_file_size() &&
3438 !srv_is_signing_active(conn->sconn);
3439 bool large_read = !srv_is_signing_active(conn->sconn);
3440 int encrypt_caps = 0;
3442 if (!lp_unix_extensions()) {
3443 return NT_STATUS_INVALID_LEVEL;
3446 switch (conn->encrypt_level) {
3447 case SMB_SIGNING_OFF:
3450 case SMB_SIGNING_IF_REQUIRED:
3451 case SMB_SIGNING_DEFAULT:
3452 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3454 case SMB_SIGNING_REQUIRED:
3455 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3456 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3457 large_write = false;
3463 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3464 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3466 /* We have POSIX ACLs, pathname, encryption,
3467 * large read/write, and locking capability. */
3469 SBIG_UINT(pdata,4,((uint64_t)(
3470 CIFS_UNIX_POSIX_ACLS_CAP|
3471 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3472 CIFS_UNIX_FCNTL_LOCKS_CAP|
3473 CIFS_UNIX_EXTATTR_CAP|
3474 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3476 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3478 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3482 case SMB_QUERY_POSIX_FS_INFO:
3485 vfs_statvfs_struct svfs;
3487 if (!lp_unix_extensions()) {
3488 return NT_STATUS_INVALID_LEVEL;
3491 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3495 SIVAL(pdata,0,svfs.OptimalTransferSize);
3496 SIVAL(pdata,4,svfs.BlockSize);
3497 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3498 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3499 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3500 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3501 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3502 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3503 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3505 } else if (rc == EOPNOTSUPP) {
3506 return NT_STATUS_INVALID_LEVEL;
3507 #endif /* EOPNOTSUPP */
3509 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3510 return NT_STATUS_DOS(ERRSRV, ERRerror);
3515 case SMB_QUERY_POSIX_WHOAMI:
3521 if (!lp_unix_extensions()) {
3522 return NT_STATUS_INVALID_LEVEL;
3525 if (max_data_bytes < 40) {
3526 return NT_STATUS_BUFFER_TOO_SMALL;
3529 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3530 flags |= SMB_WHOAMI_GUEST;
3533 /* NOTE: 8 bytes for UID/GID, irrespective of native
3534 * platform size. This matches
3535 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3537 data_len = 4 /* flags */
3544 + 4 /* pad/reserved */
3545 + (conn->session_info->unix_token->ngroups * 8)
3547 + (conn->session_info->security_token->num_sids *
3551 SIVAL(pdata, 0, flags);
3552 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3554 (uint64_t)conn->session_info->unix_token->uid);
3555 SBIG_UINT(pdata, 16,
3556 (uint64_t)conn->session_info->unix_token->gid);
3559 if (data_len >= max_data_bytes) {
3560 /* Potential overflow, skip the GIDs and SIDs. */
3562 SIVAL(pdata, 24, 0); /* num_groups */
3563 SIVAL(pdata, 28, 0); /* num_sids */
3564 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3565 SIVAL(pdata, 36, 0); /* reserved */
3571 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3572 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3574 /* We walk the SID list twice, but this call is fairly
3575 * infrequent, and I don't expect that it's performance
3576 * sensitive -- jpeach
3578 for (i = 0, sid_bytes = 0;
3579 i < conn->session_info->security_token->num_sids; ++i) {
3580 sid_bytes += ndr_size_dom_sid(
3581 &conn->session_info->security_token->sids[i],
3585 /* SID list byte count */
3586 SIVAL(pdata, 32, sid_bytes);
3588 /* 4 bytes pad/reserved - must be zero */
3589 SIVAL(pdata, 36, 0);
3593 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3594 SBIG_UINT(pdata, data_len,
3595 (uint64_t)conn->session_info->unix_token->groups[i]);
3601 i < conn->session_info->security_token->num_sids; ++i) {
3602 int sid_len = ndr_size_dom_sid(
3603 &conn->session_info->security_token->sids[i],
3606 sid_linearize(pdata + data_len, sid_len,
3607 &conn->session_info->security_token->sids[i]);
3608 data_len += sid_len;
3614 case SMB_MAC_QUERY_FS_INFO:
3616 * Thursby MAC extension... ONLY on NTFS filesystems
3617 * once we do streams then we don't need this
3619 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3621 SIVAL(pdata,84,0x100); /* Don't support mac... */
3626 return NT_STATUS_INVALID_LEVEL;
3629 *ret_data_len = data_len;
3633 /****************************************************************************
3634 Reply to a TRANS2_QFSINFO (query filesystem info).
3635 ****************************************************************************/
3637 static void call_trans2qfsinfo(connection_struct *conn,
3638 struct smb_request *req,
3639 char **pparams, int total_params,
3640 char **ppdata, int total_data,
3641 unsigned int max_data_bytes)
3643 char *params = *pparams;
3644 uint16_t info_level;
3648 if (total_params < 2) {
3649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3653 info_level = SVAL(params,0);
3655 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3656 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3657 DEBUG(0,("call_trans2qfsinfo: encryption required "
3658 "and info level 0x%x sent.\n",
3659 (unsigned int)info_level));
3660 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3665 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3667 status = smbd_do_qfsinfo(conn, req,
3673 if (!NT_STATUS_IS_OK(status)) {
3674 reply_nterror(req, status);
3678 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
3681 DEBUG( 4, ( "%s info_level = %d\n",
3682 smb_fn_name(req->cmd), info_level) );
3687 /****************************************************************************
3688 Reply to a TRANS2_SETFSINFO (set filesystem info).
3689 ****************************************************************************/
3691 static void call_trans2setfsinfo(connection_struct *conn,
3692 struct smb_request *req,
3693 char **pparams, int total_params,
3694 char **ppdata, int total_data,
3695 unsigned int max_data_bytes)
3697 struct smbd_server_connection *sconn = req->sconn;
3698 char *pdata = *ppdata;
3699 char *params = *pparams;
3702 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3703 lp_servicename(talloc_tos(), SNUM(conn))));
3706 if (total_params < 4) {
3707 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3713 info_level = SVAL(params,2);
3716 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3717 info_level != SMB_SET_CIFS_UNIX_INFO) {
3718 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3719 "info level (0x%x) on IPC$.\n",
3720 (unsigned int)info_level));
3721 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3726 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3727 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3728 DEBUG(0,("call_trans2setfsinfo: encryption required "
3729 "and info level 0x%x sent.\n",
3730 (unsigned int)info_level));
3731 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3736 switch(info_level) {
3737 case SMB_SET_CIFS_UNIX_INFO:
3738 if (!lp_unix_extensions()) {
3739 DEBUG(2,("call_trans2setfsinfo: "
3740 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3741 "unix extensions off\n"));
3743 NT_STATUS_INVALID_LEVEL);
3747 /* There should be 12 bytes of capabilities set. */
3748 if (total_data < 12) {
3751 NT_STATUS_INVALID_PARAMETER);
3754 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3755 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3756 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3757 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3758 /* Just print these values for now. */
3759 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3760 "major = %u, minor = %u cap_low = 0x%x, "
3762 (unsigned int)sconn->
3763 smb1.unix_info.client_major,
3764 (unsigned int)sconn->
3765 smb1.unix_info.client_minor,
3766 (unsigned int)sconn->
3767 smb1.unix_info.client_cap_low,
3768 (unsigned int)sconn->
3769 smb1.unix_info.client_cap_high));
3771 /* Here is where we must switch to posix pathname processing... */
3772 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3773 lp_set_posix_pathnames();
3774 mangle_change_to_posix();
3777 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3778 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3779 /* Client that knows how to do posix locks,
3780 * but not posix open/mkdir operations. Set a
3781 * default type for read/write checks. */
3783 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3788 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3791 size_t param_len = 0;
3792 size_t data_len = total_data;
3794 if (!lp_unix_extensions()) {
3797 NT_STATUS_INVALID_LEVEL);
3801 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3804 NT_STATUS_NOT_SUPPORTED);
3808 if (req->sconn->smb1.echo_handler.trusted_fde) {
3809 DEBUG( 2,("call_trans2setfsinfo: "
3810 "request transport encryption disabled"
3811 "with 'fork echo handler = yes'\n"));
3814 NT_STATUS_NOT_SUPPORTED);
3818 DEBUG( 4,("call_trans2setfsinfo: "
3819 "request transport encryption.\n"));
3821 status = srv_request_encryption_setup(conn,
3822 (unsigned char **)ppdata,
3824 (unsigned char **)pparams,
3827 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3828 !NT_STATUS_IS_OK(status)) {
3829 reply_nterror(req, status);
3833 send_trans2_replies(conn, req,
3841 if (NT_STATUS_IS_OK(status)) {
3842 /* Server-side transport
3843 * encryption is now *on*. */
3844 status = srv_encryption_start(conn);
3845 if (!NT_STATUS_IS_OK(status)) {
3846 char *reason = talloc_asprintf(talloc_tos(),
3847 "Failure in setting "
3848 "up encrypted transport: %s",
3850 exit_server_cleanly(reason);
3856 case SMB_FS_QUOTA_INFORMATION:
3858 files_struct *fsp = NULL;
3859 SMB_NTQUOTA_STRUCT quotas;
3861 ZERO_STRUCT(quotas);
3864 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3865 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3866 lp_servicename(talloc_tos(), SNUM(conn)),
3867 conn->session_info->unix_info->unix_name));
3868 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3872 /* note: normaly there're 48 bytes,
3873 * but we didn't use the last 6 bytes for now
3876 fsp = file_fsp(req, SVAL(params,0));
3878 if (!check_fsp_ntquota_handle(conn, req,
3880 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3882 req, NT_STATUS_INVALID_HANDLE);
3886 if (total_data < 42) {
3887 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3891 NT_STATUS_INVALID_PARAMETER);
3895 /* unknown_1 24 NULL bytes in pdata*/
3897 /* the soft quotas 8 bytes (uint64_t)*/
3898 quotas.softlim = BVAL(pdata,24);
3900 /* the hard quotas 8 bytes (uint64_t)*/
3901 quotas.hardlim = BVAL(pdata,32);
3903 /* quota_flags 2 bytes **/
3904 quotas.qflags = SVAL(pdata,40);
3906 /* unknown_2 6 NULL bytes follow*/
3908 /* now set the quotas */
3909 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3910 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3911 reply_nterror(req, map_nt_error_from_unix(errno));
3918 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3920 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3926 * sending this reply works fine,
3927 * but I'm not sure it's the same
3928 * like windows do...
3931 reply_outbuf(req, 10, 0);
3934 #if defined(HAVE_POSIX_ACLS)
3935 /****************************************************************************
3936 Utility function to count the number of entries in a POSIX acl.
3937 ****************************************************************************/
3939 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3941 unsigned int ace_count = 0;
3942 int entry_id = SMB_ACL_FIRST_ENTRY;
3943 SMB_ACL_ENTRY_T entry;
3945 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3947 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3948 entry_id = SMB_ACL_NEXT_ENTRY;
3955 /****************************************************************************
3956 Utility function to marshall a POSIX acl into wire format.
3957 ****************************************************************************/
3959 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3961 int entry_id = SMB_ACL_FIRST_ENTRY;
3962 SMB_ACL_ENTRY_T entry;
3964 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3965 SMB_ACL_TAG_T tagtype;
3966 SMB_ACL_PERMSET_T permset;
3967 unsigned char perms = 0;
3968 unsigned int own_grp;
3971 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3972 entry_id = SMB_ACL_NEXT_ENTRY;
3975 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3976 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3980 if (sys_acl_get_permset(entry, &permset) == -1) {
3981 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3985 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3986 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3987 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3989 SCVAL(pdata,1,perms);
3992 case SMB_ACL_USER_OBJ:
3993 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3994 own_grp = (unsigned int)pst->st_ex_uid;
3995 SIVAL(pdata,2,own_grp);
4000 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4002 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4005 own_grp = (unsigned int)*puid;
4006 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4007 SIVAL(pdata,2,own_grp);
4011 case SMB_ACL_GROUP_OBJ:
4012 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4013 own_grp = (unsigned int)pst->st_ex_gid;
4014 SIVAL(pdata,2,own_grp);
4019 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4021 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4024 own_grp = (unsigned int)*pgid;
4025 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4026 SIVAL(pdata,2,own_grp);
4031 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4032 SIVAL(pdata,2,0xFFFFFFFF);
4033 SIVAL(pdata,6,0xFFFFFFFF);
4036 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4037 SIVAL(pdata,2,0xFFFFFFFF);
4038 SIVAL(pdata,6,0xFFFFFFFF);
4041 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4044 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4051 /****************************************************************************
4052 Store the FILE_UNIX_BASIC info.
4053 ****************************************************************************/
4055 static char *store_file_unix_basic(connection_struct *conn,
4058 const SMB_STRUCT_STAT *psbuf)
4060 uint64_t file_index = get_FileIndex(conn, psbuf);
4063 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4064 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4066 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4069 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4072 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4073 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4074 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4077 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4081 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4085 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4088 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4089 devno = psbuf->st_ex_rdev;
4091 devno = psbuf->st_ex_dev;
4094 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4098 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4102 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4105 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4109 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4116 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4117 * the chflags(2) (or equivalent) flags.
4119 * XXX: this really should be behind the VFS interface. To do this, we would
4120 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4121 * Each VFS module could then implement its own mapping as appropriate for the
4122 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4124 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4128 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4132 { UF_IMMUTABLE, EXT_IMMUTABLE },
4136 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4140 { UF_HIDDEN, EXT_HIDDEN },
4143 /* Do not remove. We need to guarantee that this array has at least one
4144 * entry to build on HP-UX.
4150 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4151 uint32 *smb_fflags, uint32 *smb_fmask)
4155 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4156 *smb_fmask |= info2_flags_map[i].smb_fflag;
4157 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4158 *smb_fflags |= info2_flags_map[i].smb_fflag;
4163 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4164 const uint32 smb_fflags,
4165 const uint32 smb_fmask,
4168 uint32 max_fmask = 0;
4171 *stat_fflags = psbuf->st_ex_flags;
4173 /* For each flags requested in smb_fmask, check the state of the
4174 * corresponding flag in smb_fflags and set or clear the matching
4178 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4179 max_fmask |= info2_flags_map[i].smb_fflag;
4180 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4181 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4182 *stat_fflags |= info2_flags_map[i].stat_fflag;
4184 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4189 /* If smb_fmask is asking to set any bits that are not supported by
4190 * our flag mappings, we should fail.
4192 if ((smb_fmask & max_fmask) != smb_fmask) {
4200 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4201 * of file flags and birth (create) time.
4203 static char *store_file_unix_basic_info2(connection_struct *conn,
4206 const SMB_STRUCT_STAT *psbuf)
4208 uint32 file_flags = 0;
4209 uint32 flags_mask = 0;
4211 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4213 /* Create (birth) time 64 bit */
4214 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4217 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4218 SIVAL(pdata, 0, file_flags); /* flags */
4219 SIVAL(pdata, 4, flags_mask); /* mask */
4225 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4226 const struct stream_struct *streams,
4228 unsigned int max_data_bytes,
4229 unsigned int *data_size)
4232 unsigned int ofs = 0;
4234 for (i = 0; i < num_streams; i++) {
4235 unsigned int next_offset;
4237 smb_ucs2_t *namebuf;
4239 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4240 streams[i].name, &namelen) ||
4243 return NT_STATUS_INVALID_PARAMETER;
4247 * name_buf is now null-terminated, we need to marshall as not
4254 * We cannot overflow ...
4256 if ((ofs + 24 + namelen) > max_data_bytes) {
4257 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4259 TALLOC_FREE(namebuf);
4260 return STATUS_BUFFER_OVERFLOW;
4263 SIVAL(data, ofs+4, namelen);
4264 SOFF_T(data, ofs+8, streams[i].size);
4265 SOFF_T(data, ofs+16, streams[i].alloc_size);
4266 memcpy(data+ofs+24, namebuf, namelen);
4267 TALLOC_FREE(namebuf);
4269 next_offset = ofs + 24 + namelen;
4271 if (i == num_streams-1) {
4272 SIVAL(data, ofs, 0);
4275 unsigned int align = ndr_align_size(next_offset, 8);
4277 if ((next_offset + align) > max_data_bytes) {
4278 DEBUG(10, ("refusing to overflow align "
4279 "reply at stream %u\n",
4281 TALLOC_FREE(namebuf);
4282 return STATUS_BUFFER_OVERFLOW;
4285 memset(data+next_offset, 0, align);
4286 next_offset += align;
4288 SIVAL(data, ofs, next_offset - ofs);
4295 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4299 return NT_STATUS_OK;
4302 /****************************************************************************
4303 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4304 ****************************************************************************/
4306 static void call_trans2qpipeinfo(connection_struct *conn,
4307 struct smb_request *req,
4308 unsigned int tran_call,
4309 char **pparams, int total_params,
4310 char **ppdata, int total_data,
4311 unsigned int max_data_bytes)
4313 char *params = *pparams;
4314 char *pdata = *ppdata;
4315 unsigned int data_size = 0;
4316 unsigned int param_size = 2;
4321 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4325 if (total_params < 4) {
4326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4330 fsp = file_fsp(req, SVAL(params,0));
4331 if (!fsp_is_np(fsp)) {
4332 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4336 info_level = SVAL(params,2);
4338 *pparams = (char *)SMB_REALLOC(*pparams,2);
4339 if (*pparams == NULL) {
4340 reply_nterror(req, NT_STATUS_NO_MEMORY);
4345 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4349 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4350 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4351 if (*ppdata == NULL ) {
4352 reply_nterror(req, NT_STATUS_NO_MEMORY);
4357 switch (info_level) {
4358 case SMB_FILE_STANDARD_INFORMATION:
4360 SOFF_T(pdata,0,4096LL);
4367 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4371 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4377 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4378 TALLOC_CTX *mem_ctx,
4379 uint16_t info_level,
4381 struct smb_filename *smb_fname,
4382 bool delete_pending,
4383 struct timespec write_time_ts,
4384 struct ea_list *ea_list,
4385 int lock_data_count,
4388 unsigned int max_data_bytes,
4390 unsigned int *pdata_size)
4392 char *pdata = *ppdata;
4393 char *dstart, *dend;
4394 unsigned int data_size;
4395 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4396 time_t create_time, mtime, atime, c_time;
4397 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4404 uint64_t file_size = 0;
4406 uint64_t allocation_size = 0;
4407 uint64_t file_index = 0;
4408 uint32_t access_mask = 0;
4410 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4411 return NT_STATUS_INVALID_LEVEL;
4414 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4415 smb_fname_str_dbg(smb_fname),
4417 info_level, max_data_bytes));
4419 mode = dos_mode(conn, smb_fname);
4420 nlink = psbuf->st_ex_nlink;
4422 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4426 if ((nlink > 0) && delete_pending) {
4430 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4431 return NT_STATUS_INVALID_PARAMETER;
4434 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4435 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4436 if (*ppdata == NULL) {
4437 return NT_STATUS_NO_MEMORY;
4441 dend = dstart + data_size - 1;
4443 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4444 update_stat_ex_mtime(psbuf, write_time_ts);
4447 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4448 mtime_ts = psbuf->st_ex_mtime;
4449 atime_ts = psbuf->st_ex_atime;
4450 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4452 if (lp_dos_filetime_resolution(SNUM(conn))) {
4453 dos_filetime_timespec(&create_time_ts);
4454 dos_filetime_timespec(&mtime_ts);
4455 dos_filetime_timespec(&atime_ts);
4456 dos_filetime_timespec(&ctime_ts);
4459 create_time = convert_timespec_to_time_t(create_time_ts);
4460 mtime = convert_timespec_to_time_t(mtime_ts);
4461 atime = convert_timespec_to_time_t(atime_ts);
4462 c_time = convert_timespec_to_time_t(ctime_ts);
4464 p = strrchr_m(smb_fname->base_name,'/');
4466 base_name = smb_fname->base_name;
4470 /* NT expects the name to be in an exact form of the *full*
4471 filename. See the trans2 torture test */
4472 if (ISDOT(base_name)) {
4473 dos_fname = talloc_strdup(mem_ctx, "\\");
4475 return NT_STATUS_NO_MEMORY;
4478 dos_fname = talloc_asprintf(mem_ctx,
4480 smb_fname->base_name);
4482 return NT_STATUS_NO_MEMORY;
4484 if (is_ntfs_stream_smb_fname(smb_fname)) {
4485 dos_fname = talloc_asprintf(dos_fname, "%s",
4486 smb_fname->stream_name);
4488 return NT_STATUS_NO_MEMORY;
4492 string_replace(dos_fname, '/', '\\');
4495 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4498 /* Do we have this path open ? */
4500 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4501 fsp1 = file_find_di_first(conn->sconn, fileid);
4502 if (fsp1 && fsp1->initial_allocation_size) {
4503 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4507 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4508 file_size = get_file_size_stat(psbuf);
4512 pos = fsp->fh->position_information;
4516 access_mask = fsp->access_mask;
4518 /* GENERIC_EXECUTE mapping from Windows */
4519 access_mask = 0x12019F;
4522 /* This should be an index number - looks like
4525 I think this causes us to fail the IFSKIT
4526 BasicFileInformationTest. -tpot */
4527 file_index = get_FileIndex(conn, psbuf);
4529 switch (info_level) {
4530 case SMB_INFO_STANDARD:
4531 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4533 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4534 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4535 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4536 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4537 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4538 SSVAL(pdata,l1_attrFile,mode);
4541 case SMB_INFO_QUERY_EA_SIZE:
4543 unsigned int ea_size =
4544 estimate_ea_size(conn, fsp,
4546 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4548 srv_put_dos_date2(pdata,0,create_time);
4549 srv_put_dos_date2(pdata,4,atime);
4550 srv_put_dos_date2(pdata,8,mtime); /* write time */
4551 SIVAL(pdata,12,(uint32)file_size);
4552 SIVAL(pdata,16,(uint32)allocation_size);
4553 SSVAL(pdata,20,mode);
4554 SIVAL(pdata,22,ea_size);
4558 case SMB_INFO_IS_NAME_VALID:
4559 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4561 /* os/2 needs this ? really ?*/
4562 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4564 /* This is only reached for qpathinfo */
4568 case SMB_INFO_QUERY_EAS_FROM_LIST:
4570 size_t total_ea_len = 0;
4571 struct ea_list *ea_file_list = NULL;
4572 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4575 get_ea_list_from_file(mem_ctx, conn, fsp,
4577 &total_ea_len, &ea_file_list);
4578 if (!NT_STATUS_IS_OK(status)) {
4582 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4584 if (!ea_list || (total_ea_len > data_size)) {
4586 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4590 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4594 case SMB_INFO_QUERY_ALL_EAS:
4596 /* We have data_size bytes to put EA's into. */
4597 size_t total_ea_len = 0;
4598 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4600 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4602 &total_ea_len, &ea_list);
4603 if (!NT_STATUS_IS_OK(status)) {
4607 if (!ea_list || (total_ea_len > data_size)) {
4609 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4613 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4617 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4619 /* This is FileFullEaInformation - 0xF which maps to
4620 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4622 /* We have data_size bytes to put EA's into. */
4623 size_t total_ea_len = 0;
4624 struct ea_list *ea_file_list = NULL;
4626 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4628 /*TODO: add filtering and index handling */
4631 get_ea_list_from_file(mem_ctx, conn, fsp,
4633 &total_ea_len, &ea_file_list);
4634 if (!NT_STATUS_IS_OK(status)) {
4637 if (!ea_file_list) {
4638 return NT_STATUS_NO_EAS_ON_FILE;
4641 status = fill_ea_chained_buffer(mem_ctx,
4645 conn, ea_file_list);
4646 if (!NT_STATUS_IS_OK(status)) {
4652 case SMB_FILE_BASIC_INFORMATION:
4653 case SMB_QUERY_FILE_BASIC_INFO:
4655 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4656 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4657 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4659 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4663 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4664 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4665 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4666 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4667 SIVAL(pdata,32,mode);
4669 DEBUG(5,("SMB_QFBI - "));
4670 DEBUG(5,("create: %s ", ctime(&create_time)));
4671 DEBUG(5,("access: %s ", ctime(&atime)));
4672 DEBUG(5,("write: %s ", ctime(&mtime)));
4673 DEBUG(5,("change: %s ", ctime(&c_time)));
4674 DEBUG(5,("mode: %x\n", mode));
4677 case SMB_FILE_STANDARD_INFORMATION:
4678 case SMB_QUERY_FILE_STANDARD_INFO:
4680 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4682 SOFF_T(pdata,0,allocation_size);
4683 SOFF_T(pdata,8,file_size);
4684 SIVAL(pdata,16,nlink);
4685 SCVAL(pdata,20,delete_pending?1:0);
4686 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4687 SSVAL(pdata,22,0); /* Padding. */
4690 case SMB_FILE_EA_INFORMATION:
4691 case SMB_QUERY_FILE_EA_INFO:
4693 unsigned int ea_size =
4694 estimate_ea_size(conn, fsp, smb_fname);
4695 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4697 SIVAL(pdata,0,ea_size);
4701 /* Get the 8.3 name - used if NT SMB was negotiated. */
4702 case SMB_QUERY_FILE_ALT_NAME_INFO:
4703 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4706 char mangled_name[13];
4707 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4708 if (!name_to_8_3(base_name,mangled_name,
4709 True,conn->params)) {
4710 return NT_STATUS_NO_MEMORY;
4712 len = srvstr_push(dstart, flags2,
4713 pdata+4, mangled_name,
4714 PTR_DIFF(dend, pdata+4),
4716 data_size = 4 + len;
4721 case SMB_QUERY_FILE_NAME_INFO:
4725 this must be *exactly* right for ACLs on mapped drives to work
4727 len = srvstr_push(dstart, flags2,
4729 PTR_DIFF(dend, pdata+4),
4731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4732 data_size = 4 + len;
4737 case SMB_FILE_ALLOCATION_INFORMATION:
4738 case SMB_QUERY_FILE_ALLOCATION_INFO:
4739 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4741 SOFF_T(pdata,0,allocation_size);
4744 case SMB_FILE_END_OF_FILE_INFORMATION:
4745 case SMB_QUERY_FILE_END_OF_FILEINFO:
4746 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4748 SOFF_T(pdata,0,file_size);
4751 case SMB_QUERY_FILE_ALL_INFO:
4752 case SMB_FILE_ALL_INFORMATION:
4755 unsigned int ea_size =
4756 estimate_ea_size(conn, fsp, smb_fname);
4757 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4758 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4759 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4760 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4761 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4762 SIVAL(pdata,32,mode);
4763 SIVAL(pdata,36,0); /* padding. */
4765 SOFF_T(pdata,0,allocation_size);
4766 SOFF_T(pdata,8,file_size);
4767 SIVAL(pdata,16,nlink);
4768 SCVAL(pdata,20,delete_pending);
4769 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4772 SIVAL(pdata,0,ea_size);
4773 pdata += 4; /* EA info */
4774 len = srvstr_push(dstart, flags2,
4776 PTR_DIFF(dend, pdata+4),
4780 data_size = PTR_DIFF(pdata,(*ppdata));
4784 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4787 unsigned int ea_size =
4788 estimate_ea_size(conn, fsp, smb_fname);
4789 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4790 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4791 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4792 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4793 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4794 SIVAL(pdata, 0x20, mode);
4795 SIVAL(pdata, 0x24, 0); /* padding. */
4796 SBVAL(pdata, 0x28, allocation_size);
4797 SBVAL(pdata, 0x30, file_size);
4798 SIVAL(pdata, 0x38, nlink);
4799 SCVAL(pdata, 0x3C, delete_pending);
4800 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4801 SSVAL(pdata, 0x3E, 0); /* padding */
4802 SBVAL(pdata, 0x40, file_index);
4803 SIVAL(pdata, 0x48, ea_size);
4804 SIVAL(pdata, 0x4C, access_mask);
4805 SBVAL(pdata, 0x50, pos);
4806 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4807 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4811 len = srvstr_push(dstart, flags2,
4813 PTR_DIFF(dend, pdata+4),
4817 data_size = PTR_DIFF(pdata,(*ppdata));
4820 case SMB_FILE_INTERNAL_INFORMATION:
4822 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4823 SBVAL(pdata, 0, file_index);
4827 case SMB_FILE_ACCESS_INFORMATION:
4828 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4829 SIVAL(pdata, 0, access_mask);
4833 case SMB_FILE_NAME_INFORMATION:
4834 /* Pathname with leading '\'. */
4837 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4838 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4839 SIVAL(pdata,0,byte_len);
4840 data_size = 4 + byte_len;
4844 case SMB_FILE_DISPOSITION_INFORMATION:
4845 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4847 SCVAL(pdata,0,delete_pending);
4850 case SMB_FILE_POSITION_INFORMATION:
4851 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4853 SOFF_T(pdata,0,pos);
4856 case SMB_FILE_MODE_INFORMATION:
4857 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4858 SIVAL(pdata,0,mode);
4862 case SMB_FILE_ALIGNMENT_INFORMATION:
4863 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4864 SIVAL(pdata,0,0); /* No alignment needed. */
4869 * NT4 server just returns "invalid query" to this - if we try
4870 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4873 /* The first statement above is false - verified using Thursby
4874 * client against NT4 -- gcolley.
4876 case SMB_QUERY_FILE_STREAM_INFO:
4877 case SMB_FILE_STREAM_INFORMATION: {
4878 unsigned int num_streams = 0;
4879 struct stream_struct *streams = NULL;
4881 DEBUG(10,("smbd_do_qfilepathinfo: "
4882 "SMB_FILE_STREAM_INFORMATION\n"));
4884 if (is_ntfs_stream_smb_fname(smb_fname)) {
4885 return NT_STATUS_INVALID_PARAMETER;
4888 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4889 talloc_tos(), &num_streams, &streams);
4891 if (!NT_STATUS_IS_OK(status)) {
4892 DEBUG(10, ("could not get stream info: %s\n",
4893 nt_errstr(status)));
4897 status = marshall_stream_info(num_streams, streams,
4898 pdata, max_data_bytes,
4901 if (!NT_STATUS_IS_OK(status)) {
4902 DEBUG(10, ("marshall_stream_info failed: %s\n",
4903 nt_errstr(status)));
4904 TALLOC_FREE(streams);
4908 TALLOC_FREE(streams);
4912 case SMB_QUERY_COMPRESSION_INFO:
4913 case SMB_FILE_COMPRESSION_INFORMATION:
4914 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4915 SOFF_T(pdata,0,file_size);
4916 SIVAL(pdata,8,0); /* ??? */
4917 SIVAL(pdata,12,0); /* ??? */
4921 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4922 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4923 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4924 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4925 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4926 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4927 SOFF_T(pdata,32,allocation_size);
4928 SOFF_T(pdata,40,file_size);
4929 SIVAL(pdata,48,mode);
4930 SIVAL(pdata,52,0); /* ??? */
4934 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4935 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4936 SIVAL(pdata,0,mode);
4942 * CIFS UNIX Extensions.
4945 case SMB_QUERY_FILE_UNIX_BASIC:
4947 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4948 data_size = PTR_DIFF(pdata,(*ppdata));
4950 DEBUG(4,("smbd_do_qfilepathinfo: "
4951 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4952 dump_data(4, (uint8_t *)(*ppdata), data_size);
4956 case SMB_QUERY_FILE_UNIX_INFO2:
4958 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4959 data_size = PTR_DIFF(pdata,(*ppdata));
4963 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4965 for (i=0; i<100; i++)
4966 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4972 case SMB_QUERY_FILE_UNIX_LINK:
4975 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4978 return NT_STATUS_NO_MEMORY;
4981 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4983 if(!S_ISLNK(psbuf->st_ex_mode)) {
4984 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4987 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4989 len = SMB_VFS_READLINK(conn,
4990 smb_fname->base_name,
4993 return map_nt_error_from_unix(errno);
4996 len = srvstr_push(dstart, flags2,
4998 PTR_DIFF(dend, pdata),
5001 data_size = PTR_DIFF(pdata,(*ppdata));
5006 #if defined(HAVE_POSIX_ACLS)
5007 case SMB_QUERY_POSIX_ACL:
5009 SMB_ACL_T file_acl = NULL;
5010 SMB_ACL_T def_acl = NULL;
5011 uint16 num_file_acls = 0;
5012 uint16 num_def_acls = 0;
5014 if (fsp && fsp->fh->fd != -1) {
5015 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5019 SMB_VFS_SYS_ACL_GET_FILE(conn,
5020 smb_fname->base_name,
5021 SMB_ACL_TYPE_ACCESS,
5025 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5026 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5027 "not implemented on "
5028 "filesystem containing %s\n",
5029 smb_fname->base_name));
5030 return NT_STATUS_NOT_IMPLEMENTED;
5033 if (S_ISDIR(psbuf->st_ex_mode)) {
5034 if (fsp && fsp->is_directory) {
5036 SMB_VFS_SYS_ACL_GET_FILE(
5038 fsp->fsp_name->base_name,
5039 SMB_ACL_TYPE_DEFAULT,
5043 SMB_VFS_SYS_ACL_GET_FILE(
5045 smb_fname->base_name,
5046 SMB_ACL_TYPE_DEFAULT,
5049 def_acl = free_empty_sys_acl(conn, def_acl);
5052 num_file_acls = count_acl_entries(conn, file_acl);
5053 num_def_acls = count_acl_entries(conn, def_acl);
5055 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5056 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5058 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5059 SMB_POSIX_ACL_HEADER_SIZE) ));
5061 TALLOC_FREE(file_acl);
5064 TALLOC_FREE(def_acl);
5066 return NT_STATUS_BUFFER_TOO_SMALL;
5069 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5070 SSVAL(pdata,2,num_file_acls);
5071 SSVAL(pdata,4,num_def_acls);
5072 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5074 TALLOC_FREE(file_acl);
5077 TALLOC_FREE(def_acl);
5079 return NT_STATUS_INTERNAL_ERROR;
5081 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5083 TALLOC_FREE(file_acl);
5086 TALLOC_FREE(def_acl);
5088 return NT_STATUS_INTERNAL_ERROR;
5092 TALLOC_FREE(file_acl);
5095 TALLOC_FREE(def_acl);
5097 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5103 case SMB_QUERY_POSIX_LOCK:
5108 enum brl_type lock_type;
5110 /* We need an open file with a real fd for this. */
5111 if (!fsp || fsp->fh->fd == -1) {
5112 return NT_STATUS_INVALID_LEVEL;
5115 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5116 return NT_STATUS_INVALID_PARAMETER;
5119 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5120 case POSIX_LOCK_TYPE_READ:
5121 lock_type = READ_LOCK;
5123 case POSIX_LOCK_TYPE_WRITE:
5124 lock_type = WRITE_LOCK;
5126 case POSIX_LOCK_TYPE_UNLOCK:
5128 /* There's no point in asking for an unlock... */
5129 return NT_STATUS_INVALID_PARAMETER;
5132 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5133 #if defined(HAVE_LONGLONG)
5134 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5135 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5136 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5137 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5138 #else /* HAVE_LONGLONG */
5139 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5140 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5141 #endif /* HAVE_LONGLONG */
5143 status = query_lock(fsp,
5150 if (ERROR_WAS_LOCK_DENIED(status)) {
5151 /* Here we need to report who has it locked... */
5152 data_size = POSIX_LOCK_DATA_SIZE;
5154 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5155 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5156 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5157 #if defined(HAVE_LONGLONG)
5158 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5159 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5160 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5161 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5162 #else /* HAVE_LONGLONG */
5163 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5164 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5165 #endif /* HAVE_LONGLONG */
5167 } else if (NT_STATUS_IS_OK(status)) {
5168 /* For success we just return a copy of what we sent
5169 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5170 data_size = POSIX_LOCK_DATA_SIZE;
5171 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5172 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5180 return NT_STATUS_INVALID_LEVEL;
5183 *pdata_size = data_size;
5184 return NT_STATUS_OK;
5187 /****************************************************************************
5188 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5189 file name or file id).
5190 ****************************************************************************/
5192 static void call_trans2qfilepathinfo(connection_struct *conn,
5193 struct smb_request *req,
5194 unsigned int tran_call,
5195 char **pparams, int total_params,
5196 char **ppdata, int total_data,
5197 unsigned int max_data_bytes)
5199 char *params = *pparams;
5200 char *pdata = *ppdata;
5202 unsigned int data_size = 0;
5203 unsigned int param_size = 2;
5204 struct smb_filename *smb_fname = NULL;
5205 bool delete_pending = False;
5206 struct timespec write_time_ts;
5207 files_struct *fsp = NULL;
5208 struct file_id fileid;
5209 struct ea_list *ea_list = NULL;
5210 int lock_data_count = 0;
5211 char *lock_data = NULL;
5212 NTSTATUS status = NT_STATUS_OK;
5215 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5219 ZERO_STRUCT(write_time_ts);
5221 if (tran_call == TRANSACT2_QFILEINFO) {
5222 if (total_params < 4) {
5223 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5228 call_trans2qpipeinfo(conn, req, tran_call,
5229 pparams, total_params,
5235 fsp = file_fsp(req, SVAL(params,0));
5236 info_level = SVAL(params,2);
5238 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5240 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5241 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5245 /* Initial check for valid fsp ptr. */
5246 if (!check_fsp_open(conn, req, fsp)) {
5250 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5251 if (smb_fname == NULL) {
5252 reply_nterror(req, NT_STATUS_NO_MEMORY);
5256 if(fsp->fake_file_handle) {
5258 * This is actually for the QUOTA_FAKE_FILE --metze
5261 /* We know this name is ok, it's already passed the checks. */
5263 } else if(fsp->fh->fd == -1) {
5265 * This is actually a QFILEINFO on a directory
5266 * handle (returned from an NT SMB). NT5.0 seems
5267 * to do this call. JRA.
5270 if (INFO_LEVEL_IS_UNIX(info_level)) {
5271 /* Always do lstat for UNIX calls. */
5272 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5273 DEBUG(3,("call_trans2qfilepathinfo: "
5274 "SMB_VFS_LSTAT of %s failed "
5276 smb_fname_str_dbg(smb_fname),
5279 map_nt_error_from_unix(errno));
5282 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5283 DEBUG(3,("call_trans2qfilepathinfo: "
5284 "SMB_VFS_STAT of %s failed (%s)\n",
5285 smb_fname_str_dbg(smb_fname),
5288 map_nt_error_from_unix(errno));
5292 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5293 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5296 * Original code - this is an open file.
5298 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5299 DEBUG(3, ("fstat of %s failed (%s)\n",
5300 fsp_fnum_dbg(fsp), strerror(errno)));
5302 map_nt_error_from_unix(errno));
5305 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5306 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5312 uint32_t ucf_flags = 0;
5315 if (total_params < 7) {
5316 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5320 info_level = SVAL(params,0);
5322 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5324 if (INFO_LEVEL_IS_UNIX(info_level)) {
5325 if (!lp_unix_extensions()) {
5326 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5329 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5330 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5331 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5332 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5336 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5338 STR_TERMINATE, &status);
5339 if (!NT_STATUS_IS_OK(status)) {
5340 reply_nterror(req, status);
5344 status = filename_convert(req,
5346 req->flags2 & FLAGS2_DFS_PATHNAMES,
5351 if (!NT_STATUS_IS_OK(status)) {
5352 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5353 reply_botherror(req,
5354 NT_STATUS_PATH_NOT_COVERED,
5355 ERRSRV, ERRbadpath);
5358 reply_nterror(req, status);
5362 /* If this is a stream, check if there is a delete_pending. */
5363 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5364 && is_ntfs_stream_smb_fname(smb_fname)) {
5365 struct smb_filename *smb_fname_base;
5367 /* Create an smb_filename with stream_name == NULL. */
5368 smb_fname_base = synthetic_smb_fname(
5369 talloc_tos(), smb_fname->base_name,
5371 if (smb_fname_base == NULL) {
5372 reply_nterror(req, NT_STATUS_NO_MEMORY);
5376 if (INFO_LEVEL_IS_UNIX(info_level)) {
5377 /* Always do lstat for UNIX calls. */
5378 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5379 DEBUG(3,("call_trans2qfilepathinfo: "
5380 "SMB_VFS_LSTAT of %s failed "
5382 smb_fname_str_dbg(smb_fname_base),
5384 TALLOC_FREE(smb_fname_base);
5386 map_nt_error_from_unix(errno));
5390 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5391 DEBUG(3,("call_trans2qfilepathinfo: "
5392 "fileinfo of %s failed "
5394 smb_fname_str_dbg(smb_fname_base),
5396 TALLOC_FREE(smb_fname_base);
5398 map_nt_error_from_unix(errno));
5403 status = file_name_hash(conn,
5404 smb_fname_str_dbg(smb_fname_base),
5406 if (!NT_STATUS_IS_OK(status)) {
5407 TALLOC_FREE(smb_fname_base);
5408 reply_nterror(req, status);
5412 fileid = vfs_file_id_from_sbuf(conn,
5413 &smb_fname_base->st);
5414 TALLOC_FREE(smb_fname_base);
5415 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5416 if (delete_pending) {
5417 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5422 if (INFO_LEVEL_IS_UNIX(info_level)) {
5423 /* Always do lstat for UNIX calls. */
5424 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5425 DEBUG(3,("call_trans2qfilepathinfo: "
5426 "SMB_VFS_LSTAT of %s failed (%s)\n",
5427 smb_fname_str_dbg(smb_fname),
5430 map_nt_error_from_unix(errno));
5435 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5436 DEBUG(3,("call_trans2qfilepathinfo: "
5437 "SMB_VFS_STAT of %s failed (%s)\n",
5438 smb_fname_str_dbg(smb_fname),
5441 map_nt_error_from_unix(errno));
5446 status = file_name_hash(conn,
5447 smb_fname_str_dbg(smb_fname),
5449 if (!NT_STATUS_IS_OK(status)) {
5450 reply_nterror(req, status);
5454 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5455 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5456 if (delete_pending) {
5457 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5462 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5463 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5465 info_level,tran_call,total_data));
5467 /* Pull out any data sent here before we realloc. */
5468 switch (info_level) {
5469 case SMB_INFO_QUERY_EAS_FROM_LIST:
5471 /* Pull any EA list from the data portion. */
5474 if (total_data < 4) {
5476 req, NT_STATUS_INVALID_PARAMETER);
5479 ea_size = IVAL(pdata,0);
5481 if (total_data > 0 && ea_size != total_data) {
5482 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5483 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5485 req, NT_STATUS_INVALID_PARAMETER);
5489 if (!lp_ea_support(SNUM(conn))) {
5490 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5494 /* Pull out the list of names. */
5495 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5498 req, NT_STATUS_INVALID_PARAMETER);
5504 case SMB_QUERY_POSIX_LOCK:
5506 if (fsp == NULL || fsp->fh->fd == -1) {
5507 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5511 if (total_data != POSIX_LOCK_DATA_SIZE) {
5513 req, NT_STATUS_INVALID_PARAMETER);
5517 /* Copy the lock range data. */
5518 lock_data = (char *)talloc_memdup(
5519 req, pdata, total_data);
5521 reply_nterror(req, NT_STATUS_NO_MEMORY);
5524 lock_data_count = total_data;
5530 *pparams = (char *)SMB_REALLOC(*pparams,2);
5531 if (*pparams == NULL) {
5532 reply_nterror(req, NT_STATUS_NO_MEMORY);
5539 * draft-leach-cifs-v1-spec-02.txt
5540 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5543 * The requested information is placed in the Data portion of the
5544 * transaction response. For the information levels greater than 0x100,
5545 * the transaction response has 1 parameter word which should be
5546 * ignored by the client.
5548 * However Windows only follows this rule for the IS_NAME_VALID call.
5550 switch (info_level) {
5551 case SMB_INFO_IS_NAME_VALID:
5556 if ((info_level & 0xFF00) == 0xFF00) {
5558 * We use levels that start with 0xFF00
5559 * internally to represent SMB2 specific levels
5561 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5565 status = smbd_do_qfilepathinfo(conn, req, info_level,
5567 delete_pending, write_time_ts,
5569 lock_data_count, lock_data,
5570 req->flags2, max_data_bytes,
5571 ppdata, &data_size);
5572 if (!NT_STATUS_IS_OK(status)) {
5573 reply_nterror(req, status);
5577 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5583 /****************************************************************************
5584 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5586 ****************************************************************************/
5588 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5589 connection_struct *conn,
5590 struct smb_request *req,
5591 bool overwrite_if_exists,
5592 const struct smb_filename *smb_fname_old,
5593 struct smb_filename *smb_fname_new)
5595 NTSTATUS status = NT_STATUS_OK;
5597 /* source must already exist. */
5598 if (!VALID_STAT(smb_fname_old->st)) {
5599 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5602 if (VALID_STAT(smb_fname_new->st)) {
5603 if (overwrite_if_exists) {
5604 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5605 return NT_STATUS_FILE_IS_A_DIRECTORY;
5607 status = unlink_internals(conn,
5609 FILE_ATTRIBUTE_NORMAL,
5612 if (!NT_STATUS_IS_OK(status)) {
5616 /* Disallow if newname already exists. */
5617 return NT_STATUS_OBJECT_NAME_COLLISION;
5621 /* No links from a directory. */
5622 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5623 return NT_STATUS_FILE_IS_A_DIRECTORY;
5626 /* Setting a hardlink to/from a stream isn't currently supported. */
5627 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5628 is_ntfs_stream_smb_fname(smb_fname_new)) {
5629 return NT_STATUS_INVALID_PARAMETER;
5632 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5633 smb_fname_old->base_name, smb_fname_new->base_name));
5635 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5636 smb_fname_new->base_name) != 0) {
5637 status = map_nt_error_from_unix(errno);
5638 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5639 nt_errstr(status), smb_fname_old->base_name,
5640 smb_fname_new->base_name));
5645 /****************************************************************************
5646 Deal with setting the time from any of the setfilepathinfo functions.
5647 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5648 calling this function.
5649 ****************************************************************************/
5651 NTSTATUS smb_set_file_time(connection_struct *conn,
5653 const struct smb_filename *smb_fname,
5654 struct smb_file_time *ft,
5655 bool setting_write_time)
5657 struct smb_filename smb_fname_base;
5659 FILE_NOTIFY_CHANGE_LAST_ACCESS
5660 |FILE_NOTIFY_CHANGE_LAST_WRITE
5661 |FILE_NOTIFY_CHANGE_CREATION;
5663 if (!VALID_STAT(smb_fname->st)) {
5664 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5667 /* get some defaults (no modifications) if any info is zero or -1. */
5668 if (null_timespec(ft->create_time)) {
5669 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5672 if (null_timespec(ft->atime)) {
5673 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5676 if (null_timespec(ft->mtime)) {
5677 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5680 if (!setting_write_time) {
5681 /* ft->mtime comes from change time, not write time. */
5682 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5685 /* Ensure the resolution is the correct for
5686 * what we can store on this filesystem. */
5688 round_timespec(conn->ts_res, &ft->create_time);
5689 round_timespec(conn->ts_res, &ft->ctime);
5690 round_timespec(conn->ts_res, &ft->atime);
5691 round_timespec(conn->ts_res, &ft->mtime);
5693 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5694 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5695 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5696 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5697 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5698 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5699 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5700 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5702 if (setting_write_time) {
5704 * This was a Windows setfileinfo on an open file.
5705 * NT does this a lot. We also need to
5706 * set the time here, as it can be read by
5707 * FindFirst/FindNext and with the patch for bug #2045
5708 * in smbd/fileio.c it ensures that this timestamp is
5709 * kept sticky even after a write. We save the request
5710 * away and will set it on file close and after a write. JRA.
5713 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5714 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5717 if (fsp->base_fsp) {
5718 set_sticky_write_time_fsp(fsp->base_fsp,
5721 set_sticky_write_time_fsp(fsp, ft->mtime);
5724 set_sticky_write_time_path(
5725 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5730 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5732 /* Always call ntimes on the base, even if a stream was passed in. */
5733 smb_fname_base = *smb_fname;
5734 smb_fname_base.stream_name = NULL;
5736 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5737 return map_nt_error_from_unix(errno);
5740 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5741 smb_fname->base_name);
5742 return NT_STATUS_OK;
5745 /****************************************************************************
5746 Deal with setting the dosmode from any of the setfilepathinfo functions.
5747 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5748 done before calling this function.
5749 ****************************************************************************/
5751 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5752 const struct smb_filename *smb_fname,
5755 struct smb_filename *smb_fname_base;
5758 if (!VALID_STAT(smb_fname->st)) {
5759 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5762 /* Always operate on the base_name, even if a stream was passed in. */
5763 smb_fname_base = synthetic_smb_fname(
5764 talloc_tos(), smb_fname->base_name, NULL, &smb_fname->st);
5765 if (smb_fname_base == NULL) {
5766 return NT_STATUS_NO_MEMORY;
5770 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5771 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5773 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5777 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5779 /* check the mode isn't different, before changing it */
5780 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5781 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5782 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5783 (unsigned int)dosmode));
5785 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5787 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5789 smb_fname_str_dbg(smb_fname_base),
5791 status = map_nt_error_from_unix(errno);
5795 status = NT_STATUS_OK;
5797 TALLOC_FREE(smb_fname_base);
5801 /****************************************************************************
5802 Deal with setting the size from any of the setfilepathinfo functions.
5803 ****************************************************************************/
5805 static NTSTATUS smb_set_file_size(connection_struct *conn,
5806 struct smb_request *req,
5808 const struct smb_filename *smb_fname,
5809 const SMB_STRUCT_STAT *psbuf,
5811 bool fail_after_createfile)
5813 NTSTATUS status = NT_STATUS_OK;
5814 struct smb_filename *smb_fname_tmp = NULL;
5815 files_struct *new_fsp = NULL;
5817 if (!VALID_STAT(*psbuf)) {
5818 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5821 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5823 if (size == get_file_size_stat(psbuf)) {
5824 return NT_STATUS_OK;
5827 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5828 smb_fname_str_dbg(smb_fname), (double)size));
5830 if (fsp && fsp->fh->fd != -1) {
5831 /* Handle based call. */
5832 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5833 return NT_STATUS_ACCESS_DENIED;
5836 if (vfs_set_filelen(fsp, size) == -1) {
5837 return map_nt_error_from_unix(errno);
5839 trigger_write_time_update_immediate(fsp);
5840 return NT_STATUS_OK;
5843 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
5844 if (smb_fname_tmp == NULL) {
5845 return NT_STATUS_NO_MEMORY;
5848 smb_fname_tmp->st = *psbuf;
5850 status = SMB_VFS_CREATE_FILE(
5853 0, /* root_dir_fid */
5854 smb_fname_tmp, /* fname */
5855 FILE_WRITE_DATA, /* access_mask */
5856 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5858 FILE_OPEN, /* create_disposition*/
5859 0, /* create_options */
5860 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5861 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5862 0, /* allocation_size */
5863 0, /* private_flags */
5866 &new_fsp, /* result */
5869 TALLOC_FREE(smb_fname_tmp);
5871 if (!NT_STATUS_IS_OK(status)) {
5872 /* NB. We check for open_was_deferred in the caller. */
5876 /* See RAW-SFILEINFO-END-OF-FILE */
5877 if (fail_after_createfile) {
5878 close_file(req, new_fsp,NORMAL_CLOSE);
5879 return NT_STATUS_INVALID_LEVEL;
5882 if (vfs_set_filelen(new_fsp, size) == -1) {
5883 status = map_nt_error_from_unix(errno);
5884 close_file(req, new_fsp,NORMAL_CLOSE);
5888 trigger_write_time_update_immediate(new_fsp);
5889 close_file(req, new_fsp,NORMAL_CLOSE);
5890 return NT_STATUS_OK;
5893 /****************************************************************************
5894 Deal with SMB_INFO_SET_EA.
5895 ****************************************************************************/
5897 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5901 const struct smb_filename *smb_fname)
5903 struct ea_list *ea_list = NULL;
5904 TALLOC_CTX *ctx = NULL;
5905 NTSTATUS status = NT_STATUS_OK;
5907 if (total_data < 10) {
5909 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5910 length. They seem to have no effect. Bug #3212. JRA */
5912 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5913 /* We're done. We only get EA info in this call. */
5914 return NT_STATUS_OK;
5917 return NT_STATUS_INVALID_PARAMETER;
5920 if (IVAL(pdata,0) > total_data) {
5921 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5922 IVAL(pdata,0), (unsigned int)total_data));
5923 return NT_STATUS_INVALID_PARAMETER;
5927 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5929 return NT_STATUS_INVALID_PARAMETER;
5932 status = set_ea(conn, fsp, smb_fname, ea_list);
5937 /****************************************************************************
5938 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5939 ****************************************************************************/
5941 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5946 struct ea_list *ea_list = NULL;
5950 return NT_STATUS_INVALID_HANDLE;
5953 if (!lp_ea_support(SNUM(conn))) {
5954 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5955 "EA's not supported.\n",
5956 (unsigned int)total_data));
5957 return NT_STATUS_EAS_NOT_SUPPORTED;
5960 if (total_data < 10) {
5961 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5963 (unsigned int)total_data));
5964 return NT_STATUS_INVALID_PARAMETER;
5967 ea_list = read_nttrans_ea_list(talloc_tos(),
5972 return NT_STATUS_INVALID_PARAMETER;
5975 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5977 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5978 smb_fname_str_dbg(fsp->fsp_name),
5979 nt_errstr(status) ));
5985 /****************************************************************************
5986 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5987 ****************************************************************************/
5989 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5993 struct smb_filename *smb_fname)
5995 NTSTATUS status = NT_STATUS_OK;
5996 bool delete_on_close;
5999 if (total_data < 1) {
6000 return NT_STATUS_INVALID_PARAMETER;
6004 return NT_STATUS_INVALID_HANDLE;
6007 delete_on_close = (CVAL(pdata,0) ? True : False);
6008 dosmode = dos_mode(conn, smb_fname);
6010 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6011 "delete_on_close = %u\n",
6012 smb_fname_str_dbg(smb_fname),
6013 (unsigned int)dosmode,
6014 (unsigned int)delete_on_close ));
6016 if (delete_on_close) {
6017 status = can_set_delete_on_close(fsp, dosmode);
6018 if (!NT_STATUS_IS_OK(status)) {
6023 /* The set is across all open files on this dev/inode pair. */
6024 if (!set_delete_on_close(fsp, delete_on_close,
6025 conn->session_info->security_token,
6026 conn->session_info->unix_token)) {
6027 return NT_STATUS_ACCESS_DENIED;
6029 return NT_STATUS_OK;
6032 /****************************************************************************
6033 Deal with SMB_FILE_POSITION_INFORMATION.
6034 ****************************************************************************/
6036 static NTSTATUS smb_file_position_information(connection_struct *conn,
6041 uint64_t position_information;
6043 if (total_data < 8) {
6044 return NT_STATUS_INVALID_PARAMETER;
6048 /* Ignore on pathname based set. */
6049 return NT_STATUS_OK;
6052 position_information = (uint64_t)IVAL(pdata,0);
6053 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6055 DEBUG(10,("smb_file_position_information: Set file position "
6056 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6057 (double)position_information));
6058 fsp->fh->position_information = position_information;
6059 return NT_STATUS_OK;
6062 /****************************************************************************
6063 Deal with SMB_FILE_MODE_INFORMATION.
6064 ****************************************************************************/
6066 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6072 if (total_data < 4) {
6073 return NT_STATUS_INVALID_PARAMETER;
6075 mode = IVAL(pdata,0);
6076 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6077 return NT_STATUS_INVALID_PARAMETER;
6079 return NT_STATUS_OK;
6082 /****************************************************************************
6083 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6084 ****************************************************************************/
6086 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6087 struct smb_request *req,
6090 const struct smb_filename *smb_fname)
6092 char *link_target = NULL;
6093 const char *newname = smb_fname->base_name;
6094 TALLOC_CTX *ctx = talloc_tos();
6096 /* Set a symbolic link. */
6097 /* Don't allow this if follow links is false. */
6099 if (total_data == 0) {
6100 return NT_STATUS_INVALID_PARAMETER;
6103 if (!lp_symlinks(SNUM(conn))) {
6104 return NT_STATUS_ACCESS_DENIED;
6107 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6108 total_data, STR_TERMINATE);
6111 return NT_STATUS_INVALID_PARAMETER;
6114 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6115 newname, link_target ));
6117 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6118 return map_nt_error_from_unix(errno);
6121 return NT_STATUS_OK;
6124 /****************************************************************************
6125 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6126 ****************************************************************************/
6128 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6129 struct smb_request *req,
6130 const char *pdata, int total_data,
6131 struct smb_filename *smb_fname_new)
6133 char *oldname = NULL;
6134 struct smb_filename *smb_fname_old = NULL;
6135 TALLOC_CTX *ctx = talloc_tos();
6136 NTSTATUS status = NT_STATUS_OK;
6138 /* Set a hard link. */
6139 if (total_data == 0) {
6140 return NT_STATUS_INVALID_PARAMETER;
6143 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6144 total_data, STR_TERMINATE, &status);
6145 if (!NT_STATUS_IS_OK(status)) {
6149 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6150 smb_fname_str_dbg(smb_fname_new), oldname));
6152 status = filename_convert(ctx,
6154 req->flags2 & FLAGS2_DFS_PATHNAMES,
6159 if (!NT_STATUS_IS_OK(status)) {
6163 return hardlink_internals(ctx, conn, req, false,
6164 smb_fname_old, smb_fname_new);
6167 /****************************************************************************
6168 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6169 ****************************************************************************/
6171 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6172 struct smb_request *req,
6176 struct smb_filename *smb_fname_src)
6180 char *newname = NULL;
6181 struct smb_filename *smb_fname_dst = NULL;
6182 NTSTATUS status = NT_STATUS_OK;
6183 TALLOC_CTX *ctx = talloc_tos();
6186 return NT_STATUS_INVALID_HANDLE;
6189 if (total_data < 20) {
6190 return NT_STATUS_INVALID_PARAMETER;
6193 overwrite = (CVAL(pdata,0) ? True : False);
6194 len = IVAL(pdata,16);
6196 if (len > (total_data - 20) || (len == 0)) {
6197 return NT_STATUS_INVALID_PARAMETER;
6200 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6201 &pdata[20], len, STR_TERMINATE,
6203 if (!NT_STATUS_IS_OK(status)) {
6207 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6210 status = filename_convert(ctx,
6212 req->flags2 & FLAGS2_DFS_PATHNAMES,
6217 if (!NT_STATUS_IS_OK(status)) {
6221 if (fsp->base_fsp) {
6222 /* newname must be a stream name. */
6223 if (newname[0] != ':') {
6224 return NT_STATUS_NOT_SUPPORTED;
6227 /* Create an smb_fname to call rename_internals_fsp() with. */
6228 smb_fname_dst = synthetic_smb_fname(
6229 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6231 if (smb_fname_dst == NULL) {
6232 status = NT_STATUS_NO_MEMORY;
6237 * Set the original last component, since
6238 * rename_internals_fsp() requires it.
6240 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6242 if (smb_fname_dst->original_lcomp == NULL) {
6243 status = NT_STATUS_NO_MEMORY;
6249 DEBUG(10,("smb2_file_rename_information: "
6250 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6251 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6252 smb_fname_str_dbg(smb_fname_dst)));
6253 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6254 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6258 TALLOC_FREE(smb_fname_dst);
6262 static NTSTATUS smb_file_link_information(connection_struct *conn,
6263 struct smb_request *req,
6267 struct smb_filename *smb_fname_src)
6271 char *newname = NULL;
6272 struct smb_filename *smb_fname_dst = NULL;
6273 NTSTATUS status = NT_STATUS_OK;
6274 TALLOC_CTX *ctx = talloc_tos();
6277 return NT_STATUS_INVALID_HANDLE;
6280 if (total_data < 20) {
6281 return NT_STATUS_INVALID_PARAMETER;
6284 overwrite = (CVAL(pdata,0) ? true : false);
6285 len = IVAL(pdata,16);
6287 if (len > (total_data - 20) || (len == 0)) {
6288 return NT_STATUS_INVALID_PARAMETER;
6291 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6292 &pdata[20], len, STR_TERMINATE,
6294 if (!NT_STATUS_IS_OK(status)) {
6298 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6301 status = filename_convert(ctx,
6303 req->flags2 & FLAGS2_DFS_PATHNAMES,
6308 if (!NT_STATUS_IS_OK(status)) {
6312 if (fsp->base_fsp) {
6313 /* No stream names. */
6314 return NT_STATUS_NOT_SUPPORTED;
6317 DEBUG(10,("smb_file_link_information: "
6318 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6319 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6320 smb_fname_str_dbg(smb_fname_dst)));
6321 status = hardlink_internals(ctx,
6328 TALLOC_FREE(smb_fname_dst);
6332 /****************************************************************************
6333 Deal with SMB_FILE_RENAME_INFORMATION.
6334 ****************************************************************************/
6336 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6337 struct smb_request *req,
6341 struct smb_filename *smb_fname_src)
6346 char *newname = NULL;
6347 struct smb_filename *smb_fname_dst = NULL;
6348 bool dest_has_wcard = False;
6349 NTSTATUS status = NT_STATUS_OK;
6351 TALLOC_CTX *ctx = talloc_tos();
6353 if (total_data < 13) {
6354 return NT_STATUS_INVALID_PARAMETER;
6357 overwrite = (CVAL(pdata,0) ? True : False);
6358 root_fid = IVAL(pdata,4);
6359 len = IVAL(pdata,8);
6361 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6362 return NT_STATUS_INVALID_PARAMETER;
6365 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6368 if (!NT_STATUS_IS_OK(status)) {
6372 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6375 status = resolve_dfspath_wcard(ctx, conn,
6376 req->flags2 & FLAGS2_DFS_PATHNAMES,
6379 !conn->sconn->using_smb2,
6382 if (!NT_STATUS_IS_OK(status)) {
6386 /* Check the new name has no '/' characters. */
6387 if (strchr_m(newname, '/')) {
6388 return NT_STATUS_NOT_SUPPORTED;
6391 if (fsp && fsp->base_fsp) {
6392 /* newname must be a stream name. */
6393 if (newname[0] != ':') {
6394 return NT_STATUS_NOT_SUPPORTED;
6397 /* Create an smb_fname to call rename_internals_fsp() with. */
6398 smb_fname_dst = synthetic_smb_fname(
6399 talloc_tos(), fsp->base_fsp->fsp_name->base_name,
6401 if (smb_fname_dst == NULL) {
6402 status = NT_STATUS_NO_MEMORY;
6407 * Set the original last component, since
6408 * rename_internals_fsp() requires it.
6410 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6412 if (smb_fname_dst->original_lcomp == NULL) {
6413 status = NT_STATUS_NO_MEMORY;
6419 * Build up an smb_fname_dst based on the filename passed in.
6420 * We basically just strip off the last component, and put on
6421 * the newname instead.
6423 char *base_name = NULL;
6425 /* newname must *not* be a stream name. */
6426 if (newname[0] == ':') {
6427 return NT_STATUS_NOT_SUPPORTED;
6431 * Strip off the last component (filename) of the path passed
6434 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6436 return NT_STATUS_NO_MEMORY;
6438 p = strrchr_m(base_name, '/');
6442 base_name = talloc_strdup(ctx, "");
6444 return NT_STATUS_NO_MEMORY;
6447 /* Append the new name. */
6448 base_name = talloc_asprintf_append(base_name,
6452 return NT_STATUS_NO_MEMORY;
6455 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6458 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6461 /* If an error we expect this to be
6462 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6464 if (!NT_STATUS_IS_OK(status)) {
6465 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6469 /* Create an smb_fname to call rename_internals_fsp() */
6470 smb_fname_dst = synthetic_smb_fname(
6471 ctx, base_name, NULL, NULL);
6472 if (smb_fname_dst == NULL) {
6473 status = NT_STATUS_NO_MEMORY;
6480 DEBUG(10,("smb_file_rename_information: "
6481 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6482 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6483 smb_fname_str_dbg(smb_fname_dst)));
6484 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6487 DEBUG(10,("smb_file_rename_information: "
6488 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6489 smb_fname_str_dbg(smb_fname_src),
6490 smb_fname_str_dbg(smb_fname_dst)));
6491 status = rename_internals(ctx, conn, req, smb_fname_src,
6492 smb_fname_dst, 0, overwrite, false,
6494 FILE_WRITE_ATTRIBUTES);
6497 TALLOC_FREE(smb_fname_dst);
6501 /****************************************************************************
6502 Deal with SMB_SET_POSIX_ACL.
6503 ****************************************************************************/
6505 #if defined(HAVE_POSIX_ACLS)
6506 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6510 const struct smb_filename *smb_fname)
6512 uint16 posix_acl_version;
6513 uint16 num_file_acls;
6514 uint16 num_def_acls;
6515 bool valid_file_acls = True;
6516 bool valid_def_acls = True;
6518 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6519 return NT_STATUS_INVALID_PARAMETER;
6521 posix_acl_version = SVAL(pdata,0);
6522 num_file_acls = SVAL(pdata,2);
6523 num_def_acls = SVAL(pdata,4);
6525 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6526 valid_file_acls = False;
6530 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6531 valid_def_acls = False;
6535 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6536 return NT_STATUS_INVALID_PARAMETER;
6539 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6540 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6541 return NT_STATUS_INVALID_PARAMETER;
6544 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6545 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6546 (unsigned int)num_file_acls,
6547 (unsigned int)num_def_acls));
6549 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6550 smb_fname->base_name, num_file_acls,
6551 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6552 return map_nt_error_from_unix(errno);
6555 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6556 smb_fname->base_name, &smb_fname->st, num_def_acls,
6557 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6558 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6559 return map_nt_error_from_unix(errno);
6561 return NT_STATUS_OK;
6565 /****************************************************************************
6566 Deal with SMB_SET_POSIX_LOCK.
6567 ****************************************************************************/
6569 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6570 struct smb_request *req,
6578 bool blocking_lock = False;
6579 enum brl_type lock_type;
6581 NTSTATUS status = NT_STATUS_OK;
6583 if (fsp == NULL || fsp->fh->fd == -1) {
6584 return NT_STATUS_INVALID_HANDLE;
6587 if (total_data != POSIX_LOCK_DATA_SIZE) {
6588 return NT_STATUS_INVALID_PARAMETER;
6591 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6592 case POSIX_LOCK_TYPE_READ:
6593 lock_type = READ_LOCK;
6595 case POSIX_LOCK_TYPE_WRITE:
6596 /* Return the right POSIX-mappable error code for files opened read-only. */
6597 if (!fsp->can_write) {
6598 return NT_STATUS_INVALID_HANDLE;
6600 lock_type = WRITE_LOCK;
6602 case POSIX_LOCK_TYPE_UNLOCK:
6603 lock_type = UNLOCK_LOCK;
6606 return NT_STATUS_INVALID_PARAMETER;
6609 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6610 blocking_lock = False;
6611 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6612 blocking_lock = True;
6614 return NT_STATUS_INVALID_PARAMETER;
6617 if (!lp_blocking_locks(SNUM(conn))) {
6618 blocking_lock = False;
6621 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6622 #if defined(HAVE_LONGLONG)
6623 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6624 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6625 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6626 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6627 #else /* HAVE_LONGLONG */
6628 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6629 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6630 #endif /* HAVE_LONGLONG */
6632 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6633 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6635 (unsigned int)lock_type,
6636 (unsigned long long)smblctx,
6640 if (lock_type == UNLOCK_LOCK) {
6641 status = do_unlock(req->sconn->msg_ctx,
6648 uint64_t block_smblctx;
6650 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6662 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6664 * A blocking lock was requested. Package up
6665 * this smb into a queued request and push it
6666 * onto the blocking lock queue.
6668 if(push_blocking_lock_request(br_lck,
6671 -1, /* infinite timeout. */
6679 TALLOC_FREE(br_lck);
6683 TALLOC_FREE(br_lck);
6689 /****************************************************************************
6690 Deal with SMB_SET_FILE_BASIC_INFO.
6691 ****************************************************************************/
6693 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6697 const struct smb_filename *smb_fname)
6699 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6700 struct smb_file_time ft;
6702 NTSTATUS status = NT_STATUS_OK;
6706 if (total_data < 36) {
6707 return NT_STATUS_INVALID_PARAMETER;
6710 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6711 if (!NT_STATUS_IS_OK(status)) {
6715 /* Set the attributes */
6716 dosmode = IVAL(pdata,32);
6717 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6718 if (!NT_STATUS_IS_OK(status)) {
6723 ft.create_time = interpret_long_date(pdata);
6726 ft.atime = interpret_long_date(pdata+8);
6729 ft.mtime = interpret_long_date(pdata+16);
6732 ft.ctime = interpret_long_date(pdata+24);
6734 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6735 smb_fname_str_dbg(smb_fname)));
6737 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6741 /****************************************************************************
6742 Deal with SMB_INFO_STANDARD.
6743 ****************************************************************************/
6745 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6749 const struct smb_filename *smb_fname)
6752 struct smb_file_time ft;
6756 if (total_data < 12) {
6757 return NT_STATUS_INVALID_PARAMETER;
6761 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6763 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6765 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6767 DEBUG(10,("smb_set_info_standard: file %s\n",
6768 smb_fname_str_dbg(smb_fname)));
6770 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6771 if (!NT_STATUS_IS_OK(status)) {
6775 return smb_set_file_time(conn,
6782 /****************************************************************************
6783 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6784 ****************************************************************************/
6786 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6787 struct smb_request *req,
6791 struct smb_filename *smb_fname)
6793 uint64_t allocation_size = 0;
6794 NTSTATUS status = NT_STATUS_OK;
6795 files_struct *new_fsp = NULL;
6797 if (!VALID_STAT(smb_fname->st)) {
6798 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6801 if (total_data < 8) {
6802 return NT_STATUS_INVALID_PARAMETER;
6805 allocation_size = (uint64_t)IVAL(pdata,0);
6806 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6807 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6808 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6809 (double)allocation_size));
6811 if (allocation_size) {
6812 allocation_size = smb_roundup(conn, allocation_size);
6815 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6816 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6817 (double)allocation_size));
6819 if (fsp && fsp->fh->fd != -1) {
6820 /* Open file handle. */
6821 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6822 return NT_STATUS_ACCESS_DENIED;
6825 /* Only change if needed. */
6826 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6827 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6828 return map_nt_error_from_unix(errno);
6831 /* But always update the time. */
6833 * This is equivalent to a write. Ensure it's seen immediately
6834 * if there are no pending writes.
6836 trigger_write_time_update_immediate(fsp);
6837 return NT_STATUS_OK;
6840 /* Pathname or stat or directory file. */
6841 status = SMB_VFS_CREATE_FILE(
6844 0, /* root_dir_fid */
6845 smb_fname, /* fname */
6846 FILE_WRITE_DATA, /* access_mask */
6847 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6849 FILE_OPEN, /* create_disposition*/
6850 0, /* create_options */
6851 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6852 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6853 0, /* allocation_size */
6854 0, /* private_flags */
6857 &new_fsp, /* result */
6860 if (!NT_STATUS_IS_OK(status)) {
6861 /* NB. We check for open_was_deferred in the caller. */
6865 /* Only change if needed. */
6866 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6867 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6868 status = map_nt_error_from_unix(errno);
6869 close_file(req, new_fsp, NORMAL_CLOSE);
6874 /* Changing the allocation size should set the last mod time. */
6876 * This is equivalent to a write. Ensure it's seen immediately
6877 * if there are no pending writes.
6879 trigger_write_time_update_immediate(new_fsp);
6881 close_file(req, new_fsp, NORMAL_CLOSE);
6882 return NT_STATUS_OK;
6885 /****************************************************************************
6886 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6887 ****************************************************************************/
6889 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6890 struct smb_request *req,
6894 const struct smb_filename *smb_fname,
6895 bool fail_after_createfile)
6899 if (total_data < 8) {
6900 return NT_STATUS_INVALID_PARAMETER;
6903 size = IVAL(pdata,0);
6904 size |= (((off_t)IVAL(pdata,4)) << 32);
6905 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6906 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6909 return smb_set_file_size(conn, req,
6914 fail_after_createfile);
6917 /****************************************************************************
6918 Allow a UNIX info mknod.
6919 ****************************************************************************/
6921 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6924 const struct smb_filename *smb_fname)
6926 uint32 file_type = IVAL(pdata,56);
6927 #if defined(HAVE_MAKEDEV)
6928 uint32 dev_major = IVAL(pdata,60);
6929 uint32 dev_minor = IVAL(pdata,68);
6931 SMB_DEV_T dev = (SMB_DEV_T)0;
6932 uint32 raw_unixmode = IVAL(pdata,84);
6936 if (total_data < 100) {
6937 return NT_STATUS_INVALID_PARAMETER;
6940 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6941 PERM_NEW_FILE, &unixmode);
6942 if (!NT_STATUS_IS_OK(status)) {
6946 #if defined(HAVE_MAKEDEV)
6947 dev = makedev(dev_major, dev_minor);
6950 switch (file_type) {
6951 #if defined(S_IFIFO)
6952 case UNIX_TYPE_FIFO:
6953 unixmode |= S_IFIFO;
6956 #if defined(S_IFSOCK)
6957 case UNIX_TYPE_SOCKET:
6958 unixmode |= S_IFSOCK;
6961 #if defined(S_IFCHR)
6962 case UNIX_TYPE_CHARDEV:
6963 unixmode |= S_IFCHR;
6966 #if defined(S_IFBLK)
6967 case UNIX_TYPE_BLKDEV:
6968 unixmode |= S_IFBLK;
6972 return NT_STATUS_INVALID_PARAMETER;
6975 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6976 "%.0f mode 0%o for file %s\n", (double)dev,
6977 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6979 /* Ok - do the mknod. */
6980 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6981 return map_nt_error_from_unix(errno);
6984 /* If any of the other "set" calls fail we
6985 * don't want to end up with a half-constructed mknod.
6988 if (lp_inherit_perms(SNUM(conn))) {
6990 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6992 return NT_STATUS_NO_MEMORY;
6994 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6996 TALLOC_FREE(parent);
6999 return NT_STATUS_OK;
7002 /****************************************************************************
7003 Deal with SMB_SET_FILE_UNIX_BASIC.
7004 ****************************************************************************/
7006 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7007 struct smb_request *req,
7011 const struct smb_filename *smb_fname)
7013 struct smb_file_time ft;
7014 uint32 raw_unixmode;
7017 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7018 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7019 NTSTATUS status = NT_STATUS_OK;
7020 bool delete_on_fail = False;
7021 enum perm_type ptype;
7022 files_struct *all_fsps = NULL;
7023 bool modify_mtime = true;
7025 struct smb_filename *smb_fname_tmp = NULL;
7026 SMB_STRUCT_STAT sbuf;
7030 if (total_data < 100) {
7031 return NT_STATUS_INVALID_PARAMETER;
7034 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7035 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7036 size=IVAL(pdata,0); /* first 8 Bytes are size */
7037 size |= (((off_t)IVAL(pdata,4)) << 32);
7040 ft.atime = interpret_long_date(pdata+24); /* access_time */
7041 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7042 set_owner = (uid_t)IVAL(pdata,40);
7043 set_grp = (gid_t)IVAL(pdata,48);
7044 raw_unixmode = IVAL(pdata,84);
7046 if (VALID_STAT(smb_fname->st)) {
7047 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7048 ptype = PERM_EXISTING_DIR;
7050 ptype = PERM_EXISTING_FILE;
7053 ptype = PERM_NEW_FILE;
7056 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7058 if (!NT_STATUS_IS_OK(status)) {
7062 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7063 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7064 smb_fname_str_dbg(smb_fname), (double)size,
7065 (unsigned int)set_owner, (unsigned int)set_grp,
7066 (int)raw_unixmode));
7068 sbuf = smb_fname->st;
7070 if (!VALID_STAT(sbuf)) {
7072 * The only valid use of this is to create character and block
7073 * devices, and named pipes. This is deprecated (IMHO) and
7074 * a new info level should be used for mknod. JRA.
7077 status = smb_unix_mknod(conn,
7081 if (!NT_STATUS_IS_OK(status)) {
7085 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7086 if (smb_fname_tmp == NULL) {
7087 return NT_STATUS_NO_MEMORY;
7090 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7091 status = map_nt_error_from_unix(errno);
7092 TALLOC_FREE(smb_fname_tmp);
7093 SMB_VFS_UNLINK(conn, smb_fname);
7097 sbuf = smb_fname_tmp->st;
7098 smb_fname = smb_fname_tmp;
7100 /* Ensure we don't try and change anything else. */
7101 raw_unixmode = SMB_MODE_NO_CHANGE;
7102 size = get_file_size_stat(&sbuf);
7103 ft.atime = sbuf.st_ex_atime;
7104 ft.mtime = sbuf.st_ex_mtime;
7106 * We continue here as we might want to change the
7109 delete_on_fail = True;
7113 /* Horrible backwards compatibility hack as an old server bug
7114 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7118 size = get_file_size_stat(&sbuf);
7123 * Deal with the UNIX specific mode set.
7126 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7127 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7128 "setting mode 0%o for file %s\n",
7129 (unsigned int)unixmode,
7130 smb_fname_str_dbg(smb_fname)));
7131 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7132 return map_nt_error_from_unix(errno);
7137 * Deal with the UNIX specific uid set.
7140 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7141 (sbuf.st_ex_uid != set_owner)) {
7144 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7145 "changing owner %u for path %s\n",
7146 (unsigned int)set_owner,
7147 smb_fname_str_dbg(smb_fname)));
7149 if (S_ISLNK(sbuf.st_ex_mode)) {
7150 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7151 set_owner, (gid_t)-1);
7153 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7154 set_owner, (gid_t)-1);
7158 status = map_nt_error_from_unix(errno);
7159 if (delete_on_fail) {
7160 SMB_VFS_UNLINK(conn, smb_fname);
7167 * Deal with the UNIX specific gid set.
7170 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7171 (sbuf.st_ex_gid != set_grp)) {
7172 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7173 "changing group %u for file %s\n",
7174 (unsigned int)set_owner,
7175 smb_fname_str_dbg(smb_fname)));
7176 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7178 status = map_nt_error_from_unix(errno);
7179 if (delete_on_fail) {
7180 SMB_VFS_UNLINK(conn, smb_fname);
7186 /* Deal with any size changes. */
7188 status = smb_set_file_size(conn, req,
7194 if (!NT_STATUS_IS_OK(status)) {
7198 /* Deal with any time changes. */
7199 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7200 /* No change, don't cancel anything. */
7204 id = vfs_file_id_from_sbuf(conn, &sbuf);
7205 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7206 all_fsps = file_find_di_next(all_fsps)) {
7208 * We're setting the time explicitly for UNIX.
7209 * Cancel any pending changes over all handles.
7211 all_fsps->update_write_time_on_close = false;
7212 TALLOC_FREE(all_fsps->update_write_time_event);
7216 * Override the "setting_write_time"
7217 * parameter here as it almost does what
7218 * we need. Just remember if we modified
7219 * mtime and send the notify ourselves.
7221 if (null_timespec(ft.mtime)) {
7222 modify_mtime = false;
7225 status = smb_set_file_time(conn,
7231 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7232 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7237 /****************************************************************************
7238 Deal with SMB_SET_FILE_UNIX_INFO2.
7239 ****************************************************************************/
7241 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7242 struct smb_request *req,
7246 const struct smb_filename *smb_fname)
7252 if (total_data < 116) {
7253 return NT_STATUS_INVALID_PARAMETER;
7256 /* Start by setting all the fields that are common between UNIX_BASIC
7259 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7261 if (!NT_STATUS_IS_OK(status)) {
7265 smb_fflags = IVAL(pdata, 108);
7266 smb_fmask = IVAL(pdata, 112);
7268 /* NB: We should only attempt to alter the file flags if the client
7269 * sends a non-zero mask.
7271 if (smb_fmask != 0) {
7272 int stat_fflags = 0;
7274 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7275 smb_fmask, &stat_fflags)) {
7276 /* Client asked to alter a flag we don't understand. */
7277 return NT_STATUS_INVALID_PARAMETER;
7280 if (fsp && fsp->fh->fd != -1) {
7281 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7282 return NT_STATUS_NOT_SUPPORTED;
7284 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7285 stat_fflags) != 0) {
7286 return map_nt_error_from_unix(errno);
7291 /* XXX: need to add support for changing the create_time here. You
7292 * can do this for paths on Darwin with setattrlist(2). The right way
7293 * to hook this up is probably by extending the VFS utimes interface.
7296 return NT_STATUS_OK;
7299 /****************************************************************************
7300 Create a directory with POSIX semantics.
7301 ****************************************************************************/
7303 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7304 struct smb_request *req,
7307 struct smb_filename *smb_fname,
7308 int *pdata_return_size)
7310 NTSTATUS status = NT_STATUS_OK;
7311 uint32 raw_unixmode = 0;
7312 uint32 mod_unixmode = 0;
7313 mode_t unixmode = (mode_t)0;
7314 files_struct *fsp = NULL;
7315 uint16 info_level_return = 0;
7317 char *pdata = *ppdata;
7319 if (total_data < 18) {
7320 return NT_STATUS_INVALID_PARAMETER;
7323 raw_unixmode = IVAL(pdata,8);
7324 /* Next 4 bytes are not yet defined. */
7326 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7327 PERM_NEW_DIR, &unixmode);
7328 if (!NT_STATUS_IS_OK(status)) {
7332 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7334 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7335 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7337 status = SMB_VFS_CREATE_FILE(
7340 0, /* root_dir_fid */
7341 smb_fname, /* fname */
7342 FILE_READ_ATTRIBUTES, /* access_mask */
7343 FILE_SHARE_NONE, /* share_access */
7344 FILE_CREATE, /* create_disposition*/
7345 FILE_DIRECTORY_FILE, /* create_options */
7346 mod_unixmode, /* file_attributes */
7347 0, /* oplock_request */
7348 0, /* allocation_size */
7349 0, /* private_flags */
7355 if (NT_STATUS_IS_OK(status)) {
7356 close_file(req, fsp, NORMAL_CLOSE);
7359 info_level_return = SVAL(pdata,16);
7361 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7362 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7363 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7364 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7366 *pdata_return_size = 12;
7369 /* Realloc the data size */
7370 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7371 if (*ppdata == NULL) {
7372 *pdata_return_size = 0;
7373 return NT_STATUS_NO_MEMORY;
7377 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7378 SSVAL(pdata,2,0); /* No fnum. */
7379 SIVAL(pdata,4,info); /* Was directory created. */
7381 switch (info_level_return) {
7382 case SMB_QUERY_FILE_UNIX_BASIC:
7383 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7384 SSVAL(pdata,10,0); /* Padding. */
7385 store_file_unix_basic(conn, pdata + 12, fsp,
7388 case SMB_QUERY_FILE_UNIX_INFO2:
7389 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7390 SSVAL(pdata,10,0); /* Padding. */
7391 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7395 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7396 SSVAL(pdata,10,0); /* Padding. */
7403 /****************************************************************************
7404 Open/Create a file with POSIX semantics.
7405 ****************************************************************************/
7407 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7408 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7410 static NTSTATUS smb_posix_open(connection_struct *conn,
7411 struct smb_request *req,
7414 struct smb_filename *smb_fname,
7415 int *pdata_return_size)
7417 bool extended_oplock_granted = False;
7418 char *pdata = *ppdata;
7420 uint32 wire_open_mode = 0;
7421 uint32 raw_unixmode = 0;
7422 uint32 mod_unixmode = 0;
7423 uint32 create_disp = 0;
7424 uint32 access_mask = 0;
7425 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7426 NTSTATUS status = NT_STATUS_OK;
7427 mode_t unixmode = (mode_t)0;
7428 files_struct *fsp = NULL;
7429 int oplock_request = 0;
7431 uint16 info_level_return = 0;
7433 if (total_data < 18) {
7434 return NT_STATUS_INVALID_PARAMETER;
7437 flags = IVAL(pdata,0);
7438 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7439 if (oplock_request) {
7440 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7443 wire_open_mode = IVAL(pdata,4);
7445 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7446 return smb_posix_mkdir(conn, req,
7453 switch (wire_open_mode & SMB_ACCMODE) {
7455 access_mask = SMB_O_RDONLY_MAPPING;
7458 access_mask = SMB_O_WRONLY_MAPPING;
7461 access_mask = (SMB_O_RDONLY_MAPPING|
7462 SMB_O_WRONLY_MAPPING);
7465 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7466 (unsigned int)wire_open_mode ));
7467 return NT_STATUS_INVALID_PARAMETER;
7470 wire_open_mode &= ~SMB_ACCMODE;
7472 /* First take care of O_CREAT|O_EXCL interactions. */
7473 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7474 case (SMB_O_CREAT | SMB_O_EXCL):
7475 /* File exists fail. File not exist create. */
7476 create_disp = FILE_CREATE;
7479 /* File exists open. File not exist create. */
7480 create_disp = FILE_OPEN_IF;
7483 /* O_EXCL on its own without O_CREAT is undefined.
7484 We deliberately ignore it as some versions of
7485 Linux CIFSFS can send a bare O_EXCL on the
7486 wire which other filesystems in the kernel
7487 ignore. See bug 9519 for details. */
7492 /* File exists open. File not exist fail. */
7493 create_disp = FILE_OPEN;
7496 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7497 (unsigned int)wire_open_mode ));
7498 return NT_STATUS_INVALID_PARAMETER;
7501 /* Next factor in the effects of O_TRUNC. */
7502 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7504 if (wire_open_mode & SMB_O_TRUNC) {
7505 switch (create_disp) {
7507 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7508 /* Leave create_disp alone as
7509 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7511 /* File exists fail. File not exist create. */
7514 /* SMB_O_CREAT | SMB_O_TRUNC */
7515 /* File exists overwrite. File not exist create. */
7516 create_disp = FILE_OVERWRITE_IF;
7520 /* File exists overwrite. File not exist fail. */
7521 create_disp = FILE_OVERWRITE;
7524 /* Cannot get here. */
7525 smb_panic("smb_posix_open: logic error");
7526 return NT_STATUS_INVALID_PARAMETER;
7530 raw_unixmode = IVAL(pdata,8);
7531 /* Next 4 bytes are not yet defined. */
7533 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7534 (VALID_STAT(smb_fname->st) ?
7535 PERM_EXISTING_FILE : PERM_NEW_FILE),
7538 if (!NT_STATUS_IS_OK(status)) {
7542 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7544 if (wire_open_mode & SMB_O_SYNC) {
7545 create_options |= FILE_WRITE_THROUGH;
7547 if (wire_open_mode & SMB_O_APPEND) {
7548 access_mask |= FILE_APPEND_DATA;
7550 if (wire_open_mode & SMB_O_DIRECT) {
7551 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7554 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7555 VALID_STAT_OF_DIR(smb_fname->st)) {
7556 if (access_mask != SMB_O_RDONLY_MAPPING) {
7557 return NT_STATUS_FILE_IS_A_DIRECTORY;
7559 create_options &= ~FILE_NON_DIRECTORY_FILE;
7560 create_options |= FILE_DIRECTORY_FILE;
7563 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7564 smb_fname_str_dbg(smb_fname),
7565 (unsigned int)wire_open_mode,
7566 (unsigned int)unixmode ));
7568 status = SMB_VFS_CREATE_FILE(
7571 0, /* root_dir_fid */
7572 smb_fname, /* fname */
7573 access_mask, /* access_mask */
7574 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7576 create_disp, /* create_disposition*/
7577 create_options, /* create_options */
7578 mod_unixmode, /* file_attributes */
7579 oplock_request, /* oplock_request */
7580 0, /* allocation_size */
7581 0, /* private_flags */
7587 if (!NT_STATUS_IS_OK(status)) {
7591 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7592 extended_oplock_granted = True;
7595 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7596 extended_oplock_granted = True;
7599 info_level_return = SVAL(pdata,16);
7601 /* Allocate the correct return size. */
7603 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7604 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7605 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7606 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7608 *pdata_return_size = 12;
7611 /* Realloc the data size */
7612 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7613 if (*ppdata == NULL) {
7614 close_file(req, fsp, ERROR_CLOSE);
7615 *pdata_return_size = 0;
7616 return NT_STATUS_NO_MEMORY;
7620 if (extended_oplock_granted) {
7621 if (flags & REQUEST_BATCH_OPLOCK) {
7622 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7624 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7626 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7627 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7629 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7632 SSVAL(pdata,2,fsp->fnum);
7633 SIVAL(pdata,4,info); /* Was file created etc. */
7635 switch (info_level_return) {
7636 case SMB_QUERY_FILE_UNIX_BASIC:
7637 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7638 SSVAL(pdata,10,0); /* padding. */
7639 store_file_unix_basic(conn, pdata + 12, fsp,
7642 case SMB_QUERY_FILE_UNIX_INFO2:
7643 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7644 SSVAL(pdata,10,0); /* padding. */
7645 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7649 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7650 SSVAL(pdata,10,0); /* padding. */
7653 return NT_STATUS_OK;
7656 /****************************************************************************
7657 Delete a file with POSIX semantics.
7658 ****************************************************************************/
7660 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7661 struct smb_request *req,
7664 struct smb_filename *smb_fname)
7666 NTSTATUS status = NT_STATUS_OK;
7667 files_struct *fsp = NULL;
7671 int create_options = 0;
7673 struct share_mode_lock *lck = NULL;
7675 if (total_data < 2) {
7676 return NT_STATUS_INVALID_PARAMETER;
7679 flags = SVAL(pdata,0);
7681 if (!VALID_STAT(smb_fname->st)) {
7682 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7685 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7686 !VALID_STAT_OF_DIR(smb_fname->st)) {
7687 return NT_STATUS_NOT_A_DIRECTORY;
7690 DEBUG(10,("smb_posix_unlink: %s %s\n",
7691 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7692 smb_fname_str_dbg(smb_fname)));
7694 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7695 create_options |= FILE_DIRECTORY_FILE;
7698 status = SMB_VFS_CREATE_FILE(
7701 0, /* root_dir_fid */
7702 smb_fname, /* fname */
7703 DELETE_ACCESS, /* access_mask */
7704 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7706 FILE_OPEN, /* create_disposition*/
7707 create_options, /* create_options */
7708 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7709 0, /* oplock_request */
7710 0, /* allocation_size */
7711 0, /* private_flags */
7717 if (!NT_STATUS_IS_OK(status)) {
7722 * Don't lie to client. If we can't really delete due to
7723 * non-POSIX opens return SHARING_VIOLATION.
7726 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7728 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7729 "lock for file %s\n", fsp_str_dbg(fsp)));
7730 close_file(req, fsp, NORMAL_CLOSE);
7731 return NT_STATUS_INVALID_PARAMETER;
7735 * See if others still have the file open. If this is the case, then
7736 * don't delete. If all opens are POSIX delete we can set the delete
7737 * on close disposition.
7739 for (i=0; i<lck->data->num_share_modes; i++) {
7740 struct share_mode_entry *e = &lck->data->share_modes[i];
7741 if (is_valid_share_mode_entry(e)) {
7742 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7745 if (share_mode_stale_pid(lck->data, i)) {
7748 /* Fail with sharing violation. */
7750 close_file(req, fsp, NORMAL_CLOSE);
7751 return NT_STATUS_SHARING_VIOLATION;
7756 * Set the delete on close.
7758 status = smb_set_file_disposition_info(conn,
7766 if (!NT_STATUS_IS_OK(status)) {
7767 close_file(req, fsp, NORMAL_CLOSE);
7770 return close_file(req, fsp, NORMAL_CLOSE);
7773 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7774 struct smb_request *req,
7775 TALLOC_CTX *mem_ctx,
7776 uint16_t info_level,
7778 struct smb_filename *smb_fname,
7779 char **ppdata, int total_data,
7782 char *pdata = *ppdata;
7783 NTSTATUS status = NT_STATUS_OK;
7784 int data_return_size = 0;
7788 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7789 return NT_STATUS_INVALID_LEVEL;
7792 if (!CAN_WRITE(conn)) {
7793 /* Allow POSIX opens. The open path will deny
7794 * any non-readonly opens. */
7795 if (info_level != SMB_POSIX_PATH_OPEN) {
7796 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7800 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7801 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7803 info_level, total_data));
7805 switch (info_level) {
7807 case SMB_INFO_STANDARD:
7809 status = smb_set_info_standard(conn,
7817 case SMB_INFO_SET_EA:
7819 status = smb_info_set_ea(conn,
7827 case SMB_SET_FILE_BASIC_INFO:
7828 case SMB_FILE_BASIC_INFORMATION:
7830 status = smb_set_file_basic_info(conn,
7838 case SMB_FILE_ALLOCATION_INFORMATION:
7839 case SMB_SET_FILE_ALLOCATION_INFO:
7841 status = smb_set_file_allocation_info(conn, req,
7849 case SMB_FILE_END_OF_FILE_INFORMATION:
7850 case SMB_SET_FILE_END_OF_FILE_INFO:
7853 * XP/Win7 both fail after the createfile with
7854 * SMB_SET_FILE_END_OF_FILE_INFO but not
7855 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7856 * The level is known here, so pass it down
7860 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7862 status = smb_set_file_end_of_file_info(conn, req,
7871 case SMB_FILE_DISPOSITION_INFORMATION:
7872 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7875 /* JRA - We used to just ignore this on a path ?
7876 * Shouldn't this be invalid level on a pathname
7879 if (tran_call != TRANSACT2_SETFILEINFO) {
7880 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7883 status = smb_set_file_disposition_info(conn,
7891 case SMB_FILE_POSITION_INFORMATION:
7893 status = smb_file_position_information(conn,
7900 case SMB_FILE_FULL_EA_INFORMATION:
7902 status = smb_set_file_full_ea_info(conn,
7909 /* From tridge Samba4 :
7910 * MODE_INFORMATION in setfileinfo (I have no
7911 * idea what "mode information" on a file is - it takes a value of 0,
7912 * 2, 4 or 6. What could it be?).
7915 case SMB_FILE_MODE_INFORMATION:
7917 status = smb_file_mode_information(conn,
7924 * CIFS UNIX extensions.
7927 case SMB_SET_FILE_UNIX_BASIC:
7929 status = smb_set_file_unix_basic(conn, req,
7937 case SMB_SET_FILE_UNIX_INFO2:
7939 status = smb_set_file_unix_info2(conn, req,
7947 case SMB_SET_FILE_UNIX_LINK:
7950 /* We must have a pathname for this. */
7951 return NT_STATUS_INVALID_LEVEL;
7953 status = smb_set_file_unix_link(conn, req, pdata,
7954 total_data, smb_fname);
7958 case SMB_SET_FILE_UNIX_HLINK:
7961 /* We must have a pathname for this. */
7962 return NT_STATUS_INVALID_LEVEL;
7964 status = smb_set_file_unix_hlink(conn, req,
7970 case SMB_FILE_RENAME_INFORMATION:
7972 status = smb_file_rename_information(conn, req,
7978 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7980 /* SMB2 rename information. */
7981 status = smb2_file_rename_information(conn, req,
7987 case SMB_FILE_LINK_INFORMATION:
7989 status = smb_file_link_information(conn, req,
7995 #if defined(HAVE_POSIX_ACLS)
7996 case SMB_SET_POSIX_ACL:
7998 status = smb_set_posix_acl(conn,
8007 case SMB_SET_POSIX_LOCK:
8010 return NT_STATUS_INVALID_LEVEL;
8012 status = smb_set_posix_lock(conn, req,
8013 pdata, total_data, fsp);
8017 case SMB_POSIX_PATH_OPEN:
8020 /* We must have a pathname for this. */
8021 return NT_STATUS_INVALID_LEVEL;
8024 status = smb_posix_open(conn, req,
8032 case SMB_POSIX_PATH_UNLINK:
8035 /* We must have a pathname for this. */
8036 return NT_STATUS_INVALID_LEVEL;
8039 status = smb_posix_unlink(conn, req,
8047 return NT_STATUS_INVALID_LEVEL;
8050 if (!NT_STATUS_IS_OK(status)) {
8054 *ret_data_size = data_return_size;
8055 return NT_STATUS_OK;
8058 /****************************************************************************
8059 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8060 ****************************************************************************/
8062 static void call_trans2setfilepathinfo(connection_struct *conn,
8063 struct smb_request *req,
8064 unsigned int tran_call,
8065 char **pparams, int total_params,
8066 char **ppdata, int total_data,
8067 unsigned int max_data_bytes)
8069 char *params = *pparams;
8070 char *pdata = *ppdata;
8072 struct smb_filename *smb_fname = NULL;
8073 files_struct *fsp = NULL;
8074 NTSTATUS status = NT_STATUS_OK;
8075 int data_return_size = 0;
8078 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8082 if (tran_call == TRANSACT2_SETFILEINFO) {
8083 if (total_params < 4) {
8084 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8088 fsp = file_fsp(req, SVAL(params,0));
8089 /* Basic check for non-null fsp. */
8090 if (!check_fsp_open(conn, req, fsp)) {
8093 info_level = SVAL(params,2);
8095 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8096 if (smb_fname == NULL) {
8097 reply_nterror(req, NT_STATUS_NO_MEMORY);
8101 if(fsp->fh->fd == -1) {
8103 * This is actually a SETFILEINFO on a directory
8104 * handle (returned from an NT SMB). NT5.0 seems
8105 * to do this call. JRA.
8107 if (INFO_LEVEL_IS_UNIX(info_level)) {
8108 /* Always do lstat for UNIX calls. */
8109 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8110 DEBUG(3,("call_trans2setfilepathinfo: "
8111 "SMB_VFS_LSTAT of %s failed "
8113 smb_fname_str_dbg(smb_fname),
8115 reply_nterror(req, map_nt_error_from_unix(errno));
8119 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8120 DEBUG(3,("call_trans2setfilepathinfo: "
8121 "fileinfo of %s failed (%s)\n",
8122 smb_fname_str_dbg(smb_fname),
8124 reply_nterror(req, map_nt_error_from_unix(errno));
8128 } else if (fsp->print_file) {
8130 * Doing a DELETE_ON_CLOSE should cancel a print job.
8132 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8133 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8135 DEBUG(3,("call_trans2setfilepathinfo: "
8136 "Cancelling print job (%s)\n",
8140 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8146 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8151 * Original code - this is an open file.
8153 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8154 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8155 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8157 reply_nterror(req, map_nt_error_from_unix(errno));
8163 uint32_t ucf_flags = 0;
8166 if (total_params < 7) {
8167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8171 info_level = SVAL(params,0);
8172 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8173 total_params - 6, STR_TERMINATE,
8175 if (!NT_STATUS_IS_OK(status)) {
8176 reply_nterror(req, status);
8180 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8181 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8182 info_level == SMB_FILE_RENAME_INFORMATION ||
8183 info_level == SMB_POSIX_PATH_UNLINK) {
8184 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8187 status = filename_convert(req, conn,
8188 req->flags2 & FLAGS2_DFS_PATHNAMES,
8193 if (!NT_STATUS_IS_OK(status)) {
8194 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8195 reply_botherror(req,
8196 NT_STATUS_PATH_NOT_COVERED,
8197 ERRSRV, ERRbadpath);
8200 reply_nterror(req, status);
8204 if (INFO_LEVEL_IS_UNIX(info_level)) {
8206 * For CIFS UNIX extensions the target name may not exist.
8209 /* Always do lstat for UNIX calls. */
8210 SMB_VFS_LSTAT(conn, smb_fname);
8212 } else if (!VALID_STAT(smb_fname->st) &&
8213 SMB_VFS_STAT(conn, smb_fname)) {
8214 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8216 smb_fname_str_dbg(smb_fname),
8218 reply_nterror(req, map_nt_error_from_unix(errno));
8223 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8224 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8226 info_level,total_data));
8228 /* Realloc the parameter size */
8229 *pparams = (char *)SMB_REALLOC(*pparams,2);
8230 if (*pparams == NULL) {
8231 reply_nterror(req, NT_STATUS_NO_MEMORY);
8238 status = smbd_do_setfilepathinfo(conn, req, req,
8244 if (!NT_STATUS_IS_OK(status)) {
8245 if (open_was_deferred(req->sconn, req->mid)) {
8246 /* We have re-scheduled this call. */
8249 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8250 /* We have re-scheduled this call. */
8253 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8254 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8255 ERRSRV, ERRbadpath);
8258 if (info_level == SMB_POSIX_PATH_OPEN) {
8259 reply_openerror(req, status);
8264 * Invalid EA name needs to return 2 param bytes,
8265 * not a zero-length error packet.
8267 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8268 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8271 reply_nterror(req, status);
8276 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8282 /****************************************************************************
8283 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8284 ****************************************************************************/
8286 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8287 char **pparams, int total_params,
8288 char **ppdata, int total_data,
8289 unsigned int max_data_bytes)
8291 struct smb_filename *smb_dname = NULL;
8292 char *params = *pparams;
8293 char *pdata = *ppdata;
8294 char *directory = NULL;
8295 NTSTATUS status = NT_STATUS_OK;
8296 struct ea_list *ea_list = NULL;
8297 TALLOC_CTX *ctx = talloc_tos();
8299 if (!CAN_WRITE(conn)) {
8300 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8304 if (total_params < 5) {
8305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8309 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8310 total_params - 4, STR_TERMINATE,
8312 if (!NT_STATUS_IS_OK(status)) {
8313 reply_nterror(req, status);
8317 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8319 status = filename_convert(ctx,
8321 req->flags2 & FLAGS2_DFS_PATHNAMES,
8327 if (!NT_STATUS_IS_OK(status)) {
8328 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8329 reply_botherror(req,
8330 NT_STATUS_PATH_NOT_COVERED,
8331 ERRSRV, ERRbadpath);
8334 reply_nterror(req, status);
8339 * OS/2 workplace shell seems to send SET_EA requests of "null"
8340 * length (4 bytes containing IVAL 4).
8341 * They seem to have no effect. Bug #3212. JRA.
8344 if (total_data && (total_data != 4)) {
8345 /* Any data in this call is an EA list. */
8346 if (total_data < 10) {
8347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8351 if (IVAL(pdata,0) > total_data) {
8352 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8353 IVAL(pdata,0), (unsigned int)total_data));
8354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8358 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8361 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8365 if (!lp_ea_support(SNUM(conn))) {
8366 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8370 /* If total_data == 4 Windows doesn't care what values
8371 * are placed in that field, it just ignores them.
8372 * The System i QNTC IBM SMB client puts bad values here,
8373 * so ignore them. */
8375 status = create_directory(conn, req, smb_dname);
8377 if (!NT_STATUS_IS_OK(status)) {
8378 reply_nterror(req, status);
8382 /* Try and set any given EA. */
8384 status = set_ea(conn, NULL, smb_dname, ea_list);
8385 if (!NT_STATUS_IS_OK(status)) {
8386 reply_nterror(req, status);
8391 /* Realloc the parameter and data sizes */
8392 *pparams = (char *)SMB_REALLOC(*pparams,2);
8393 if(*pparams == NULL) {
8394 reply_nterror(req, NT_STATUS_NO_MEMORY);
8401 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
8404 TALLOC_FREE(smb_dname);
8408 /****************************************************************************
8409 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8410 We don't actually do this - we just send a null response.
8411 ****************************************************************************/
8413 static void call_trans2findnotifyfirst(connection_struct *conn,
8414 struct smb_request *req,
8415 char **pparams, int total_params,
8416 char **ppdata, int total_data,
8417 unsigned int max_data_bytes)
8419 char *params = *pparams;
8422 if (total_params < 6) {
8423 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8427 info_level = SVAL(params,4);
8428 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8430 switch (info_level) {
8435 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8439 /* Realloc the parameter and data sizes */
8440 *pparams = (char *)SMB_REALLOC(*pparams,6);
8441 if (*pparams == NULL) {
8442 reply_nterror(req, NT_STATUS_NO_MEMORY);
8447 SSVAL(params,0,fnf_handle);
8448 SSVAL(params,2,0); /* No changes */
8449 SSVAL(params,4,0); /* No EA errors */
8456 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
8461 /****************************************************************************
8462 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8463 changes). Currently this does nothing.
8464 ****************************************************************************/
8466 static void call_trans2findnotifynext(connection_struct *conn,
8467 struct smb_request *req,
8468 char **pparams, int total_params,
8469 char **ppdata, int total_data,
8470 unsigned int max_data_bytes)
8472 char *params = *pparams;
8474 DEBUG(3,("call_trans2findnotifynext\n"));
8476 /* Realloc the parameter and data sizes */
8477 *pparams = (char *)SMB_REALLOC(*pparams,4);
8478 if (*pparams == NULL) {
8479 reply_nterror(req, NT_STATUS_NO_MEMORY);
8484 SSVAL(params,0,0); /* No changes */
8485 SSVAL(params,2,0); /* No EA errors */
8487 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
8492 /****************************************************************************
8493 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8494 ****************************************************************************/
8496 static void call_trans2getdfsreferral(connection_struct *conn,
8497 struct smb_request *req,
8498 char **pparams, int total_params,
8499 char **ppdata, int total_data,
8500 unsigned int max_data_bytes)
8502 char *params = *pparams;
8503 char *pathname = NULL;
8505 int max_referral_level;
8506 NTSTATUS status = NT_STATUS_OK;
8507 TALLOC_CTX *ctx = talloc_tos();
8509 DEBUG(10,("call_trans2getdfsreferral\n"));
8511 if (total_params < 3) {
8512 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8516 max_referral_level = SVAL(params,0);
8518 if(!lp_host_msdfs()) {
8519 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8523 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8524 total_params - 2, STR_TERMINATE);
8526 reply_nterror(req, NT_STATUS_NOT_FOUND);
8529 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8530 ppdata,&status)) < 0) {
8531 reply_nterror(req, status);
8535 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8536 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8537 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
8542 #define LMCAT_SPL 0x53
8543 #define LMFUNC_GETJOBID 0x60
8545 /****************************************************************************
8546 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8547 ****************************************************************************/
8549 static void call_trans2ioctl(connection_struct *conn,
8550 struct smb_request *req,
8551 char **pparams, int total_params,
8552 char **ppdata, int total_data,
8553 unsigned int max_data_bytes)
8555 char *pdata = *ppdata;
8556 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8558 /* check for an invalid fid before proceeding */
8561 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8565 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8566 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8567 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8568 if (*ppdata == NULL) {
8569 reply_nterror(req, NT_STATUS_NO_MEMORY);
8574 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8575 CAN ACCEPT THIS IN UNICODE. JRA. */
8578 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8580 srvstr_push(pdata, req->flags2, pdata + 2,
8581 lp_netbios_name(), 15,
8582 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8583 srvstr_push(pdata, req->flags2, pdata+18,
8584 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8585 STR_ASCII|STR_TERMINATE); /* Service name */
8586 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
8591 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8592 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8595 /****************************************************************************
8596 Reply to a SMBfindclose (stop trans2 directory search).
8597 ****************************************************************************/
8599 void reply_findclose(struct smb_request *req)
8602 struct smbd_server_connection *sconn = req->sconn;
8604 START_PROFILE(SMBfindclose);
8607 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8608 END_PROFILE(SMBfindclose);
8612 dptr_num = SVALS(req->vwv+0, 0);
8614 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8616 dptr_close(sconn, &dptr_num);
8618 reply_outbuf(req, 0, 0);
8620 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8622 END_PROFILE(SMBfindclose);
8626 /****************************************************************************
8627 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8628 ****************************************************************************/
8630 void reply_findnclose(struct smb_request *req)
8634 START_PROFILE(SMBfindnclose);
8637 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8638 END_PROFILE(SMBfindnclose);
8642 dptr_num = SVAL(req->vwv+0, 0);
8644 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8646 /* We never give out valid handles for a
8647 findnotifyfirst - so any dptr_num is ok here.
8650 reply_outbuf(req, 0, 0);
8652 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8654 END_PROFILE(SMBfindnclose);
8658 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8659 struct trans_state *state)
8661 if (get_Protocol() >= PROTOCOL_NT1) {
8662 req->flags2 |= 0x40; /* IS_LONG_NAME */
8663 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8666 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8667 if (state->call != TRANSACT2_QFSINFO &&
8668 state->call != TRANSACT2_SETFSINFO) {
8669 DEBUG(0,("handle_trans2: encryption required "
8671 (unsigned int)state->call));
8672 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8677 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8679 /* Now we must call the relevant TRANS2 function */
8680 switch(state->call) {
8681 case TRANSACT2_OPEN:
8683 START_PROFILE(Trans2_open);
8684 call_trans2open(conn, req,
8685 &state->param, state->total_param,
8686 &state->data, state->total_data,
8687 state->max_data_return);
8688 END_PROFILE(Trans2_open);
8692 case TRANSACT2_FINDFIRST:
8694 START_PROFILE(Trans2_findfirst);
8695 call_trans2findfirst(conn, req,
8696 &state->param, state->total_param,
8697 &state->data, state->total_data,
8698 state->max_data_return);
8699 END_PROFILE(Trans2_findfirst);
8703 case TRANSACT2_FINDNEXT:
8705 START_PROFILE(Trans2_findnext);
8706 call_trans2findnext(conn, req,
8707 &state->param, state->total_param,
8708 &state->data, state->total_data,
8709 state->max_data_return);
8710 END_PROFILE(Trans2_findnext);
8714 case TRANSACT2_QFSINFO:
8716 START_PROFILE(Trans2_qfsinfo);
8717 call_trans2qfsinfo(conn, req,
8718 &state->param, state->total_param,
8719 &state->data, state->total_data,
8720 state->max_data_return);
8721 END_PROFILE(Trans2_qfsinfo);
8725 case TRANSACT2_SETFSINFO:
8727 START_PROFILE(Trans2_setfsinfo);
8728 call_trans2setfsinfo(conn, req,
8729 &state->param, state->total_param,
8730 &state->data, state->total_data,
8731 state->max_data_return);
8732 END_PROFILE(Trans2_setfsinfo);
8736 case TRANSACT2_QPATHINFO:
8737 case TRANSACT2_QFILEINFO:
8739 START_PROFILE(Trans2_qpathinfo);
8740 call_trans2qfilepathinfo(conn, req, state->call,
8741 &state->param, state->total_param,
8742 &state->data, state->total_data,
8743 state->max_data_return);
8744 END_PROFILE(Trans2_qpathinfo);
8748 case TRANSACT2_SETPATHINFO:
8749 case TRANSACT2_SETFILEINFO:
8751 START_PROFILE(Trans2_setpathinfo);
8752 call_trans2setfilepathinfo(conn, req, state->call,
8753 &state->param, state->total_param,
8754 &state->data, state->total_data,
8755 state->max_data_return);
8756 END_PROFILE(Trans2_setpathinfo);
8760 case TRANSACT2_FINDNOTIFYFIRST:
8762 START_PROFILE(Trans2_findnotifyfirst);
8763 call_trans2findnotifyfirst(conn, req,
8764 &state->param, state->total_param,
8765 &state->data, state->total_data,
8766 state->max_data_return);
8767 END_PROFILE(Trans2_findnotifyfirst);
8771 case TRANSACT2_FINDNOTIFYNEXT:
8773 START_PROFILE(Trans2_findnotifynext);
8774 call_trans2findnotifynext(conn, req,
8775 &state->param, state->total_param,
8776 &state->data, state->total_data,
8777 state->max_data_return);
8778 END_PROFILE(Trans2_findnotifynext);
8782 case TRANSACT2_MKDIR:
8784 START_PROFILE(Trans2_mkdir);
8785 call_trans2mkdir(conn, req,
8786 &state->param, state->total_param,
8787 &state->data, state->total_data,
8788 state->max_data_return);
8789 END_PROFILE(Trans2_mkdir);
8793 case TRANSACT2_GET_DFS_REFERRAL:
8795 START_PROFILE(Trans2_get_dfs_referral);
8796 call_trans2getdfsreferral(conn, req,
8797 &state->param, state->total_param,
8798 &state->data, state->total_data,
8799 state->max_data_return);
8800 END_PROFILE(Trans2_get_dfs_referral);
8804 case TRANSACT2_IOCTL:
8806 START_PROFILE(Trans2_ioctl);
8807 call_trans2ioctl(conn, req,
8808 &state->param, state->total_param,
8809 &state->data, state->total_data,
8810 state->max_data_return);
8811 END_PROFILE(Trans2_ioctl);
8816 /* Error in request */
8817 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8818 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8822 /****************************************************************************
8823 Reply to a SMBtrans2.
8824 ****************************************************************************/
8826 void reply_trans2(struct smb_request *req)
8828 connection_struct *conn = req->conn;
8833 unsigned int tran_call;
8834 struct trans_state *state;
8837 START_PROFILE(SMBtrans2);
8839 if (req->wct < 14) {
8840 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8841 END_PROFILE(SMBtrans2);
8845 dsoff = SVAL(req->vwv+12, 0);
8846 dscnt = SVAL(req->vwv+11, 0);
8847 psoff = SVAL(req->vwv+10, 0);
8848 pscnt = SVAL(req->vwv+9, 0);
8849 tran_call = SVAL(req->vwv+14, 0);
8851 result = allow_new_trans(conn->pending_trans, req->mid);
8852 if (!NT_STATUS_IS_OK(result)) {
8853 DEBUG(2, ("Got invalid trans2 request: %s\n",
8854 nt_errstr(result)));
8855 reply_nterror(req, result);
8856 END_PROFILE(SMBtrans2);
8861 switch (tran_call) {
8862 /* List the allowed trans2 calls on IPC$ */
8863 case TRANSACT2_OPEN:
8864 case TRANSACT2_GET_DFS_REFERRAL:
8865 case TRANSACT2_QFILEINFO:
8866 case TRANSACT2_QFSINFO:
8867 case TRANSACT2_SETFSINFO:
8870 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8871 END_PROFILE(SMBtrans2);
8876 if ((state = talloc(conn, struct trans_state)) == NULL) {
8877 DEBUG(0, ("talloc failed\n"));
8878 reply_nterror(req, NT_STATUS_NO_MEMORY);
8879 END_PROFILE(SMBtrans2);
8883 state->cmd = SMBtrans2;
8885 state->mid = req->mid;
8886 state->vuid = req->vuid;
8887 state->setup_count = SVAL(req->vwv+13, 0);
8888 state->setup = NULL;
8889 state->total_param = SVAL(req->vwv+0, 0);
8890 state->param = NULL;
8891 state->total_data = SVAL(req->vwv+1, 0);
8893 state->max_param_return = SVAL(req->vwv+2, 0);
8894 state->max_data_return = SVAL(req->vwv+3, 0);
8895 state->max_setup_return = SVAL(req->vwv+4, 0);
8896 state->close_on_completion = BITSETW(req->vwv+5, 0);
8897 state->one_way = BITSETW(req->vwv+5, 1);
8899 state->call = tran_call;
8901 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8902 is so as a sanity check */
8903 if (state->setup_count != 1) {
8905 * Need to have rc=0 for ioctl to get job id for OS/2.
8906 * Network printing will fail if function is not successful.
8907 * Similar function in reply.c will be used if protocol
8908 * is LANMAN1.0 instead of LM1.2X002.
8909 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8910 * outbuf doesn't have to be set(only job id is used).
8912 if ( (state->setup_count == 4)
8913 && (tran_call == TRANSACT2_IOCTL)
8914 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8915 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8916 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8918 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8919 DEBUG(2,("Transaction is %d\n",tran_call));
8921 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8922 END_PROFILE(SMBtrans2);
8927 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8930 if (state->total_data) {
8932 if (trans_oob(state->total_data, 0, dscnt)
8933 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8937 /* Can't use talloc here, the core routines do realloc on the
8938 * params and data. */
8939 state->data = (char *)SMB_MALLOC(state->total_data);
8940 if (state->data == NULL) {
8941 DEBUG(0,("reply_trans2: data malloc fail for %u "
8942 "bytes !\n", (unsigned int)state->total_data));
8944 reply_nterror(req, NT_STATUS_NO_MEMORY);
8945 END_PROFILE(SMBtrans2);
8949 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8952 if (state->total_param) {
8954 if (trans_oob(state->total_param, 0, pscnt)
8955 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8959 /* Can't use talloc here, the core routines do realloc on the
8960 * params and data. */
8961 state->param = (char *)SMB_MALLOC(state->total_param);
8962 if (state->param == NULL) {
8963 DEBUG(0,("reply_trans: param malloc fail for %u "
8964 "bytes !\n", (unsigned int)state->total_param));
8965 SAFE_FREE(state->data);
8967 reply_nterror(req, NT_STATUS_NO_MEMORY);
8968 END_PROFILE(SMBtrans2);
8972 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8975 state->received_data = dscnt;
8976 state->received_param = pscnt;
8978 if ((state->received_param == state->total_param) &&
8979 (state->received_data == state->total_data)) {
8981 handle_trans2(conn, req, state);
8983 SAFE_FREE(state->data);
8984 SAFE_FREE(state->param);
8986 END_PROFILE(SMBtrans2);
8990 DLIST_ADD(conn->pending_trans, state);
8992 /* We need to send an interim response then receive the rest
8993 of the parameter/data bytes */
8994 reply_outbuf(req, 0, 0);
8995 show_msg((char *)req->outbuf);
8996 END_PROFILE(SMBtrans2);
9001 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9002 SAFE_FREE(state->data);
9003 SAFE_FREE(state->param);
9005 END_PROFILE(SMBtrans2);
9006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9010 /****************************************************************************
9011 Reply to a SMBtranss2
9012 ****************************************************************************/
9014 void reply_transs2(struct smb_request *req)
9016 connection_struct *conn = req->conn;
9017 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9018 struct trans_state *state;
9020 START_PROFILE(SMBtranss2);
9022 show_msg((const char *)req->inbuf);
9024 /* Windows clients expect all replies to
9025 a transact secondary (SMBtranss2 0x33)
9026 to have a command code of transact
9027 (SMBtrans2 0x32). See bug #8989
9028 and also [MS-CIFS] section 2.2.4.47.2
9031 req->cmd = SMBtrans2;
9034 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9035 END_PROFILE(SMBtranss2);
9039 for (state = conn->pending_trans; state != NULL;
9040 state = state->next) {
9041 if (state->mid == req->mid) {
9046 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9047 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9048 END_PROFILE(SMBtranss2);
9052 /* Revise state->total_param and state->total_data in case they have
9053 changed downwards */
9055 if (SVAL(req->vwv+0, 0) < state->total_param)
9056 state->total_param = SVAL(req->vwv+0, 0);
9057 if (SVAL(req->vwv+1, 0) < state->total_data)
9058 state->total_data = SVAL(req->vwv+1, 0);
9060 pcnt = SVAL(req->vwv+2, 0);
9061 poff = SVAL(req->vwv+3, 0);
9062 pdisp = SVAL(req->vwv+4, 0);
9064 dcnt = SVAL(req->vwv+5, 0);
9065 doff = SVAL(req->vwv+6, 0);
9066 ddisp = SVAL(req->vwv+7, 0);
9068 state->received_param += pcnt;
9069 state->received_data += dcnt;
9071 if ((state->received_data > state->total_data) ||
9072 (state->received_param > state->total_param))
9076 if (trans_oob(state->total_param, pdisp, pcnt)
9077 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9080 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9084 if (trans_oob(state->total_data, ddisp, dcnt)
9085 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9088 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9091 if ((state->received_param < state->total_param) ||
9092 (state->received_data < state->total_data)) {
9093 END_PROFILE(SMBtranss2);
9097 handle_trans2(conn, req, state);
9099 DLIST_REMOVE(conn->pending_trans, state);
9100 SAFE_FREE(state->data);
9101 SAFE_FREE(state->param);
9104 END_PROFILE(SMBtranss2);
9109 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9110 DLIST_REMOVE(conn->pending_trans, state);
9111 SAFE_FREE(state->data);
9112 SAFE_FREE(state->param);
9114 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9115 END_PROFILE(SMBtranss2);