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/>.
27 #include "system/filesys.h"
29 #include "smbd/smbd.h"
30 #include "smbd/globals.h"
31 #include "../libcli/auth/libcli_auth.h"
32 #include "../librpc/gen_ndr/xattr.h"
33 #include "../librpc/gen_ndr/ndr_security.h"
34 #include "../librpc/gen_ndr/open_files.h"
35 #include "libcli/security/security.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
42 #define DIR_ENTRY_SAFETY_MARGIN 4096
44 static char *store_file_unix_basic(connection_struct *conn,
47 const SMB_STRUCT_STAT *psbuf);
49 static char *store_file_unix_basic_info2(connection_struct *conn,
52 const SMB_STRUCT_STAT *psbuf);
54 /********************************************************************
55 The canonical "check access" based on object handle or path function.
56 ********************************************************************/
58 NTSTATUS check_access(connection_struct *conn,
60 const struct smb_filename *smb_fname,
64 if (!(fsp->access_mask & access_mask)) {
65 return NT_STATUS_ACCESS_DENIED;
68 NTSTATUS status = smbd_check_access_rights(conn,
71 if (!NT_STATUS_IS_OK(status)) {
78 /********************************************************************
79 Roundup a value to the nearest allocation roundup size boundary.
80 Only do this for Windows clients.
81 ********************************************************************/
83 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
85 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
87 /* Only roundup for Windows clients. */
88 enum remote_arch_types ra_type = get_remote_arch();
89 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
90 val = SMB_ROUNDUP(val,rval);
95 /********************************************************************
96 Create a 64 bit FileIndex. If the file is on the same device as
97 the root of the share, just return the 64-bit inode. If it isn't,
98 mangle as we used to do.
99 ********************************************************************/
101 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
104 if (conn->base_share_dev == psbuf->st_ex_dev) {
105 return (uint64_t)psbuf->st_ex_ino;
107 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
108 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
112 /****************************************************************************
113 Utility functions for dealing with extended attributes.
114 ****************************************************************************/
116 /****************************************************************************
117 Refuse to allow clients to overwrite our private xattrs.
118 ****************************************************************************/
120 static bool samba_private_attr_name(const char *unix_ea_name)
122 static const char * const prohibited_ea_names[] = {
123 SAMBA_POSIX_INHERITANCE_EA_NAME,
124 SAMBA_XATTR_DOS_ATTRIB,
132 for (i = 0; prohibited_ea_names[i]; i++) {
133 if (strequal( prohibited_ea_names[i], unix_ea_name))
136 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
137 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
143 /****************************************************************************
144 Get one EA value. Fill in a struct ea_struct.
145 ****************************************************************************/
147 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
148 files_struct *fsp, const char *fname,
149 const char *ea_name, struct ea_struct *pea)
151 /* Get the value of this xattr. Max size is 64k. */
152 size_t attr_size = 256;
158 val = talloc_realloc(mem_ctx, val, char, attr_size);
160 return NT_STATUS_NO_MEMORY;
163 if (fsp && fsp->fh->fd != -1) {
164 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
166 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
169 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
175 return map_nt_error_from_unix(errno);
178 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
179 dump_data(10, (uint8 *)val, sizeret);
182 if (strnequal(ea_name, "user.", 5)) {
183 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
185 pea->name = talloc_strdup(mem_ctx, ea_name);
187 if (pea->name == NULL) {
189 return NT_STATUS_NO_MEMORY;
191 pea->value.data = (unsigned char *)val;
192 pea->value.length = (size_t)sizeret;
196 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
197 files_struct *fsp, const char *fname,
198 char ***pnames, size_t *pnum_names)
200 /* Get a list of all xattrs. Max namesize is 64k. */
201 size_t ea_namelist_size = 1024;
202 char *ea_namelist = NULL;
207 ssize_t sizeret = -1;
209 if (!lp_ea_support(SNUM(conn))) {
218 * TALLOC the result early to get the talloc hierarchy right.
221 names = talloc_array(mem_ctx, char *, 1);
223 DEBUG(0, ("talloc failed\n"));
224 return NT_STATUS_NO_MEMORY;
227 while (ea_namelist_size <= 65536) {
229 ea_namelist = talloc_realloc(
230 names, ea_namelist, char, ea_namelist_size);
231 if (ea_namelist == NULL) {
232 DEBUG(0, ("talloc failed\n"));
234 return NT_STATUS_NO_MEMORY;
237 if (fsp && fsp->fh->fd != -1) {
238 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
241 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
245 if ((sizeret == -1) && (errno == ERANGE)) {
246 ea_namelist_size *= 2;
255 return map_nt_error_from_unix(errno);
258 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
259 (unsigned int)sizeret));
271 * Ensure the result is 0-terminated
274 if (ea_namelist[sizeret-1] != '\0') {
276 return NT_STATUS_INTERNAL_ERROR;
284 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
288 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
290 DEBUG(0, ("talloc failed\n"));
292 return NT_STATUS_NO_MEMORY;
298 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
299 names[num_names++] = p;
307 *pnum_names = num_names;
311 /****************************************************************************
312 Return a linked list of the total EA's. Plus the total size
313 ****************************************************************************/
315 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
316 const char *fname, size_t *pea_total_len, struct ea_list **ea_list)
318 /* Get a list of all xattrs. Max namesize is 64k. */
321 struct ea_list *ea_list_head = NULL;
326 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
329 if (!NT_STATUS_IS_OK(status)) {
333 if (num_names == 0) {
338 for (i=0; i<num_names; i++) {
339 struct ea_list *listp;
342 if (strnequal(names[i], "system.", 7)
343 || samba_private_attr_name(names[i]))
346 listp = talloc(mem_ctx, struct ea_list);
348 return NT_STATUS_NO_MEMORY;
351 status = get_ea_value(mem_ctx, conn, fsp,
355 if (!NT_STATUS_IS_OK(status)) {
359 push_ascii_fstring(dos_ea_name, listp->ea.name);
362 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
364 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
365 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
366 (unsigned int)listp->ea.value.length));
368 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
372 /* Add on 4 for total length. */
373 if (*pea_total_len) {
377 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
378 (unsigned int)*pea_total_len));
380 *ea_list = ea_list_head;
384 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
385 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
390 if (!lp_ea_support(SNUM(conn))) {
394 if (is_ntfs_stream_smb_fname(smb_fname)) {
395 return NT_STATUS_INVALID_PARAMETER;
398 return get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, pea_total_len, ea_list);
401 /****************************************************************************
402 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
404 ****************************************************************************/
406 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
407 connection_struct *conn, struct ea_list *ea_list)
409 unsigned int ret_data_size = 4;
412 SMB_ASSERT(total_data_size >= 4);
414 if (!lp_ea_support(SNUM(conn))) {
419 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
422 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
423 dos_namelen = strlen(dos_ea_name);
424 if (dos_namelen > 255 || dos_namelen == 0) {
427 if (ea_list->ea.value.length > 65535) {
430 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
434 /* We know we have room. */
435 SCVAL(p,0,ea_list->ea.flags);
436 SCVAL(p,1,dos_namelen);
437 SSVAL(p,2,ea_list->ea.value.length);
438 strlcpy(p+4, dos_ea_name, dos_namelen+1);
439 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
441 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
442 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
445 ret_data_size = PTR_DIFF(p, pdata);
446 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
447 SIVAL(pdata,0,ret_data_size);
448 return ret_data_size;
451 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
453 unsigned int total_data_size,
454 unsigned int *ret_data_size,
455 connection_struct *conn,
456 struct ea_list *ea_list)
458 uint8_t *p = (uint8_t *)pdata;
459 uint8_t *last_start = NULL;
463 if (!lp_ea_support(SNUM(conn))) {
464 return NT_STATUS_NO_EAS_ON_FILE;
467 for (; ea_list; ea_list = ea_list->next) {
473 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
477 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
478 dos_namelen = strlen(dos_ea_name);
479 if (dos_namelen > 255 || dos_namelen == 0) {
480 return NT_STATUS_INTERNAL_ERROR;
482 if (ea_list->ea.value.length > 65535) {
483 return NT_STATUS_INTERNAL_ERROR;
486 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
489 size_t pad = 4 - (this_size % 4);
493 if (this_size > total_data_size) {
494 return NT_STATUS_INFO_LENGTH_MISMATCH;
497 /* We know we have room. */
498 SIVAL(p, 0x00, 0); /* next offset */
499 SCVAL(p, 0x04, ea_list->ea.flags);
500 SCVAL(p, 0x05, dos_namelen);
501 SSVAL(p, 0x06, ea_list->ea.value.length);
502 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
503 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
505 total_data_size -= this_size;
509 *ret_data_size = PTR_DIFF(p, pdata);
510 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
514 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
516 size_t total_ea_len = 0;
518 struct ea_list *ea_list;
520 if (!lp_ea_support(SNUM(conn))) {
523 mem_ctx = talloc_stackframe();
525 /* If this is a stream fsp, then we need to instead find the
526 * estimated ea len from the main file, not the stream
527 * (streams cannot have EAs), but the estimate isn't just 0 in
529 if (is_ntfs_stream_smb_fname(smb_fname)) {
532 (void)get_ea_list_from_file_path(mem_ctx, conn, fsp, smb_fname->base_name, &total_ea_len, &ea_list);
533 TALLOC_FREE(mem_ctx);
537 /****************************************************************************
538 Ensure the EA name is case insensitive by matching any existing EA name.
539 ****************************************************************************/
541 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
544 TALLOC_CTX *mem_ctx = talloc_tos();
545 struct ea_list *ea_list;
546 NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
547 if (!NT_STATUS_IS_OK(status)) {
551 for (; ea_list; ea_list = ea_list->next) {
552 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
553 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
554 &unix_ea_name[5], ea_list->ea.name));
555 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
561 /****************************************************************************
562 Set or delete an extended attribute.
563 ****************************************************************************/
565 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
566 const struct smb_filename *smb_fname, struct ea_list *ea_list)
571 if (!lp_ea_support(SNUM(conn))) {
572 return NT_STATUS_EAS_NOT_SUPPORTED;
575 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
576 if (!NT_STATUS_IS_OK(status)) {
580 /* Setting EAs on streams isn't supported. */
581 if (is_ntfs_stream_smb_fname(smb_fname)) {
582 return NT_STATUS_INVALID_PARAMETER;
585 fname = smb_fname->base_name;
587 for (;ea_list; ea_list = ea_list->next) {
589 fstring unix_ea_name;
591 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
592 fstrcat(unix_ea_name, ea_list->ea.name);
594 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
596 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
598 if (samba_private_attr_name(unix_ea_name)) {
599 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
600 return NT_STATUS_ACCESS_DENIED;
603 if (ea_list->ea.value.length == 0) {
604 /* Remove the attribute. */
605 if (fsp && (fsp->fh->fd != -1)) {
606 DEBUG(10,("set_ea: deleting ea name %s on "
607 "file %s by file descriptor.\n",
608 unix_ea_name, fsp_str_dbg(fsp)));
609 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
611 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
612 unix_ea_name, fname));
613 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
616 /* Removing a non existent attribute always succeeds. */
617 if (ret == -1 && errno == ENOATTR) {
618 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
624 if (fsp && (fsp->fh->fd != -1)) {
625 DEBUG(10,("set_ea: setting ea name %s on file "
626 "%s by file descriptor.\n",
627 unix_ea_name, fsp_str_dbg(fsp)));
628 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
629 ea_list->ea.value.data, ea_list->ea.value.length, 0);
631 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
632 unix_ea_name, fname));
633 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
634 ea_list->ea.value.data, ea_list->ea.value.length, 0);
640 if (errno == ENOTSUP) {
641 return NT_STATUS_EAS_NOT_SUPPORTED;
644 return map_nt_error_from_unix(errno);
650 /****************************************************************************
651 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
652 ****************************************************************************/
654 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
656 struct ea_list *ea_list_head = NULL;
657 size_t converted_size, offset = 0;
659 while (offset + 2 < data_size) {
660 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
661 unsigned int namelen = CVAL(pdata,offset);
663 offset++; /* Go past the namelen byte. */
665 /* integer wrap paranioa. */
666 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
667 (offset > data_size) || (namelen > data_size) ||
668 (offset + namelen >= data_size)) {
671 /* Ensure the name is null terminated. */
672 if (pdata[offset + namelen] != '\0') {
675 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
677 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
678 "failed: %s", strerror(errno)));
684 offset += (namelen + 1); /* Go past the name + terminating zero. */
685 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
686 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
692 /****************************************************************************
693 Read one EA list entry from the buffer.
694 ****************************************************************************/
696 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
698 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
700 unsigned int namelen;
701 size_t converted_size;
711 eal->ea.flags = CVAL(pdata,0);
712 namelen = CVAL(pdata,1);
713 val_len = SVAL(pdata,2);
715 if (4 + namelen + 1 + val_len > data_size) {
719 /* Ensure the name is null terminated. */
720 if (pdata[namelen + 4] != '\0') {
723 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
724 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
731 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
732 if (!eal->ea.value.data) {
736 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
738 /* Ensure we're null terminated just in case we print the value. */
739 eal->ea.value.data[val_len] = '\0';
740 /* But don't count the null. */
741 eal->ea.value.length--;
744 *pbytes_used = 4 + namelen + 1 + val_len;
747 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
748 dump_data(10, eal->ea.value.data, eal->ea.value.length);
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,
846 /* As we are using a protocol > LANMAN1 then the max_send
847 variable must have been set in the sessetupX call.
848 This takes precedence over the max_xmit field in the
849 global struct. These different max_xmit variables should
850 be merged as this is now too confusing */
852 int data_to_send = datasize;
853 int params_to_send = paramsize;
855 const char *pp = params;
856 const char *pd = pdata;
857 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
858 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
859 int data_alignment_offset = 0;
860 bool overflow = False;
861 struct smbd_server_connection *sconn = req->sconn;
862 int max_send = sconn->smb1.sessions.max_send;
864 /* Modify the data_to_send and datasize and set the error if
865 we're trying to send more than max_data_bytes. We still send
866 the part of the packet(s) that fit. Strange, but needed
869 if (max_data_bytes > 0 && datasize > max_data_bytes) {
870 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
871 max_data_bytes, datasize ));
872 datasize = data_to_send = max_data_bytes;
876 /* If there genuinely are no parameters or data to send just send the empty packet */
878 if(params_to_send == 0 && data_to_send == 0) {
879 reply_outbuf(req, 10, 0);
880 show_msg((char *)req->outbuf);
881 if (!srv_send_smb(sconn,
884 IS_CONN_ENCRYPTED(conn),
886 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
888 TALLOC_FREE(req->outbuf);
892 /* When sending params and data ensure that both are nicely aligned */
893 /* Only do this alignment when there is also data to send - else
894 can cause NT redirector problems. */
896 if (((params_to_send % 4) != 0) && (data_to_send != 0))
897 data_alignment_offset = 4 - (params_to_send % 4);
899 /* Space is bufsize minus Netbios over TCP header minus SMB header */
900 /* The alignment_offset is to align the param bytes on an even byte
901 boundary. NT 4.0 Beta needs this to work correctly. */
903 useable_space = max_send - (smb_size
906 + data_alignment_offset);
908 if (useable_space < 0) {
909 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
910 "= %d!!!", useable_space));
911 exit_server_cleanly("send_trans2_replies: Not enough space");
914 while (params_to_send || data_to_send) {
915 /* Calculate whether we will totally or partially fill this packet */
917 total_sent_thistime = params_to_send + data_to_send;
919 /* We can never send more than useable_space */
921 * Note that 'useable_space' does not include the alignment offsets,
922 * but we must include the alignment offsets in the calculation of
923 * the length of the data we send over the wire, as the alignment offsets
924 * are sent here. Fix from Marc_Jacobsen@hp.com.
927 total_sent_thistime = MIN(total_sent_thistime, useable_space);
929 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
930 + data_alignment_offset);
932 /* Set total params and data to be sent */
933 SSVAL(req->outbuf,smb_tprcnt,paramsize);
934 SSVAL(req->outbuf,smb_tdrcnt,datasize);
936 /* Calculate how many parameters and data we can fit into
937 * this packet. Parameters get precedence
940 params_sent_thistime = MIN(params_to_send,useable_space);
941 data_sent_thistime = useable_space - params_sent_thistime;
942 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
944 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
946 /* smb_proff is the offset from the start of the SMB header to the
947 parameter bytes, however the first 4 bytes of outbuf are
948 the Netbios over TCP header. Thus use smb_base() to subtract
949 them from the calculation */
951 SSVAL(req->outbuf,smb_proff,
952 ((smb_buf(req->outbuf)+alignment_offset)
953 - smb_base(req->outbuf)));
955 if(params_sent_thistime == 0)
956 SSVAL(req->outbuf,smb_prdisp,0);
958 /* Absolute displacement of param bytes sent in this packet */
959 SSVAL(req->outbuf,smb_prdisp,pp - params);
961 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
962 if(data_sent_thistime == 0) {
963 SSVAL(req->outbuf,smb_droff,0);
964 SSVAL(req->outbuf,smb_drdisp, 0);
966 /* The offset of the data bytes is the offset of the
967 parameter bytes plus the number of parameters being sent this time */
968 SSVAL(req->outbuf, smb_droff,
969 ((smb_buf(req->outbuf)+alignment_offset)
970 - smb_base(req->outbuf))
971 + params_sent_thistime + data_alignment_offset);
972 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
975 /* Initialize the padding for alignment */
977 if (alignment_offset != 0) {
978 memset(smb_buf(req->outbuf), 0, alignment_offset);
981 /* Copy the param bytes into the packet */
983 if(params_sent_thistime) {
984 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
985 params_sent_thistime);
988 /* Copy in the data bytes */
989 if(data_sent_thistime) {
990 if (data_alignment_offset != 0) {
991 memset((smb_buf(req->outbuf)+alignment_offset+
992 params_sent_thistime), 0,
993 data_alignment_offset);
995 memcpy(smb_buf(req->outbuf)+alignment_offset
996 +params_sent_thistime+data_alignment_offset,
997 pd,data_sent_thistime);
1000 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1001 params_sent_thistime, data_sent_thistime, useable_space));
1002 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1003 params_to_send, data_to_send, paramsize, datasize));
1006 error_packet_set((char *)req->outbuf,
1007 ERRDOS,ERRbufferoverflow,
1008 STATUS_BUFFER_OVERFLOW,
1012 /* Send the packet */
1013 show_msg((char *)req->outbuf);
1014 if (!srv_send_smb(sconn,
1015 (char *)req->outbuf,
1016 true, req->seqnum+1,
1017 IS_CONN_ENCRYPTED(conn),
1019 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1021 TALLOC_FREE(req->outbuf);
1023 pp += params_sent_thistime;
1024 pd += data_sent_thistime;
1026 params_to_send -= params_sent_thistime;
1027 data_to_send -= data_sent_thistime;
1030 if(params_to_send < 0 || data_to_send < 0) {
1031 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1032 params_to_send, data_to_send));
1040 /****************************************************************************
1041 Reply to a TRANSACT2_OPEN.
1042 ****************************************************************************/
1044 static void call_trans2open(connection_struct *conn,
1045 struct smb_request *req,
1046 char **pparams, int total_params,
1047 char **ppdata, int total_data,
1048 unsigned int max_data_bytes)
1050 struct smb_filename *smb_fname = NULL;
1051 char *params = *pparams;
1052 char *pdata = *ppdata;
1055 bool oplock_request;
1057 bool return_additional_info;
1066 int fattr=0,mtime=0;
1067 SMB_INO_T inode = 0;
1070 struct ea_list *ea_list = NULL;
1075 uint32 create_disposition;
1076 uint32 create_options = 0;
1077 uint32_t private_flags = 0;
1078 TALLOC_CTX *ctx = talloc_tos();
1081 * Ensure we have enough parameters to perform the operation.
1084 if (total_params < 29) {
1085 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1089 flags = SVAL(params, 0);
1090 deny_mode = SVAL(params, 2);
1091 open_attr = SVAL(params,6);
1092 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1093 if (oplock_request) {
1094 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1098 return_additional_info = BITSETW(params,0);
1099 open_sattr = SVAL(params, 4);
1100 open_time = make_unix_date3(params+8);
1102 open_ofun = SVAL(params,12);
1103 open_size = IVAL(params,14);
1104 pname = ¶ms[28];
1107 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1111 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1112 total_params - 28, STR_TERMINATE,
1114 if (!NT_STATUS_IS_OK(status)) {
1115 reply_nterror(req, status);
1119 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1120 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1121 (unsigned int)open_ofun, open_size));
1123 status = filename_convert(ctx,
1125 req->flags2 & FLAGS2_DFS_PATHNAMES,
1130 if (!NT_STATUS_IS_OK(status)) {
1131 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1132 reply_botherror(req,
1133 NT_STATUS_PATH_NOT_COVERED,
1134 ERRSRV, ERRbadpath);
1137 reply_nterror(req, status);
1141 if (open_ofun == 0) {
1142 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1146 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1148 &access_mask, &share_mode,
1149 &create_disposition,
1152 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1156 /* Any data in this call is an EA list. */
1157 if (total_data && (total_data != 4)) {
1158 if (total_data < 10) {
1159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1163 if (IVAL(pdata,0) > total_data) {
1164 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1165 IVAL(pdata,0), (unsigned int)total_data));
1166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1170 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1173 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1177 if (!lp_ea_support(SNUM(conn))) {
1178 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1183 status = SMB_VFS_CREATE_FILE(
1186 0, /* root_dir_fid */
1187 smb_fname, /* fname */
1188 access_mask, /* access_mask */
1189 share_mode, /* share_access */
1190 create_disposition, /* create_disposition*/
1191 create_options, /* create_options */
1192 open_attr, /* file_attributes */
1193 oplock_request, /* oplock_request */
1194 open_size, /* allocation_size */
1197 ea_list, /* ea_list */
1199 &smb_action); /* psbuf */
1201 if (!NT_STATUS_IS_OK(status)) {
1202 if (open_was_deferred(req->sconn, req->mid)) {
1203 /* We have re-scheduled this call. */
1206 reply_openerror(req, status);
1210 size = get_file_size_stat(&smb_fname->st);
1211 fattr = dos_mode(conn, smb_fname);
1212 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1213 inode = smb_fname->st.st_ex_ino;
1214 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1215 close_file(req, fsp, ERROR_CLOSE);
1216 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1220 /* Realloc the size of parameters and data we will return */
1221 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1222 if(*pparams == NULL ) {
1223 reply_nterror(req, NT_STATUS_NO_MEMORY);
1228 SSVAL(params,0,fsp->fnum);
1229 SSVAL(params,2,fattr);
1230 srv_put_dos_date2(params,4, mtime);
1231 SIVAL(params,8, (uint32)size);
1232 SSVAL(params,12,deny_mode);
1233 SSVAL(params,14,0); /* open_type - file or directory. */
1234 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1236 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1237 smb_action |= EXTENDED_OPLOCK_GRANTED;
1240 SSVAL(params,18,smb_action);
1243 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1245 SIVAL(params,20,inode);
1246 SSVAL(params,24,0); /* Padding. */
1248 uint32 ea_size = estimate_ea_size(conn, fsp,
1250 SIVAL(params, 26, ea_size);
1252 SIVAL(params, 26, 0);
1255 /* Send the required number of replies */
1256 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1258 TALLOC_FREE(smb_fname);
1261 /*********************************************************
1262 Routine to check if a given string matches exactly.
1263 as a special case a mask of "." does NOT match. That
1264 is required for correct wildcard semantics
1265 Case can be significant or not.
1266 **********************************************************/
1268 static bool exact_match(bool has_wild,
1269 bool case_sensitive,
1273 if (mask[0] == '.' && mask[1] == 0) {
1281 if (case_sensitive) {
1282 return strcmp(str,mask)==0;
1284 return strcasecmp_m(str,mask) == 0;
1288 /****************************************************************************
1289 Return the filetype for UNIX extensions.
1290 ****************************************************************************/
1292 static uint32 unix_filetype(mode_t mode)
1295 return UNIX_TYPE_FILE;
1296 else if(S_ISDIR(mode))
1297 return UNIX_TYPE_DIR;
1299 else if(S_ISLNK(mode))
1300 return UNIX_TYPE_SYMLINK;
1303 else if(S_ISCHR(mode))
1304 return UNIX_TYPE_CHARDEV;
1307 else if(S_ISBLK(mode))
1308 return UNIX_TYPE_BLKDEV;
1311 else if(S_ISFIFO(mode))
1312 return UNIX_TYPE_FIFO;
1315 else if(S_ISSOCK(mode))
1316 return UNIX_TYPE_SOCKET;
1319 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1320 return UNIX_TYPE_UNKNOWN;
1323 /****************************************************************************
1324 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1325 ****************************************************************************/
1327 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1329 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1330 const SMB_STRUCT_STAT *psbuf,
1332 enum perm_type ptype,
1337 if (perms == SMB_MODE_NO_CHANGE) {
1338 if (!VALID_STAT(*psbuf)) {
1339 return NT_STATUS_INVALID_PARAMETER;
1341 *ret_perms = psbuf->st_ex_mode;
1342 return NT_STATUS_OK;
1346 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1347 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1348 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1349 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1350 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1351 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1352 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1353 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1354 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1356 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1359 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1362 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1367 case PERM_EXISTING_FILE:
1368 /* Apply mode mask */
1369 ret &= lp_create_mask(SNUM(conn));
1370 /* Add in force bits */
1371 ret |= lp_force_create_mode(SNUM(conn));
1374 case PERM_EXISTING_DIR:
1375 ret &= lp_dir_mask(SNUM(conn));
1376 /* Add in force bits */
1377 ret |= lp_force_dir_mode(SNUM(conn));
1382 return NT_STATUS_OK;
1385 /****************************************************************************
1386 Needed to show the msdfs symlinks as directories. Modifies psbuf
1387 to be a directory if it's a msdfs link.
1388 ****************************************************************************/
1390 static bool check_msdfs_link(connection_struct *conn,
1391 const char *pathname,
1392 SMB_STRUCT_STAT *psbuf)
1394 int saved_errno = errno;
1395 if(lp_host_msdfs() &&
1396 lp_msdfs_root(SNUM(conn)) &&
1397 is_msdfs_link(conn, pathname, psbuf)) {
1399 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1402 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1403 errno = saved_errno;
1406 errno = saved_errno;
1411 /****************************************************************************
1412 Get a level dependent lanman2 dir entry.
1413 ****************************************************************************/
1415 struct smbd_dirptr_lanman2_state {
1416 connection_struct *conn;
1417 uint32_t info_level;
1418 bool check_mangled_names;
1420 bool got_exact_match;
1423 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1429 struct smbd_dirptr_lanman2_state *state =
1430 (struct smbd_dirptr_lanman2_state *)private_data;
1432 char mangled_name[13]; /* mangled 8.3 name. */
1436 /* Mangle fname if it's an illegal name. */
1437 if (mangle_must_mangle(dname, state->conn->params)) {
1438 ok = name_to_8_3(dname, mangled_name,
1439 true, state->conn->params);
1443 fname = mangled_name;
1448 got_match = exact_match(state->has_wild,
1449 state->conn->case_sensitive,
1451 state->got_exact_match = got_match;
1453 got_match = mask_match(fname, mask,
1454 state->conn->case_sensitive);
1457 if(!got_match && state->check_mangled_names &&
1458 !mangle_is_8_3(fname, false, state->conn->params)) {
1460 * It turns out that NT matches wildcards against
1461 * both long *and* short names. This may explain some
1462 * of the wildcard wierdness from old DOS clients
1463 * that some people have been seeing.... JRA.
1465 /* Force the mangling into 8.3. */
1466 ok = name_to_8_3(fname, mangled_name,
1467 false, state->conn->params);
1472 got_match = exact_match(state->has_wild,
1473 state->conn->case_sensitive,
1474 mangled_name, mask);
1475 state->got_exact_match = got_match;
1477 got_match = mask_match(mangled_name, mask,
1478 state->conn->case_sensitive);
1486 *_fname = talloc_strdup(ctx, fname);
1487 if (*_fname == NULL) {
1494 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1496 struct smb_filename *smb_fname,
1499 struct smbd_dirptr_lanman2_state *state =
1500 (struct smbd_dirptr_lanman2_state *)private_data;
1501 bool ms_dfs_link = false;
1504 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1505 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1506 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1507 "Couldn't lstat [%s] (%s)\n",
1508 smb_fname_str_dbg(smb_fname),
1512 } else if (!VALID_STAT(smb_fname->st) &&
1513 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1514 /* Needed to show the msdfs symlinks as
1517 ms_dfs_link = check_msdfs_link(state->conn,
1518 smb_fname->base_name,
1521 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1522 "Couldn't stat [%s] (%s)\n",
1523 smb_fname_str_dbg(smb_fname),
1530 mode = dos_mode_msdfs(state->conn, smb_fname);
1532 mode = dos_mode(state->conn, smb_fname);
1539 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1540 connection_struct *conn,
1542 uint32_t info_level,
1543 struct ea_list *name_list,
1544 bool check_mangled_names,
1545 bool requires_resume_key,
1548 const struct smb_filename *smb_fname,
1549 int space_remaining,
1556 uint64_t *last_entry_off)
1558 char *p, *q, *pdata = *ppdata;
1560 uint64_t file_size = 0;
1561 uint64_t allocation_size = 0;
1562 uint64_t file_index = 0;
1564 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1565 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1567 char *last_entry_ptr;
1572 *out_of_space = false;
1574 ZERO_STRUCT(mdate_ts);
1575 ZERO_STRUCT(adate_ts);
1576 ZERO_STRUCT(create_date_ts);
1577 ZERO_STRUCT(cdate_ts);
1579 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1580 file_size = get_file_size_stat(&smb_fname->st);
1582 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1584 file_index = get_FileIndex(conn, &smb_fname->st);
1586 mdate_ts = smb_fname->st.st_ex_mtime;
1587 adate_ts = smb_fname->st.st_ex_atime;
1588 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1589 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1591 if (lp_dos_filetime_resolution(SNUM(conn))) {
1592 dos_filetime_timespec(&create_date_ts);
1593 dos_filetime_timespec(&mdate_ts);
1594 dos_filetime_timespec(&adate_ts);
1595 dos_filetime_timespec(&cdate_ts);
1598 create_date = convert_timespec_to_time_t(create_date_ts);
1599 mdate = convert_timespec_to_time_t(mdate_ts);
1600 adate = convert_timespec_to_time_t(adate_ts);
1602 /* align the record */
1603 SMB_ASSERT(align >= 1);
1605 off = (int)PTR_DIFF(pdata, base_data);
1606 pad = (off + (align-1)) & ~(align-1);
1609 if (pad && pad > space_remaining) {
1610 *out_of_space = true;
1611 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1612 "for padding (wanted %u, had %d)\n",
1615 return false; /* Not finished - just out of space */
1619 /* initialize padding to 0 */
1621 memset(pdata, 0, pad);
1623 space_remaining -= pad;
1625 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1635 switch (info_level) {
1636 case SMB_FIND_INFO_STANDARD:
1637 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1638 if(requires_resume_key) {
1642 srv_put_dos_date2(p,0,create_date);
1643 srv_put_dos_date2(p,4,adate);
1644 srv_put_dos_date2(p,8,mdate);
1645 SIVAL(p,12,(uint32)file_size);
1646 SIVAL(p,16,(uint32)allocation_size);
1650 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1651 p += ucs2_align(base_data, p, 0);
1653 len = srvstr_push(base_data, flags2, p,
1654 fname, PTR_DIFF(end_data, p),
1656 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1658 SCVAL(nameptr, -1, len - 2);
1660 SCVAL(nameptr, -1, 0);
1664 SCVAL(nameptr, -1, len - 1);
1666 SCVAL(nameptr, -1, 0);
1672 case SMB_FIND_EA_SIZE:
1673 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1674 if (requires_resume_key) {
1678 srv_put_dos_date2(p,0,create_date);
1679 srv_put_dos_date2(p,4,adate);
1680 srv_put_dos_date2(p,8,mdate);
1681 SIVAL(p,12,(uint32)file_size);
1682 SIVAL(p,16,(uint32)allocation_size);
1685 unsigned int ea_size = estimate_ea_size(conn, NULL,
1687 SIVAL(p,22,ea_size); /* Extended attributes */
1691 len = srvstr_push(base_data, flags2,
1692 p, fname, PTR_DIFF(end_data, p),
1693 STR_TERMINATE | STR_NOALIGN);
1694 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1707 SCVAL(nameptr,0,len);
1709 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1712 case SMB_FIND_EA_LIST:
1714 struct ea_list *file_list = NULL;
1718 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1722 if (requires_resume_key) {
1726 srv_put_dos_date2(p,0,create_date);
1727 srv_put_dos_date2(p,4,adate);
1728 srv_put_dos_date2(p,8,mdate);
1729 SIVAL(p,12,(uint32)file_size);
1730 SIVAL(p,16,(uint32)allocation_size);
1732 p += 22; /* p now points to the EA area. */
1734 status = get_ea_list_from_file(ctx, conn, NULL,
1736 &ea_len, &file_list);
1737 if (!NT_STATUS_IS_OK(status)) {
1740 name_list = ea_list_union(name_list, file_list, &ea_len);
1742 /* We need to determine if this entry will fit in the space available. */
1743 /* Max string size is 255 bytes. */
1744 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1745 *out_of_space = true;
1746 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1747 "(wanted %u, had %d)\n",
1748 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1750 return False; /* Not finished - just out of space */
1753 /* Push the ea_data followed by the name. */
1754 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1756 len = srvstr_push(base_data, flags2,
1757 p + 1, fname, PTR_DIFF(end_data, p+1),
1758 STR_TERMINATE | STR_NOALIGN);
1759 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1772 SCVAL(nameptr,0,len);
1774 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1778 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1779 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1780 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1782 SIVAL(p,0,reskey); p += 4;
1783 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1784 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1785 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1787 SOFF_T(p,0,file_size); p += 8;
1788 SOFF_T(p,0,allocation_size); p += 8;
1789 SIVAL(p,0,mode); p += 4;
1790 q = p; p += 4; /* q is placeholder for name length. */
1792 unsigned int ea_size = estimate_ea_size(conn, NULL,
1794 SIVAL(p,0,ea_size); /* Extended attributes */
1797 /* Clear the short name buffer. This is
1798 * IMPORTANT as not doing so will trigger
1799 * a Win2k client bug. JRA.
1801 if (!was_8_3 && check_mangled_names) {
1802 char mangled_name[13]; /* mangled 8.3 name. */
1803 if (!name_to_8_3(fname,mangled_name,True,
1805 /* Error - mangle failed ! */
1806 memset(mangled_name,'\0',12);
1808 mangled_name[12] = 0;
1809 len = srvstr_push(base_data, flags2,
1810 p+2, mangled_name, 24,
1811 STR_UPPER|STR_UNICODE);
1813 memset(p + 2 + len,'\0',24 - len);
1820 len = srvstr_push(base_data, flags2, p,
1821 fname, PTR_DIFF(end_data, p),
1822 STR_TERMINATE_ASCII);
1826 len = PTR_DIFF(p, pdata);
1827 pad = (len + (align-1)) & ~(align-1);
1829 * offset to the next entry, the caller
1830 * will overwrite it for the last entry
1831 * that's why we always include the padding
1835 * set padding to zero
1838 memset(p, 0, pad - len);
1845 case SMB_FIND_FILE_DIRECTORY_INFO:
1846 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1848 SIVAL(p,0,reskey); p += 4;
1849 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1850 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1851 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1852 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1853 SOFF_T(p,0,file_size); p += 8;
1854 SOFF_T(p,0,allocation_size); p += 8;
1855 SIVAL(p,0,mode); p += 4;
1856 len = srvstr_push(base_data, flags2,
1857 p + 4, fname, PTR_DIFF(end_data, p+4),
1858 STR_TERMINATE_ASCII);
1862 len = PTR_DIFF(p, pdata);
1863 pad = (len + (align-1)) & ~(align-1);
1865 * offset to the next entry, the caller
1866 * will overwrite it for the last entry
1867 * that's why we always include the padding
1871 * set padding to zero
1874 memset(p, 0, pad - len);
1881 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1882 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1884 SIVAL(p,0,reskey); p += 4;
1885 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1886 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1887 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1888 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1889 SOFF_T(p,0,file_size); p += 8;
1890 SOFF_T(p,0,allocation_size); p += 8;
1891 SIVAL(p,0,mode); p += 4;
1892 q = p; p += 4; /* q is placeholder for name length. */
1894 unsigned int ea_size = estimate_ea_size(conn, NULL,
1896 SIVAL(p,0,ea_size); /* Extended attributes */
1899 len = srvstr_push(base_data, flags2, p,
1900 fname, PTR_DIFF(end_data, p),
1901 STR_TERMINATE_ASCII);
1905 len = PTR_DIFF(p, pdata);
1906 pad = (len + (align-1)) & ~(align-1);
1908 * offset to the next entry, the caller
1909 * will overwrite it for the last entry
1910 * that's why we always include the padding
1914 * set padding to zero
1917 memset(p, 0, pad - len);
1924 case SMB_FIND_FILE_NAMES_INFO:
1925 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1927 SIVAL(p,0,reskey); p += 4;
1929 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1930 acl on a dir (tridge) */
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_ID_FULL_DIRECTORY_INFO:
1957 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1959 SIVAL(p,0,reskey); p += 4;
1960 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1961 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1962 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1963 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1964 SOFF_T(p,0,file_size); p += 8;
1965 SOFF_T(p,0,allocation_size); p += 8;
1966 SIVAL(p,0,mode); p += 4;
1967 q = p; p += 4; /* q is placeholder for name length. */
1969 unsigned int ea_size = estimate_ea_size(conn, NULL,
1971 SIVAL(p,0,ea_size); /* Extended attributes */
1974 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1975 SBVAL(p,0,file_index); p += 8;
1976 len = srvstr_push(base_data, flags2, p,
1977 fname, PTR_DIFF(end_data, p),
1978 STR_TERMINATE_ASCII);
1982 len = PTR_DIFF(p, pdata);
1983 pad = (len + (align-1)) & ~(align-1);
1985 * offset to the next entry, the caller
1986 * will overwrite it for the last entry
1987 * that's why we always include the padding
1991 * set padding to zero
1994 memset(p, 0, pad - len);
2001 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2002 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2003 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2005 SIVAL(p,0,reskey); p += 4;
2006 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2007 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2008 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2009 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2010 SOFF_T(p,0,file_size); p += 8;
2011 SOFF_T(p,0,allocation_size); p += 8;
2012 SIVAL(p,0,mode); p += 4;
2013 q = p; p += 4; /* q is placeholder for name length */
2015 unsigned int ea_size = estimate_ea_size(conn, NULL,
2017 SIVAL(p,0,ea_size); /* Extended attributes */
2020 /* Clear the short name buffer. This is
2021 * IMPORTANT as not doing so will trigger
2022 * a Win2k client bug. JRA.
2024 if (!was_8_3 && check_mangled_names) {
2025 char mangled_name[13]; /* mangled 8.3 name. */
2026 if (!name_to_8_3(fname,mangled_name,True,
2028 /* Error - mangle failed ! */
2029 memset(mangled_name,'\0',12);
2031 mangled_name[12] = 0;
2032 len = srvstr_push(base_data, flags2,
2033 p+2, mangled_name, 24,
2034 STR_UPPER|STR_UNICODE);
2037 memset(p + 2 + len,'\0',24 - len);
2044 SSVAL(p,0,0); p += 2; /* Reserved ? */
2045 SBVAL(p,0,file_index); p += 8;
2046 len = srvstr_push(base_data, flags2, p,
2047 fname, PTR_DIFF(end_data, p),
2048 STR_TERMINATE_ASCII);
2052 len = PTR_DIFF(p, pdata);
2053 pad = (len + (align-1)) & ~(align-1);
2055 * offset to the next entry, the caller
2056 * will overwrite it for the last entry
2057 * that's why we always include the padding
2061 * set padding to zero
2064 memset(p, 0, pad - len);
2071 /* CIFS UNIX Extension. */
2073 case SMB_FIND_FILE_UNIX:
2074 case SMB_FIND_FILE_UNIX_INFO2:
2076 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2078 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2080 if (info_level == SMB_FIND_FILE_UNIX) {
2081 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2082 p = store_file_unix_basic(conn, p,
2083 NULL, &smb_fname->st);
2084 len = srvstr_push(base_data, flags2, p,
2085 fname, PTR_DIFF(end_data, p),
2088 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2089 p = store_file_unix_basic_info2(conn, p,
2090 NULL, &smb_fname->st);
2093 len = srvstr_push(base_data, flags2, p, fname,
2094 PTR_DIFF(end_data, p), 0);
2095 SIVAL(nameptr, 0, len);
2100 len = PTR_DIFF(p, pdata);
2101 pad = (len + (align-1)) & ~(align-1);
2103 * offset to the next entry, the caller
2104 * will overwrite it for the last entry
2105 * that's why we always include the padding
2109 * set padding to zero
2112 memset(p, 0, pad - len);
2117 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2125 if (PTR_DIFF(p,pdata) > space_remaining) {
2126 *out_of_space = true;
2127 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2128 "(wanted %u, had %d)\n",
2129 (unsigned int)PTR_DIFF(p,pdata),
2131 return false; /* Not finished - just out of space */
2134 /* Setup the last entry pointer, as an offset from base_data */
2135 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2136 /* Advance the data pointer to the next slot */
2142 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2143 connection_struct *conn,
2144 struct dptr_struct *dirptr,
2146 const char *path_mask,
2149 int requires_resume_key,
2157 int space_remaining,
2159 bool *got_exact_match,
2160 int *_last_entry_off,
2161 struct ea_list *name_list)
2164 const char *mask = NULL;
2165 long prev_dirpos = 0;
2168 struct smb_filename *smb_fname = NULL;
2169 struct smbd_dirptr_lanman2_state state;
2171 uint64_t last_entry_off = 0;
2175 state.info_level = info_level;
2176 state.check_mangled_names = lp_manglednames(conn->params);
2177 state.has_wild = dptr_has_wild(dirptr);
2178 state.got_exact_match = false;
2180 *out_of_space = false;
2181 *got_exact_match = false;
2183 p = strrchr_m(path_mask,'/');
2194 ok = smbd_dirptr_get_entry(ctx,
2200 smbd_dirptr_lanman2_match_fn,
2201 smbd_dirptr_lanman2_mode_fn,
2211 *got_exact_match = state.got_exact_match;
2213 ok = smbd_marshall_dir_entry(ctx,
2218 state.check_mangled_names,
2219 requires_resume_key,
2232 TALLOC_FREE(smb_fname);
2233 if (*out_of_space) {
2234 dptr_SeekDir(dirptr, prev_dirpos);
2241 *_last_entry_off = last_entry_off;
2245 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2246 connection_struct *conn,
2247 struct dptr_struct *dirptr,
2249 const char *path_mask,
2252 bool requires_resume_key,
2258 int space_remaining,
2260 bool *got_exact_match,
2261 int *last_entry_off,
2262 struct ea_list *name_list)
2265 const bool do_pad = true;
2267 if (info_level >= 1 && info_level <= 3) {
2268 /* No alignment on earlier info levels. */
2272 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2273 path_mask, dirtype, info_level,
2274 requires_resume_key, dont_descend, ask_sharemode,
2276 ppdata, base_data, end_data,
2278 out_of_space, got_exact_match,
2279 last_entry_off, name_list);
2282 /****************************************************************************
2283 Reply to a TRANS2_FINDFIRST.
2284 ****************************************************************************/
2286 static void call_trans2findfirst(connection_struct *conn,
2287 struct smb_request *req,
2288 char **pparams, int total_params,
2289 char **ppdata, int total_data,
2290 unsigned int max_data_bytes)
2292 /* We must be careful here that we don't return more than the
2293 allowed number of data bytes. If this means returning fewer than
2294 maxentries then so be it. We assume that the redirector has
2295 enough room for the fixed number of parameter bytes it has
2297 struct smb_filename *smb_dname = NULL;
2298 char *params = *pparams;
2299 char *pdata = *ppdata;
2303 uint16 findfirst_flags;
2304 bool close_after_first;
2306 bool requires_resume_key;
2308 char *directory = NULL;
2311 int last_entry_off=0;
2315 bool finished = False;
2316 bool dont_descend = False;
2317 bool out_of_space = False;
2318 int space_remaining;
2319 bool mask_contains_wcard = False;
2320 struct ea_list *ea_list = NULL;
2321 NTSTATUS ntstatus = NT_STATUS_OK;
2322 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2323 TALLOC_CTX *ctx = talloc_tos();
2324 struct dptr_struct *dirptr = NULL;
2325 struct smbd_server_connection *sconn = req->sconn;
2326 uint32_t ucf_flags = (UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP);
2327 bool backup_priv = false;
2329 if (total_params < 13) {
2330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2334 dirtype = SVAL(params,0);
2335 maxentries = SVAL(params,2);
2336 findfirst_flags = SVAL(params,4);
2337 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2338 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2339 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2340 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2341 security_token_has_privilege(get_current_nttok(conn),
2344 info_level = SVAL(params,6);
2346 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2347 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2348 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2350 info_level, max_data_bytes));
2353 /* W2K3 seems to treat zero as 1. */
2357 switch (info_level) {
2358 case SMB_FIND_INFO_STANDARD:
2359 case SMB_FIND_EA_SIZE:
2360 case SMB_FIND_EA_LIST:
2361 case SMB_FIND_FILE_DIRECTORY_INFO:
2362 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2363 case SMB_FIND_FILE_NAMES_INFO:
2364 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2365 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2366 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2368 case SMB_FIND_FILE_UNIX:
2369 case SMB_FIND_FILE_UNIX_INFO2:
2370 /* Always use filesystem for UNIX mtime query. */
2371 ask_sharemode = false;
2372 if (!lp_unix_extensions()) {
2373 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2376 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2379 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2383 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2384 params+12, total_params - 12,
2385 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2386 if (!NT_STATUS_IS_OK(ntstatus)) {
2387 reply_nterror(req, ntstatus);
2393 ntstatus = filename_convert_with_privilege(ctx,
2398 &mask_contains_wcard,
2401 ntstatus = filename_convert(ctx, conn,
2402 req->flags2 & FLAGS2_DFS_PATHNAMES,
2405 &mask_contains_wcard,
2409 if (!NT_STATUS_IS_OK(ntstatus)) {
2410 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2411 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2412 ERRSRV, ERRbadpath);
2415 reply_nterror(req, ntstatus);
2419 mask = smb_dname->original_lcomp;
2421 directory = smb_dname->base_name;
2423 p = strrchr_m(directory,'/');
2425 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2426 if((directory[0] == '.') && (directory[1] == '\0')) {
2427 mask = talloc_strdup(ctx,"*");
2429 reply_nterror(req, NT_STATUS_NO_MEMORY);
2432 mask_contains_wcard = True;
2438 if (p == NULL || p == directory) {
2439 /* Ensure we don't have a directory name of "". */
2440 directory = talloc_strdup(talloc_tos(), ".");
2442 reply_nterror(req, NT_STATUS_NO_MEMORY);
2447 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2449 if (info_level == SMB_FIND_EA_LIST) {
2452 if (total_data < 4) {
2453 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2457 ea_size = IVAL(pdata,0);
2458 if (ea_size != total_data) {
2459 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2460 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2461 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2465 if (!lp_ea_support(SNUM(conn))) {
2466 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2470 /* Pull out the list of names. */
2471 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2473 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2478 *ppdata = (char *)SMB_REALLOC(
2479 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2480 if(*ppdata == NULL ) {
2481 reply_nterror(req, NT_STATUS_NO_MEMORY);
2485 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2487 /* Realloc the params space */
2488 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2489 if (*pparams == NULL) {
2490 reply_nterror(req, NT_STATUS_NO_MEMORY);
2495 /* Save the wildcard match and attribs we are using on this directory -
2496 needed as lanman2 assumes these are being saved between calls */
2498 ntstatus = dptr_create(conn,
2506 mask_contains_wcard,
2510 if (!NT_STATUS_IS_OK(ntstatus)) {
2511 reply_nterror(req, ntstatus);
2516 /* Remember this in case we have
2517 to do a findnext. */
2518 dptr_set_priv(dirptr);
2521 dptr_num = dptr_dnum(dirptr);
2522 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2524 /* Initialize per TRANS2_FIND_FIRST operation data */
2525 dptr_init_search_op(dirptr);
2527 /* We don't need to check for VOL here as this is returned by
2528 a different TRANS2 call. */
2530 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2531 directory,lp_dontdescend(ctx, SNUM(conn))));
2532 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2533 dont_descend = True;
2536 space_remaining = max_data_bytes;
2537 out_of_space = False;
2539 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2540 bool got_exact_match = False;
2542 /* this is a heuristic to avoid seeking the dirptr except when
2543 absolutely necessary. It allows for a filename of about 40 chars */
2544 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2545 out_of_space = True;
2548 finished = !get_lanman2_dir_entry(ctx,
2552 mask,dirtype,info_level,
2553 requires_resume_key,dont_descend,
2556 space_remaining, &out_of_space,
2558 &last_entry_off, ea_list);
2561 if (finished && out_of_space)
2564 if (!finished && !out_of_space)
2568 * As an optimisation if we know we aren't looking
2569 * for a wildcard name (ie. the name matches the wildcard exactly)
2570 * then we can finish on any (first) match.
2571 * This speeds up large directory searches. JRA.
2577 /* Ensure space_remaining never goes -ve. */
2578 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2579 space_remaining = 0;
2580 out_of_space = true;
2582 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2586 /* Check if we can close the dirptr */
2587 if(close_after_first || (finished && close_if_end)) {
2588 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2589 dptr_close(sconn, &dptr_num);
2593 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2594 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2595 * the protocol level is less than NT1. Tested with smbclient. JRA.
2596 * This should fix the OS/2 client bug #2335.
2599 if(numentries == 0) {
2600 dptr_close(sconn, &dptr_num);
2601 if (get_Protocol() < PROTOCOL_NT1) {
2602 reply_force_doserror(req, ERRDOS, ERRnofiles);
2605 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2606 ERRDOS, ERRbadfile);
2611 /* At this point pdata points to numentries directory entries. */
2613 /* Set up the return parameter block */
2614 SSVAL(params,0,dptr_num);
2615 SSVAL(params,2,numentries);
2616 SSVAL(params,4,finished);
2617 SSVAL(params,6,0); /* Never an EA error */
2618 SSVAL(params,8,last_entry_off);
2620 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2623 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2624 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2626 reply_nterror(req, NT_STATUS_NO_MEMORY);
2630 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2631 smb_fn_name(req->cmd),
2632 mask, directory, dirtype, numentries ) );
2635 * Force a name mangle here to ensure that the
2636 * mask as an 8.3 name is top of the mangled cache.
2637 * The reasons for this are subtle. Don't remove
2638 * this code unless you know what you are doing
2639 * (see PR#13758). JRA.
2642 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2643 char mangled_name[13];
2644 name_to_8_3(mask, mangled_name, True, conn->params);
2652 TALLOC_FREE(smb_dname);
2656 /****************************************************************************
2657 Reply to a TRANS2_FINDNEXT.
2658 ****************************************************************************/
2660 static void call_trans2findnext(connection_struct *conn,
2661 struct smb_request *req,
2662 char **pparams, int total_params,
2663 char **ppdata, int total_data,
2664 unsigned int max_data_bytes)
2666 /* We must be careful here that we don't return more than the
2667 allowed number of data bytes. If this means returning fewer than
2668 maxentries then so be it. We assume that the redirector has
2669 enough room for the fixed number of parameter bytes it has
2671 char *params = *pparams;
2672 char *pdata = *ppdata;
2678 uint16 findnext_flags;
2679 bool close_after_request;
2681 bool requires_resume_key;
2683 bool mask_contains_wcard = False;
2684 char *resume_name = NULL;
2685 const char *mask = NULL;
2686 const char *directory = NULL;
2690 int i, last_entry_off=0;
2691 bool finished = False;
2692 bool dont_descend = False;
2693 bool out_of_space = False;
2694 int space_remaining;
2695 struct ea_list *ea_list = NULL;
2696 NTSTATUS ntstatus = NT_STATUS_OK;
2697 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2698 TALLOC_CTX *ctx = talloc_tos();
2699 struct dptr_struct *dirptr;
2700 struct smbd_server_connection *sconn = req->sconn;
2701 bool backup_priv = false;
2703 if (total_params < 13) {
2704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2708 dptr_num = SVAL(params,0);
2709 maxentries = SVAL(params,2);
2710 info_level = SVAL(params,4);
2711 resume_key = IVAL(params,6);
2712 findnext_flags = SVAL(params,10);
2713 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2714 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2715 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2716 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2718 if (!continue_bit) {
2719 /* We only need resume_name if continue_bit is zero. */
2720 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2722 total_params - 12, STR_TERMINATE, &ntstatus,
2723 &mask_contains_wcard);
2724 if (!NT_STATUS_IS_OK(ntstatus)) {
2725 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2726 complain (it thinks we're asking for the directory above the shared
2727 path or an invalid name). Catch this as the resume name is only compared, never used in
2728 a file access. JRA. */
2729 srvstr_pull_talloc(ctx, params, req->flags2,
2730 &resume_name, params+12,
2734 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2735 reply_nterror(req, ntstatus);
2741 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2742 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2743 resume_key = %d resume name = %s continue=%d level = %d\n",
2744 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2745 requires_resume_key, resume_key,
2746 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2749 /* W2K3 seems to treat zero as 1. */
2753 switch (info_level) {
2754 case SMB_FIND_INFO_STANDARD:
2755 case SMB_FIND_EA_SIZE:
2756 case SMB_FIND_EA_LIST:
2757 case SMB_FIND_FILE_DIRECTORY_INFO:
2758 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2759 case SMB_FIND_FILE_NAMES_INFO:
2760 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2761 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2762 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2764 case SMB_FIND_FILE_UNIX:
2765 case SMB_FIND_FILE_UNIX_INFO2:
2766 /* Always use filesystem for UNIX mtime query. */
2767 ask_sharemode = false;
2768 if (!lp_unix_extensions()) {
2769 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2774 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2778 if (info_level == SMB_FIND_EA_LIST) {
2781 if (total_data < 4) {
2782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2786 ea_size = IVAL(pdata,0);
2787 if (ea_size != total_data) {
2788 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2789 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2794 if (!lp_ea_support(SNUM(conn))) {
2795 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2799 /* Pull out the list of names. */
2800 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2807 *ppdata = (char *)SMB_REALLOC(
2808 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2809 if(*ppdata == NULL) {
2810 reply_nterror(req, NT_STATUS_NO_MEMORY);
2815 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2817 /* Realloc the params space */
2818 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2819 if(*pparams == NULL ) {
2820 reply_nterror(req, NT_STATUS_NO_MEMORY);
2826 /* Check that the dptr is valid */
2827 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2828 reply_nterror(req, STATUS_NO_MORE_FILES);
2832 directory = dptr_path(sconn, dptr_num);
2834 /* Get the wildcard mask from the dptr */
2835 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
2836 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2837 reply_nterror(req, STATUS_NO_MORE_FILES);
2841 /* Get the attr mask from the dptr */
2842 dirtype = dptr_attr(sconn, dptr_num);
2844 backup_priv = dptr_get_priv(dirptr);
2846 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
2847 "backup_priv = %d\n",
2848 dptr_num, mask, dirtype,
2850 dptr_TellDir(dirptr),
2853 /* Initialize per TRANS2_FIND_NEXT operation data */
2854 dptr_init_search_op(dirptr);
2856 /* We don't need to check for VOL here as this is returned by
2857 a different TRANS2 call. */
2859 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2860 directory,lp_dontdescend(ctx, SNUM(conn))));
2861 if (in_list(directory,lp_dontdescend(ctx, SNUM(conn)),conn->case_sensitive))
2862 dont_descend = True;
2865 space_remaining = max_data_bytes;
2866 out_of_space = False;
2873 * Seek to the correct position. We no longer use the resume key but
2874 * depend on the last file name instead.
2877 if(!continue_bit && resume_name && *resume_name) {
2880 long current_pos = 0;
2882 * Remember, name_to_8_3 is called by
2883 * get_lanman2_dir_entry(), so the resume name
2884 * could be mangled. Ensure we check the unmangled name.
2887 if (mangle_is_mangled(resume_name, conn->params)) {
2888 char *new_resume_name = NULL;
2889 mangle_lookup_name_from_8_3(ctx,
2893 if (new_resume_name) {
2894 resume_name = new_resume_name;
2899 * Fix for NT redirector problem triggered by resume key indexes
2900 * changing between directory scans. We now return a resume key of 0
2901 * and instead look for the filename to continue from (also given
2902 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2903 * findfirst/findnext (as is usual) then the directory pointer
2904 * should already be at the correct place.
2907 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2908 } /* end if resume_name && !continue_bit */
2910 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2911 bool got_exact_match = False;
2913 /* this is a heuristic to avoid seeking the dirptr except when
2914 absolutely necessary. It allows for a filename of about 40 chars */
2915 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2916 out_of_space = True;
2919 finished = !get_lanman2_dir_entry(ctx,
2923 mask,dirtype,info_level,
2924 requires_resume_key,dont_descend,
2927 space_remaining, &out_of_space,
2929 &last_entry_off, ea_list);
2932 if (finished && out_of_space)
2935 if (!finished && !out_of_space)
2939 * As an optimisation if we know we aren't looking
2940 * for a wildcard name (ie. the name matches the wildcard exactly)
2941 * then we can finish on any (first) match.
2942 * This speeds up large directory searches. JRA.
2948 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2951 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2952 smb_fn_name(req->cmd),
2953 mask, directory, dirtype, numentries ) );
2955 /* Check if we can close the dirptr */
2956 if(close_after_request || (finished && close_if_end)) {
2957 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2958 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2965 /* Set up the return parameter block */
2966 SSVAL(params,0,numentries);
2967 SSVAL(params,2,finished);
2968 SSVAL(params,4,0); /* Never an EA error */
2969 SSVAL(params,6,last_entry_off);
2971 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2977 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2979 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
2983 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2985 SMB_ASSERT(extended_info != NULL);
2987 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2988 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2989 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2990 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2991 #ifdef SAMBA_VERSION_REVISION
2992 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2994 extended_info->samba_subversion = 0;
2995 #ifdef SAMBA_VERSION_RC_RELEASE
2996 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2998 #ifdef SAMBA_VERSION_PRE_RELEASE
2999 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3002 #ifdef SAMBA_VERSION_VENDOR_PATCH
3003 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3005 extended_info->samba_gitcommitdate = 0;
3006 #ifdef SAMBA_VERSION_COMMIT_TIME
3007 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3010 memset(extended_info->samba_version_string, 0,
3011 sizeof(extended_info->samba_version_string));
3013 snprintf (extended_info->samba_version_string,
3014 sizeof(extended_info->samba_version_string),
3015 "%s", samba_version_string());
3018 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
3019 TALLOC_CTX *mem_ctx,
3020 uint16_t info_level,
3022 unsigned int max_data_bytes,
3023 struct smb_filename *fname,
3027 char *pdata, *end_data;
3028 int data_len = 0, len;
3029 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3030 int snum = SNUM(conn);
3031 char *fstype = lp_fstype(talloc_tos(), SNUM(conn));
3032 char *filename = NULL;
3033 uint32 additional_flags = 0;
3034 struct smb_filename smb_fname;
3037 if (fname == NULL || fname->base_name == NULL) {
3040 filename = fname->base_name;
3044 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3045 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3046 "info level (0x%x) on IPC$.\n",
3047 (unsigned int)info_level));
3048 return NT_STATUS_ACCESS_DENIED;
3052 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3054 ZERO_STRUCT(smb_fname);
3055 smb_fname.base_name = discard_const_p(char, filename);
3057 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3058 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3059 return map_nt_error_from_unix(errno);
3064 *ppdata = (char *)SMB_REALLOC(
3065 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3066 if (*ppdata == NULL) {
3067 return NT_STATUS_NO_MEMORY;
3071 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3072 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3074 switch (info_level) {
3075 case SMB_INFO_ALLOCATION:
3077 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3079 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3080 return map_nt_error_from_unix(errno);
3083 block_size = lp_block_size(snum);
3084 if (bsize < block_size) {
3085 uint64_t factor = block_size/bsize;
3090 if (bsize > block_size) {
3091 uint64_t factor = bsize/block_size;
3096 bytes_per_sector = 512;
3097 sectors_per_unit = bsize/bytes_per_sector;
3099 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3100 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3101 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3103 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3104 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3105 SIVAL(pdata,l1_cUnit,dsize);
3106 SIVAL(pdata,l1_cUnitAvail,dfree);
3107 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3111 case SMB_INFO_VOLUME:
3112 /* Return volume name */
3114 * Add volume serial number - hash of a combination of
3115 * the called hostname and the service name.
3117 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3119 * Win2k3 and previous mess this up by sending a name length
3120 * one byte short. I believe only older clients (OS/2 Win9x) use
3121 * this call so try fixing this by adding a terminating null to
3122 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3126 pdata+l2_vol_szVolLabel, vname,
3127 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3128 STR_NOALIGN|STR_TERMINATE);
3129 SCVAL(pdata,l2_vol_cch,len);
3130 data_len = l2_vol_szVolLabel + len;
3131 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3132 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3136 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3137 case SMB_FS_ATTRIBUTE_INFORMATION:
3139 additional_flags = 0;
3140 #if defined(HAVE_SYS_QUOTAS)
3141 additional_flags |= FILE_VOLUME_QUOTAS;
3144 if(lp_nt_acl_support(SNUM(conn))) {
3145 additional_flags |= FILE_PERSISTENT_ACLS;
3148 /* Capabilities are filled in at connection time through STATVFS call */
3149 additional_flags |= conn->fs_capabilities;
3150 additional_flags |= lp_parm_int(conn->params->service,
3151 "share", "fake_fscaps",
3154 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3155 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3156 additional_flags); /* FS ATTRIBUTES */
3158 SIVAL(pdata,4,255); /* Max filename component length */
3159 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3160 and will think we can't do long filenames */
3161 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3162 PTR_DIFF(end_data, pdata+12),
3165 data_len = 12 + len;
3168 case SMB_QUERY_FS_LABEL_INFO:
3169 case SMB_FS_LABEL_INFORMATION:
3170 len = srvstr_push(pdata, flags2, pdata+4, vname,
3171 PTR_DIFF(end_data, pdata+4), 0);
3176 case SMB_QUERY_FS_VOLUME_INFO:
3177 case SMB_FS_VOLUME_INFORMATION:
3180 * Add volume serial number - hash of a combination of
3181 * the called hostname and the service name.
3183 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3184 (str_checksum(get_local_machine_name())<<16));
3186 /* Max label len is 32 characters. */
3187 len = srvstr_push(pdata, flags2, pdata+18, vname,
3188 PTR_DIFF(end_data, pdata+18),
3190 SIVAL(pdata,12,len);
3193 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3194 (int)strlen(vname),vname,
3195 lp_servicename(talloc_tos(), snum)));
3198 case SMB_QUERY_FS_SIZE_INFO:
3199 case SMB_FS_SIZE_INFORMATION:
3201 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3203 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3204 return map_nt_error_from_unix(errno);
3206 block_size = lp_block_size(snum);
3207 if (bsize < block_size) {
3208 uint64_t factor = block_size/bsize;
3213 if (bsize > block_size) {
3214 uint64_t factor = bsize/block_size;
3219 bytes_per_sector = 512;
3220 sectors_per_unit = bsize/bytes_per_sector;
3221 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3222 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3223 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3224 SBIG_UINT(pdata,0,dsize);
3225 SBIG_UINT(pdata,8,dfree);
3226 SIVAL(pdata,16,sectors_per_unit);
3227 SIVAL(pdata,20,bytes_per_sector);
3231 case SMB_FS_FULL_SIZE_INFORMATION:
3233 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3235 if (get_dfree_info(conn,filename,False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3236 return map_nt_error_from_unix(errno);
3238 block_size = lp_block_size(snum);
3239 if (bsize < block_size) {
3240 uint64_t factor = block_size/bsize;
3245 if (bsize > block_size) {
3246 uint64_t factor = bsize/block_size;
3251 bytes_per_sector = 512;
3252 sectors_per_unit = bsize/bytes_per_sector;
3253 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3254 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3255 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3256 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3257 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3258 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3259 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3260 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3264 case SMB_QUERY_FS_DEVICE_INFO:
3265 case SMB_FS_DEVICE_INFORMATION:
3267 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3269 if (!CAN_WRITE(conn)) {
3270 characteristics |= FILE_READ_ONLY_DEVICE;
3273 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3274 SIVAL(pdata,4,characteristics);
3278 #ifdef HAVE_SYS_QUOTAS
3279 case SMB_FS_QUOTA_INFORMATION:
3281 * what we have to send --metze:
3283 * Unknown1: 24 NULL bytes
3284 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3285 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3286 * Quota Flags: 2 byte :
3287 * Unknown3: 6 NULL bytes
3291 * details for Quota Flags:
3293 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3294 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3295 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3296 * 0x0001 Enable Quotas: enable quota for this fs
3300 /* we need to fake up a fsp here,
3301 * because its not send in this call
3304 SMB_NTQUOTA_STRUCT quotas;
3307 ZERO_STRUCT(quotas);
3310 fsp.fnum = FNUM_FIELD_INVALID;
3313 if (get_current_uid(conn) != 0) {
3314 DEBUG(0,("set_user_quota: access_denied "
3315 "service [%s] user [%s]\n",
3316 lp_servicename(talloc_tos(), SNUM(conn)),
3317 conn->session_info->unix_info->unix_name));
3318 return NT_STATUS_ACCESS_DENIED;
3321 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3322 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3323 return map_nt_error_from_unix(errno);
3328 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3329 lp_servicename(talloc_tos(), SNUM(conn))));
3331 /* Unknown1 24 NULL bytes*/
3332 SBIG_UINT(pdata,0,(uint64_t)0);
3333 SBIG_UINT(pdata,8,(uint64_t)0);
3334 SBIG_UINT(pdata,16,(uint64_t)0);
3336 /* Default Soft Quota 8 bytes */
3337 SBIG_UINT(pdata,24,quotas.softlim);
3339 /* Default Hard Quota 8 bytes */
3340 SBIG_UINT(pdata,32,quotas.hardlim);
3342 /* Quota flag 2 bytes */
3343 SSVAL(pdata,40,quotas.qflags);
3345 /* Unknown3 6 NULL bytes */
3351 #endif /* HAVE_SYS_QUOTAS */
3352 case SMB_FS_OBJECTID_INFORMATION:
3354 unsigned char objid[16];
3355 struct smb_extended_info extended_info;
3356 memcpy(pdata,create_volume_objectid(conn, objid),16);
3357 samba_extended_info_version (&extended_info);
3358 SIVAL(pdata,16,extended_info.samba_magic);
3359 SIVAL(pdata,20,extended_info.samba_version);
3360 SIVAL(pdata,24,extended_info.samba_subversion);
3361 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3362 memcpy(pdata+36,extended_info.samba_version_string,28);
3368 * Query the version and capabilities of the CIFS UNIX extensions
3372 case SMB_QUERY_CIFS_UNIX_INFO:
3374 bool large_write = lp_min_receive_file_size() &&
3375 !srv_is_signing_active(conn->sconn);
3376 bool large_read = !srv_is_signing_active(conn->sconn);
3377 int encrypt_caps = 0;
3379 if (!lp_unix_extensions()) {
3380 return NT_STATUS_INVALID_LEVEL;
3383 switch (conn->encrypt_level) {
3384 case SMB_SIGNING_OFF:
3387 case SMB_SIGNING_IF_REQUIRED:
3388 case SMB_SIGNING_DEFAULT:
3389 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3391 case SMB_SIGNING_REQUIRED:
3392 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3393 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3394 large_write = false;
3400 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3401 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3403 /* We have POSIX ACLs, pathname, encryption,
3404 * large read/write, and locking capability. */
3406 SBIG_UINT(pdata,4,((uint64_t)(
3407 CIFS_UNIX_POSIX_ACLS_CAP|
3408 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3409 CIFS_UNIX_FCNTL_LOCKS_CAP|
3410 CIFS_UNIX_EXTATTR_CAP|
3411 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3413 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3415 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3419 case SMB_QUERY_POSIX_FS_INFO:
3422 vfs_statvfs_struct svfs;
3424 if (!lp_unix_extensions()) {
3425 return NT_STATUS_INVALID_LEVEL;
3428 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3432 SIVAL(pdata,0,svfs.OptimalTransferSize);
3433 SIVAL(pdata,4,svfs.BlockSize);
3434 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3435 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3436 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3437 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3438 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3439 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3440 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3442 } else if (rc == EOPNOTSUPP) {
3443 return NT_STATUS_INVALID_LEVEL;
3444 #endif /* EOPNOTSUPP */
3446 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3447 return NT_STATUS_DOS(ERRSRV, ERRerror);
3452 case SMB_QUERY_POSIX_WHOAMI:
3458 if (!lp_unix_extensions()) {
3459 return NT_STATUS_INVALID_LEVEL;
3462 if (max_data_bytes < 40) {
3463 return NT_STATUS_BUFFER_TOO_SMALL;
3466 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3467 flags |= SMB_WHOAMI_GUEST;
3470 /* NOTE: 8 bytes for UID/GID, irrespective of native
3471 * platform size. This matches
3472 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3474 data_len = 4 /* flags */
3481 + 4 /* pad/reserved */
3482 + (conn->session_info->unix_token->ngroups * 8)
3484 + (conn->session_info->security_token->num_sids *
3488 SIVAL(pdata, 0, flags);
3489 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3491 (uint64_t)conn->session_info->unix_token->uid);
3492 SBIG_UINT(pdata, 16,
3493 (uint64_t)conn->session_info->unix_token->gid);
3496 if (data_len >= max_data_bytes) {
3497 /* Potential overflow, skip the GIDs and SIDs. */
3499 SIVAL(pdata, 24, 0); /* num_groups */
3500 SIVAL(pdata, 28, 0); /* num_sids */
3501 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3502 SIVAL(pdata, 36, 0); /* reserved */
3508 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3509 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3511 /* We walk the SID list twice, but this call is fairly
3512 * infrequent, and I don't expect that it's performance
3513 * sensitive -- jpeach
3515 for (i = 0, sid_bytes = 0;
3516 i < conn->session_info->security_token->num_sids; ++i) {
3517 sid_bytes += ndr_size_dom_sid(
3518 &conn->session_info->security_token->sids[i],
3522 /* SID list byte count */
3523 SIVAL(pdata, 32, sid_bytes);
3525 /* 4 bytes pad/reserved - must be zero */
3526 SIVAL(pdata, 36, 0);
3530 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3531 SBIG_UINT(pdata, data_len,
3532 (uint64_t)conn->session_info->unix_token->groups[i]);
3538 i < conn->session_info->security_token->num_sids; ++i) {
3539 int sid_len = ndr_size_dom_sid(
3540 &conn->session_info->security_token->sids[i],
3543 sid_linearize(pdata + data_len, sid_len,
3544 &conn->session_info->security_token->sids[i]);
3545 data_len += sid_len;
3551 case SMB_MAC_QUERY_FS_INFO:
3553 * Thursby MAC extension... ONLY on NTFS filesystems
3554 * once we do streams then we don't need this
3556 if (strequal(lp_fstype(talloc_tos(), SNUM(conn)),"NTFS")) {
3558 SIVAL(pdata,84,0x100); /* Don't support mac... */
3563 return NT_STATUS_INVALID_LEVEL;
3566 *ret_data_len = data_len;
3567 return NT_STATUS_OK;
3570 /****************************************************************************
3571 Reply to a TRANS2_QFSINFO (query filesystem info).
3572 ****************************************************************************/
3574 static void call_trans2qfsinfo(connection_struct *conn,
3575 struct smb_request *req,
3576 char **pparams, int total_params,
3577 char **ppdata, int total_data,
3578 unsigned int max_data_bytes)
3580 char *params = *pparams;
3581 uint16_t info_level;
3585 if (total_params < 2) {
3586 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3590 info_level = SVAL(params,0);
3592 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3593 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3594 DEBUG(0,("call_trans2qfsinfo: encryption required "
3595 "and info level 0x%x sent.\n",
3596 (unsigned int)info_level));
3597 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3602 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3604 status = smbd_do_qfsinfo(conn, req,
3610 if (!NT_STATUS_IS_OK(status)) {
3611 reply_nterror(req, status);
3615 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3618 DEBUG( 4, ( "%s info_level = %d\n",
3619 smb_fn_name(req->cmd), info_level) );
3624 /****************************************************************************
3625 Reply to a TRANS2_SETFSINFO (set filesystem info).
3626 ****************************************************************************/
3628 static void call_trans2setfsinfo(connection_struct *conn,
3629 struct smb_request *req,
3630 char **pparams, int total_params,
3631 char **ppdata, int total_data,
3632 unsigned int max_data_bytes)
3634 struct smbd_server_connection *sconn = req->sconn;
3635 char *pdata = *ppdata;
3636 char *params = *pparams;
3639 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
3640 lp_servicename(talloc_tos(), SNUM(conn))));
3643 if (total_params < 4) {
3644 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3646 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3650 info_level = SVAL(params,2);
3653 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3654 info_level != SMB_SET_CIFS_UNIX_INFO) {
3655 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3656 "info level (0x%x) on IPC$.\n",
3657 (unsigned int)info_level));
3658 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3663 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3664 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3665 DEBUG(0,("call_trans2setfsinfo: encryption required "
3666 "and info level 0x%x sent.\n",
3667 (unsigned int)info_level));
3668 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3673 switch(info_level) {
3674 case SMB_SET_CIFS_UNIX_INFO:
3675 if (!lp_unix_extensions()) {
3676 DEBUG(2,("call_trans2setfsinfo: "
3677 "SMB_SET_CIFS_UNIX_INFO is invalid with "
3678 "unix extensions off\n"));
3680 NT_STATUS_INVALID_LEVEL);
3684 /* There should be 12 bytes of capabilities set. */
3685 if (total_data < 12) {
3688 NT_STATUS_INVALID_PARAMETER);
3691 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3692 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3693 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3694 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3695 /* Just print these values for now. */
3696 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
3697 "major = %u, minor = %u cap_low = 0x%x, "
3699 (unsigned int)sconn->
3700 smb1.unix_info.client_major,
3701 (unsigned int)sconn->
3702 smb1.unix_info.client_minor,
3703 (unsigned int)sconn->
3704 smb1.unix_info.client_cap_low,
3705 (unsigned int)sconn->
3706 smb1.unix_info.client_cap_high));
3708 /* Here is where we must switch to posix pathname processing... */
3709 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3710 lp_set_posix_pathnames();
3711 mangle_change_to_posix();
3714 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3715 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3716 /* Client that knows how to do posix locks,
3717 * but not posix open/mkdir operations. Set a
3718 * default type for read/write checks. */
3720 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3725 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3728 size_t param_len = 0;
3729 size_t data_len = total_data;
3731 if (!lp_unix_extensions()) {
3734 NT_STATUS_INVALID_LEVEL);
3738 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
3741 NT_STATUS_NOT_SUPPORTED);
3745 if (req->sconn->smb1.echo_handler.trusted_fde) {
3746 DEBUG( 2,("call_trans2setfsinfo: "
3747 "request transport encryption disabled"
3748 "with 'fork echo handler = yes'\n"));
3751 NT_STATUS_NOT_SUPPORTED);
3755 DEBUG( 4,("call_trans2setfsinfo: "
3756 "request transport encryption.\n"));
3758 status = srv_request_encryption_setup(conn,
3759 (unsigned char **)ppdata,
3761 (unsigned char **)pparams,
3764 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3765 !NT_STATUS_IS_OK(status)) {
3766 reply_nterror(req, status);
3770 send_trans2_replies(conn, req,
3777 if (NT_STATUS_IS_OK(status)) {
3778 /* Server-side transport
3779 * encryption is now *on*. */
3780 status = srv_encryption_start(conn);
3781 if (!NT_STATUS_IS_OK(status)) {
3782 char *reason = talloc_asprintf(talloc_tos(),
3783 "Failure in setting "
3784 "up encrypted transport: %s",
3786 exit_server_cleanly(reason);
3792 case SMB_FS_QUOTA_INFORMATION:
3794 files_struct *fsp = NULL;
3795 SMB_NTQUOTA_STRUCT quotas;
3797 ZERO_STRUCT(quotas);
3800 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3801 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3802 lp_servicename(talloc_tos(), SNUM(conn)),
3803 conn->session_info->unix_info->unix_name));
3804 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3808 /* note: normaly there're 48 bytes,
3809 * but we didn't use the last 6 bytes for now
3812 fsp = file_fsp(req, SVAL(params,0));
3814 if (!check_fsp_ntquota_handle(conn, req,
3816 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3818 req, NT_STATUS_INVALID_HANDLE);
3822 if (total_data < 42) {
3823 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3827 NT_STATUS_INVALID_PARAMETER);
3831 /* unknown_1 24 NULL bytes in pdata*/
3833 /* the soft quotas 8 bytes (uint64_t)*/
3834 quotas.softlim = BVAL(pdata,24);
3836 /* the hard quotas 8 bytes (uint64_t)*/
3837 quotas.hardlim = BVAL(pdata,32);
3839 /* quota_flags 2 bytes **/
3840 quotas.qflags = SVAL(pdata,40);
3842 /* unknown_2 6 NULL bytes follow*/
3844 /* now set the quotas */
3845 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3846 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3847 reply_nterror(req, map_nt_error_from_unix(errno));
3854 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3856 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3862 * sending this reply works fine,
3863 * but I'm not sure it's the same
3864 * like windows do...
3867 reply_outbuf(req, 10, 0);
3870 #if defined(HAVE_POSIX_ACLS)
3871 /****************************************************************************
3872 Utility function to count the number of entries in a POSIX acl.
3873 ****************************************************************************/
3875 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3877 unsigned int ace_count = 0;
3878 int entry_id = SMB_ACL_FIRST_ENTRY;
3879 SMB_ACL_ENTRY_T entry;
3881 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3883 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3884 entry_id = SMB_ACL_NEXT_ENTRY;
3891 /****************************************************************************
3892 Utility function to marshall a POSIX acl into wire format.
3893 ****************************************************************************/
3895 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3897 int entry_id = SMB_ACL_FIRST_ENTRY;
3898 SMB_ACL_ENTRY_T entry;
3900 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
3901 SMB_ACL_TAG_T tagtype;
3902 SMB_ACL_PERMSET_T permset;
3903 unsigned char perms = 0;
3904 unsigned int own_grp;
3907 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3908 entry_id = SMB_ACL_NEXT_ENTRY;
3911 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
3912 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3916 if (sys_acl_get_permset(entry, &permset) == -1) {
3917 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3921 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3922 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3923 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3925 SCVAL(pdata,1,perms);
3928 case SMB_ACL_USER_OBJ:
3929 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3930 own_grp = (unsigned int)pst->st_ex_uid;
3931 SIVAL(pdata,2,own_grp);
3936 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
3938 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3941 own_grp = (unsigned int)*puid;
3942 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3943 SIVAL(pdata,2,own_grp);
3947 case SMB_ACL_GROUP_OBJ:
3948 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3949 own_grp = (unsigned int)pst->st_ex_gid;
3950 SIVAL(pdata,2,own_grp);
3955 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3957 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3960 own_grp = (unsigned int)*pgid;
3961 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3962 SIVAL(pdata,2,own_grp);
3967 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3968 SIVAL(pdata,2,0xFFFFFFFF);
3969 SIVAL(pdata,6,0xFFFFFFFF);
3972 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3973 SIVAL(pdata,2,0xFFFFFFFF);
3974 SIVAL(pdata,6,0xFFFFFFFF);
3977 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3980 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3987 /****************************************************************************
3988 Store the FILE_UNIX_BASIC info.
3989 ****************************************************************************/
3991 static char *store_file_unix_basic(connection_struct *conn,
3994 const SMB_STRUCT_STAT *psbuf)
3996 uint64_t file_index = get_FileIndex(conn, psbuf);
3999 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4000 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4002 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4005 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4008 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4009 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4010 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4013 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4017 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4021 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4024 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4025 devno = psbuf->st_ex_rdev;
4027 devno = psbuf->st_ex_dev;
4030 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4034 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4038 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4041 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4045 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4052 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4053 * the chflags(2) (or equivalent) flags.
4055 * XXX: this really should be behind the VFS interface. To do this, we would
4056 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4057 * Each VFS module could then implement its own mapping as appropriate for the
4058 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4060 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4064 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4068 { UF_IMMUTABLE, EXT_IMMUTABLE },
4072 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4076 { UF_HIDDEN, EXT_HIDDEN },
4079 /* Do not remove. We need to guarantee that this array has at least one
4080 * entry to build on HP-UX.
4086 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4087 uint32 *smb_fflags, uint32 *smb_fmask)
4091 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4092 *smb_fmask |= info2_flags_map[i].smb_fflag;
4093 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4094 *smb_fflags |= info2_flags_map[i].smb_fflag;
4099 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4100 const uint32 smb_fflags,
4101 const uint32 smb_fmask,
4104 uint32 max_fmask = 0;
4107 *stat_fflags = psbuf->st_ex_flags;
4109 /* For each flags requested in smb_fmask, check the state of the
4110 * corresponding flag in smb_fflags and set or clear the matching
4114 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4115 max_fmask |= info2_flags_map[i].smb_fflag;
4116 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4117 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4118 *stat_fflags |= info2_flags_map[i].stat_fflag;
4120 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4125 /* If smb_fmask is asking to set any bits that are not supported by
4126 * our flag mappings, we should fail.
4128 if ((smb_fmask & max_fmask) != smb_fmask) {
4136 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4137 * of file flags and birth (create) time.
4139 static char *store_file_unix_basic_info2(connection_struct *conn,
4142 const SMB_STRUCT_STAT *psbuf)
4144 uint32 file_flags = 0;
4145 uint32 flags_mask = 0;
4147 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4149 /* Create (birth) time 64 bit */
4150 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4153 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4154 SIVAL(pdata, 0, file_flags); /* flags */
4155 SIVAL(pdata, 4, flags_mask); /* mask */
4161 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4162 const struct stream_struct *streams,
4164 unsigned int max_data_bytes,
4165 unsigned int *data_size)
4168 unsigned int ofs = 0;
4170 for (i = 0; i < num_streams; i++) {
4171 unsigned int next_offset;
4173 smb_ucs2_t *namebuf;
4175 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4176 streams[i].name, &namelen) ||
4179 return NT_STATUS_INVALID_PARAMETER;
4183 * name_buf is now null-terminated, we need to marshall as not
4190 * We cannot overflow ...
4192 if ((ofs + 24 + namelen) > max_data_bytes) {
4193 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4195 TALLOC_FREE(namebuf);
4196 return STATUS_BUFFER_OVERFLOW;
4199 SIVAL(data, ofs+4, namelen);
4200 SOFF_T(data, ofs+8, streams[i].size);
4201 SOFF_T(data, ofs+16, streams[i].alloc_size);
4202 memcpy(data+ofs+24, namebuf, namelen);
4203 TALLOC_FREE(namebuf);
4205 next_offset = ofs + 24 + namelen;
4207 if (i == num_streams-1) {
4208 SIVAL(data, ofs, 0);
4211 unsigned int align = ndr_align_size(next_offset, 8);
4213 if ((next_offset + align) > max_data_bytes) {
4214 DEBUG(10, ("refusing to overflow align "
4215 "reply at stream %u\n",
4217 TALLOC_FREE(namebuf);
4218 return STATUS_BUFFER_OVERFLOW;
4221 memset(data+next_offset, 0, align);
4222 next_offset += align;
4224 SIVAL(data, ofs, next_offset - ofs);
4231 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4235 return NT_STATUS_OK;
4238 /****************************************************************************
4239 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4240 ****************************************************************************/
4242 static void call_trans2qpipeinfo(connection_struct *conn,
4243 struct smb_request *req,
4244 unsigned int tran_call,
4245 char **pparams, int total_params,
4246 char **ppdata, int total_data,
4247 unsigned int max_data_bytes)
4249 char *params = *pparams;
4250 char *pdata = *ppdata;
4251 unsigned int data_size = 0;
4252 unsigned int param_size = 2;
4257 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4261 if (total_params < 4) {
4262 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4266 fsp = file_fsp(req, SVAL(params,0));
4267 if (!fsp_is_np(fsp)) {
4268 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4272 info_level = SVAL(params,2);
4274 *pparams = (char *)SMB_REALLOC(*pparams,2);
4275 if (*pparams == NULL) {
4276 reply_nterror(req, NT_STATUS_NO_MEMORY);
4281 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4282 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4283 if (*ppdata == NULL ) {
4284 reply_nterror(req, NT_STATUS_NO_MEMORY);
4289 switch (info_level) {
4290 case SMB_FILE_STANDARD_INFORMATION:
4292 SOFF_T(pdata,0,4096LL);
4299 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4303 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4309 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4310 TALLOC_CTX *mem_ctx,
4311 uint16_t info_level,
4313 struct smb_filename *smb_fname,
4314 bool delete_pending,
4315 struct timespec write_time_ts,
4316 struct ea_list *ea_list,
4317 int lock_data_count,
4320 unsigned int max_data_bytes,
4322 unsigned int *pdata_size)
4324 char *pdata = *ppdata;
4325 char *dstart, *dend;
4326 unsigned int data_size;
4327 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4328 time_t create_time, mtime, atime, c_time;
4329 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4336 uint64_t file_size = 0;
4338 uint64_t allocation_size = 0;
4339 uint64_t file_index = 0;
4340 uint32_t access_mask = 0;
4342 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4343 return NT_STATUS_INVALID_LEVEL;
4346 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4347 smb_fname_str_dbg(smb_fname),
4349 info_level, max_data_bytes));
4351 mode = dos_mode(conn, smb_fname);
4352 nlink = psbuf->st_ex_nlink;
4354 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4358 if ((nlink > 0) && delete_pending) {
4362 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4363 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4364 if (*ppdata == NULL) {
4365 return NT_STATUS_NO_MEMORY;
4369 dend = dstart + data_size - 1;
4371 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4372 update_stat_ex_mtime(psbuf, write_time_ts);
4375 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4376 mtime_ts = psbuf->st_ex_mtime;
4377 atime_ts = psbuf->st_ex_atime;
4378 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4380 if (lp_dos_filetime_resolution(SNUM(conn))) {
4381 dos_filetime_timespec(&create_time_ts);
4382 dos_filetime_timespec(&mtime_ts);
4383 dos_filetime_timespec(&atime_ts);
4384 dos_filetime_timespec(&ctime_ts);
4387 create_time = convert_timespec_to_time_t(create_time_ts);
4388 mtime = convert_timespec_to_time_t(mtime_ts);
4389 atime = convert_timespec_to_time_t(atime_ts);
4390 c_time = convert_timespec_to_time_t(ctime_ts);
4392 p = strrchr_m(smb_fname->base_name,'/');
4394 base_name = smb_fname->base_name;
4398 /* NT expects the name to be in an exact form of the *full*
4399 filename. See the trans2 torture test */
4400 if (ISDOT(base_name)) {
4401 dos_fname = talloc_strdup(mem_ctx, "\\");
4403 return NT_STATUS_NO_MEMORY;
4406 dos_fname = talloc_asprintf(mem_ctx,
4408 smb_fname->base_name);
4410 return NT_STATUS_NO_MEMORY;
4412 if (is_ntfs_stream_smb_fname(smb_fname)) {
4413 dos_fname = talloc_asprintf(dos_fname, "%s",
4414 smb_fname->stream_name);
4416 return NT_STATUS_NO_MEMORY;
4420 string_replace(dos_fname, '/', '\\');
4423 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4426 /* Do we have this path open ? */
4428 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4429 fsp1 = file_find_di_first(conn->sconn, fileid);
4430 if (fsp1 && fsp1->initial_allocation_size) {
4431 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4435 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4436 file_size = get_file_size_stat(psbuf);
4440 pos = fsp->fh->position_information;
4444 access_mask = fsp->access_mask;
4446 /* GENERIC_EXECUTE mapping from Windows */
4447 access_mask = 0x12019F;
4450 /* This should be an index number - looks like
4453 I think this causes us to fail the IFSKIT
4454 BasicFileInformationTest. -tpot */
4455 file_index = get_FileIndex(conn, psbuf);
4457 switch (info_level) {
4458 case SMB_INFO_STANDARD:
4459 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4461 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4462 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4463 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4464 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4465 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4466 SSVAL(pdata,l1_attrFile,mode);
4469 case SMB_INFO_QUERY_EA_SIZE:
4471 unsigned int ea_size =
4472 estimate_ea_size(conn, fsp,
4474 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4476 srv_put_dos_date2(pdata,0,create_time);
4477 srv_put_dos_date2(pdata,4,atime);
4478 srv_put_dos_date2(pdata,8,mtime); /* write time */
4479 SIVAL(pdata,12,(uint32)file_size);
4480 SIVAL(pdata,16,(uint32)allocation_size);
4481 SSVAL(pdata,20,mode);
4482 SIVAL(pdata,22,ea_size);
4486 case SMB_INFO_IS_NAME_VALID:
4487 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4489 /* os/2 needs this ? really ?*/
4490 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4492 /* This is only reached for qpathinfo */
4496 case SMB_INFO_QUERY_EAS_FROM_LIST:
4498 size_t total_ea_len = 0;
4499 struct ea_list *ea_file_list = NULL;
4500 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4503 get_ea_list_from_file(mem_ctx, conn, fsp,
4505 &total_ea_len, &ea_file_list);
4506 if (!NT_STATUS_IS_OK(status)) {
4510 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4512 if (!ea_list || (total_ea_len > data_size)) {
4514 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4518 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4522 case SMB_INFO_QUERY_ALL_EAS:
4524 /* We have data_size bytes to put EA's into. */
4525 size_t total_ea_len = 0;
4526 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4528 status = get_ea_list_from_file(mem_ctx, conn, fsp,
4530 &total_ea_len, &ea_list);
4531 if (!NT_STATUS_IS_OK(status)) {
4535 if (!ea_list || (total_ea_len > data_size)) {
4537 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4541 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4545 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4547 /* This is FileFullEaInformation - 0xF which maps to
4548 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4550 /* We have data_size bytes to put EA's into. */
4551 size_t total_ea_len = 0;
4552 struct ea_list *ea_file_list = NULL;
4554 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4556 /*TODO: add filtering and index handling */
4559 get_ea_list_from_file(mem_ctx, conn, fsp,
4561 &total_ea_len, &ea_file_list);
4562 if (!NT_STATUS_IS_OK(status)) {
4565 if (!ea_file_list) {
4566 return NT_STATUS_NO_EAS_ON_FILE;
4569 status = fill_ea_chained_buffer(mem_ctx,
4573 conn, ea_file_list);
4574 if (!NT_STATUS_IS_OK(status)) {
4580 case SMB_FILE_BASIC_INFORMATION:
4581 case SMB_QUERY_FILE_BASIC_INFO:
4583 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4584 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4585 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4587 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4591 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4592 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4593 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4594 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4595 SIVAL(pdata,32,mode);
4597 DEBUG(5,("SMB_QFBI - "));
4598 DEBUG(5,("create: %s ", ctime(&create_time)));
4599 DEBUG(5,("access: %s ", ctime(&atime)));
4600 DEBUG(5,("write: %s ", ctime(&mtime)));
4601 DEBUG(5,("change: %s ", ctime(&c_time)));
4602 DEBUG(5,("mode: %x\n", mode));
4605 case SMB_FILE_STANDARD_INFORMATION:
4606 case SMB_QUERY_FILE_STANDARD_INFO:
4608 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4610 SOFF_T(pdata,0,allocation_size);
4611 SOFF_T(pdata,8,file_size);
4612 SIVAL(pdata,16,nlink);
4613 SCVAL(pdata,20,delete_pending?1:0);
4614 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4615 SSVAL(pdata,22,0); /* Padding. */
4618 case SMB_FILE_EA_INFORMATION:
4619 case SMB_QUERY_FILE_EA_INFO:
4621 unsigned int ea_size =
4622 estimate_ea_size(conn, fsp, smb_fname);
4623 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4625 SIVAL(pdata,0,ea_size);
4629 /* Get the 8.3 name - used if NT SMB was negotiated. */
4630 case SMB_QUERY_FILE_ALT_NAME_INFO:
4631 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4634 char mangled_name[13];
4635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4636 if (!name_to_8_3(base_name,mangled_name,
4637 True,conn->params)) {
4638 return NT_STATUS_NO_MEMORY;
4640 len = srvstr_push(dstart, flags2,
4641 pdata+4, mangled_name,
4642 PTR_DIFF(dend, pdata+4),
4644 data_size = 4 + len;
4649 case SMB_QUERY_FILE_NAME_INFO:
4653 this must be *exactly* right for ACLs on mapped drives to work
4655 len = srvstr_push(dstart, flags2,
4657 PTR_DIFF(dend, pdata+4),
4659 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4660 data_size = 4 + len;
4665 case SMB_FILE_ALLOCATION_INFORMATION:
4666 case SMB_QUERY_FILE_ALLOCATION_INFO:
4667 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4669 SOFF_T(pdata,0,allocation_size);
4672 case SMB_FILE_END_OF_FILE_INFORMATION:
4673 case SMB_QUERY_FILE_END_OF_FILEINFO:
4674 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4676 SOFF_T(pdata,0,file_size);
4679 case SMB_QUERY_FILE_ALL_INFO:
4680 case SMB_FILE_ALL_INFORMATION:
4683 unsigned int ea_size =
4684 estimate_ea_size(conn, fsp, smb_fname);
4685 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4686 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4687 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4688 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4689 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4690 SIVAL(pdata,32,mode);
4691 SIVAL(pdata,36,0); /* padding. */
4693 SOFF_T(pdata,0,allocation_size);
4694 SOFF_T(pdata,8,file_size);
4695 SIVAL(pdata,16,nlink);
4696 SCVAL(pdata,20,delete_pending);
4697 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4700 SIVAL(pdata,0,ea_size);
4701 pdata += 4; /* EA info */
4702 len = srvstr_push(dstart, flags2,
4704 PTR_DIFF(dend, pdata+4),
4708 data_size = PTR_DIFF(pdata,(*ppdata));
4712 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4715 unsigned int ea_size =
4716 estimate_ea_size(conn, fsp, smb_fname);
4717 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4718 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4719 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4720 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4721 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4722 SIVAL(pdata, 0x20, mode);
4723 SIVAL(pdata, 0x24, 0); /* padding. */
4724 SBVAL(pdata, 0x28, allocation_size);
4725 SBVAL(pdata, 0x30, file_size);
4726 SIVAL(pdata, 0x38, nlink);
4727 SCVAL(pdata, 0x3C, delete_pending);
4728 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4729 SSVAL(pdata, 0x3E, 0); /* padding */
4730 SBVAL(pdata, 0x40, file_index);
4731 SIVAL(pdata, 0x48, ea_size);
4732 SIVAL(pdata, 0x4C, access_mask);
4733 SBVAL(pdata, 0x50, pos);
4734 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4735 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4739 len = srvstr_push(dstart, flags2,
4741 PTR_DIFF(dend, pdata+4),
4745 data_size = PTR_DIFF(pdata,(*ppdata));
4748 case SMB_FILE_INTERNAL_INFORMATION:
4750 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4751 SBVAL(pdata, 0, file_index);
4755 case SMB_FILE_ACCESS_INFORMATION:
4756 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4757 SIVAL(pdata, 0, access_mask);
4761 case SMB_FILE_NAME_INFORMATION:
4762 /* Pathname with leading '\'. */
4765 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4766 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4767 SIVAL(pdata,0,byte_len);
4768 data_size = 4 + byte_len;
4772 case SMB_FILE_DISPOSITION_INFORMATION:
4773 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4775 SCVAL(pdata,0,delete_pending);
4778 case SMB_FILE_POSITION_INFORMATION:
4779 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4781 SOFF_T(pdata,0,pos);
4784 case SMB_FILE_MODE_INFORMATION:
4785 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4786 SIVAL(pdata,0,mode);
4790 case SMB_FILE_ALIGNMENT_INFORMATION:
4791 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4792 SIVAL(pdata,0,0); /* No alignment needed. */
4797 * NT4 server just returns "invalid query" to this - if we try
4798 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4801 /* The first statement above is false - verified using Thursby
4802 * client against NT4 -- gcolley.
4804 case SMB_QUERY_FILE_STREAM_INFO:
4805 case SMB_FILE_STREAM_INFORMATION: {
4806 unsigned int num_streams = 0;
4807 struct stream_struct *streams = NULL;
4809 DEBUG(10,("smbd_do_qfilepathinfo: "
4810 "SMB_FILE_STREAM_INFORMATION\n"));
4812 if (is_ntfs_stream_smb_fname(smb_fname)) {
4813 return NT_STATUS_INVALID_PARAMETER;
4816 status = vfs_streaminfo(conn, fsp, smb_fname->base_name,
4817 talloc_tos(), &num_streams, &streams);
4819 if (!NT_STATUS_IS_OK(status)) {
4820 DEBUG(10, ("could not get stream info: %s\n",
4821 nt_errstr(status)));
4825 status = marshall_stream_info(num_streams, streams,
4826 pdata, max_data_bytes,
4829 if (!NT_STATUS_IS_OK(status)) {
4830 DEBUG(10, ("marshall_stream_info failed: %s\n",
4831 nt_errstr(status)));
4832 TALLOC_FREE(streams);
4836 TALLOC_FREE(streams);
4840 case SMB_QUERY_COMPRESSION_INFO:
4841 case SMB_FILE_COMPRESSION_INFORMATION:
4842 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4843 SOFF_T(pdata,0,file_size);
4844 SIVAL(pdata,8,0); /* ??? */
4845 SIVAL(pdata,12,0); /* ??? */
4849 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4850 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4851 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4852 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4853 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4854 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4855 SOFF_T(pdata,32,allocation_size);
4856 SOFF_T(pdata,40,file_size);
4857 SIVAL(pdata,48,mode);
4858 SIVAL(pdata,52,0); /* ??? */
4862 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4863 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4864 SIVAL(pdata,0,mode);
4870 * CIFS UNIX Extensions.
4873 case SMB_QUERY_FILE_UNIX_BASIC:
4875 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4876 data_size = PTR_DIFF(pdata,(*ppdata));
4878 DEBUG(4,("smbd_do_qfilepathinfo: "
4879 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4880 dump_data(4, (uint8_t *)(*ppdata), data_size);
4884 case SMB_QUERY_FILE_UNIX_INFO2:
4886 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4887 data_size = PTR_DIFF(pdata,(*ppdata));
4891 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4893 for (i=0; i<100; i++)
4894 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4900 case SMB_QUERY_FILE_UNIX_LINK:
4903 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4906 return NT_STATUS_NO_MEMORY;
4909 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4911 if(!S_ISLNK(psbuf->st_ex_mode)) {
4912 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4915 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4917 len = SMB_VFS_READLINK(conn,
4918 smb_fname->base_name,
4921 return map_nt_error_from_unix(errno);
4924 len = srvstr_push(dstart, flags2,
4926 PTR_DIFF(dend, pdata),
4929 data_size = PTR_DIFF(pdata,(*ppdata));
4934 #if defined(HAVE_POSIX_ACLS)
4935 case SMB_QUERY_POSIX_ACL:
4937 SMB_ACL_T file_acl = NULL;
4938 SMB_ACL_T def_acl = NULL;
4939 uint16 num_file_acls = 0;
4940 uint16 num_def_acls = 0;
4942 if (fsp && fsp->fh->fd != -1) {
4943 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4947 SMB_VFS_SYS_ACL_GET_FILE(conn,
4948 smb_fname->base_name,
4949 SMB_ACL_TYPE_ACCESS,
4953 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4954 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4955 "not implemented on "
4956 "filesystem containing %s\n",
4957 smb_fname->base_name));
4958 return NT_STATUS_NOT_IMPLEMENTED;
4961 if (S_ISDIR(psbuf->st_ex_mode)) {
4962 if (fsp && fsp->is_directory) {
4964 SMB_VFS_SYS_ACL_GET_FILE(
4966 fsp->fsp_name->base_name,
4967 SMB_ACL_TYPE_DEFAULT,
4971 SMB_VFS_SYS_ACL_GET_FILE(
4973 smb_fname->base_name,
4974 SMB_ACL_TYPE_DEFAULT,
4977 def_acl = free_empty_sys_acl(conn, def_acl);
4980 num_file_acls = count_acl_entries(conn, file_acl);
4981 num_def_acls = count_acl_entries(conn, def_acl);
4983 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4984 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4986 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4987 SMB_POSIX_ACL_HEADER_SIZE) ));
4989 TALLOC_FREE(file_acl);
4992 TALLOC_FREE(def_acl);
4994 return NT_STATUS_BUFFER_TOO_SMALL;
4997 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4998 SSVAL(pdata,2,num_file_acls);
4999 SSVAL(pdata,4,num_def_acls);
5000 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5002 TALLOC_FREE(file_acl);
5005 TALLOC_FREE(def_acl);
5007 return NT_STATUS_INTERNAL_ERROR;
5009 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5011 TALLOC_FREE(file_acl);
5014 TALLOC_FREE(def_acl);
5016 return NT_STATUS_INTERNAL_ERROR;
5020 TALLOC_FREE(file_acl);
5023 TALLOC_FREE(def_acl);
5025 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5031 case SMB_QUERY_POSIX_LOCK:
5036 enum brl_type lock_type;
5038 /* We need an open file with a real fd for this. */
5039 if (!fsp || fsp->fh->fd == -1) {
5040 return NT_STATUS_INVALID_LEVEL;
5043 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5044 return NT_STATUS_INVALID_PARAMETER;
5047 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5048 case POSIX_LOCK_TYPE_READ:
5049 lock_type = READ_LOCK;
5051 case POSIX_LOCK_TYPE_WRITE:
5052 lock_type = WRITE_LOCK;
5054 case POSIX_LOCK_TYPE_UNLOCK:
5056 /* There's no point in asking for an unlock... */
5057 return NT_STATUS_INVALID_PARAMETER;
5060 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5061 #if defined(HAVE_LONGLONG)
5062 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
5063 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
5064 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
5065 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
5066 #else /* HAVE_LONGLONG */
5067 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
5068 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5069 #endif /* HAVE_LONGLONG */
5071 status = query_lock(fsp,
5078 if (ERROR_WAS_LOCK_DENIED(status)) {
5079 /* Here we need to report who has it locked... */
5080 data_size = POSIX_LOCK_DATA_SIZE;
5082 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5083 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5084 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5085 #if defined(HAVE_LONGLONG)
5086 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
5087 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
5088 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
5089 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
5090 #else /* HAVE_LONGLONG */
5091 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5092 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5093 #endif /* HAVE_LONGLONG */
5095 } else if (NT_STATUS_IS_OK(status)) {
5096 /* For success we just return a copy of what we sent
5097 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5098 data_size = POSIX_LOCK_DATA_SIZE;
5099 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5100 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5108 return NT_STATUS_INVALID_LEVEL;
5111 *pdata_size = data_size;
5112 return NT_STATUS_OK;
5115 /****************************************************************************
5116 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5117 file name or file id).
5118 ****************************************************************************/
5120 static void call_trans2qfilepathinfo(connection_struct *conn,
5121 struct smb_request *req,
5122 unsigned int tran_call,
5123 char **pparams, int total_params,
5124 char **ppdata, int total_data,
5125 unsigned int max_data_bytes)
5127 char *params = *pparams;
5128 char *pdata = *ppdata;
5130 unsigned int data_size = 0;
5131 unsigned int param_size = 2;
5132 struct smb_filename *smb_fname = NULL;
5133 bool delete_pending = False;
5134 struct timespec write_time_ts;
5135 files_struct *fsp = NULL;
5136 struct file_id fileid;
5137 struct ea_list *ea_list = NULL;
5138 int lock_data_count = 0;
5139 char *lock_data = NULL;
5140 NTSTATUS status = NT_STATUS_OK;
5143 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5147 ZERO_STRUCT(write_time_ts);
5149 if (tran_call == TRANSACT2_QFILEINFO) {
5150 if (total_params < 4) {
5151 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5156 call_trans2qpipeinfo(conn, req, tran_call,
5157 pparams, total_params,
5163 fsp = file_fsp(req, SVAL(params,0));
5164 info_level = SVAL(params,2);
5166 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5168 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5169 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5173 /* Initial check for valid fsp ptr. */
5174 if (!check_fsp_open(conn, req, fsp)) {
5178 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5180 if (!NT_STATUS_IS_OK(status)) {
5181 reply_nterror(req, status);
5185 if(fsp->fake_file_handle) {
5187 * This is actually for the QUOTA_FAKE_FILE --metze
5190 /* We know this name is ok, it's already passed the checks. */
5192 } else if(fsp->fh->fd == -1) {
5194 * This is actually a QFILEINFO on a directory
5195 * handle (returned from an NT SMB). NT5.0 seems
5196 * to do this call. JRA.
5199 if (INFO_LEVEL_IS_UNIX(info_level)) {
5200 /* Always do lstat for UNIX calls. */
5201 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5202 DEBUG(3,("call_trans2qfilepathinfo: "
5203 "SMB_VFS_LSTAT of %s failed "
5205 smb_fname_str_dbg(smb_fname),
5208 map_nt_error_from_unix(errno));
5211 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5212 DEBUG(3,("call_trans2qfilepathinfo: "
5213 "SMB_VFS_STAT of %s failed (%s)\n",
5214 smb_fname_str_dbg(smb_fname),
5217 map_nt_error_from_unix(errno));
5221 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5222 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5225 * Original code - this is an open file.
5227 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5228 DEBUG(3, ("fstat of %s failed (%s)\n",
5229 fsp_fnum_dbg(fsp), strerror(errno)));
5231 map_nt_error_from_unix(errno));
5234 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5235 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5241 uint32_t ucf_flags = 0;
5244 if (total_params < 7) {
5245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5249 info_level = SVAL(params,0);
5251 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5253 if (INFO_LEVEL_IS_UNIX(info_level)) {
5254 if (!lp_unix_extensions()) {
5255 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5258 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5259 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5260 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5261 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5265 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5267 STR_TERMINATE, &status);
5268 if (!NT_STATUS_IS_OK(status)) {
5269 reply_nterror(req, status);
5273 status = filename_convert(req,
5275 req->flags2 & FLAGS2_DFS_PATHNAMES,
5280 if (!NT_STATUS_IS_OK(status)) {
5281 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5282 reply_botherror(req,
5283 NT_STATUS_PATH_NOT_COVERED,
5284 ERRSRV, ERRbadpath);
5287 reply_nterror(req, status);
5291 /* If this is a stream, check if there is a delete_pending. */
5292 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5293 && is_ntfs_stream_smb_fname(smb_fname)) {
5294 struct smb_filename *smb_fname_base = NULL;
5296 /* Create an smb_filename with stream_name == NULL. */
5298 create_synthetic_smb_fname(talloc_tos(),
5299 smb_fname->base_name,
5302 if (!NT_STATUS_IS_OK(status)) {
5303 reply_nterror(req, status);
5307 if (INFO_LEVEL_IS_UNIX(info_level)) {
5308 /* Always do lstat for UNIX calls. */
5309 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5310 DEBUG(3,("call_trans2qfilepathinfo: "
5311 "SMB_VFS_LSTAT of %s failed "
5313 smb_fname_str_dbg(smb_fname_base),
5315 TALLOC_FREE(smb_fname_base);
5317 map_nt_error_from_unix(errno));
5321 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5322 DEBUG(3,("call_trans2qfilepathinfo: "
5323 "fileinfo of %s failed "
5325 smb_fname_str_dbg(smb_fname_base),
5327 TALLOC_FREE(smb_fname_base);
5329 map_nt_error_from_unix(errno));
5334 status = file_name_hash(conn,
5335 smb_fname_str_dbg(smb_fname_base),
5337 if (!NT_STATUS_IS_OK(status)) {
5338 TALLOC_FREE(smb_fname_base);
5339 reply_nterror(req, status);
5343 fileid = vfs_file_id_from_sbuf(conn,
5344 &smb_fname_base->st);
5345 TALLOC_FREE(smb_fname_base);
5346 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5347 if (delete_pending) {
5348 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5353 if (INFO_LEVEL_IS_UNIX(info_level)) {
5354 /* Always do lstat for UNIX calls. */
5355 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5356 DEBUG(3,("call_trans2qfilepathinfo: "
5357 "SMB_VFS_LSTAT of %s failed (%s)\n",
5358 smb_fname_str_dbg(smb_fname),
5361 map_nt_error_from_unix(errno));
5366 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5367 DEBUG(3,("call_trans2qfilepathinfo: "
5368 "SMB_VFS_STAT of %s failed (%s)\n",
5369 smb_fname_str_dbg(smb_fname),
5372 map_nt_error_from_unix(errno));
5377 status = file_name_hash(conn,
5378 smb_fname_str_dbg(smb_fname),
5380 if (!NT_STATUS_IS_OK(status)) {
5381 reply_nterror(req, status);
5385 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5386 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5387 if (delete_pending) {
5388 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5393 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5394 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5396 info_level,tran_call,total_data));
5398 /* Pull out any data sent here before we realloc. */
5399 switch (info_level) {
5400 case SMB_INFO_QUERY_EAS_FROM_LIST:
5402 /* Pull any EA list from the data portion. */
5405 if (total_data < 4) {
5407 req, NT_STATUS_INVALID_PARAMETER);
5410 ea_size = IVAL(pdata,0);
5412 if (total_data > 0 && ea_size != total_data) {
5413 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5414 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5416 req, NT_STATUS_INVALID_PARAMETER);
5420 if (!lp_ea_support(SNUM(conn))) {
5421 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5425 /* Pull out the list of names. */
5426 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5429 req, NT_STATUS_INVALID_PARAMETER);
5435 case SMB_QUERY_POSIX_LOCK:
5437 if (fsp == NULL || fsp->fh->fd == -1) {
5438 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5442 if (total_data != POSIX_LOCK_DATA_SIZE) {
5444 req, NT_STATUS_INVALID_PARAMETER);
5448 /* Copy the lock range data. */
5449 lock_data = (char *)talloc_memdup(
5450 req, pdata, total_data);
5452 reply_nterror(req, NT_STATUS_NO_MEMORY);
5455 lock_data_count = total_data;
5461 *pparams = (char *)SMB_REALLOC(*pparams,2);
5462 if (*pparams == NULL) {
5463 reply_nterror(req, NT_STATUS_NO_MEMORY);
5470 * draft-leach-cifs-v1-spec-02.txt
5471 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5474 * The requested information is placed in the Data portion of the
5475 * transaction response. For the information levels greater than 0x100,
5476 * the transaction response has 1 parameter word which should be
5477 * ignored by the client.
5479 * However Windows only follows this rule for the IS_NAME_VALID call.
5481 switch (info_level) {
5482 case SMB_INFO_IS_NAME_VALID:
5487 if ((info_level & 0xFF00) == 0xFF00) {
5489 * We use levels that start with 0xFF00
5490 * internally to represent SMB2 specific levels
5492 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5496 status = smbd_do_qfilepathinfo(conn, req, info_level,
5498 delete_pending, write_time_ts,
5500 lock_data_count, lock_data,
5501 req->flags2, max_data_bytes,
5502 ppdata, &data_size);
5503 if (!NT_STATUS_IS_OK(status)) {
5504 reply_nterror(req, status);
5508 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5514 /****************************************************************************
5515 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5517 ****************************************************************************/
5519 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5520 connection_struct *conn,
5521 struct smb_request *req,
5522 bool overwrite_if_exists,
5523 const struct smb_filename *smb_fname_old,
5524 struct smb_filename *smb_fname_new)
5526 NTSTATUS status = NT_STATUS_OK;
5528 /* source must already exist. */
5529 if (!VALID_STAT(smb_fname_old->st)) {
5530 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5533 if (VALID_STAT(smb_fname_new->st)) {
5534 if (overwrite_if_exists) {
5535 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5536 return NT_STATUS_FILE_IS_A_DIRECTORY;
5538 status = unlink_internals(conn,
5540 FILE_ATTRIBUTE_NORMAL,
5543 if (!NT_STATUS_IS_OK(status)) {
5547 /* Disallow if newname already exists. */
5548 return NT_STATUS_OBJECT_NAME_COLLISION;
5552 /* No links from a directory. */
5553 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5554 return NT_STATUS_FILE_IS_A_DIRECTORY;
5557 /* Setting a hardlink to/from a stream isn't currently supported. */
5558 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5559 is_ntfs_stream_smb_fname(smb_fname_new)) {
5560 return NT_STATUS_INVALID_PARAMETER;
5563 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5564 smb_fname_old->base_name, smb_fname_new->base_name));
5566 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5567 smb_fname_new->base_name) != 0) {
5568 status = map_nt_error_from_unix(errno);
5569 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5570 nt_errstr(status), smb_fname_old->base_name,
5571 smb_fname_new->base_name));
5576 /****************************************************************************
5577 Deal with setting the time from any of the setfilepathinfo functions.
5578 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
5579 calling this function.
5580 ****************************************************************************/
5582 NTSTATUS smb_set_file_time(connection_struct *conn,
5584 const struct smb_filename *smb_fname,
5585 struct smb_file_time *ft,
5586 bool setting_write_time)
5588 struct smb_filename smb_fname_base;
5590 FILE_NOTIFY_CHANGE_LAST_ACCESS
5591 |FILE_NOTIFY_CHANGE_LAST_WRITE
5592 |FILE_NOTIFY_CHANGE_CREATION;
5594 if (!VALID_STAT(smb_fname->st)) {
5595 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5598 /* get some defaults (no modifications) if any info is zero or -1. */
5599 if (null_timespec(ft->create_time)) {
5600 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5603 if (null_timespec(ft->atime)) {
5604 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5607 if (null_timespec(ft->mtime)) {
5608 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5611 if (!setting_write_time) {
5612 /* ft->mtime comes from change time, not write time. */
5613 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5616 /* Ensure the resolution is the correct for
5617 * what we can store on this filesystem. */
5619 round_timespec(conn->ts_res, &ft->create_time);
5620 round_timespec(conn->ts_res, &ft->ctime);
5621 round_timespec(conn->ts_res, &ft->atime);
5622 round_timespec(conn->ts_res, &ft->mtime);
5624 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5625 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5626 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5627 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5628 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5629 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5630 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5631 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5633 if (setting_write_time) {
5635 * This was a Windows setfileinfo on an open file.
5636 * NT does this a lot. We also need to
5637 * set the time here, as it can be read by
5638 * FindFirst/FindNext and with the patch for bug #2045
5639 * in smbd/fileio.c it ensures that this timestamp is
5640 * kept sticky even after a write. We save the request
5641 * away and will set it on file close and after a write. JRA.
5644 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5645 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5648 if (fsp->base_fsp) {
5649 set_sticky_write_time_fsp(fsp->base_fsp,
5652 set_sticky_write_time_fsp(fsp, ft->mtime);
5655 set_sticky_write_time_path(
5656 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5661 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5663 /* Always call ntimes on the base, even if a stream was passed in. */
5664 smb_fname_base = *smb_fname;
5665 smb_fname_base.stream_name = NULL;
5667 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5668 return map_nt_error_from_unix(errno);
5671 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5672 smb_fname->base_name);
5673 return NT_STATUS_OK;
5676 /****************************************************************************
5677 Deal with setting the dosmode from any of the setfilepathinfo functions.
5678 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
5679 done before calling this function.
5680 ****************************************************************************/
5682 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5683 const struct smb_filename *smb_fname,
5686 struct smb_filename *smb_fname_base = NULL;
5689 if (!VALID_STAT(smb_fname->st)) {
5690 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5693 /* Always operate on the base_name, even if a stream was passed in. */
5694 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5695 NULL, &smb_fname->st,
5697 if (!NT_STATUS_IS_OK(status)) {
5702 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5703 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5705 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5709 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5711 /* check the mode isn't different, before changing it */
5712 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5713 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5714 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5715 (unsigned int)dosmode));
5717 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5719 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5721 smb_fname_str_dbg(smb_fname_base),
5723 status = map_nt_error_from_unix(errno);
5727 status = NT_STATUS_OK;
5729 TALLOC_FREE(smb_fname_base);
5733 /****************************************************************************
5734 Deal with setting the size from any of the setfilepathinfo functions.
5735 ****************************************************************************/
5737 static NTSTATUS smb_set_file_size(connection_struct *conn,
5738 struct smb_request *req,
5740 const struct smb_filename *smb_fname,
5741 const SMB_STRUCT_STAT *psbuf,
5743 bool fail_after_createfile)
5745 NTSTATUS status = NT_STATUS_OK;
5746 struct smb_filename *smb_fname_tmp = NULL;
5747 files_struct *new_fsp = NULL;
5749 if (!VALID_STAT(*psbuf)) {
5750 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5753 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5755 if (size == get_file_size_stat(psbuf)) {
5756 return NT_STATUS_OK;
5759 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5760 smb_fname_str_dbg(smb_fname), (double)size));
5762 if (fsp && fsp->fh->fd != -1) {
5763 /* Handle based call. */
5764 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5765 return NT_STATUS_ACCESS_DENIED;
5768 if (vfs_set_filelen(fsp, size) == -1) {
5769 return map_nt_error_from_unix(errno);
5771 trigger_write_time_update_immediate(fsp);
5772 return NT_STATUS_OK;
5775 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5776 if (!NT_STATUS_IS_OK(status)) {
5780 smb_fname_tmp->st = *psbuf;
5782 status = SMB_VFS_CREATE_FILE(
5785 0, /* root_dir_fid */
5786 smb_fname_tmp, /* fname */
5787 FILE_WRITE_DATA, /* access_mask */
5788 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5790 FILE_OPEN, /* create_disposition*/
5791 0, /* create_options */
5792 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5793 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5794 0, /* allocation_size */
5795 0, /* private_flags */
5798 &new_fsp, /* result */
5801 TALLOC_FREE(smb_fname_tmp);
5803 if (!NT_STATUS_IS_OK(status)) {
5804 /* NB. We check for open_was_deferred in the caller. */
5808 /* See RAW-SFILEINFO-END-OF-FILE */
5809 if (fail_after_createfile) {
5810 close_file(req, new_fsp,NORMAL_CLOSE);
5811 return NT_STATUS_INVALID_LEVEL;
5814 if (vfs_set_filelen(new_fsp, size) == -1) {
5815 status = map_nt_error_from_unix(errno);
5816 close_file(req, new_fsp,NORMAL_CLOSE);
5820 trigger_write_time_update_immediate(new_fsp);
5821 close_file(req, new_fsp,NORMAL_CLOSE);
5822 return NT_STATUS_OK;
5825 /****************************************************************************
5826 Deal with SMB_INFO_SET_EA.
5827 ****************************************************************************/
5829 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5833 const struct smb_filename *smb_fname)
5835 struct ea_list *ea_list = NULL;
5836 TALLOC_CTX *ctx = NULL;
5837 NTSTATUS status = NT_STATUS_OK;
5839 if (total_data < 10) {
5841 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5842 length. They seem to have no effect. Bug #3212. JRA */
5844 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5845 /* We're done. We only get EA info in this call. */
5846 return NT_STATUS_OK;
5849 return NT_STATUS_INVALID_PARAMETER;
5852 if (IVAL(pdata,0) > total_data) {
5853 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5854 IVAL(pdata,0), (unsigned int)total_data));
5855 return NT_STATUS_INVALID_PARAMETER;
5859 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5861 return NT_STATUS_INVALID_PARAMETER;
5864 status = set_ea(conn, fsp, smb_fname, ea_list);
5869 /****************************************************************************
5870 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5871 ****************************************************************************/
5873 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5878 struct ea_list *ea_list = NULL;
5882 return NT_STATUS_INVALID_HANDLE;
5885 if (!lp_ea_support(SNUM(conn))) {
5886 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5887 "EA's not supported.\n",
5888 (unsigned int)total_data));
5889 return NT_STATUS_EAS_NOT_SUPPORTED;
5892 if (total_data < 10) {
5893 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5895 (unsigned int)total_data));
5896 return NT_STATUS_INVALID_PARAMETER;
5899 ea_list = read_nttrans_ea_list(talloc_tos(),
5904 return NT_STATUS_INVALID_PARAMETER;
5907 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5909 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5910 smb_fname_str_dbg(fsp->fsp_name),
5911 nt_errstr(status) ));
5917 /****************************************************************************
5918 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5919 ****************************************************************************/
5921 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5925 struct smb_filename *smb_fname)
5927 NTSTATUS status = NT_STATUS_OK;
5928 bool delete_on_close;
5931 if (total_data < 1) {
5932 return NT_STATUS_INVALID_PARAMETER;
5936 return NT_STATUS_INVALID_HANDLE;
5939 delete_on_close = (CVAL(pdata,0) ? True : False);
5940 dosmode = dos_mode(conn, smb_fname);
5942 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5943 "delete_on_close = %u\n",
5944 smb_fname_str_dbg(smb_fname),
5945 (unsigned int)dosmode,
5946 (unsigned int)delete_on_close ));
5948 if (delete_on_close) {
5949 status = can_set_delete_on_close(fsp, dosmode);
5950 if (!NT_STATUS_IS_OK(status)) {
5955 /* The set is across all open files on this dev/inode pair. */
5956 if (!set_delete_on_close(fsp, delete_on_close,
5957 conn->session_info->security_token,
5958 conn->session_info->unix_token)) {
5959 return NT_STATUS_ACCESS_DENIED;
5961 return NT_STATUS_OK;
5964 /****************************************************************************
5965 Deal with SMB_FILE_POSITION_INFORMATION.
5966 ****************************************************************************/
5968 static NTSTATUS smb_file_position_information(connection_struct *conn,
5973 uint64_t position_information;
5975 if (total_data < 8) {
5976 return NT_STATUS_INVALID_PARAMETER;
5980 /* Ignore on pathname based set. */
5981 return NT_STATUS_OK;
5984 position_information = (uint64_t)IVAL(pdata,0);
5985 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5987 DEBUG(10,("smb_file_position_information: Set file position "
5988 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5989 (double)position_information));
5990 fsp->fh->position_information = position_information;
5991 return NT_STATUS_OK;
5994 /****************************************************************************
5995 Deal with SMB_FILE_MODE_INFORMATION.
5996 ****************************************************************************/
5998 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6004 if (total_data < 4) {
6005 return NT_STATUS_INVALID_PARAMETER;
6007 mode = IVAL(pdata,0);
6008 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6009 return NT_STATUS_INVALID_PARAMETER;
6011 return NT_STATUS_OK;
6014 /****************************************************************************
6015 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6016 ****************************************************************************/
6018 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6019 struct smb_request *req,
6022 const struct smb_filename *smb_fname)
6024 char *link_target = NULL;
6025 const char *newname = smb_fname->base_name;
6026 TALLOC_CTX *ctx = talloc_tos();
6028 /* Set a symbolic link. */
6029 /* Don't allow this if follow links is false. */
6031 if (total_data == 0) {
6032 return NT_STATUS_INVALID_PARAMETER;
6035 if (!lp_symlinks(SNUM(conn))) {
6036 return NT_STATUS_ACCESS_DENIED;
6039 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6040 total_data, STR_TERMINATE);
6043 return NT_STATUS_INVALID_PARAMETER;
6046 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6047 newname, link_target ));
6049 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6050 return map_nt_error_from_unix(errno);
6053 return NT_STATUS_OK;
6056 /****************************************************************************
6057 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6058 ****************************************************************************/
6060 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6061 struct smb_request *req,
6062 const char *pdata, int total_data,
6063 struct smb_filename *smb_fname_new)
6065 char *oldname = NULL;
6066 struct smb_filename *smb_fname_old = NULL;
6067 TALLOC_CTX *ctx = talloc_tos();
6068 NTSTATUS status = NT_STATUS_OK;
6070 /* Set a hard link. */
6071 if (total_data == 0) {
6072 return NT_STATUS_INVALID_PARAMETER;
6075 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
6076 total_data, STR_TERMINATE, &status);
6077 if (!NT_STATUS_IS_OK(status)) {
6081 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6082 smb_fname_str_dbg(smb_fname_new), oldname));
6084 status = filename_convert(ctx,
6086 req->flags2 & FLAGS2_DFS_PATHNAMES,
6091 if (!NT_STATUS_IS_OK(status)) {
6095 return hardlink_internals(ctx, conn, req, false,
6096 smb_fname_old, smb_fname_new);
6099 /****************************************************************************
6100 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6101 ****************************************************************************/
6103 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6104 struct smb_request *req,
6108 struct smb_filename *smb_fname_src)
6112 char *newname = NULL;
6113 struct smb_filename *smb_fname_dst = NULL;
6114 NTSTATUS status = NT_STATUS_OK;
6115 TALLOC_CTX *ctx = talloc_tos();
6118 return NT_STATUS_INVALID_HANDLE;
6121 if (total_data < 20) {
6122 return NT_STATUS_INVALID_PARAMETER;
6125 overwrite = (CVAL(pdata,0) ? True : False);
6126 len = IVAL(pdata,16);
6128 if (len > (total_data - 20) || (len == 0)) {
6129 return NT_STATUS_INVALID_PARAMETER;
6132 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6133 &pdata[20], len, STR_TERMINATE,
6135 if (!NT_STATUS_IS_OK(status)) {
6139 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6142 status = filename_convert(ctx,
6144 req->flags2 & FLAGS2_DFS_PATHNAMES,
6149 if (!NT_STATUS_IS_OK(status)) {
6153 if (fsp->base_fsp) {
6154 /* newname must be a stream name. */
6155 if (newname[0] != ':') {
6156 return NT_STATUS_NOT_SUPPORTED;
6159 /* Create an smb_fname to call rename_internals_fsp() with. */
6160 status = create_synthetic_smb_fname(talloc_tos(),
6161 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6163 if (!NT_STATUS_IS_OK(status)) {
6168 * Set the original last component, since
6169 * rename_internals_fsp() requires it.
6171 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6173 if (smb_fname_dst->original_lcomp == NULL) {
6174 status = NT_STATUS_NO_MEMORY;
6180 DEBUG(10,("smb2_file_rename_information: "
6181 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6182 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6183 smb_fname_str_dbg(smb_fname_dst)));
6184 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6185 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6189 TALLOC_FREE(smb_fname_dst);
6193 static NTSTATUS smb_file_link_information(connection_struct *conn,
6194 struct smb_request *req,
6198 struct smb_filename *smb_fname_src)
6202 char *newname = NULL;
6203 struct smb_filename *smb_fname_dst = NULL;
6204 NTSTATUS status = NT_STATUS_OK;
6205 TALLOC_CTX *ctx = talloc_tos();
6208 return NT_STATUS_INVALID_HANDLE;
6211 if (total_data < 20) {
6212 return NT_STATUS_INVALID_PARAMETER;
6215 overwrite = (CVAL(pdata,0) ? true : false);
6216 len = IVAL(pdata,16);
6218 if (len > (total_data - 20) || (len == 0)) {
6219 return NT_STATUS_INVALID_PARAMETER;
6222 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6223 &pdata[20], len, STR_TERMINATE,
6225 if (!NT_STATUS_IS_OK(status)) {
6229 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6232 status = filename_convert(ctx,
6234 req->flags2 & FLAGS2_DFS_PATHNAMES,
6239 if (!NT_STATUS_IS_OK(status)) {
6243 if (fsp->base_fsp) {
6244 /* No stream names. */
6245 return NT_STATUS_NOT_SUPPORTED;
6248 DEBUG(10,("smb_file_link_information: "
6249 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6250 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6251 smb_fname_str_dbg(smb_fname_dst)));
6252 status = hardlink_internals(ctx,
6259 TALLOC_FREE(smb_fname_dst);
6263 /****************************************************************************
6264 Deal with SMB_FILE_RENAME_INFORMATION.
6265 ****************************************************************************/
6267 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6268 struct smb_request *req,
6272 struct smb_filename *smb_fname_src)
6277 char *newname = NULL;
6278 struct smb_filename *smb_fname_dst = NULL;
6279 bool dest_has_wcard = False;
6280 NTSTATUS status = NT_STATUS_OK;
6282 TALLOC_CTX *ctx = talloc_tos();
6284 if (total_data < 13) {
6285 return NT_STATUS_INVALID_PARAMETER;
6288 overwrite = (CVAL(pdata,0) ? True : False);
6289 root_fid = IVAL(pdata,4);
6290 len = IVAL(pdata,8);
6292 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6293 return NT_STATUS_INVALID_PARAMETER;
6296 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6299 if (!NT_STATUS_IS_OK(status)) {
6303 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6306 status = resolve_dfspath_wcard(ctx, conn,
6307 req->flags2 & FLAGS2_DFS_PATHNAMES,
6310 !conn->sconn->using_smb2,
6313 if (!NT_STATUS_IS_OK(status)) {
6317 /* Check the new name has no '/' characters. */
6318 if (strchr_m(newname, '/')) {
6319 return NT_STATUS_NOT_SUPPORTED;
6322 if (fsp && fsp->base_fsp) {
6323 /* newname must be a stream name. */
6324 if (newname[0] != ':') {
6325 return NT_STATUS_NOT_SUPPORTED;
6328 /* Create an smb_fname to call rename_internals_fsp() with. */
6329 status = create_synthetic_smb_fname(talloc_tos(),
6330 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6332 if (!NT_STATUS_IS_OK(status)) {
6337 * Set the original last component, since
6338 * rename_internals_fsp() requires it.
6340 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6342 if (smb_fname_dst->original_lcomp == NULL) {
6343 status = NT_STATUS_NO_MEMORY;
6349 * Build up an smb_fname_dst based on the filename passed in.
6350 * We basically just strip off the last component, and put on
6351 * the newname instead.
6353 char *base_name = NULL;
6355 /* newname must *not* be a stream name. */
6356 if (newname[0] == ':') {
6357 return NT_STATUS_NOT_SUPPORTED;
6361 * Strip off the last component (filename) of the path passed
6364 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6366 return NT_STATUS_NO_MEMORY;
6368 p = strrchr_m(base_name, '/');
6372 base_name = talloc_strdup(ctx, "");
6374 return NT_STATUS_NO_MEMORY;
6377 /* Append the new name. */
6378 base_name = talloc_asprintf_append(base_name,
6382 return NT_STATUS_NO_MEMORY;
6385 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6388 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6391 /* If an error we expect this to be
6392 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6394 if (!NT_STATUS_IS_OK(status)) {
6395 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6399 /* Create an smb_fname to call rename_internals_fsp() */
6400 status = create_synthetic_smb_fname(ctx,
6404 if (!NT_STATUS_IS_OK(status)) {
6411 DEBUG(10,("smb_file_rename_information: "
6412 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6413 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6414 smb_fname_str_dbg(smb_fname_dst)));
6415 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6418 DEBUG(10,("smb_file_rename_information: "
6419 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6420 smb_fname_str_dbg(smb_fname_src),
6421 smb_fname_str_dbg(smb_fname_dst)));
6422 status = rename_internals(ctx, conn, req, smb_fname_src,
6423 smb_fname_dst, 0, overwrite, false,
6425 FILE_WRITE_ATTRIBUTES);
6428 TALLOC_FREE(smb_fname_dst);
6432 /****************************************************************************
6433 Deal with SMB_SET_POSIX_ACL.
6434 ****************************************************************************/
6436 #if defined(HAVE_POSIX_ACLS)
6437 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6441 const struct smb_filename *smb_fname)
6443 uint16 posix_acl_version;
6444 uint16 num_file_acls;
6445 uint16 num_def_acls;
6446 bool valid_file_acls = True;
6447 bool valid_def_acls = True;
6449 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6450 return NT_STATUS_INVALID_PARAMETER;
6452 posix_acl_version = SVAL(pdata,0);
6453 num_file_acls = SVAL(pdata,2);
6454 num_def_acls = SVAL(pdata,4);
6456 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6457 valid_file_acls = False;
6461 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6462 valid_def_acls = False;
6466 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6467 return NT_STATUS_INVALID_PARAMETER;
6470 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6471 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6472 return NT_STATUS_INVALID_PARAMETER;
6475 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6476 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6477 (unsigned int)num_file_acls,
6478 (unsigned int)num_def_acls));
6480 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6481 smb_fname->base_name, num_file_acls,
6482 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6483 return map_nt_error_from_unix(errno);
6486 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6487 smb_fname->base_name, &smb_fname->st, num_def_acls,
6488 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6489 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6490 return map_nt_error_from_unix(errno);
6492 return NT_STATUS_OK;
6496 /****************************************************************************
6497 Deal with SMB_SET_POSIX_LOCK.
6498 ****************************************************************************/
6500 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6501 struct smb_request *req,
6509 bool blocking_lock = False;
6510 enum brl_type lock_type;
6512 NTSTATUS status = NT_STATUS_OK;
6514 if (fsp == NULL || fsp->fh->fd == -1) {
6515 return NT_STATUS_INVALID_HANDLE;
6518 if (total_data != POSIX_LOCK_DATA_SIZE) {
6519 return NT_STATUS_INVALID_PARAMETER;
6522 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6523 case POSIX_LOCK_TYPE_READ:
6524 lock_type = READ_LOCK;
6526 case POSIX_LOCK_TYPE_WRITE:
6527 /* Return the right POSIX-mappable error code for files opened read-only. */
6528 if (!fsp->can_write) {
6529 return NT_STATUS_INVALID_HANDLE;
6531 lock_type = WRITE_LOCK;
6533 case POSIX_LOCK_TYPE_UNLOCK:
6534 lock_type = UNLOCK_LOCK;
6537 return NT_STATUS_INVALID_PARAMETER;
6540 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6541 blocking_lock = False;
6542 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6543 blocking_lock = True;
6545 return NT_STATUS_INVALID_PARAMETER;
6548 if (!lp_blocking_locks(SNUM(conn))) {
6549 blocking_lock = False;
6552 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6553 #if defined(HAVE_LONGLONG)
6554 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6555 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6556 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6557 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6558 #else /* HAVE_LONGLONG */
6559 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6560 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6561 #endif /* HAVE_LONGLONG */
6563 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6564 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6566 (unsigned int)lock_type,
6567 (unsigned long long)smblctx,
6571 if (lock_type == UNLOCK_LOCK) {
6572 status = do_unlock(req->sconn->msg_ctx,
6579 uint64_t block_smblctx;
6581 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6593 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6595 * A blocking lock was requested. Package up
6596 * this smb into a queued request and push it
6597 * onto the blocking lock queue.
6599 if(push_blocking_lock_request(br_lck,
6602 -1, /* infinite timeout. */
6610 TALLOC_FREE(br_lck);
6614 TALLOC_FREE(br_lck);
6620 /****************************************************************************
6621 Deal with SMB_SET_FILE_BASIC_INFO.
6622 ****************************************************************************/
6624 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6628 const struct smb_filename *smb_fname)
6630 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6631 struct smb_file_time ft;
6633 NTSTATUS status = NT_STATUS_OK;
6637 if (total_data < 36) {
6638 return NT_STATUS_INVALID_PARAMETER;
6641 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6642 if (!NT_STATUS_IS_OK(status)) {
6646 /* Set the attributes */
6647 dosmode = IVAL(pdata,32);
6648 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6649 if (!NT_STATUS_IS_OK(status)) {
6654 ft.create_time = interpret_long_date(pdata);
6657 ft.atime = interpret_long_date(pdata+8);
6660 ft.mtime = interpret_long_date(pdata+16);
6663 ft.ctime = interpret_long_date(pdata+24);
6665 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6666 smb_fname_str_dbg(smb_fname)));
6668 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6672 /****************************************************************************
6673 Deal with SMB_INFO_STANDARD.
6674 ****************************************************************************/
6676 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6680 const struct smb_filename *smb_fname)
6683 struct smb_file_time ft;
6687 if (total_data < 12) {
6688 return NT_STATUS_INVALID_PARAMETER;
6692 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6694 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6696 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6698 DEBUG(10,("smb_set_info_standard: file %s\n",
6699 smb_fname_str_dbg(smb_fname)));
6701 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
6702 if (!NT_STATUS_IS_OK(status)) {
6706 return smb_set_file_time(conn,
6713 /****************************************************************************
6714 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6715 ****************************************************************************/
6717 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6718 struct smb_request *req,
6722 struct smb_filename *smb_fname)
6724 uint64_t allocation_size = 0;
6725 NTSTATUS status = NT_STATUS_OK;
6726 files_struct *new_fsp = NULL;
6728 if (!VALID_STAT(smb_fname->st)) {
6729 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6732 if (total_data < 8) {
6733 return NT_STATUS_INVALID_PARAMETER;
6736 allocation_size = (uint64_t)IVAL(pdata,0);
6737 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6738 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6739 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6740 (double)allocation_size));
6742 if (allocation_size) {
6743 allocation_size = smb_roundup(conn, allocation_size);
6746 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6747 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6748 (double)allocation_size));
6750 if (fsp && fsp->fh->fd != -1) {
6751 /* Open file handle. */
6752 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6753 return NT_STATUS_ACCESS_DENIED;
6756 /* Only change if needed. */
6757 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6758 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6759 return map_nt_error_from_unix(errno);
6762 /* But always update the time. */
6764 * This is equivalent to a write. Ensure it's seen immediately
6765 * if there are no pending writes.
6767 trigger_write_time_update_immediate(fsp);
6768 return NT_STATUS_OK;
6771 /* Pathname or stat or directory file. */
6772 status = SMB_VFS_CREATE_FILE(
6775 0, /* root_dir_fid */
6776 smb_fname, /* fname */
6777 FILE_WRITE_DATA, /* access_mask */
6778 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6780 FILE_OPEN, /* create_disposition*/
6781 0, /* create_options */
6782 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6783 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6784 0, /* allocation_size */
6785 0, /* private_flags */
6788 &new_fsp, /* result */
6791 if (!NT_STATUS_IS_OK(status)) {
6792 /* NB. We check for open_was_deferred in the caller. */
6796 /* Only change if needed. */
6797 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6798 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6799 status = map_nt_error_from_unix(errno);
6800 close_file(req, new_fsp, NORMAL_CLOSE);
6805 /* Changing the allocation size should set the last mod time. */
6807 * This is equivalent to a write. Ensure it's seen immediately
6808 * if there are no pending writes.
6810 trigger_write_time_update_immediate(new_fsp);
6812 close_file(req, new_fsp, NORMAL_CLOSE);
6813 return NT_STATUS_OK;
6816 /****************************************************************************
6817 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6818 ****************************************************************************/
6820 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6821 struct smb_request *req,
6825 const struct smb_filename *smb_fname,
6826 bool fail_after_createfile)
6830 if (total_data < 8) {
6831 return NT_STATUS_INVALID_PARAMETER;
6834 size = IVAL(pdata,0);
6835 size |= (((off_t)IVAL(pdata,4)) << 32);
6836 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6837 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6840 return smb_set_file_size(conn, req,
6845 fail_after_createfile);
6848 /****************************************************************************
6849 Allow a UNIX info mknod.
6850 ****************************************************************************/
6852 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6855 const struct smb_filename *smb_fname)
6857 uint32 file_type = IVAL(pdata,56);
6858 #if defined(HAVE_MAKEDEV)
6859 uint32 dev_major = IVAL(pdata,60);
6860 uint32 dev_minor = IVAL(pdata,68);
6862 SMB_DEV_T dev = (SMB_DEV_T)0;
6863 uint32 raw_unixmode = IVAL(pdata,84);
6867 if (total_data < 100) {
6868 return NT_STATUS_INVALID_PARAMETER;
6871 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6872 PERM_NEW_FILE, &unixmode);
6873 if (!NT_STATUS_IS_OK(status)) {
6877 #if defined(HAVE_MAKEDEV)
6878 dev = makedev(dev_major, dev_minor);
6881 switch (file_type) {
6882 #if defined(S_IFIFO)
6883 case UNIX_TYPE_FIFO:
6884 unixmode |= S_IFIFO;
6887 #if defined(S_IFSOCK)
6888 case UNIX_TYPE_SOCKET:
6889 unixmode |= S_IFSOCK;
6892 #if defined(S_IFCHR)
6893 case UNIX_TYPE_CHARDEV:
6894 unixmode |= S_IFCHR;
6897 #if defined(S_IFBLK)
6898 case UNIX_TYPE_BLKDEV:
6899 unixmode |= S_IFBLK;
6903 return NT_STATUS_INVALID_PARAMETER;
6906 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6907 "%.0f mode 0%o for file %s\n", (double)dev,
6908 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6910 /* Ok - do the mknod. */
6911 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6912 return map_nt_error_from_unix(errno);
6915 /* If any of the other "set" calls fail we
6916 * don't want to end up with a half-constructed mknod.
6919 if (lp_inherit_perms(SNUM(conn))) {
6921 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6923 return NT_STATUS_NO_MEMORY;
6925 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6927 TALLOC_FREE(parent);
6930 return NT_STATUS_OK;
6933 /****************************************************************************
6934 Deal with SMB_SET_FILE_UNIX_BASIC.
6935 ****************************************************************************/
6937 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6938 struct smb_request *req,
6942 const struct smb_filename *smb_fname)
6944 struct smb_file_time ft;
6945 uint32 raw_unixmode;
6948 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6949 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6950 NTSTATUS status = NT_STATUS_OK;
6951 bool delete_on_fail = False;
6952 enum perm_type ptype;
6953 files_struct *all_fsps = NULL;
6954 bool modify_mtime = true;
6956 struct smb_filename *smb_fname_tmp = NULL;
6957 SMB_STRUCT_STAT sbuf;
6961 if (total_data < 100) {
6962 return NT_STATUS_INVALID_PARAMETER;
6965 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6966 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6967 size=IVAL(pdata,0); /* first 8 Bytes are size */
6968 size |= (((off_t)IVAL(pdata,4)) << 32);
6971 ft.atime = interpret_long_date(pdata+24); /* access_time */
6972 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6973 set_owner = (uid_t)IVAL(pdata,40);
6974 set_grp = (gid_t)IVAL(pdata,48);
6975 raw_unixmode = IVAL(pdata,84);
6977 if (VALID_STAT(smb_fname->st)) {
6978 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6979 ptype = PERM_EXISTING_DIR;
6981 ptype = PERM_EXISTING_FILE;
6984 ptype = PERM_NEW_FILE;
6987 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6989 if (!NT_STATUS_IS_OK(status)) {
6993 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6994 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6995 smb_fname_str_dbg(smb_fname), (double)size,
6996 (unsigned int)set_owner, (unsigned int)set_grp,
6997 (int)raw_unixmode));
6999 sbuf = smb_fname->st;
7001 if (!VALID_STAT(sbuf)) {
7003 * The only valid use of this is to create character and block
7004 * devices, and named pipes. This is deprecated (IMHO) and
7005 * a new info level should be used for mknod. JRA.
7008 status = smb_unix_mknod(conn,
7012 if (!NT_STATUS_IS_OK(status)) {
7016 status = copy_smb_filename(talloc_tos(), smb_fname,
7018 if (!NT_STATUS_IS_OK(status)) {
7022 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7023 status = map_nt_error_from_unix(errno);
7024 TALLOC_FREE(smb_fname_tmp);
7025 SMB_VFS_UNLINK(conn, smb_fname);
7029 sbuf = smb_fname_tmp->st;
7030 smb_fname = smb_fname_tmp;
7032 /* Ensure we don't try and change anything else. */
7033 raw_unixmode = SMB_MODE_NO_CHANGE;
7034 size = get_file_size_stat(&sbuf);
7035 ft.atime = sbuf.st_ex_atime;
7036 ft.mtime = sbuf.st_ex_mtime;
7038 * We continue here as we might want to change the
7041 delete_on_fail = True;
7045 /* Horrible backwards compatibility hack as an old server bug
7046 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7050 size = get_file_size_stat(&sbuf);
7055 * Deal with the UNIX specific mode set.
7058 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7059 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7060 "setting mode 0%o for file %s\n",
7061 (unsigned int)unixmode,
7062 smb_fname_str_dbg(smb_fname)));
7063 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
7064 return map_nt_error_from_unix(errno);
7069 * Deal with the UNIX specific uid set.
7072 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7073 (sbuf.st_ex_uid != set_owner)) {
7076 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7077 "changing owner %u for path %s\n",
7078 (unsigned int)set_owner,
7079 smb_fname_str_dbg(smb_fname)));
7081 if (S_ISLNK(sbuf.st_ex_mode)) {
7082 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
7083 set_owner, (gid_t)-1);
7085 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
7086 set_owner, (gid_t)-1);
7090 status = map_nt_error_from_unix(errno);
7091 if (delete_on_fail) {
7092 SMB_VFS_UNLINK(conn, smb_fname);
7099 * Deal with the UNIX specific gid set.
7102 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7103 (sbuf.st_ex_gid != set_grp)) {
7104 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7105 "changing group %u for file %s\n",
7106 (unsigned int)set_owner,
7107 smb_fname_str_dbg(smb_fname)));
7108 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
7110 status = map_nt_error_from_unix(errno);
7111 if (delete_on_fail) {
7112 SMB_VFS_UNLINK(conn, smb_fname);
7118 /* Deal with any size changes. */
7120 status = smb_set_file_size(conn, req,
7126 if (!NT_STATUS_IS_OK(status)) {
7130 /* Deal with any time changes. */
7131 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7132 /* No change, don't cancel anything. */
7136 id = vfs_file_id_from_sbuf(conn, &sbuf);
7137 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7138 all_fsps = file_find_di_next(all_fsps)) {
7140 * We're setting the time explicitly for UNIX.
7141 * Cancel any pending changes over all handles.
7143 all_fsps->update_write_time_on_close = false;
7144 TALLOC_FREE(all_fsps->update_write_time_event);
7148 * Override the "setting_write_time"
7149 * parameter here as it almost does what
7150 * we need. Just remember if we modified
7151 * mtime and send the notify ourselves.
7153 if (null_timespec(ft.mtime)) {
7154 modify_mtime = false;
7157 status = smb_set_file_time(conn,
7163 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7164 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7169 /****************************************************************************
7170 Deal with SMB_SET_FILE_UNIX_INFO2.
7171 ****************************************************************************/
7173 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7174 struct smb_request *req,
7178 const struct smb_filename *smb_fname)
7184 if (total_data < 116) {
7185 return NT_STATUS_INVALID_PARAMETER;
7188 /* Start by setting all the fields that are common between UNIX_BASIC
7191 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7193 if (!NT_STATUS_IS_OK(status)) {
7197 smb_fflags = IVAL(pdata, 108);
7198 smb_fmask = IVAL(pdata, 112);
7200 /* NB: We should only attempt to alter the file flags if the client
7201 * sends a non-zero mask.
7203 if (smb_fmask != 0) {
7204 int stat_fflags = 0;
7206 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7207 smb_fmask, &stat_fflags)) {
7208 /* Client asked to alter a flag we don't understand. */
7209 return NT_STATUS_INVALID_PARAMETER;
7212 if (fsp && fsp->fh->fd != -1) {
7213 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7214 return NT_STATUS_NOT_SUPPORTED;
7216 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7217 stat_fflags) != 0) {
7218 return map_nt_error_from_unix(errno);
7223 /* XXX: need to add support for changing the create_time here. You
7224 * can do this for paths on Darwin with setattrlist(2). The right way
7225 * to hook this up is probably by extending the VFS utimes interface.
7228 return NT_STATUS_OK;
7231 /****************************************************************************
7232 Create a directory with POSIX semantics.
7233 ****************************************************************************/
7235 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7236 struct smb_request *req,
7239 struct smb_filename *smb_fname,
7240 int *pdata_return_size)
7242 NTSTATUS status = NT_STATUS_OK;
7243 uint32 raw_unixmode = 0;
7244 uint32 mod_unixmode = 0;
7245 mode_t unixmode = (mode_t)0;
7246 files_struct *fsp = NULL;
7247 uint16 info_level_return = 0;
7249 char *pdata = *ppdata;
7251 if (total_data < 18) {
7252 return NT_STATUS_INVALID_PARAMETER;
7255 raw_unixmode = IVAL(pdata,8);
7256 /* Next 4 bytes are not yet defined. */
7258 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7259 PERM_NEW_DIR, &unixmode);
7260 if (!NT_STATUS_IS_OK(status)) {
7264 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7266 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7267 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7269 status = SMB_VFS_CREATE_FILE(
7272 0, /* root_dir_fid */
7273 smb_fname, /* fname */
7274 FILE_READ_ATTRIBUTES, /* access_mask */
7275 FILE_SHARE_NONE, /* share_access */
7276 FILE_CREATE, /* create_disposition*/
7277 FILE_DIRECTORY_FILE, /* create_options */
7278 mod_unixmode, /* file_attributes */
7279 0, /* oplock_request */
7280 0, /* allocation_size */
7281 0, /* private_flags */
7287 if (NT_STATUS_IS_OK(status)) {
7288 close_file(req, fsp, NORMAL_CLOSE);
7291 info_level_return = SVAL(pdata,16);
7293 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7294 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7295 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7296 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7298 *pdata_return_size = 12;
7301 /* Realloc the data size */
7302 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7303 if (*ppdata == NULL) {
7304 *pdata_return_size = 0;
7305 return NT_STATUS_NO_MEMORY;
7309 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7310 SSVAL(pdata,2,0); /* No fnum. */
7311 SIVAL(pdata,4,info); /* Was directory created. */
7313 switch (info_level_return) {
7314 case SMB_QUERY_FILE_UNIX_BASIC:
7315 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7316 SSVAL(pdata,10,0); /* Padding. */
7317 store_file_unix_basic(conn, pdata + 12, fsp,
7320 case SMB_QUERY_FILE_UNIX_INFO2:
7321 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7322 SSVAL(pdata,10,0); /* Padding. */
7323 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7327 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7328 SSVAL(pdata,10,0); /* Padding. */
7335 /****************************************************************************
7336 Open/Create a file with POSIX semantics.
7337 ****************************************************************************/
7339 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7340 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7342 static NTSTATUS smb_posix_open(connection_struct *conn,
7343 struct smb_request *req,
7346 struct smb_filename *smb_fname,
7347 int *pdata_return_size)
7349 bool extended_oplock_granted = False;
7350 char *pdata = *ppdata;
7352 uint32 wire_open_mode = 0;
7353 uint32 raw_unixmode = 0;
7354 uint32 mod_unixmode = 0;
7355 uint32 create_disp = 0;
7356 uint32 access_mask = 0;
7357 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7358 NTSTATUS status = NT_STATUS_OK;
7359 mode_t unixmode = (mode_t)0;
7360 files_struct *fsp = NULL;
7361 int oplock_request = 0;
7363 uint16 info_level_return = 0;
7365 if (total_data < 18) {
7366 return NT_STATUS_INVALID_PARAMETER;
7369 flags = IVAL(pdata,0);
7370 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7371 if (oplock_request) {
7372 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7375 wire_open_mode = IVAL(pdata,4);
7377 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7378 return smb_posix_mkdir(conn, req,
7385 switch (wire_open_mode & SMB_ACCMODE) {
7387 access_mask = SMB_O_RDONLY_MAPPING;
7390 access_mask = SMB_O_WRONLY_MAPPING;
7393 access_mask = (SMB_O_RDONLY_MAPPING|
7394 SMB_O_WRONLY_MAPPING);
7397 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7398 (unsigned int)wire_open_mode ));
7399 return NT_STATUS_INVALID_PARAMETER;
7402 wire_open_mode &= ~SMB_ACCMODE;
7404 /* First take care of O_CREAT|O_EXCL interactions. */
7405 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7406 case (SMB_O_CREAT | SMB_O_EXCL):
7407 /* File exists fail. File not exist create. */
7408 create_disp = FILE_CREATE;
7411 /* File exists open. File not exist create. */
7412 create_disp = FILE_OPEN_IF;
7415 /* O_EXCL on its own without O_CREAT is undefined.
7416 We deliberately ignore it as some versions of
7417 Linux CIFSFS can send a bare O_EXCL on the
7418 wire which other filesystems in the kernel
7419 ignore. See bug 9519 for details. */
7424 /* File exists open. File not exist fail. */
7425 create_disp = FILE_OPEN;
7428 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7429 (unsigned int)wire_open_mode ));
7430 return NT_STATUS_INVALID_PARAMETER;
7433 /* Next factor in the effects of O_TRUNC. */
7434 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7436 if (wire_open_mode & SMB_O_TRUNC) {
7437 switch (create_disp) {
7439 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7440 /* Leave create_disp alone as
7441 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7443 /* File exists fail. File not exist create. */
7446 /* SMB_O_CREAT | SMB_O_TRUNC */
7447 /* File exists overwrite. File not exist create. */
7448 create_disp = FILE_OVERWRITE_IF;
7452 /* File exists overwrite. File not exist fail. */
7453 create_disp = FILE_OVERWRITE;
7456 /* Cannot get here. */
7457 smb_panic("smb_posix_open: logic error");
7458 return NT_STATUS_INVALID_PARAMETER;
7462 raw_unixmode = IVAL(pdata,8);
7463 /* Next 4 bytes are not yet defined. */
7465 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7466 (VALID_STAT(smb_fname->st) ?
7467 PERM_EXISTING_FILE : PERM_NEW_FILE),
7470 if (!NT_STATUS_IS_OK(status)) {
7474 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7476 if (wire_open_mode & SMB_O_SYNC) {
7477 create_options |= FILE_WRITE_THROUGH;
7479 if (wire_open_mode & SMB_O_APPEND) {
7480 access_mask |= FILE_APPEND_DATA;
7482 if (wire_open_mode & SMB_O_DIRECT) {
7483 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7486 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7487 VALID_STAT_OF_DIR(smb_fname->st)) {
7488 if (access_mask != SMB_O_RDONLY_MAPPING) {
7489 return NT_STATUS_FILE_IS_A_DIRECTORY;
7491 create_options &= ~FILE_NON_DIRECTORY_FILE;
7492 create_options |= FILE_DIRECTORY_FILE;
7495 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7496 smb_fname_str_dbg(smb_fname),
7497 (unsigned int)wire_open_mode,
7498 (unsigned int)unixmode ));
7500 status = SMB_VFS_CREATE_FILE(
7503 0, /* root_dir_fid */
7504 smb_fname, /* fname */
7505 access_mask, /* access_mask */
7506 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7508 create_disp, /* create_disposition*/
7509 create_options, /* create_options */
7510 mod_unixmode, /* file_attributes */
7511 oplock_request, /* oplock_request */
7512 0, /* allocation_size */
7513 0, /* private_flags */
7519 if (!NT_STATUS_IS_OK(status)) {
7523 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7524 extended_oplock_granted = True;
7527 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7528 extended_oplock_granted = True;
7531 info_level_return = SVAL(pdata,16);
7533 /* Allocate the correct return size. */
7535 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7536 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7537 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7538 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7540 *pdata_return_size = 12;
7543 /* Realloc the data size */
7544 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7545 if (*ppdata == NULL) {
7546 close_file(req, fsp, ERROR_CLOSE);
7547 *pdata_return_size = 0;
7548 return NT_STATUS_NO_MEMORY;
7552 if (extended_oplock_granted) {
7553 if (flags & REQUEST_BATCH_OPLOCK) {
7554 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7556 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7558 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7559 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7561 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7564 SSVAL(pdata,2,fsp->fnum);
7565 SIVAL(pdata,4,info); /* Was file created etc. */
7567 switch (info_level_return) {
7568 case SMB_QUERY_FILE_UNIX_BASIC:
7569 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7570 SSVAL(pdata,10,0); /* padding. */
7571 store_file_unix_basic(conn, pdata + 12, fsp,
7574 case SMB_QUERY_FILE_UNIX_INFO2:
7575 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7576 SSVAL(pdata,10,0); /* padding. */
7577 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7581 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7582 SSVAL(pdata,10,0); /* padding. */
7585 return NT_STATUS_OK;
7588 /****************************************************************************
7589 Delete a file with POSIX semantics.
7590 ****************************************************************************/
7592 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7593 struct smb_request *req,
7596 struct smb_filename *smb_fname)
7598 NTSTATUS status = NT_STATUS_OK;
7599 files_struct *fsp = NULL;
7603 int create_options = 0;
7605 struct share_mode_lock *lck = NULL;
7607 if (total_data < 2) {
7608 return NT_STATUS_INVALID_PARAMETER;
7611 flags = SVAL(pdata,0);
7613 if (!VALID_STAT(smb_fname->st)) {
7614 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7617 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7618 !VALID_STAT_OF_DIR(smb_fname->st)) {
7619 return NT_STATUS_NOT_A_DIRECTORY;
7622 DEBUG(10,("smb_posix_unlink: %s %s\n",
7623 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7624 smb_fname_str_dbg(smb_fname)));
7626 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7627 create_options |= FILE_DIRECTORY_FILE;
7630 status = SMB_VFS_CREATE_FILE(
7633 0, /* root_dir_fid */
7634 smb_fname, /* fname */
7635 DELETE_ACCESS, /* access_mask */
7636 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7638 FILE_OPEN, /* create_disposition*/
7639 create_options, /* create_options */
7640 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7641 0, /* oplock_request */
7642 0, /* allocation_size */
7643 0, /* private_flags */
7649 if (!NT_STATUS_IS_OK(status)) {
7654 * Don't lie to client. If we can't really delete due to
7655 * non-POSIX opens return SHARING_VIOLATION.
7658 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
7660 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7661 "lock for file %s\n", fsp_str_dbg(fsp)));
7662 close_file(req, fsp, NORMAL_CLOSE);
7663 return NT_STATUS_INVALID_PARAMETER;
7667 * See if others still have the file open. If this is the case, then
7668 * don't delete. If all opens are POSIX delete we can set the delete
7669 * on close disposition.
7671 for (i=0; i<lck->data->num_share_modes; i++) {
7672 struct share_mode_entry *e = &lck->data->share_modes[i];
7673 if (is_valid_share_mode_entry(e)) {
7674 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7677 if (share_mode_stale_pid(lck->data, i)) {
7680 /* Fail with sharing violation. */
7682 close_file(req, fsp, NORMAL_CLOSE);
7683 return NT_STATUS_SHARING_VIOLATION;
7688 * Set the delete on close.
7690 status = smb_set_file_disposition_info(conn,
7698 if (!NT_STATUS_IS_OK(status)) {
7699 close_file(req, fsp, NORMAL_CLOSE);
7702 return close_file(req, fsp, NORMAL_CLOSE);
7705 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7706 struct smb_request *req,
7707 TALLOC_CTX *mem_ctx,
7708 uint16_t info_level,
7710 struct smb_filename *smb_fname,
7711 char **ppdata, int total_data,
7714 char *pdata = *ppdata;
7715 NTSTATUS status = NT_STATUS_OK;
7716 int data_return_size = 0;
7720 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7721 return NT_STATUS_INVALID_LEVEL;
7724 if (!CAN_WRITE(conn)) {
7725 /* Allow POSIX opens. The open path will deny
7726 * any non-readonly opens. */
7727 if (info_level != SMB_POSIX_PATH_OPEN) {
7728 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7732 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
7733 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7735 info_level, total_data));
7737 switch (info_level) {
7739 case SMB_INFO_STANDARD:
7741 status = smb_set_info_standard(conn,
7749 case SMB_INFO_SET_EA:
7751 status = smb_info_set_ea(conn,
7759 case SMB_SET_FILE_BASIC_INFO:
7760 case SMB_FILE_BASIC_INFORMATION:
7762 status = smb_set_file_basic_info(conn,
7770 case SMB_FILE_ALLOCATION_INFORMATION:
7771 case SMB_SET_FILE_ALLOCATION_INFO:
7773 status = smb_set_file_allocation_info(conn, req,
7781 case SMB_FILE_END_OF_FILE_INFORMATION:
7782 case SMB_SET_FILE_END_OF_FILE_INFO:
7785 * XP/Win7 both fail after the createfile with
7786 * SMB_SET_FILE_END_OF_FILE_INFO but not
7787 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7788 * The level is known here, so pass it down
7792 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7794 status = smb_set_file_end_of_file_info(conn, req,
7803 case SMB_FILE_DISPOSITION_INFORMATION:
7804 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7807 /* JRA - We used to just ignore this on a path ?
7808 * Shouldn't this be invalid level on a pathname
7811 if (tran_call != TRANSACT2_SETFILEINFO) {
7812 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7815 status = smb_set_file_disposition_info(conn,
7823 case SMB_FILE_POSITION_INFORMATION:
7825 status = smb_file_position_information(conn,
7832 case SMB_FILE_FULL_EA_INFORMATION:
7834 status = smb_set_file_full_ea_info(conn,
7841 /* From tridge Samba4 :
7842 * MODE_INFORMATION in setfileinfo (I have no
7843 * idea what "mode information" on a file is - it takes a value of 0,
7844 * 2, 4 or 6. What could it be?).
7847 case SMB_FILE_MODE_INFORMATION:
7849 status = smb_file_mode_information(conn,
7856 * CIFS UNIX extensions.
7859 case SMB_SET_FILE_UNIX_BASIC:
7861 status = smb_set_file_unix_basic(conn, req,
7869 case SMB_SET_FILE_UNIX_INFO2:
7871 status = smb_set_file_unix_info2(conn, req,
7879 case SMB_SET_FILE_UNIX_LINK:
7882 /* We must have a pathname for this. */
7883 return NT_STATUS_INVALID_LEVEL;
7885 status = smb_set_file_unix_link(conn, req, pdata,
7886 total_data, smb_fname);
7890 case SMB_SET_FILE_UNIX_HLINK:
7893 /* We must have a pathname for this. */
7894 return NT_STATUS_INVALID_LEVEL;
7896 status = smb_set_file_unix_hlink(conn, req,
7902 case SMB_FILE_RENAME_INFORMATION:
7904 status = smb_file_rename_information(conn, req,
7910 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7912 /* SMB2 rename information. */
7913 status = smb2_file_rename_information(conn, req,
7919 case SMB_FILE_LINK_INFORMATION:
7921 status = smb_file_link_information(conn, req,
7927 #if defined(HAVE_POSIX_ACLS)
7928 case SMB_SET_POSIX_ACL:
7930 status = smb_set_posix_acl(conn,
7939 case SMB_SET_POSIX_LOCK:
7942 return NT_STATUS_INVALID_LEVEL;
7944 status = smb_set_posix_lock(conn, req,
7945 pdata, total_data, fsp);
7949 case SMB_POSIX_PATH_OPEN:
7952 /* We must have a pathname for this. */
7953 return NT_STATUS_INVALID_LEVEL;
7956 status = smb_posix_open(conn, req,
7964 case SMB_POSIX_PATH_UNLINK:
7967 /* We must have a pathname for this. */
7968 return NT_STATUS_INVALID_LEVEL;
7971 status = smb_posix_unlink(conn, req,
7979 return NT_STATUS_INVALID_LEVEL;
7982 if (!NT_STATUS_IS_OK(status)) {
7986 *ret_data_size = data_return_size;
7987 return NT_STATUS_OK;
7990 /****************************************************************************
7991 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7992 ****************************************************************************/
7994 static void call_trans2setfilepathinfo(connection_struct *conn,
7995 struct smb_request *req,
7996 unsigned int tran_call,
7997 char **pparams, int total_params,
7998 char **ppdata, int total_data,
7999 unsigned int max_data_bytes)
8001 char *params = *pparams;
8002 char *pdata = *ppdata;
8004 struct smb_filename *smb_fname = NULL;
8005 files_struct *fsp = NULL;
8006 NTSTATUS status = NT_STATUS_OK;
8007 int data_return_size = 0;
8010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8014 if (tran_call == TRANSACT2_SETFILEINFO) {
8015 if (total_params < 4) {
8016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8020 fsp = file_fsp(req, SVAL(params,0));
8021 /* Basic check for non-null fsp. */
8022 if (!check_fsp_open(conn, req, fsp)) {
8025 info_level = SVAL(params,2);
8027 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
8029 if (!NT_STATUS_IS_OK(status)) {
8030 reply_nterror(req, status);
8034 if(fsp->fh->fd == -1) {
8036 * This is actually a SETFILEINFO on a directory
8037 * handle (returned from an NT SMB). NT5.0 seems
8038 * to do this call. JRA.
8040 if (INFO_LEVEL_IS_UNIX(info_level)) {
8041 /* Always do lstat for UNIX calls. */
8042 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8043 DEBUG(3,("call_trans2setfilepathinfo: "
8044 "SMB_VFS_LSTAT of %s failed "
8046 smb_fname_str_dbg(smb_fname),
8048 reply_nterror(req, map_nt_error_from_unix(errno));
8052 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8053 DEBUG(3,("call_trans2setfilepathinfo: "
8054 "fileinfo of %s failed (%s)\n",
8055 smb_fname_str_dbg(smb_fname),
8057 reply_nterror(req, map_nt_error_from_unix(errno));
8061 } else if (fsp->print_file) {
8063 * Doing a DELETE_ON_CLOSE should cancel a print job.
8065 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8066 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8068 DEBUG(3,("call_trans2setfilepathinfo: "
8069 "Cancelling print job (%s)\n",
8073 send_trans2_replies(conn, req, params, 2,
8079 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8084 * Original code - this is an open file.
8086 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8087 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8088 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8090 reply_nterror(req, map_nt_error_from_unix(errno));
8096 uint32_t ucf_flags = 0;
8099 if (total_params < 7) {
8100 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8104 info_level = SVAL(params,0);
8105 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
8106 total_params - 6, STR_TERMINATE,
8108 if (!NT_STATUS_IS_OK(status)) {
8109 reply_nterror(req, status);
8113 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8114 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8115 info_level == SMB_FILE_RENAME_INFORMATION ||
8116 info_level == SMB_POSIX_PATH_UNLINK) {
8117 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8120 status = filename_convert(req, conn,
8121 req->flags2 & FLAGS2_DFS_PATHNAMES,
8126 if (!NT_STATUS_IS_OK(status)) {
8127 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8128 reply_botherror(req,
8129 NT_STATUS_PATH_NOT_COVERED,
8130 ERRSRV, ERRbadpath);
8133 reply_nterror(req, status);
8137 if (INFO_LEVEL_IS_UNIX(info_level)) {
8139 * For CIFS UNIX extensions the target name may not exist.
8142 /* Always do lstat for UNIX calls. */
8143 SMB_VFS_LSTAT(conn, smb_fname);
8145 } else if (!VALID_STAT(smb_fname->st) &&
8146 SMB_VFS_STAT(conn, smb_fname)) {
8147 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8149 smb_fname_str_dbg(smb_fname),
8151 reply_nterror(req, map_nt_error_from_unix(errno));
8156 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8157 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8159 info_level,total_data));
8161 /* Realloc the parameter size */
8162 *pparams = (char *)SMB_REALLOC(*pparams,2);
8163 if (*pparams == NULL) {
8164 reply_nterror(req, NT_STATUS_NO_MEMORY);
8171 status = smbd_do_setfilepathinfo(conn, req, req,
8177 if (!NT_STATUS_IS_OK(status)) {
8178 if (open_was_deferred(req->sconn, req->mid)) {
8179 /* We have re-scheduled this call. */
8182 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8183 /* We have re-scheduled this call. */
8186 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8187 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8188 ERRSRV, ERRbadpath);
8191 if (info_level == SMB_POSIX_PATH_OPEN) {
8192 reply_openerror(req, status);
8196 reply_nterror(req, status);
8200 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8206 /****************************************************************************
8207 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8208 ****************************************************************************/
8210 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8211 char **pparams, int total_params,
8212 char **ppdata, int total_data,
8213 unsigned int max_data_bytes)
8215 struct smb_filename *smb_dname = NULL;
8216 char *params = *pparams;
8217 char *pdata = *ppdata;
8218 char *directory = NULL;
8219 NTSTATUS status = NT_STATUS_OK;
8220 struct ea_list *ea_list = NULL;
8221 TALLOC_CTX *ctx = talloc_tos();
8223 if (!CAN_WRITE(conn)) {
8224 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8228 if (total_params < 5) {
8229 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8233 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8234 total_params - 4, STR_TERMINATE,
8236 if (!NT_STATUS_IS_OK(status)) {
8237 reply_nterror(req, status);
8241 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8243 status = filename_convert(ctx,
8245 req->flags2 & FLAGS2_DFS_PATHNAMES,
8251 if (!NT_STATUS_IS_OK(status)) {
8252 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8253 reply_botherror(req,
8254 NT_STATUS_PATH_NOT_COVERED,
8255 ERRSRV, ERRbadpath);
8258 reply_nterror(req, status);
8263 * OS/2 workplace shell seems to send SET_EA requests of "null"
8264 * length (4 bytes containing IVAL 4).
8265 * They seem to have no effect. Bug #3212. JRA.
8268 if (total_data && (total_data != 4)) {
8269 /* Any data in this call is an EA list. */
8270 if (total_data < 10) {
8271 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8275 if (IVAL(pdata,0) > total_data) {
8276 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8277 IVAL(pdata,0), (unsigned int)total_data));
8278 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8282 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8289 if (!lp_ea_support(SNUM(conn))) {
8290 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8294 /* If total_data == 4 Windows doesn't care what values
8295 * are placed in that field, it just ignores them.
8296 * The System i QNTC IBM SMB client puts bad values here,
8297 * so ignore them. */
8299 status = create_directory(conn, req, smb_dname);
8301 if (!NT_STATUS_IS_OK(status)) {
8302 reply_nterror(req, status);
8306 /* Try and set any given EA. */
8308 status = set_ea(conn, NULL, smb_dname, ea_list);
8309 if (!NT_STATUS_IS_OK(status)) {
8310 reply_nterror(req, status);
8315 /* Realloc the parameter and data sizes */
8316 *pparams = (char *)SMB_REALLOC(*pparams,2);
8317 if(*pparams == NULL) {
8318 reply_nterror(req, NT_STATUS_NO_MEMORY);
8325 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8328 TALLOC_FREE(smb_dname);
8332 /****************************************************************************
8333 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8334 We don't actually do this - we just send a null response.
8335 ****************************************************************************/
8337 static void call_trans2findnotifyfirst(connection_struct *conn,
8338 struct smb_request *req,
8339 char **pparams, int total_params,
8340 char **ppdata, int total_data,
8341 unsigned int max_data_bytes)
8343 char *params = *pparams;
8346 if (total_params < 6) {
8347 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8351 info_level = SVAL(params,4);
8352 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8354 switch (info_level) {
8359 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8363 /* Realloc the parameter and data sizes */
8364 *pparams = (char *)SMB_REALLOC(*pparams,6);
8365 if (*pparams == NULL) {
8366 reply_nterror(req, NT_STATUS_NO_MEMORY);
8371 SSVAL(params,0,fnf_handle);
8372 SSVAL(params,2,0); /* No changes */
8373 SSVAL(params,4,0); /* No EA errors */
8380 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8385 /****************************************************************************
8386 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8387 changes). Currently this does nothing.
8388 ****************************************************************************/
8390 static void call_trans2findnotifynext(connection_struct *conn,
8391 struct smb_request *req,
8392 char **pparams, int total_params,
8393 char **ppdata, int total_data,
8394 unsigned int max_data_bytes)
8396 char *params = *pparams;
8398 DEBUG(3,("call_trans2findnotifynext\n"));
8400 /* Realloc the parameter and data sizes */
8401 *pparams = (char *)SMB_REALLOC(*pparams,4);
8402 if (*pparams == NULL) {
8403 reply_nterror(req, NT_STATUS_NO_MEMORY);
8408 SSVAL(params,0,0); /* No changes */
8409 SSVAL(params,2,0); /* No EA errors */
8411 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8416 /****************************************************************************
8417 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8418 ****************************************************************************/
8420 static void call_trans2getdfsreferral(connection_struct *conn,
8421 struct smb_request *req,
8422 char **pparams, int total_params,
8423 char **ppdata, int total_data,
8424 unsigned int max_data_bytes)
8426 char *params = *pparams;
8427 char *pathname = NULL;
8429 int max_referral_level;
8430 NTSTATUS status = NT_STATUS_OK;
8431 TALLOC_CTX *ctx = talloc_tos();
8433 DEBUG(10,("call_trans2getdfsreferral\n"));
8435 if (total_params < 3) {
8436 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8440 max_referral_level = SVAL(params,0);
8442 if(!lp_host_msdfs()) {
8443 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8447 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8448 total_params - 2, STR_TERMINATE);
8450 reply_nterror(req, NT_STATUS_NOT_FOUND);
8453 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8454 ppdata,&status)) < 0) {
8455 reply_nterror(req, status);
8459 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8460 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8461 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8466 #define LMCAT_SPL 0x53
8467 #define LMFUNC_GETJOBID 0x60
8469 /****************************************************************************
8470 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8471 ****************************************************************************/
8473 static void call_trans2ioctl(connection_struct *conn,
8474 struct smb_request *req,
8475 char **pparams, int total_params,
8476 char **ppdata, int total_data,
8477 unsigned int max_data_bytes)
8479 char *pdata = *ppdata;
8480 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8482 /* check for an invalid fid before proceeding */
8485 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8489 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8490 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8491 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8492 if (*ppdata == NULL) {
8493 reply_nterror(req, NT_STATUS_NO_MEMORY);
8498 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8499 CAN ACCEPT THIS IN UNICODE. JRA. */
8502 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
8504 srvstr_push(pdata, req->flags2, pdata + 2,
8505 lp_netbios_name(), 15,
8506 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8507 srvstr_push(pdata, req->flags2, pdata+18,
8508 lp_servicename(talloc_tos(), SNUM(conn)), 13,
8509 STR_ASCII|STR_TERMINATE); /* Service name */
8510 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8515 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8516 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8519 /****************************************************************************
8520 Reply to a SMBfindclose (stop trans2 directory search).
8521 ****************************************************************************/
8523 void reply_findclose(struct smb_request *req)
8526 struct smbd_server_connection *sconn = req->sconn;
8528 START_PROFILE(SMBfindclose);
8531 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8532 END_PROFILE(SMBfindclose);
8536 dptr_num = SVALS(req->vwv+0, 0);
8538 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8540 dptr_close(sconn, &dptr_num);
8542 reply_outbuf(req, 0, 0);
8544 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8546 END_PROFILE(SMBfindclose);
8550 /****************************************************************************
8551 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8552 ****************************************************************************/
8554 void reply_findnclose(struct smb_request *req)
8558 START_PROFILE(SMBfindnclose);
8561 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8562 END_PROFILE(SMBfindnclose);
8566 dptr_num = SVAL(req->vwv+0, 0);
8568 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8570 /* We never give out valid handles for a
8571 findnotifyfirst - so any dptr_num is ok here.
8574 reply_outbuf(req, 0, 0);
8576 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8578 END_PROFILE(SMBfindnclose);
8582 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8583 struct trans_state *state)
8585 if (get_Protocol() >= PROTOCOL_NT1) {
8586 req->flags2 |= 0x40; /* IS_LONG_NAME */
8587 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8590 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
8591 if (state->call != TRANSACT2_QFSINFO &&
8592 state->call != TRANSACT2_SETFSINFO) {
8593 DEBUG(0,("handle_trans2: encryption required "
8595 (unsigned int)state->call));
8596 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8601 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8603 /* Now we must call the relevant TRANS2 function */
8604 switch(state->call) {
8605 case TRANSACT2_OPEN:
8607 START_PROFILE(Trans2_open);
8608 call_trans2open(conn, req,
8609 &state->param, state->total_param,
8610 &state->data, state->total_data,
8611 state->max_data_return);
8612 END_PROFILE(Trans2_open);
8616 case TRANSACT2_FINDFIRST:
8618 START_PROFILE(Trans2_findfirst);
8619 call_trans2findfirst(conn, req,
8620 &state->param, state->total_param,
8621 &state->data, state->total_data,
8622 state->max_data_return);
8623 END_PROFILE(Trans2_findfirst);
8627 case TRANSACT2_FINDNEXT:
8629 START_PROFILE(Trans2_findnext);
8630 call_trans2findnext(conn, req,
8631 &state->param, state->total_param,
8632 &state->data, state->total_data,
8633 state->max_data_return);
8634 END_PROFILE(Trans2_findnext);
8638 case TRANSACT2_QFSINFO:
8640 START_PROFILE(Trans2_qfsinfo);
8641 call_trans2qfsinfo(conn, req,
8642 &state->param, state->total_param,
8643 &state->data, state->total_data,
8644 state->max_data_return);
8645 END_PROFILE(Trans2_qfsinfo);
8649 case TRANSACT2_SETFSINFO:
8651 START_PROFILE(Trans2_setfsinfo);
8652 call_trans2setfsinfo(conn, req,
8653 &state->param, state->total_param,
8654 &state->data, state->total_data,
8655 state->max_data_return);
8656 END_PROFILE(Trans2_setfsinfo);
8660 case TRANSACT2_QPATHINFO:
8661 case TRANSACT2_QFILEINFO:
8663 START_PROFILE(Trans2_qpathinfo);
8664 call_trans2qfilepathinfo(conn, req, state->call,
8665 &state->param, state->total_param,
8666 &state->data, state->total_data,
8667 state->max_data_return);
8668 END_PROFILE(Trans2_qpathinfo);
8672 case TRANSACT2_SETPATHINFO:
8673 case TRANSACT2_SETFILEINFO:
8675 START_PROFILE(Trans2_setpathinfo);
8676 call_trans2setfilepathinfo(conn, req, state->call,
8677 &state->param, state->total_param,
8678 &state->data, state->total_data,
8679 state->max_data_return);
8680 END_PROFILE(Trans2_setpathinfo);
8684 case TRANSACT2_FINDNOTIFYFIRST:
8686 START_PROFILE(Trans2_findnotifyfirst);
8687 call_trans2findnotifyfirst(conn, req,
8688 &state->param, state->total_param,
8689 &state->data, state->total_data,
8690 state->max_data_return);
8691 END_PROFILE(Trans2_findnotifyfirst);
8695 case TRANSACT2_FINDNOTIFYNEXT:
8697 START_PROFILE(Trans2_findnotifynext);
8698 call_trans2findnotifynext(conn, req,
8699 &state->param, state->total_param,
8700 &state->data, state->total_data,
8701 state->max_data_return);
8702 END_PROFILE(Trans2_findnotifynext);
8706 case TRANSACT2_MKDIR:
8708 START_PROFILE(Trans2_mkdir);
8709 call_trans2mkdir(conn, req,
8710 &state->param, state->total_param,
8711 &state->data, state->total_data,
8712 state->max_data_return);
8713 END_PROFILE(Trans2_mkdir);
8717 case TRANSACT2_GET_DFS_REFERRAL:
8719 START_PROFILE(Trans2_get_dfs_referral);
8720 call_trans2getdfsreferral(conn, req,
8721 &state->param, state->total_param,
8722 &state->data, state->total_data,
8723 state->max_data_return);
8724 END_PROFILE(Trans2_get_dfs_referral);
8728 case TRANSACT2_IOCTL:
8730 START_PROFILE(Trans2_ioctl);
8731 call_trans2ioctl(conn, req,
8732 &state->param, state->total_param,
8733 &state->data, state->total_data,
8734 state->max_data_return);
8735 END_PROFILE(Trans2_ioctl);
8740 /* Error in request */
8741 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8742 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8746 /****************************************************************************
8747 Reply to a SMBtrans2.
8748 ****************************************************************************/
8750 void reply_trans2(struct smb_request *req)
8752 connection_struct *conn = req->conn;
8757 unsigned int tran_call;
8758 struct trans_state *state;
8761 START_PROFILE(SMBtrans2);
8763 if (req->wct < 14) {
8764 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8765 END_PROFILE(SMBtrans2);
8769 dsoff = SVAL(req->vwv+12, 0);
8770 dscnt = SVAL(req->vwv+11, 0);
8771 psoff = SVAL(req->vwv+10, 0);
8772 pscnt = SVAL(req->vwv+9, 0);
8773 tran_call = SVAL(req->vwv+14, 0);
8775 result = allow_new_trans(conn->pending_trans, req->mid);
8776 if (!NT_STATUS_IS_OK(result)) {
8777 DEBUG(2, ("Got invalid trans2 request: %s\n",
8778 nt_errstr(result)));
8779 reply_nterror(req, result);
8780 END_PROFILE(SMBtrans2);
8785 switch (tran_call) {
8786 /* List the allowed trans2 calls on IPC$ */
8787 case TRANSACT2_OPEN:
8788 case TRANSACT2_GET_DFS_REFERRAL:
8789 case TRANSACT2_QFILEINFO:
8790 case TRANSACT2_QFSINFO:
8791 case TRANSACT2_SETFSINFO:
8794 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8795 END_PROFILE(SMBtrans2);
8800 if ((state = talloc(conn, struct trans_state)) == NULL) {
8801 DEBUG(0, ("talloc failed\n"));
8802 reply_nterror(req, NT_STATUS_NO_MEMORY);
8803 END_PROFILE(SMBtrans2);
8807 state->cmd = SMBtrans2;
8809 state->mid = req->mid;
8810 state->vuid = req->vuid;
8811 state->setup_count = SVAL(req->vwv+13, 0);
8812 state->setup = NULL;
8813 state->total_param = SVAL(req->vwv+0, 0);
8814 state->param = NULL;
8815 state->total_data = SVAL(req->vwv+1, 0);
8817 state->max_param_return = SVAL(req->vwv+2, 0);
8818 state->max_data_return = SVAL(req->vwv+3, 0);
8819 state->max_setup_return = SVAL(req->vwv+4, 0);
8820 state->close_on_completion = BITSETW(req->vwv+5, 0);
8821 state->one_way = BITSETW(req->vwv+5, 1);
8823 state->call = tran_call;
8825 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8826 is so as a sanity check */
8827 if (state->setup_count != 1) {
8829 * Need to have rc=0 for ioctl to get job id for OS/2.
8830 * Network printing will fail if function is not successful.
8831 * Similar function in reply.c will be used if protocol
8832 * is LANMAN1.0 instead of LM1.2X002.
8833 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8834 * outbuf doesn't have to be set(only job id is used).
8836 if ( (state->setup_count == 4)
8837 && (tran_call == TRANSACT2_IOCTL)
8838 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8839 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8840 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8842 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8843 DEBUG(2,("Transaction is %d\n",tran_call));
8845 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8846 END_PROFILE(SMBtrans2);
8851 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8854 if (state->total_data) {
8856 if (trans_oob(state->total_data, 0, dscnt)
8857 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8861 /* Can't use talloc here, the core routines do realloc on the
8862 * params and data. */
8863 state->data = (char *)SMB_MALLOC(state->total_data);
8864 if (state->data == NULL) {
8865 DEBUG(0,("reply_trans2: data malloc fail for %u "
8866 "bytes !\n", (unsigned int)state->total_data));
8868 reply_nterror(req, NT_STATUS_NO_MEMORY);
8869 END_PROFILE(SMBtrans2);
8873 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8876 if (state->total_param) {
8878 if (trans_oob(state->total_param, 0, pscnt)
8879 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8883 /* Can't use talloc here, the core routines do realloc on the
8884 * params and data. */
8885 state->param = (char *)SMB_MALLOC(state->total_param);
8886 if (state->param == NULL) {
8887 DEBUG(0,("reply_trans: param malloc fail for %u "
8888 "bytes !\n", (unsigned int)state->total_param));
8889 SAFE_FREE(state->data);
8891 reply_nterror(req, NT_STATUS_NO_MEMORY);
8892 END_PROFILE(SMBtrans2);
8896 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8899 state->received_data = dscnt;
8900 state->received_param = pscnt;
8902 if ((state->received_param == state->total_param) &&
8903 (state->received_data == state->total_data)) {
8905 handle_trans2(conn, req, state);
8907 SAFE_FREE(state->data);
8908 SAFE_FREE(state->param);
8910 END_PROFILE(SMBtrans2);
8914 DLIST_ADD(conn->pending_trans, state);
8916 /* We need to send an interim response then receive the rest
8917 of the parameter/data bytes */
8918 reply_outbuf(req, 0, 0);
8919 show_msg((char *)req->outbuf);
8920 END_PROFILE(SMBtrans2);
8925 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8926 SAFE_FREE(state->data);
8927 SAFE_FREE(state->param);
8929 END_PROFILE(SMBtrans2);
8930 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8934 /****************************************************************************
8935 Reply to a SMBtranss2
8936 ****************************************************************************/
8938 void reply_transs2(struct smb_request *req)
8940 connection_struct *conn = req->conn;
8941 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8942 struct trans_state *state;
8944 START_PROFILE(SMBtranss2);
8946 show_msg((const char *)req->inbuf);
8948 /* Windows clients expect all replies to
8949 a transact secondary (SMBtranss2 0x33)
8950 to have a command code of transact
8951 (SMBtrans2 0x32). See bug #8989
8952 and also [MS-CIFS] section 2.2.4.47.2
8955 req->cmd = SMBtrans2;
8958 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8959 END_PROFILE(SMBtranss2);
8963 for (state = conn->pending_trans; state != NULL;
8964 state = state->next) {
8965 if (state->mid == req->mid) {
8970 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8971 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8972 END_PROFILE(SMBtranss2);
8976 /* Revise state->total_param and state->total_data in case they have
8977 changed downwards */
8979 if (SVAL(req->vwv+0, 0) < state->total_param)
8980 state->total_param = SVAL(req->vwv+0, 0);
8981 if (SVAL(req->vwv+1, 0) < state->total_data)
8982 state->total_data = SVAL(req->vwv+1, 0);
8984 pcnt = SVAL(req->vwv+2, 0);
8985 poff = SVAL(req->vwv+3, 0);
8986 pdisp = SVAL(req->vwv+4, 0);
8988 dcnt = SVAL(req->vwv+5, 0);
8989 doff = SVAL(req->vwv+6, 0);
8990 ddisp = SVAL(req->vwv+7, 0);
8992 state->received_param += pcnt;
8993 state->received_data += dcnt;
8995 if ((state->received_data > state->total_data) ||
8996 (state->received_param > state->total_param))
9000 if (trans_oob(state->total_param, pdisp, pcnt)
9001 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9004 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9008 if (trans_oob(state->total_data, ddisp, dcnt)
9009 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9012 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9015 if ((state->received_param < state->total_param) ||
9016 (state->received_data < state->total_data)) {
9017 END_PROFILE(SMBtranss2);
9021 handle_trans2(conn, req, state);
9023 DLIST_REMOVE(conn->pending_trans, state);
9024 SAFE_FREE(state->data);
9025 SAFE_FREE(state->param);
9028 END_PROFILE(SMBtranss2);
9033 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9034 DLIST_REMOVE(conn->pending_trans, state);
9035 SAFE_FREE(state->data);
9036 SAFE_FREE(state->param);
9038 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9039 END_PROFILE(SMBtranss2);