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 "libcli/security/security.h"
37 #include "smbprofile.h"
38 #include "rpc_server/srv_pipe_hnd.h"
40 #define DIR_ENTRY_SAFETY_MARGIN 4096
42 static char *store_file_unix_basic(connection_struct *conn,
45 const SMB_STRUCT_STAT *psbuf);
47 static char *store_file_unix_basic_info2(connection_struct *conn,
50 const SMB_STRUCT_STAT *psbuf);
52 /********************************************************************
53 Roundup a value to the nearest allocation roundup size boundary.
54 Only do this for Windows clients.
55 ********************************************************************/
57 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
59 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
61 /* Only roundup for Windows clients. */
62 enum remote_arch_types ra_type = get_remote_arch();
63 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
64 val = SMB_ROUNDUP(val,rval);
69 /********************************************************************
70 Create a 64 bit FileIndex. If the file is on the same device as
71 the root of the share, just return the 64-bit inode. If it isn't,
72 mangle as we used to do.
73 ********************************************************************/
75 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
78 if (conn->base_share_dev == psbuf->st_ex_dev) {
79 return (uint64_t)psbuf->st_ex_ino;
81 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
82 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
86 /****************************************************************************
87 Utility functions for dealing with extended attributes.
88 ****************************************************************************/
90 /****************************************************************************
91 Refuse to allow clients to overwrite our private xattrs.
92 ****************************************************************************/
94 static bool samba_private_attr_name(const char *unix_ea_name)
96 static const char * const prohibited_ea_names[] = {
97 SAMBA_POSIX_INHERITANCE_EA_NAME,
98 SAMBA_XATTR_DOS_ATTRIB,
106 for (i = 0; prohibited_ea_names[i]; i++) {
107 if (strequal( prohibited_ea_names[i], unix_ea_name))
110 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
111 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
117 /****************************************************************************
118 Get one EA value. Fill in a struct ea_struct.
119 ****************************************************************************/
121 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
122 files_struct *fsp, const char *fname,
123 const char *ea_name, struct ea_struct *pea)
125 /* Get the value of this xattr. Max size is 64k. */
126 size_t attr_size = 256;
132 val = talloc_realloc(mem_ctx, val, char, attr_size);
134 return NT_STATUS_NO_MEMORY;
137 if (fsp && fsp->fh->fd != -1) {
138 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
140 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
143 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
149 return map_nt_error_from_unix(errno);
152 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
153 dump_data(10, (uint8 *)val, sizeret);
156 if (strnequal(ea_name, "user.", 5)) {
157 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
159 pea->name = talloc_strdup(mem_ctx, ea_name);
161 if (pea->name == NULL) {
163 return NT_STATUS_NO_MEMORY;
165 pea->value.data = (unsigned char *)val;
166 pea->value.length = (size_t)sizeret;
170 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
171 files_struct *fsp, const char *fname,
172 char ***pnames, size_t *pnum_names)
174 /* Get a list of all xattrs. Max namesize is 64k. */
175 size_t ea_namelist_size = 1024;
176 char *ea_namelist = NULL;
181 ssize_t sizeret = -1;
183 if (!lp_ea_support(SNUM(conn))) {
192 * TALLOC the result early to get the talloc hierarchy right.
195 names = talloc_array(mem_ctx, char *, 1);
197 DEBUG(0, ("talloc failed\n"));
198 return NT_STATUS_NO_MEMORY;
201 while (ea_namelist_size <= 65536) {
203 ea_namelist = talloc_realloc(
204 names, ea_namelist, char, ea_namelist_size);
205 if (ea_namelist == NULL) {
206 DEBUG(0, ("talloc failed\n"));
208 return NT_STATUS_NO_MEMORY;
211 if (fsp && fsp->fh->fd != -1) {
212 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
215 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
219 if ((sizeret == -1) && (errno == ERANGE)) {
220 ea_namelist_size *= 2;
229 return map_nt_error_from_unix(errno);
232 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
233 (unsigned int)sizeret));
245 * Ensure the result is 0-terminated
248 if (ea_namelist[sizeret-1] != '\0') {
250 return NT_STATUS_INTERNAL_ERROR;
258 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
262 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
264 DEBUG(0, ("talloc failed\n"));
266 return NT_STATUS_NO_MEMORY;
272 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
273 names[num_names++] = p;
281 *pnum_names = num_names;
285 /****************************************************************************
286 Return a linked list of the total EA's. Plus the total size
287 ****************************************************************************/
289 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
290 const char *fname, size_t *pea_total_len)
292 /* Get a list of all xattrs. Max namesize is 64k. */
295 struct ea_list *ea_list_head = NULL;
300 if (!lp_ea_support(SNUM(conn))) {
304 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
307 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
311 for (i=0; i<num_names; i++) {
312 struct ea_list *listp;
315 if (strnequal(names[i], "system.", 7)
316 || samba_private_attr_name(names[i]))
319 listp = talloc(mem_ctx, struct ea_list);
324 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
330 push_ascii_fstring(dos_ea_name, listp->ea.name);
333 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
335 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
336 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
337 (unsigned int)listp->ea.value.length));
339 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
343 /* Add on 4 for total length. */
344 if (*pea_total_len) {
348 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
349 (unsigned int)*pea_total_len));
354 /****************************************************************************
355 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
357 ****************************************************************************/
359 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
360 connection_struct *conn, struct ea_list *ea_list)
362 unsigned int ret_data_size = 4;
365 SMB_ASSERT(total_data_size >= 4);
367 if (!lp_ea_support(SNUM(conn))) {
372 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
375 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
376 dos_namelen = strlen(dos_ea_name);
377 if (dos_namelen > 255 || dos_namelen == 0) {
380 if (ea_list->ea.value.length > 65535) {
383 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
387 /* We know we have room. */
388 SCVAL(p,0,ea_list->ea.flags);
389 SCVAL(p,1,dos_namelen);
390 SSVAL(p,2,ea_list->ea.value.length);
391 strlcpy(p+4, dos_ea_name, dos_namelen+1);
392 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
394 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
395 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
398 ret_data_size = PTR_DIFF(p, pdata);
399 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
400 SIVAL(pdata,0,ret_data_size);
401 return ret_data_size;
404 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
406 unsigned int total_data_size,
407 unsigned int *ret_data_size,
408 connection_struct *conn,
409 struct ea_list *ea_list)
411 uint8_t *p = (uint8_t *)pdata;
412 uint8_t *last_start = NULL;
416 if (!lp_ea_support(SNUM(conn))) {
417 return NT_STATUS_NO_EAS_ON_FILE;
420 for (; ea_list; ea_list = ea_list->next) {
426 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
430 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
431 dos_namelen = strlen(dos_ea_name);
432 if (dos_namelen > 255 || dos_namelen == 0) {
433 return NT_STATUS_INTERNAL_ERROR;
435 if (ea_list->ea.value.length > 65535) {
436 return NT_STATUS_INTERNAL_ERROR;
439 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
442 size_t pad = 4 - (this_size % 4);
446 if (this_size > total_data_size) {
447 return NT_STATUS_INFO_LENGTH_MISMATCH;
450 /* We know we have room. */
451 SIVAL(p, 0x00, 0); /* next offset */
452 SCVAL(p, 0x04, ea_list->ea.flags);
453 SCVAL(p, 0x05, dos_namelen);
454 SSVAL(p, 0x06, ea_list->ea.value.length);
455 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
456 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
458 total_data_size -= this_size;
462 *ret_data_size = PTR_DIFF(p, pdata);
463 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
467 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
469 size_t total_ea_len = 0;
470 TALLOC_CTX *mem_ctx = NULL;
472 if (!lp_ea_support(SNUM(conn))) {
475 mem_ctx = talloc_tos();
476 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
480 /****************************************************************************
481 Ensure the EA name is case insensitive by matching any existing EA name.
482 ****************************************************************************/
484 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
487 TALLOC_CTX *mem_ctx = talloc_tos();
488 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
490 for (; ea_list; ea_list = ea_list->next) {
491 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
492 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
493 &unix_ea_name[5], ea_list->ea.name));
494 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
500 /****************************************************************************
501 Set or delete an extended attribute.
502 ****************************************************************************/
504 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
505 const struct smb_filename *smb_fname, struct ea_list *ea_list)
509 if (!lp_ea_support(SNUM(conn))) {
510 return NT_STATUS_EAS_NOT_SUPPORTED;
513 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
514 return NT_STATUS_ACCESS_DENIED;
517 /* For now setting EAs on streams isn't supported. */
518 fname = smb_fname->base_name;
520 for (;ea_list; ea_list = ea_list->next) {
522 fstring unix_ea_name;
524 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
525 fstrcat(unix_ea_name, ea_list->ea.name);
527 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
529 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
531 if (samba_private_attr_name(unix_ea_name)) {
532 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
533 return NT_STATUS_ACCESS_DENIED;
536 if (ea_list->ea.value.length == 0) {
537 /* Remove the attribute. */
538 if (fsp && (fsp->fh->fd != -1)) {
539 DEBUG(10,("set_ea: deleting ea name %s on "
540 "file %s by file descriptor.\n",
541 unix_ea_name, fsp_str_dbg(fsp)));
542 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
544 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
545 unix_ea_name, fname));
546 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
549 /* Removing a non existent attribute always succeeds. */
550 if (ret == -1 && errno == ENOATTR) {
551 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
557 if (fsp && (fsp->fh->fd != -1)) {
558 DEBUG(10,("set_ea: setting ea name %s on file "
559 "%s by file descriptor.\n",
560 unix_ea_name, fsp_str_dbg(fsp)));
561 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
562 ea_list->ea.value.data, ea_list->ea.value.length, 0);
564 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
565 unix_ea_name, fname));
566 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
567 ea_list->ea.value.data, ea_list->ea.value.length, 0);
573 if (errno == ENOTSUP) {
574 return NT_STATUS_EAS_NOT_SUPPORTED;
577 return map_nt_error_from_unix(errno);
583 /****************************************************************************
584 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
585 ****************************************************************************/
587 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
589 struct ea_list *ea_list_head = NULL;
590 size_t converted_size, offset = 0;
592 while (offset + 2 < data_size) {
593 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
594 unsigned int namelen = CVAL(pdata,offset);
596 offset++; /* Go past the namelen byte. */
598 /* integer wrap paranioa. */
599 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
600 (offset > data_size) || (namelen > data_size) ||
601 (offset + namelen >= data_size)) {
604 /* Ensure the name is null terminated. */
605 if (pdata[offset + namelen] != '\0') {
608 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
610 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
611 "failed: %s", strerror(errno)));
617 offset += (namelen + 1); /* Go past the name + terminating zero. */
618 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
619 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
625 /****************************************************************************
626 Read one EA list entry from the buffer.
627 ****************************************************************************/
629 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
631 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
633 unsigned int namelen;
634 size_t converted_size;
644 eal->ea.flags = CVAL(pdata,0);
645 namelen = CVAL(pdata,1);
646 val_len = SVAL(pdata,2);
648 if (4 + namelen + 1 + val_len > data_size) {
652 /* Ensure the name is null terminated. */
653 if (pdata[namelen + 4] != '\0') {
656 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
657 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
664 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
665 if (!eal->ea.value.data) {
669 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
671 /* Ensure we're null terminated just in case we print the value. */
672 eal->ea.value.data[val_len] = '\0';
673 /* But don't count the null. */
674 eal->ea.value.length--;
677 *pbytes_used = 4 + namelen + 1 + val_len;
680 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
681 dump_data(10, eal->ea.value.data, eal->ea.value.length);
686 /****************************************************************************
687 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
688 ****************************************************************************/
690 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
692 struct ea_list *ea_list_head = NULL;
694 size_t bytes_used = 0;
696 while (offset < data_size) {
697 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
703 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
704 offset += bytes_used;
710 /****************************************************************************
711 Count the total EA size needed.
712 ****************************************************************************/
714 static size_t ea_list_size(struct ea_list *ealist)
717 struct ea_list *listp;
720 for (listp = ealist; listp; listp = listp->next) {
721 push_ascii_fstring(dos_ea_name, listp->ea.name);
722 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
724 /* Add on 4 for total length. */
732 /****************************************************************************
733 Return a union of EA's from a file list and a list of names.
734 The TALLOC context for the two lists *MUST* be identical as we steal
735 memory from one list to add to another. JRA.
736 ****************************************************************************/
738 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
740 struct ea_list *nlistp, *flistp;
742 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
743 for (flistp = file_list; flistp; flistp = flistp->next) {
744 if (strequal(nlistp->ea.name, flistp->ea.name)) {
750 /* Copy the data from this entry. */
751 nlistp->ea.flags = flistp->ea.flags;
752 nlistp->ea.value = flistp->ea.value;
755 nlistp->ea.flags = 0;
756 ZERO_STRUCT(nlistp->ea.value);
760 *total_ea_len = ea_list_size(name_list);
764 /****************************************************************************
765 Send the required number of replies back.
766 We assume all fields other than the data fields are
767 set correctly for the type of call.
768 HACK ! Always assumes smb_setup field is zero.
769 ****************************************************************************/
771 void send_trans2_replies(connection_struct *conn,
772 struct smb_request *req,
779 /* As we are using a protocol > LANMAN1 then the max_send
780 variable must have been set in the sessetupX call.
781 This takes precedence over the max_xmit field in the
782 global struct. These different max_xmit variables should
783 be merged as this is now too confusing */
785 int data_to_send = datasize;
786 int params_to_send = paramsize;
788 const char *pp = params;
789 const char *pd = pdata;
790 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
791 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
792 int data_alignment_offset = 0;
793 bool overflow = False;
794 struct smbd_server_connection *sconn = req->sconn;
795 int max_send = sconn->smb1.sessions.max_send;
797 /* Modify the data_to_send and datasize and set the error if
798 we're trying to send more than max_data_bytes. We still send
799 the part of the packet(s) that fit. Strange, but needed
802 if (max_data_bytes > 0 && datasize > max_data_bytes) {
803 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
804 max_data_bytes, datasize ));
805 datasize = data_to_send = max_data_bytes;
809 /* If there genuinely are no parameters or data to send just send the empty packet */
811 if(params_to_send == 0 && data_to_send == 0) {
812 reply_outbuf(req, 10, 0);
813 show_msg((char *)req->outbuf);
814 if (!srv_send_smb(sconn,
817 IS_CONN_ENCRYPTED(conn),
819 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
821 TALLOC_FREE(req->outbuf);
825 /* When sending params and data ensure that both are nicely aligned */
826 /* Only do this alignment when there is also data to send - else
827 can cause NT redirector problems. */
829 if (((params_to_send % 4) != 0) && (data_to_send != 0))
830 data_alignment_offset = 4 - (params_to_send % 4);
832 /* Space is bufsize minus Netbios over TCP header minus SMB header */
833 /* The alignment_offset is to align the param bytes on an even byte
834 boundary. NT 4.0 Beta needs this to work correctly. */
836 useable_space = max_send - (smb_size
839 + data_alignment_offset);
841 if (useable_space < 0) {
842 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
843 "= %d!!!", useable_space));
844 exit_server_cleanly("send_trans2_replies: Not enough space");
847 while (params_to_send || data_to_send) {
848 /* Calculate whether we will totally or partially fill this packet */
850 total_sent_thistime = params_to_send + data_to_send;
852 /* We can never send more than useable_space */
854 * Note that 'useable_space' does not include the alignment offsets,
855 * but we must include the alignment offsets in the calculation of
856 * the length of the data we send over the wire, as the alignment offsets
857 * are sent here. Fix from Marc_Jacobsen@hp.com.
860 total_sent_thistime = MIN(total_sent_thistime, useable_space);
862 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
863 + data_alignment_offset);
866 * We might have SMBtrans2s in req which was transferred to
867 * the outbuf, fix that.
869 SCVAL(req->outbuf, smb_com, SMBtrans2);
871 /* Set total params and data to be sent */
872 SSVAL(req->outbuf,smb_tprcnt,paramsize);
873 SSVAL(req->outbuf,smb_tdrcnt,datasize);
875 /* Calculate how many parameters and data we can fit into
876 * this packet. Parameters get precedence
879 params_sent_thistime = MIN(params_to_send,useable_space);
880 data_sent_thistime = useable_space - params_sent_thistime;
881 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
883 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
885 /* smb_proff is the offset from the start of the SMB header to the
886 parameter bytes, however the first 4 bytes of outbuf are
887 the Netbios over TCP header. Thus use smb_base() to subtract
888 them from the calculation */
890 SSVAL(req->outbuf,smb_proff,
891 ((smb_buf(req->outbuf)+alignment_offset)
892 - smb_base(req->outbuf)));
894 if(params_sent_thistime == 0)
895 SSVAL(req->outbuf,smb_prdisp,0);
897 /* Absolute displacement of param bytes sent in this packet */
898 SSVAL(req->outbuf,smb_prdisp,pp - params);
900 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
901 if(data_sent_thistime == 0) {
902 SSVAL(req->outbuf,smb_droff,0);
903 SSVAL(req->outbuf,smb_drdisp, 0);
905 /* The offset of the data bytes is the offset of the
906 parameter bytes plus the number of parameters being sent this time */
907 SSVAL(req->outbuf, smb_droff,
908 ((smb_buf(req->outbuf)+alignment_offset)
909 - smb_base(req->outbuf))
910 + params_sent_thistime + data_alignment_offset);
911 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
914 /* Initialize the padding for alignment */
916 if (alignment_offset != 0) {
917 memset(smb_buf(req->outbuf), 0, alignment_offset);
920 /* Copy the param bytes into the packet */
922 if(params_sent_thistime) {
923 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
924 params_sent_thistime);
927 /* Copy in the data bytes */
928 if(data_sent_thistime) {
929 if (data_alignment_offset != 0) {
930 memset((smb_buf(req->outbuf)+alignment_offset+
931 params_sent_thistime), 0,
932 data_alignment_offset);
934 memcpy(smb_buf(req->outbuf)+alignment_offset
935 +params_sent_thistime+data_alignment_offset,
936 pd,data_sent_thistime);
939 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
940 params_sent_thistime, data_sent_thistime, useable_space));
941 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
942 params_to_send, data_to_send, paramsize, datasize));
945 error_packet_set((char *)req->outbuf,
946 ERRDOS,ERRbufferoverflow,
947 STATUS_BUFFER_OVERFLOW,
951 /* Send the packet */
952 show_msg((char *)req->outbuf);
953 if (!srv_send_smb(sconn,
956 IS_CONN_ENCRYPTED(conn),
958 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
960 TALLOC_FREE(req->outbuf);
962 pp += params_sent_thistime;
963 pd += data_sent_thistime;
965 params_to_send -= params_sent_thistime;
966 data_to_send -= data_sent_thistime;
969 if(params_to_send < 0 || data_to_send < 0) {
970 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
971 params_to_send, data_to_send));
979 /****************************************************************************
980 Reply to a TRANSACT2_OPEN.
981 ****************************************************************************/
983 static void call_trans2open(connection_struct *conn,
984 struct smb_request *req,
985 char **pparams, int total_params,
986 char **ppdata, int total_data,
987 unsigned int max_data_bytes)
989 struct smb_filename *smb_fname = NULL;
990 char *params = *pparams;
991 char *pdata = *ppdata;
996 bool return_additional_info;
1005 int fattr=0,mtime=0;
1006 SMB_INO_T inode = 0;
1009 struct ea_list *ea_list = NULL;
1014 uint32 create_disposition;
1015 uint32 create_options = 0;
1016 uint32_t private_flags = 0;
1017 TALLOC_CTX *ctx = talloc_tos();
1020 * Ensure we have enough parameters to perform the operation.
1023 if (total_params < 29) {
1024 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1028 flags = SVAL(params, 0);
1029 deny_mode = SVAL(params, 2);
1030 open_attr = SVAL(params,6);
1031 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1032 if (oplock_request) {
1033 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1037 return_additional_info = BITSETW(params,0);
1038 open_sattr = SVAL(params, 4);
1039 open_time = make_unix_date3(params+8);
1041 open_ofun = SVAL(params,12);
1042 open_size = IVAL(params,14);
1043 pname = ¶ms[28];
1046 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1050 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1051 total_params - 28, STR_TERMINATE,
1053 if (!NT_STATUS_IS_OK(status)) {
1054 reply_nterror(req, status);
1058 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1059 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1060 (unsigned int)open_ofun, open_size));
1062 status = filename_convert(ctx,
1064 req->flags2 & FLAGS2_DFS_PATHNAMES,
1069 if (!NT_STATUS_IS_OK(status)) {
1070 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1071 reply_botherror(req,
1072 NT_STATUS_PATH_NOT_COVERED,
1073 ERRSRV, ERRbadpath);
1076 reply_nterror(req, status);
1080 if (open_ofun == 0) {
1081 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1085 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1087 &access_mask, &share_mode,
1088 &create_disposition,
1091 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1095 /* Any data in this call is an EA list. */
1096 if (total_data && (total_data != 4)) {
1097 if (total_data < 10) {
1098 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1102 if (IVAL(pdata,0) > total_data) {
1103 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1104 IVAL(pdata,0), (unsigned int)total_data));
1105 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1109 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1112 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1116 if (!lp_ea_support(SNUM(conn))) {
1117 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1122 status = SMB_VFS_CREATE_FILE(
1125 0, /* root_dir_fid */
1126 smb_fname, /* fname */
1127 access_mask, /* access_mask */
1128 share_mode, /* share_access */
1129 create_disposition, /* create_disposition*/
1130 create_options, /* create_options */
1131 open_attr, /* file_attributes */
1132 oplock_request, /* oplock_request */
1133 open_size, /* allocation_size */
1136 ea_list, /* ea_list */
1138 &smb_action); /* psbuf */
1140 if (!NT_STATUS_IS_OK(status)) {
1141 if (open_was_deferred(req->sconn, req->mid)) {
1142 /* We have re-scheduled this call. */
1145 reply_openerror(req, status);
1149 size = get_file_size_stat(&smb_fname->st);
1150 fattr = dos_mode(conn, smb_fname);
1151 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1152 inode = smb_fname->st.st_ex_ino;
1153 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1154 close_file(req, fsp, ERROR_CLOSE);
1155 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1159 /* Realloc the size of parameters and data we will return */
1160 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1161 if(*pparams == NULL ) {
1162 reply_nterror(req, NT_STATUS_NO_MEMORY);
1167 SSVAL(params,0,fsp->fnum);
1168 SSVAL(params,2,fattr);
1169 srv_put_dos_date2(params,4, mtime);
1170 SIVAL(params,8, (uint32)size);
1171 SSVAL(params,12,deny_mode);
1172 SSVAL(params,14,0); /* open_type - file or directory. */
1173 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1175 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1176 smb_action |= EXTENDED_OPLOCK_GRANTED;
1179 SSVAL(params,18,smb_action);
1182 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1184 SIVAL(params,20,inode);
1185 SSVAL(params,24,0); /* Padding. */
1187 uint32 ea_size = estimate_ea_size(conn, fsp,
1188 fsp->fsp_name->base_name);
1189 SIVAL(params, 26, ea_size);
1191 SIVAL(params, 26, 0);
1194 /* Send the required number of replies */
1195 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1197 TALLOC_FREE(smb_fname);
1200 /*********************************************************
1201 Routine to check if a given string matches exactly.
1202 as a special case a mask of "." does NOT match. That
1203 is required for correct wildcard semantics
1204 Case can be significant or not.
1205 **********************************************************/
1207 static bool exact_match(bool has_wild,
1208 bool case_sensitive,
1212 if (mask[0] == '.' && mask[1] == 0) {
1220 if (case_sensitive) {
1221 return strcmp(str,mask)==0;
1223 return strcasecmp_m(str,mask) == 0;
1227 /****************************************************************************
1228 Return the filetype for UNIX extensions.
1229 ****************************************************************************/
1231 static uint32 unix_filetype(mode_t mode)
1234 return UNIX_TYPE_FILE;
1235 else if(S_ISDIR(mode))
1236 return UNIX_TYPE_DIR;
1238 else if(S_ISLNK(mode))
1239 return UNIX_TYPE_SYMLINK;
1242 else if(S_ISCHR(mode))
1243 return UNIX_TYPE_CHARDEV;
1246 else if(S_ISBLK(mode))
1247 return UNIX_TYPE_BLKDEV;
1250 else if(S_ISFIFO(mode))
1251 return UNIX_TYPE_FIFO;
1254 else if(S_ISSOCK(mode))
1255 return UNIX_TYPE_SOCKET;
1258 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1259 return UNIX_TYPE_UNKNOWN;
1262 /****************************************************************************
1263 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1264 ****************************************************************************/
1266 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1268 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1269 const SMB_STRUCT_STAT *psbuf,
1271 enum perm_type ptype,
1276 if (perms == SMB_MODE_NO_CHANGE) {
1277 if (!VALID_STAT(*psbuf)) {
1278 return NT_STATUS_INVALID_PARAMETER;
1280 *ret_perms = psbuf->st_ex_mode;
1281 return NT_STATUS_OK;
1285 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1286 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1287 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1288 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1289 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1290 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1291 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1292 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1293 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1295 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1298 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1301 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1306 /* Apply mode mask */
1307 ret &= lp_create_mask(SNUM(conn));
1308 /* Add in force bits */
1309 ret |= lp_force_create_mode(SNUM(conn));
1312 ret &= lp_dir_mask(SNUM(conn));
1313 /* Add in force bits */
1314 ret |= lp_force_dir_mode(SNUM(conn));
1316 case PERM_EXISTING_FILE:
1317 /* Apply mode mask */
1318 ret &= lp_security_mask(SNUM(conn));
1319 /* Add in force bits */
1320 ret |= lp_force_security_mode(SNUM(conn));
1322 case PERM_EXISTING_DIR:
1323 /* Apply mode mask */
1324 ret &= lp_dir_security_mask(SNUM(conn));
1325 /* Add in force bits */
1326 ret |= lp_force_dir_security_mode(SNUM(conn));
1331 return NT_STATUS_OK;
1334 /****************************************************************************
1335 Needed to show the msdfs symlinks as directories. Modifies psbuf
1336 to be a directory if it's a msdfs link.
1337 ****************************************************************************/
1339 static bool check_msdfs_link(connection_struct *conn,
1340 const char *pathname,
1341 SMB_STRUCT_STAT *psbuf)
1343 int saved_errno = errno;
1344 if(lp_host_msdfs() &&
1345 lp_msdfs_root(SNUM(conn)) &&
1346 is_msdfs_link(conn, pathname, psbuf)) {
1348 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1351 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1352 errno = saved_errno;
1355 errno = saved_errno;
1360 /****************************************************************************
1361 Get a level dependent lanman2 dir entry.
1362 ****************************************************************************/
1364 struct smbd_dirptr_lanman2_state {
1365 connection_struct *conn;
1366 uint32_t info_level;
1367 bool check_mangled_names;
1369 bool got_exact_match;
1372 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1378 struct smbd_dirptr_lanman2_state *state =
1379 (struct smbd_dirptr_lanman2_state *)private_data;
1381 char mangled_name[13]; /* mangled 8.3 name. */
1385 /* Mangle fname if it's an illegal name. */
1386 if (mangle_must_mangle(dname, state->conn->params)) {
1387 ok = name_to_8_3(dname, mangled_name,
1388 true, state->conn->params);
1392 fname = mangled_name;
1397 got_match = exact_match(state->has_wild,
1398 state->conn->case_sensitive,
1400 state->got_exact_match = got_match;
1402 got_match = mask_match(fname, mask,
1403 state->conn->case_sensitive);
1406 if(!got_match && state->check_mangled_names &&
1407 !mangle_is_8_3(fname, false, state->conn->params)) {
1409 * It turns out that NT matches wildcards against
1410 * both long *and* short names. This may explain some
1411 * of the wildcard wierdness from old DOS clients
1412 * that some people have been seeing.... JRA.
1414 /* Force the mangling into 8.3. */
1415 ok = name_to_8_3(fname, mangled_name,
1416 false, state->conn->params);
1421 got_match = exact_match(state->has_wild,
1422 state->conn->case_sensitive,
1423 mangled_name, mask);
1424 state->got_exact_match = got_match;
1426 got_match = mask_match(mangled_name, mask,
1427 state->conn->case_sensitive);
1435 *_fname = talloc_strdup(ctx, fname);
1436 if (*_fname == NULL) {
1443 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1445 struct smb_filename *smb_fname,
1448 struct smbd_dirptr_lanman2_state *state =
1449 (struct smbd_dirptr_lanman2_state *)private_data;
1450 bool ms_dfs_link = false;
1453 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1454 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1455 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1456 "Couldn't lstat [%s] (%s)\n",
1457 smb_fname_str_dbg(smb_fname),
1461 } else if (!VALID_STAT(smb_fname->st) &&
1462 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1463 /* Needed to show the msdfs symlinks as
1466 ms_dfs_link = check_msdfs_link(state->conn,
1467 smb_fname->base_name,
1470 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1471 "Couldn't stat [%s] (%s)\n",
1472 smb_fname_str_dbg(smb_fname),
1479 mode = dos_mode_msdfs(state->conn, smb_fname);
1481 mode = dos_mode(state->conn, smb_fname);
1488 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1489 connection_struct *conn,
1491 uint32_t info_level,
1492 struct ea_list *name_list,
1493 bool check_mangled_names,
1494 bool requires_resume_key,
1497 const struct smb_filename *smb_fname,
1498 int space_remaining,
1505 uint64_t *last_entry_off)
1507 char *p, *q, *pdata = *ppdata;
1509 uint64_t file_size = 0;
1510 uint64_t allocation_size = 0;
1511 uint64_t file_index = 0;
1513 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1514 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1515 time_t c_date = (time_t)0;
1517 char *last_entry_ptr;
1522 *out_of_space = false;
1524 ZERO_STRUCT(mdate_ts);
1525 ZERO_STRUCT(adate_ts);
1526 ZERO_STRUCT(create_date_ts);
1527 ZERO_STRUCT(cdate_ts);
1529 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1530 file_size = get_file_size_stat(&smb_fname->st);
1532 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1534 file_index = get_FileIndex(conn, &smb_fname->st);
1536 mdate_ts = smb_fname->st.st_ex_mtime;
1537 adate_ts = smb_fname->st.st_ex_atime;
1538 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1539 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1541 if (lp_dos_filetime_resolution(SNUM(conn))) {
1542 dos_filetime_timespec(&create_date_ts);
1543 dos_filetime_timespec(&mdate_ts);
1544 dos_filetime_timespec(&adate_ts);
1545 dos_filetime_timespec(&cdate_ts);
1548 create_date = convert_timespec_to_time_t(create_date_ts);
1549 mdate = convert_timespec_to_time_t(mdate_ts);
1550 adate = convert_timespec_to_time_t(adate_ts);
1551 c_date = convert_timespec_to_time_t(cdate_ts);
1553 /* align the record */
1554 SMB_ASSERT(align >= 1);
1556 off = (int)PTR_DIFF(pdata, base_data);
1557 pad = (off + (align-1)) & ~(align-1);
1560 if (pad && pad > space_remaining) {
1561 *out_of_space = true;
1562 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1563 "for padding (wanted %u, had %d)\n",
1566 return false; /* Not finished - just out of space */
1570 /* initialize padding to 0 */
1572 memset(pdata, 0, pad);
1574 space_remaining -= pad;
1576 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1586 switch (info_level) {
1587 case SMB_FIND_INFO_STANDARD:
1588 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1589 if(requires_resume_key) {
1593 srv_put_dos_date2(p,0,create_date);
1594 srv_put_dos_date2(p,4,adate);
1595 srv_put_dos_date2(p,8,mdate);
1596 SIVAL(p,12,(uint32)file_size);
1597 SIVAL(p,16,(uint32)allocation_size);
1601 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1602 p += ucs2_align(base_data, p, 0);
1604 len = srvstr_push(base_data, flags2, p,
1605 fname, PTR_DIFF(end_data, p),
1607 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1609 SCVAL(nameptr, -1, len - 2);
1611 SCVAL(nameptr, -1, 0);
1615 SCVAL(nameptr, -1, len - 1);
1617 SCVAL(nameptr, -1, 0);
1623 case SMB_FIND_EA_SIZE:
1624 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1625 if (requires_resume_key) {
1629 srv_put_dos_date2(p,0,create_date);
1630 srv_put_dos_date2(p,4,adate);
1631 srv_put_dos_date2(p,8,mdate);
1632 SIVAL(p,12,(uint32)file_size);
1633 SIVAL(p,16,(uint32)allocation_size);
1636 unsigned int ea_size = estimate_ea_size(conn, NULL,
1637 smb_fname->base_name);
1638 SIVAL(p,22,ea_size); /* Extended attributes */
1642 len = srvstr_push(base_data, flags2,
1643 p, fname, PTR_DIFF(end_data, p),
1644 STR_TERMINATE | STR_NOALIGN);
1645 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1658 SCVAL(nameptr,0,len);
1660 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1663 case SMB_FIND_EA_LIST:
1665 struct ea_list *file_list = NULL;
1668 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1672 if (requires_resume_key) {
1676 srv_put_dos_date2(p,0,create_date);
1677 srv_put_dos_date2(p,4,adate);
1678 srv_put_dos_date2(p,8,mdate);
1679 SIVAL(p,12,(uint32)file_size);
1680 SIVAL(p,16,(uint32)allocation_size);
1682 p += 22; /* p now points to the EA area. */
1684 file_list = get_ea_list_from_file(ctx, conn, NULL,
1685 smb_fname->base_name,
1687 name_list = ea_list_union(name_list, file_list, &ea_len);
1689 /* We need to determine if this entry will fit in the space available. */
1690 /* Max string size is 255 bytes. */
1691 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1692 *out_of_space = true;
1693 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1694 "(wanted %u, had %d)\n",
1695 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1697 return False; /* Not finished - just out of space */
1700 /* Push the ea_data followed by the name. */
1701 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1703 len = srvstr_push(base_data, flags2,
1704 p + 1, fname, PTR_DIFF(end_data, p+1),
1705 STR_TERMINATE | STR_NOALIGN);
1706 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1719 SCVAL(nameptr,0,len);
1721 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1725 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1726 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1727 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1729 SIVAL(p,0,reskey); p += 4;
1730 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1731 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1732 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1733 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1734 SOFF_T(p,0,file_size); p += 8;
1735 SOFF_T(p,0,allocation_size); p += 8;
1736 SIVAL(p,0,mode); p += 4;
1737 q = p; p += 4; /* q is placeholder for name length. */
1739 unsigned int ea_size = estimate_ea_size(conn, NULL,
1740 smb_fname->base_name);
1741 SIVAL(p,0,ea_size); /* Extended attributes */
1744 /* Clear the short name buffer. This is
1745 * IMPORTANT as not doing so will trigger
1746 * a Win2k client bug. JRA.
1748 if (!was_8_3 && check_mangled_names) {
1749 char mangled_name[13]; /* mangled 8.3 name. */
1750 if (!name_to_8_3(fname,mangled_name,True,
1752 /* Error - mangle failed ! */
1753 memset(mangled_name,'\0',12);
1755 mangled_name[12] = 0;
1756 len = srvstr_push(base_data, flags2,
1757 p+2, mangled_name, 24,
1758 STR_UPPER|STR_UNICODE);
1760 memset(p + 2 + len,'\0',24 - len);
1767 len = srvstr_push(base_data, flags2, p,
1768 fname, PTR_DIFF(end_data, p),
1769 STR_TERMINATE_ASCII);
1773 len = PTR_DIFF(p, pdata);
1774 pad = (len + (align-1)) & ~(align-1);
1776 * offset to the next entry, the caller
1777 * will overwrite it for the last entry
1778 * that's why we always include the padding
1782 * set padding to zero
1785 memset(p, 0, pad - len);
1792 case SMB_FIND_FILE_DIRECTORY_INFO:
1793 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1795 SIVAL(p,0,reskey); p += 4;
1796 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1797 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1798 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1799 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1800 SOFF_T(p,0,file_size); p += 8;
1801 SOFF_T(p,0,allocation_size); p += 8;
1802 SIVAL(p,0,mode); p += 4;
1803 len = srvstr_push(base_data, flags2,
1804 p + 4, fname, PTR_DIFF(end_data, p+4),
1805 STR_TERMINATE_ASCII);
1809 len = PTR_DIFF(p, pdata);
1810 pad = (len + (align-1)) & ~(align-1);
1812 * offset to the next entry, the caller
1813 * will overwrite it for the last entry
1814 * that's why we always include the padding
1818 * set padding to zero
1821 memset(p, 0, pad - len);
1828 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1829 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1831 SIVAL(p,0,reskey); p += 4;
1832 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1833 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1834 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1835 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1836 SOFF_T(p,0,file_size); p += 8;
1837 SOFF_T(p,0,allocation_size); p += 8;
1838 SIVAL(p,0,mode); p += 4;
1839 q = p; p += 4; /* q is placeholder for name length. */
1841 unsigned int ea_size = estimate_ea_size(conn, NULL,
1842 smb_fname->base_name);
1843 SIVAL(p,0,ea_size); /* Extended attributes */
1846 len = srvstr_push(base_data, flags2, p,
1847 fname, PTR_DIFF(end_data, p),
1848 STR_TERMINATE_ASCII);
1852 len = PTR_DIFF(p, pdata);
1853 pad = (len + (align-1)) & ~(align-1);
1855 * offset to the next entry, the caller
1856 * will overwrite it for the last entry
1857 * that's why we always include the padding
1861 * set padding to zero
1864 memset(p, 0, pad - len);
1871 case SMB_FIND_FILE_NAMES_INFO:
1872 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1874 SIVAL(p,0,reskey); p += 4;
1876 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1877 acl on a dir (tridge) */
1878 len = srvstr_push(base_data, flags2, p,
1879 fname, PTR_DIFF(end_data, p),
1880 STR_TERMINATE_ASCII);
1884 len = PTR_DIFF(p, pdata);
1885 pad = (len + (align-1)) & ~(align-1);
1887 * offset to the next entry, the caller
1888 * will overwrite it for the last entry
1889 * that's why we always include the padding
1893 * set padding to zero
1896 memset(p, 0, pad - len);
1903 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1906 SIVAL(p,0,reskey); p += 4;
1907 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1908 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1909 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1910 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1911 SOFF_T(p,0,file_size); p += 8;
1912 SOFF_T(p,0,allocation_size); p += 8;
1913 SIVAL(p,0,mode); p += 4;
1914 q = p; p += 4; /* q is placeholder for name length. */
1916 unsigned int ea_size = estimate_ea_size(conn, NULL,
1917 smb_fname->base_name);
1918 SIVAL(p,0,ea_size); /* Extended attributes */
1921 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1922 SBVAL(p,0,file_index); p += 8;
1923 len = srvstr_push(base_data, flags2, p,
1924 fname, PTR_DIFF(end_data, p),
1925 STR_TERMINATE_ASCII);
1929 len = PTR_DIFF(p, pdata);
1930 pad = (len + (align-1)) & ~(align-1);
1932 * offset to the next entry, the caller
1933 * will overwrite it for the last entry
1934 * that's why we always include the padding
1938 * set padding to zero
1941 memset(p, 0, pad - len);
1948 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1949 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1950 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1952 SIVAL(p,0,reskey); p += 4;
1953 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1954 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1955 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1956 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1957 SOFF_T(p,0,file_size); p += 8;
1958 SOFF_T(p,0,allocation_size); p += 8;
1959 SIVAL(p,0,mode); p += 4;
1960 q = p; p += 4; /* q is placeholder for name length */
1962 unsigned int ea_size = estimate_ea_size(conn, NULL,
1963 smb_fname->base_name);
1964 SIVAL(p,0,ea_size); /* Extended attributes */
1967 /* Clear the short name buffer. This is
1968 * IMPORTANT as not doing so will trigger
1969 * a Win2k client bug. JRA.
1971 if (!was_8_3 && check_mangled_names) {
1972 char mangled_name[13]; /* mangled 8.3 name. */
1973 if (!name_to_8_3(fname,mangled_name,True,
1975 /* Error - mangle failed ! */
1976 memset(mangled_name,'\0',12);
1978 mangled_name[12] = 0;
1979 len = srvstr_push(base_data, flags2,
1980 p+2, mangled_name, 24,
1981 STR_UPPER|STR_UNICODE);
1984 memset(p + 2 + len,'\0',24 - len);
1991 SSVAL(p,0,0); p += 2; /* Reserved ? */
1992 SBVAL(p,0,file_index); p += 8;
1993 len = srvstr_push(base_data, flags2, p,
1994 fname, PTR_DIFF(end_data, p),
1995 STR_TERMINATE_ASCII);
1999 len = PTR_DIFF(p, pdata);
2000 pad = (len + (align-1)) & ~(align-1);
2002 * offset to the next entry, the caller
2003 * will overwrite it for the last entry
2004 * that's why we always include the padding
2008 * set padding to zero
2011 memset(p, 0, pad - len);
2018 /* CIFS UNIX Extension. */
2020 case SMB_FIND_FILE_UNIX:
2021 case SMB_FIND_FILE_UNIX_INFO2:
2023 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2025 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2027 if (info_level == SMB_FIND_FILE_UNIX) {
2028 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2029 p = store_file_unix_basic(conn, p,
2030 NULL, &smb_fname->st);
2031 len = srvstr_push(base_data, flags2, p,
2032 fname, PTR_DIFF(end_data, p),
2035 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2036 p = store_file_unix_basic_info2(conn, p,
2037 NULL, &smb_fname->st);
2040 len = srvstr_push(base_data, flags2, p, fname,
2041 PTR_DIFF(end_data, p), 0);
2042 SIVAL(nameptr, 0, len);
2047 len = PTR_DIFF(p, pdata);
2048 pad = (len + (align-1)) & ~(align-1);
2050 * offset to the next entry, the caller
2051 * will overwrite it for the last entry
2052 * that's why we always include the padding
2056 * set padding to zero
2059 memset(p, 0, pad - len);
2064 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2072 if (PTR_DIFF(p,pdata) > space_remaining) {
2073 *out_of_space = true;
2074 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2075 "(wanted %u, had %d)\n",
2076 (unsigned int)PTR_DIFF(p,pdata),
2078 return false; /* Not finished - just out of space */
2081 /* Setup the last entry pointer, as an offset from base_data */
2082 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2083 /* Advance the data pointer to the next slot */
2089 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2090 connection_struct *conn,
2091 struct dptr_struct *dirptr,
2093 const char *path_mask,
2096 int requires_resume_key,
2104 int space_remaining,
2106 bool *got_exact_match,
2107 int *_last_entry_off,
2108 struct ea_list *name_list)
2111 const char *mask = NULL;
2112 long prev_dirpos = 0;
2115 struct smb_filename *smb_fname = NULL;
2116 struct smbd_dirptr_lanman2_state state;
2118 uint64_t last_entry_off = 0;
2122 state.info_level = info_level;
2123 state.check_mangled_names = lp_manglednames(conn->params);
2124 state.has_wild = dptr_has_wild(dirptr);
2125 state.got_exact_match = false;
2127 *out_of_space = false;
2128 *got_exact_match = false;
2130 p = strrchr_m(path_mask,'/');
2141 ok = smbd_dirptr_get_entry(ctx,
2147 smbd_dirptr_lanman2_match_fn,
2148 smbd_dirptr_lanman2_mode_fn,
2158 *got_exact_match = state.got_exact_match;
2160 ok = smbd_marshall_dir_entry(ctx,
2165 state.check_mangled_names,
2166 requires_resume_key,
2179 TALLOC_FREE(smb_fname);
2180 if (*out_of_space) {
2181 dptr_SeekDir(dirptr, prev_dirpos);
2188 *_last_entry_off = last_entry_off;
2192 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2193 connection_struct *conn,
2194 struct dptr_struct *dirptr,
2196 const char *path_mask,
2199 bool requires_resume_key,
2205 int space_remaining,
2207 bool *got_exact_match,
2208 int *last_entry_off,
2209 struct ea_list *name_list)
2212 const bool do_pad = true;
2214 if (info_level >= 1 && info_level <= 3) {
2215 /* No alignment on earlier info levels. */
2219 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2220 path_mask, dirtype, info_level,
2221 requires_resume_key, dont_descend, ask_sharemode,
2223 ppdata, base_data, end_data,
2225 out_of_space, got_exact_match,
2226 last_entry_off, name_list);
2229 /****************************************************************************
2230 Reply to a TRANS2_FINDFIRST.
2231 ****************************************************************************/
2233 static void call_trans2findfirst(connection_struct *conn,
2234 struct smb_request *req,
2235 char **pparams, int total_params,
2236 char **ppdata, int total_data,
2237 unsigned int max_data_bytes)
2239 /* We must be careful here that we don't return more than the
2240 allowed number of data bytes. If this means returning fewer than
2241 maxentries then so be it. We assume that the redirector has
2242 enough room for the fixed number of parameter bytes it has
2244 struct smb_filename *smb_dname = NULL;
2245 char *params = *pparams;
2246 char *pdata = *ppdata;
2250 uint16 findfirst_flags;
2251 bool close_after_first;
2253 bool requires_resume_key;
2255 char *directory = NULL;
2258 int last_entry_off=0;
2262 bool finished = False;
2263 bool dont_descend = False;
2264 bool out_of_space = False;
2265 int space_remaining;
2266 bool mask_contains_wcard = False;
2267 struct ea_list *ea_list = NULL;
2268 NTSTATUS ntstatus = NT_STATUS_OK;
2269 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2270 TALLOC_CTX *ctx = talloc_tos();
2271 struct dptr_struct *dirptr = NULL;
2272 struct smbd_server_connection *sconn = req->sconn;
2274 if (total_params < 13) {
2275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2279 dirtype = SVAL(params,0);
2280 maxentries = SVAL(params,2);
2281 findfirst_flags = SVAL(params,4);
2282 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2283 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2284 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2285 info_level = SVAL(params,6);
2287 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2288 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2289 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2290 info_level, max_data_bytes));
2293 /* W2K3 seems to treat zero as 1. */
2297 switch (info_level) {
2298 case SMB_FIND_INFO_STANDARD:
2299 case SMB_FIND_EA_SIZE:
2300 case SMB_FIND_EA_LIST:
2301 case SMB_FIND_FILE_DIRECTORY_INFO:
2302 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2303 case SMB_FIND_FILE_NAMES_INFO:
2304 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2305 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2306 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2308 case SMB_FIND_FILE_UNIX:
2309 case SMB_FIND_FILE_UNIX_INFO2:
2310 /* Always use filesystem for UNIX mtime query. */
2311 ask_sharemode = false;
2312 if (!lp_unix_extensions()) {
2313 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2318 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2322 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2323 params+12, total_params - 12,
2324 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2325 if (!NT_STATUS_IS_OK(ntstatus)) {
2326 reply_nterror(req, ntstatus);
2330 ntstatus = filename_convert(ctx, conn,
2331 req->flags2 & FLAGS2_DFS_PATHNAMES,
2334 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2335 &mask_contains_wcard,
2337 if (!NT_STATUS_IS_OK(ntstatus)) {
2338 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2339 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2340 ERRSRV, ERRbadpath);
2343 reply_nterror(req, ntstatus);
2347 mask = smb_dname->original_lcomp;
2349 directory = smb_dname->base_name;
2351 p = strrchr_m(directory,'/');
2353 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2354 if((directory[0] == '.') && (directory[1] == '\0')) {
2355 mask = talloc_strdup(ctx,"*");
2357 reply_nterror(req, NT_STATUS_NO_MEMORY);
2360 mask_contains_wcard = True;
2366 if (p == NULL || p == directory) {
2367 /* Ensure we don't have a directory name of "". */
2368 directory = talloc_strdup(talloc_tos(), ".");
2370 reply_nterror(req, NT_STATUS_NO_MEMORY);
2375 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2377 if (info_level == SMB_FIND_EA_LIST) {
2380 if (total_data < 4) {
2381 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2385 ea_size = IVAL(pdata,0);
2386 if (ea_size != total_data) {
2387 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2388 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2389 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2393 if (!lp_ea_support(SNUM(conn))) {
2394 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2398 /* Pull out the list of names. */
2399 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2406 *ppdata = (char *)SMB_REALLOC(
2407 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2408 if(*ppdata == NULL ) {
2409 reply_nterror(req, NT_STATUS_NO_MEMORY);
2413 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2415 /* Realloc the params space */
2416 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2417 if (*pparams == NULL) {
2418 reply_nterror(req, NT_STATUS_NO_MEMORY);
2423 /* Save the wildcard match and attribs we are using on this directory -
2424 needed as lanman2 assumes these are being saved between calls */
2426 ntstatus = dptr_create(conn,
2433 mask_contains_wcard,
2437 if (!NT_STATUS_IS_OK(ntstatus)) {
2438 reply_nterror(req, ntstatus);
2442 dptr_num = dptr_dnum(dirptr);
2443 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2445 /* Initialize per TRANS2_FIND_FIRST operation data */
2446 dptr_init_search_op(dirptr);
2448 /* We don't need to check for VOL here as this is returned by
2449 a different TRANS2 call. */
2451 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2452 directory,lp_dontdescend(SNUM(conn))));
2453 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2454 dont_descend = True;
2457 space_remaining = max_data_bytes;
2458 out_of_space = False;
2460 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2461 bool got_exact_match = False;
2463 /* this is a heuristic to avoid seeking the dirptr except when
2464 absolutely necessary. It allows for a filename of about 40 chars */
2465 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2466 out_of_space = True;
2469 finished = !get_lanman2_dir_entry(ctx,
2473 mask,dirtype,info_level,
2474 requires_resume_key,dont_descend,
2477 space_remaining, &out_of_space,
2479 &last_entry_off, ea_list);
2482 if (finished && out_of_space)
2485 if (!finished && !out_of_space)
2489 * As an optimisation if we know we aren't looking
2490 * for a wildcard name (ie. the name matches the wildcard exactly)
2491 * then we can finish on any (first) match.
2492 * This speeds up large directory searches. JRA.
2498 /* Ensure space_remaining never goes -ve. */
2499 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2500 space_remaining = 0;
2501 out_of_space = true;
2503 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2507 /* Check if we can close the dirptr */
2508 if(close_after_first || (finished && close_if_end)) {
2509 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2510 dptr_close(sconn, &dptr_num);
2514 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2515 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2516 * the protocol level is less than NT1. Tested with smbclient. JRA.
2517 * This should fix the OS/2 client bug #2335.
2520 if(numentries == 0) {
2521 dptr_close(sconn, &dptr_num);
2522 if (get_Protocol() < PROTOCOL_NT1) {
2523 reply_force_doserror(req, ERRDOS, ERRnofiles);
2526 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2527 ERRDOS, ERRbadfile);
2532 /* At this point pdata points to numentries directory entries. */
2534 /* Set up the return parameter block */
2535 SSVAL(params,0,dptr_num);
2536 SSVAL(params,2,numentries);
2537 SSVAL(params,4,finished);
2538 SSVAL(params,6,0); /* Never an EA error */
2539 SSVAL(params,8,last_entry_off);
2541 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2544 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2545 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2547 reply_nterror(req, NT_STATUS_NO_MEMORY);
2551 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2552 smb_fn_name(req->cmd),
2553 mask, directory, dirtype, numentries ) );
2556 * Force a name mangle here to ensure that the
2557 * mask as an 8.3 name is top of the mangled cache.
2558 * The reasons for this are subtle. Don't remove
2559 * this code unless you know what you are doing
2560 * (see PR#13758). JRA.
2563 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2564 char mangled_name[13];
2565 name_to_8_3(mask, mangled_name, True, conn->params);
2568 TALLOC_FREE(smb_dname);
2572 /****************************************************************************
2573 Reply to a TRANS2_FINDNEXT.
2574 ****************************************************************************/
2576 static void call_trans2findnext(connection_struct *conn,
2577 struct smb_request *req,
2578 char **pparams, int total_params,
2579 char **ppdata, int total_data,
2580 unsigned int max_data_bytes)
2582 /* We must be careful here that we don't return more than the
2583 allowed number of data bytes. If this means returning fewer than
2584 maxentries then so be it. We assume that the redirector has
2585 enough room for the fixed number of parameter bytes it has
2587 char *params = *pparams;
2588 char *pdata = *ppdata;
2594 uint16 findnext_flags;
2595 bool close_after_request;
2597 bool requires_resume_key;
2599 bool mask_contains_wcard = False;
2600 char *resume_name = NULL;
2601 const char *mask = NULL;
2602 const char *directory = NULL;
2606 int i, last_entry_off=0;
2607 bool finished = False;
2608 bool dont_descend = False;
2609 bool out_of_space = False;
2610 int space_remaining;
2611 struct ea_list *ea_list = NULL;
2612 NTSTATUS ntstatus = NT_STATUS_OK;
2613 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2614 TALLOC_CTX *ctx = talloc_tos();
2615 struct dptr_struct *dirptr;
2616 struct smbd_server_connection *sconn = req->sconn;
2618 if (total_params < 13) {
2619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2623 dptr_num = SVAL(params,0);
2624 maxentries = SVAL(params,2);
2625 info_level = SVAL(params,4);
2626 resume_key = IVAL(params,6);
2627 findnext_flags = SVAL(params,10);
2628 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2629 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2630 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2631 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2633 if (!continue_bit) {
2634 /* We only need resume_name if continue_bit is zero. */
2635 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2637 total_params - 12, STR_TERMINATE, &ntstatus,
2638 &mask_contains_wcard);
2639 if (!NT_STATUS_IS_OK(ntstatus)) {
2640 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2641 complain (it thinks we're asking for the directory above the shared
2642 path or an invalid name). Catch this as the resume name is only compared, never used in
2643 a file access. JRA. */
2644 srvstr_pull_talloc(ctx, params, req->flags2,
2645 &resume_name, params+12,
2649 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2650 reply_nterror(req, ntstatus);
2656 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2657 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2658 resume_key = %d resume name = %s continue=%d level = %d\n",
2659 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2660 requires_resume_key, resume_key,
2661 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2664 /* W2K3 seems to treat zero as 1. */
2668 switch (info_level) {
2669 case SMB_FIND_INFO_STANDARD:
2670 case SMB_FIND_EA_SIZE:
2671 case SMB_FIND_EA_LIST:
2672 case SMB_FIND_FILE_DIRECTORY_INFO:
2673 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2674 case SMB_FIND_FILE_NAMES_INFO:
2675 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2676 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2677 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2679 case SMB_FIND_FILE_UNIX:
2680 case SMB_FIND_FILE_UNIX_INFO2:
2681 /* Always use filesystem for UNIX mtime query. */
2682 ask_sharemode = false;
2683 if (!lp_unix_extensions()) {
2684 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2689 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2693 if (info_level == SMB_FIND_EA_LIST) {
2696 if (total_data < 4) {
2697 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2701 ea_size = IVAL(pdata,0);
2702 if (ea_size != total_data) {
2703 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2704 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2709 if (!lp_ea_support(SNUM(conn))) {
2710 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2714 /* Pull out the list of names. */
2715 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2717 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2722 *ppdata = (char *)SMB_REALLOC(
2723 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2724 if(*ppdata == NULL) {
2725 reply_nterror(req, NT_STATUS_NO_MEMORY);
2730 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2732 /* Realloc the params space */
2733 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2734 if(*pparams == NULL ) {
2735 reply_nterror(req, NT_STATUS_NO_MEMORY);
2741 /* Check that the dptr is valid */
2742 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2743 reply_nterror(req, STATUS_NO_MORE_FILES);
2747 directory = dptr_path(sconn, dptr_num);
2749 /* Get the wildcard mask from the dptr */
2750 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2751 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2752 reply_nterror(req, STATUS_NO_MORE_FILES);
2758 /* Get the attr mask from the dptr */
2759 dirtype = dptr_attr(sconn, dptr_num);
2761 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2762 dptr_num, mask, dirtype,
2764 dptr_TellDir(dirptr)));
2766 /* Initialize per TRANS2_FIND_NEXT operation data */
2767 dptr_init_search_op(dirptr);
2769 /* We don't need to check for VOL here as this is returned by
2770 a different TRANS2 call. */
2772 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2773 directory,lp_dontdescend(SNUM(conn))));
2774 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2775 dont_descend = True;
2778 space_remaining = max_data_bytes;
2779 out_of_space = False;
2782 * Seek to the correct position. We no longer use the resume key but
2783 * depend on the last file name instead.
2786 if(!continue_bit && resume_name && *resume_name) {
2789 long current_pos = 0;
2791 * Remember, name_to_8_3 is called by
2792 * get_lanman2_dir_entry(), so the resume name
2793 * could be mangled. Ensure we check the unmangled name.
2796 if (mangle_is_mangled(resume_name, conn->params)) {
2797 char *new_resume_name = NULL;
2798 mangle_lookup_name_from_8_3(ctx,
2802 if (new_resume_name) {
2803 resume_name = new_resume_name;
2808 * Fix for NT redirector problem triggered by resume key indexes
2809 * changing between directory scans. We now return a resume key of 0
2810 * and instead look for the filename to continue from (also given
2811 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2812 * findfirst/findnext (as is usual) then the directory pointer
2813 * should already be at the correct place.
2816 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2817 } /* end if resume_name && !continue_bit */
2819 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2820 bool got_exact_match = False;
2822 /* this is a heuristic to avoid seeking the dirptr except when
2823 absolutely necessary. It allows for a filename of about 40 chars */
2824 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2825 out_of_space = True;
2828 finished = !get_lanman2_dir_entry(ctx,
2832 mask,dirtype,info_level,
2833 requires_resume_key,dont_descend,
2836 space_remaining, &out_of_space,
2838 &last_entry_off, ea_list);
2841 if (finished && out_of_space)
2844 if (!finished && !out_of_space)
2848 * As an optimisation if we know we aren't looking
2849 * for a wildcard name (ie. the name matches the wildcard exactly)
2850 * then we can finish on any (first) match.
2851 * This speeds up large directory searches. JRA.
2857 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2860 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2861 smb_fn_name(req->cmd),
2862 mask, directory, dirtype, numentries ) );
2864 /* Check if we can close the dirptr */
2865 if(close_after_request || (finished && close_if_end)) {
2866 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2867 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2870 /* Set up the return parameter block */
2871 SSVAL(params,0,numentries);
2872 SSVAL(params,2,finished);
2873 SSVAL(params,4,0); /* Never an EA error */
2874 SSVAL(params,6,last_entry_off);
2876 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2882 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2884 E_md4hash(lp_servicename(SNUM(conn)),objid);
2888 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2890 SMB_ASSERT(extended_info != NULL);
2892 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2893 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2894 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2895 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2896 #ifdef SAMBA_VERSION_REVISION
2897 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2899 extended_info->samba_subversion = 0;
2900 #ifdef SAMBA_VERSION_RC_RELEASE
2901 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2903 #ifdef SAMBA_VERSION_PRE_RELEASE
2904 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2907 #ifdef SAMBA_VERSION_VENDOR_PATCH
2908 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2910 extended_info->samba_gitcommitdate = 0;
2911 #ifdef SAMBA_VERSION_COMMIT_TIME
2912 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2915 memset(extended_info->samba_version_string, 0,
2916 sizeof(extended_info->samba_version_string));
2918 snprintf (extended_info->samba_version_string,
2919 sizeof(extended_info->samba_version_string),
2920 "%s", samba_version_string());
2923 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2924 TALLOC_CTX *mem_ctx,
2925 uint16_t info_level,
2927 unsigned int max_data_bytes,
2931 char *pdata, *end_data;
2932 int data_len = 0, len;
2933 const char *vname = volume_label(SNUM(conn));
2934 int snum = SNUM(conn);
2935 char *fstype = lp_fstype(SNUM(conn));
2936 uint32 additional_flags = 0;
2937 struct smb_filename smb_fname_dot;
2941 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2942 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2943 "info level (0x%x) on IPC$.\n",
2944 (unsigned int)info_level));
2945 return NT_STATUS_ACCESS_DENIED;
2949 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2951 ZERO_STRUCT(smb_fname_dot);
2952 smb_fname_dot.base_name = discard_const_p(char, ".");
2954 if(SMB_VFS_STAT(conn, &smb_fname_dot) != 0) {
2955 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2956 return map_nt_error_from_unix(errno);
2959 st = smb_fname_dot.st;
2961 *ppdata = (char *)SMB_REALLOC(
2962 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2963 if (*ppdata == NULL) {
2964 return NT_STATUS_NO_MEMORY;
2968 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2969 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2971 switch (info_level) {
2972 case SMB_INFO_ALLOCATION:
2974 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2976 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2977 return map_nt_error_from_unix(errno);
2980 block_size = lp_block_size(snum);
2981 if (bsize < block_size) {
2982 uint64_t factor = block_size/bsize;
2987 if (bsize > block_size) {
2988 uint64_t factor = bsize/block_size;
2993 bytes_per_sector = 512;
2994 sectors_per_unit = bsize/bytes_per_sector;
2996 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2997 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2998 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3000 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3001 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3002 SIVAL(pdata,l1_cUnit,dsize);
3003 SIVAL(pdata,l1_cUnitAvail,dfree);
3004 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3008 case SMB_INFO_VOLUME:
3009 /* Return volume name */
3011 * Add volume serial number - hash of a combination of
3012 * the called hostname and the service name.
3014 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3016 * Win2k3 and previous mess this up by sending a name length
3017 * one byte short. I believe only older clients (OS/2 Win9x) use
3018 * this call so try fixing this by adding a terminating null to
3019 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3023 pdata+l2_vol_szVolLabel, vname,
3024 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3025 STR_NOALIGN|STR_TERMINATE);
3026 SCVAL(pdata,l2_vol_cch,len);
3027 data_len = l2_vol_szVolLabel + len;
3028 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
3029 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3033 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3034 case SMB_FS_ATTRIBUTE_INFORMATION:
3036 additional_flags = 0;
3037 #if defined(HAVE_SYS_QUOTAS)
3038 additional_flags |= FILE_VOLUME_QUOTAS;
3041 if(lp_nt_acl_support(SNUM(conn))) {
3042 additional_flags |= FILE_PERSISTENT_ACLS;
3045 /* Capabilities are filled in at connection time through STATVFS call */
3046 additional_flags |= conn->fs_capabilities;
3047 additional_flags |= lp_parm_int(conn->params->service,
3048 "share", "fake_fscaps",
3051 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3052 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3053 additional_flags); /* FS ATTRIBUTES */
3055 SIVAL(pdata,4,255); /* Max filename component length */
3056 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3057 and will think we can't do long filenames */
3058 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3059 PTR_DIFF(end_data, pdata+12),
3062 data_len = 12 + len;
3065 case SMB_QUERY_FS_LABEL_INFO:
3066 case SMB_FS_LABEL_INFORMATION:
3067 len = srvstr_push(pdata, flags2, pdata+4, vname,
3068 PTR_DIFF(end_data, pdata+4), 0);
3073 case SMB_QUERY_FS_VOLUME_INFO:
3074 case SMB_FS_VOLUME_INFORMATION:
3077 * Add volume serial number - hash of a combination of
3078 * the called hostname and the service name.
3080 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3081 (str_checksum(get_local_machine_name())<<16));
3083 /* Max label len is 32 characters. */
3084 len = srvstr_push(pdata, flags2, pdata+18, vname,
3085 PTR_DIFF(end_data, pdata+18),
3087 SIVAL(pdata,12,len);
3090 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3091 (int)strlen(vname),vname, lp_servicename(snum)));
3094 case SMB_QUERY_FS_SIZE_INFO:
3095 case SMB_FS_SIZE_INFORMATION:
3097 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3099 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3100 return map_nt_error_from_unix(errno);
3102 block_size = lp_block_size(snum);
3103 if (bsize < block_size) {
3104 uint64_t factor = block_size/bsize;
3109 if (bsize > block_size) {
3110 uint64_t factor = bsize/block_size;
3115 bytes_per_sector = 512;
3116 sectors_per_unit = bsize/bytes_per_sector;
3117 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3118 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3119 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3120 SBIG_UINT(pdata,0,dsize);
3121 SBIG_UINT(pdata,8,dfree);
3122 SIVAL(pdata,16,sectors_per_unit);
3123 SIVAL(pdata,20,bytes_per_sector);
3127 case SMB_FS_FULL_SIZE_INFORMATION:
3129 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3131 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3132 return map_nt_error_from_unix(errno);
3134 block_size = lp_block_size(snum);
3135 if (bsize < block_size) {
3136 uint64_t factor = block_size/bsize;
3141 if (bsize > block_size) {
3142 uint64_t factor = bsize/block_size;
3147 bytes_per_sector = 512;
3148 sectors_per_unit = bsize/bytes_per_sector;
3149 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3150 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3151 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3152 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3153 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3154 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3155 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3156 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3160 case SMB_QUERY_FS_DEVICE_INFO:
3161 case SMB_FS_DEVICE_INFORMATION:
3163 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3165 if (!CAN_WRITE(conn)) {
3166 characteristics |= FILE_READ_ONLY_DEVICE;
3169 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3170 SIVAL(pdata,4,characteristics);
3174 #ifdef HAVE_SYS_QUOTAS
3175 case SMB_FS_QUOTA_INFORMATION:
3177 * what we have to send --metze:
3179 * Unknown1: 24 NULL bytes
3180 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3181 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3182 * Quota Flags: 2 byte :
3183 * Unknown3: 6 NULL bytes
3187 * details for Quota Flags:
3189 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3190 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3191 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3192 * 0x0001 Enable Quotas: enable quota for this fs
3196 /* we need to fake up a fsp here,
3197 * because its not send in this call
3200 SMB_NTQUOTA_STRUCT quotas;
3203 ZERO_STRUCT(quotas);
3209 if (get_current_uid(conn) != 0) {
3210 DEBUG(0,("set_user_quota: access_denied "
3211 "service [%s] user [%s]\n",
3212 lp_servicename(SNUM(conn)),
3213 conn->session_info->unix_info->unix_name));
3214 return NT_STATUS_ACCESS_DENIED;
3217 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3218 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3219 return map_nt_error_from_unix(errno);
3224 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3225 lp_servicename(SNUM(conn))));
3227 /* Unknown1 24 NULL bytes*/
3228 SBIG_UINT(pdata,0,(uint64_t)0);
3229 SBIG_UINT(pdata,8,(uint64_t)0);
3230 SBIG_UINT(pdata,16,(uint64_t)0);
3232 /* Default Soft Quota 8 bytes */
3233 SBIG_UINT(pdata,24,quotas.softlim);
3235 /* Default Hard Quota 8 bytes */
3236 SBIG_UINT(pdata,32,quotas.hardlim);
3238 /* Quota flag 2 bytes */
3239 SSVAL(pdata,40,quotas.qflags);
3241 /* Unknown3 6 NULL bytes */
3247 #endif /* HAVE_SYS_QUOTAS */
3248 case SMB_FS_OBJECTID_INFORMATION:
3250 unsigned char objid[16];
3251 struct smb_extended_info extended_info;
3252 memcpy(pdata,create_volume_objectid(conn, objid),16);
3253 samba_extended_info_version (&extended_info);
3254 SIVAL(pdata,16,extended_info.samba_magic);
3255 SIVAL(pdata,20,extended_info.samba_version);
3256 SIVAL(pdata,24,extended_info.samba_subversion);
3257 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3258 memcpy(pdata+36,extended_info.samba_version_string,28);
3264 * Query the version and capabilities of the CIFS UNIX extensions
3268 case SMB_QUERY_CIFS_UNIX_INFO:
3270 bool large_write = lp_min_receive_file_size() &&
3271 !srv_is_signing_active(conn->sconn);
3272 bool large_read = !srv_is_signing_active(conn->sconn);
3273 int encrypt_caps = 0;
3275 if (!lp_unix_extensions()) {
3276 return NT_STATUS_INVALID_LEVEL;
3279 switch (conn->encrypt_level) {
3285 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3288 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3289 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3290 large_write = false;
3296 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3297 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3299 /* We have POSIX ACLs, pathname, encryption,
3300 * large read/write, and locking capability. */
3302 SBIG_UINT(pdata,4,((uint64_t)(
3303 CIFS_UNIX_POSIX_ACLS_CAP|
3304 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3305 CIFS_UNIX_FCNTL_LOCKS_CAP|
3306 CIFS_UNIX_EXTATTR_CAP|
3307 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3309 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3311 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3315 case SMB_QUERY_POSIX_FS_INFO:
3318 vfs_statvfs_struct svfs;
3320 if (!lp_unix_extensions()) {
3321 return NT_STATUS_INVALID_LEVEL;
3324 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3328 SIVAL(pdata,0,svfs.OptimalTransferSize);
3329 SIVAL(pdata,4,svfs.BlockSize);
3330 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3331 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3332 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3333 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3334 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3335 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3336 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3338 } else if (rc == EOPNOTSUPP) {
3339 return NT_STATUS_INVALID_LEVEL;
3340 #endif /* EOPNOTSUPP */
3342 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3343 return NT_STATUS_DOS(ERRSRV, ERRerror);
3348 case SMB_QUERY_POSIX_WHOAMI:
3354 if (!lp_unix_extensions()) {
3355 return NT_STATUS_INVALID_LEVEL;
3358 if (max_data_bytes < 40) {
3359 return NT_STATUS_BUFFER_TOO_SMALL;
3362 /* We ARE guest if global_sid_Builtin_Guests is
3363 * in our list of SIDs.
3365 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3366 conn->session_info->security_token)) {
3367 flags |= SMB_WHOAMI_GUEST;
3370 /* We are NOT guest if global_sid_Authenticated_Users
3371 * is in our list of SIDs.
3373 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3374 conn->session_info->security_token)) {
3375 flags &= ~SMB_WHOAMI_GUEST;
3378 /* NOTE: 8 bytes for UID/GID, irrespective of native
3379 * platform size. This matches
3380 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3382 data_len = 4 /* flags */
3389 + 4 /* pad/reserved */
3390 + (conn->session_info->unix_token->ngroups * 8)
3392 + (conn->session_info->security_token->num_sids *
3396 SIVAL(pdata, 0, flags);
3397 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3399 (uint64_t)conn->session_info->unix_token->uid);
3400 SBIG_UINT(pdata, 16,
3401 (uint64_t)conn->session_info->unix_token->gid);
3404 if (data_len >= max_data_bytes) {
3405 /* Potential overflow, skip the GIDs and SIDs. */
3407 SIVAL(pdata, 24, 0); /* num_groups */
3408 SIVAL(pdata, 28, 0); /* num_sids */
3409 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3410 SIVAL(pdata, 36, 0); /* reserved */
3416 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3417 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3419 /* We walk the SID list twice, but this call is fairly
3420 * infrequent, and I don't expect that it's performance
3421 * sensitive -- jpeach
3423 for (i = 0, sid_bytes = 0;
3424 i < conn->session_info->security_token->num_sids; ++i) {
3425 sid_bytes += ndr_size_dom_sid(
3426 &conn->session_info->security_token->sids[i],
3430 /* SID list byte count */
3431 SIVAL(pdata, 32, sid_bytes);
3433 /* 4 bytes pad/reserved - must be zero */
3434 SIVAL(pdata, 36, 0);
3438 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3439 SBIG_UINT(pdata, data_len,
3440 (uint64_t)conn->session_info->unix_token->groups[i]);
3446 i < conn->session_info->security_token->num_sids; ++i) {
3447 int sid_len = ndr_size_dom_sid(
3448 &conn->session_info->security_token->sids[i],
3451 sid_linearize(pdata + data_len, sid_len,
3452 &conn->session_info->security_token->sids[i]);
3453 data_len += sid_len;
3459 case SMB_MAC_QUERY_FS_INFO:
3461 * Thursby MAC extension... ONLY on NTFS filesystems
3462 * once we do streams then we don't need this
3464 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3466 SIVAL(pdata,84,0x100); /* Don't support mac... */
3471 return NT_STATUS_INVALID_LEVEL;
3474 *ret_data_len = data_len;
3475 return NT_STATUS_OK;
3478 /****************************************************************************
3479 Reply to a TRANS2_QFSINFO (query filesystem info).
3480 ****************************************************************************/
3482 static void call_trans2qfsinfo(connection_struct *conn,
3483 struct smb_request *req,
3484 char **pparams, int total_params,
3485 char **ppdata, int total_data,
3486 unsigned int max_data_bytes)
3488 char *params = *pparams;
3489 uint16_t info_level;
3493 if (total_params < 2) {
3494 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3498 info_level = SVAL(params,0);
3500 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3501 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3502 DEBUG(0,("call_trans2qfsinfo: encryption required "
3503 "and info level 0x%x sent.\n",
3504 (unsigned int)info_level));
3505 exit_server_cleanly("encryption required "
3511 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3513 status = smbd_do_qfsinfo(conn, req,
3518 if (!NT_STATUS_IS_OK(status)) {
3519 reply_nterror(req, status);
3523 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3526 DEBUG( 4, ( "%s info_level = %d\n",
3527 smb_fn_name(req->cmd), info_level) );
3532 /****************************************************************************
3533 Reply to a TRANS2_SETFSINFO (set filesystem info).
3534 ****************************************************************************/
3536 static void call_trans2setfsinfo(connection_struct *conn,
3537 struct smb_request *req,
3538 char **pparams, int total_params,
3539 char **ppdata, int total_data,
3540 unsigned int max_data_bytes)
3542 struct smbd_server_connection *sconn = req->sconn;
3543 char *pdata = *ppdata;
3544 char *params = *pparams;
3547 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3550 if (total_params < 4) {
3551 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3553 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3557 info_level = SVAL(params,2);
3560 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3561 info_level != SMB_SET_CIFS_UNIX_INFO) {
3562 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3563 "info level (0x%x) on IPC$.\n",
3564 (unsigned int)info_level));
3565 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3570 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3571 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3572 DEBUG(0,("call_trans2setfsinfo: encryption required "
3573 "and info level 0x%x sent.\n",
3574 (unsigned int)info_level));
3575 exit_server_cleanly("encryption required "
3581 switch(info_level) {
3582 case SMB_SET_CIFS_UNIX_INFO:
3583 if (!lp_unix_extensions()) {
3585 NT_STATUS_INVALID_LEVEL);
3589 /* There should be 12 bytes of capabilities set. */
3590 if (total_data < 8) {
3593 NT_STATUS_INVALID_PARAMETER);
3596 sconn->smb1.unix_info.client_major = SVAL(pdata,0);
3597 sconn->smb1.unix_info.client_minor = SVAL(pdata,2);
3598 sconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
3599 sconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
3600 /* Just print these values for now. */
3601 DEBUG(10,("call_trans2setfsinfo: set unix_info info. major = %u, minor = %u \
3602 cap_low = 0x%x, cap_high = 0x%xn",
3603 (unsigned int)sconn->smb1.unix_info.client_major,
3604 (unsigned int)sconn->smb1.unix_info.client_minor,
3605 (unsigned int)sconn->smb1.unix_info.client_cap_low,
3606 (unsigned int)sconn->smb1.unix_info.client_cap_high));
3608 /* Here is where we must switch to posix pathname processing... */
3609 if (sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3610 lp_set_posix_pathnames();
3611 mangle_change_to_posix();
3614 if ((sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3615 !(sconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3616 /* Client that knows how to do posix locks,
3617 * but not posix open/mkdir operations. Set a
3618 * default type for read/write checks. */
3620 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3625 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3628 size_t param_len = 0;
3629 size_t data_len = total_data;
3631 if (!lp_unix_extensions()) {
3634 NT_STATUS_INVALID_LEVEL);
3638 if (lp_smb_encrypt(SNUM(conn)) == false) {
3641 NT_STATUS_NOT_SUPPORTED);
3645 if (req->sconn->smb1.echo_handler.trusted_fde) {
3646 DEBUG( 2,("call_trans2setfsinfo: "
3647 "request transport encryption disabled"
3648 "with 'fork echo handler = yes'\n"));
3651 NT_STATUS_NOT_SUPPORTED);
3655 DEBUG( 4,("call_trans2setfsinfo: "
3656 "request transport encryption.\n"));
3658 status = srv_request_encryption_setup(conn,
3659 (unsigned char **)ppdata,
3661 (unsigned char **)pparams,
3664 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3665 !NT_STATUS_IS_OK(status)) {
3666 reply_nterror(req, status);
3670 send_trans2_replies(conn, req,
3677 if (NT_STATUS_IS_OK(status)) {
3678 /* Server-side transport
3679 * encryption is now *on*. */
3680 status = srv_encryption_start(conn);
3681 if (!NT_STATUS_IS_OK(status)) {
3682 exit_server_cleanly(
3683 "Failure in setting "
3684 "up encrypted transport");
3690 case SMB_FS_QUOTA_INFORMATION:
3692 files_struct *fsp = NULL;
3693 SMB_NTQUOTA_STRUCT quotas;
3695 ZERO_STRUCT(quotas);
3698 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
3699 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3700 lp_servicename(SNUM(conn)),
3701 conn->session_info->unix_info->unix_name));
3702 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3706 /* note: normaly there're 48 bytes,
3707 * but we didn't use the last 6 bytes for now
3710 fsp = file_fsp(req, SVAL(params,0));
3712 if (!check_fsp_ntquota_handle(conn, req,
3714 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3716 req, NT_STATUS_INVALID_HANDLE);
3720 if (total_data < 42) {
3721 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3725 NT_STATUS_INVALID_PARAMETER);
3729 /* unknown_1 24 NULL bytes in pdata*/
3731 /* the soft quotas 8 bytes (uint64_t)*/
3732 quotas.softlim = BVAL(pdata,24);
3734 /* the hard quotas 8 bytes (uint64_t)*/
3735 quotas.hardlim = BVAL(pdata,32);
3737 /* quota_flags 2 bytes **/
3738 quotas.qflags = SVAL(pdata,40);
3740 /* unknown_2 6 NULL bytes follow*/
3742 /* now set the quotas */
3743 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3744 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3745 reply_nterror(req, map_nt_error_from_unix(errno));
3752 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3754 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3760 * sending this reply works fine,
3761 * but I'm not sure it's the same
3762 * like windows do...
3765 reply_outbuf(req, 10, 0);
3768 #if defined(HAVE_POSIX_ACLS)
3769 /****************************************************************************
3770 Utility function to count the number of entries in a POSIX acl.
3771 ****************************************************************************/
3773 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3775 unsigned int ace_count = 0;
3776 int entry_id = SMB_ACL_FIRST_ENTRY;
3777 SMB_ACL_ENTRY_T entry;
3779 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3781 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3782 entry_id = SMB_ACL_NEXT_ENTRY;
3789 /****************************************************************************
3790 Utility function to marshall a POSIX acl into wire format.
3791 ****************************************************************************/
3793 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3795 int entry_id = SMB_ACL_FIRST_ENTRY;
3796 SMB_ACL_ENTRY_T entry;
3798 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3799 SMB_ACL_TAG_T tagtype;
3800 SMB_ACL_PERMSET_T permset;
3801 unsigned char perms = 0;
3802 unsigned int own_grp;
3805 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3806 entry_id = SMB_ACL_NEXT_ENTRY;
3809 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3810 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3814 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3815 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3819 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3820 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3821 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3823 SCVAL(pdata,1,perms);
3826 case SMB_ACL_USER_OBJ:
3827 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3828 own_grp = (unsigned int)pst->st_ex_uid;
3829 SIVAL(pdata,2,own_grp);
3834 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3836 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3839 own_grp = (unsigned int)*puid;
3840 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3841 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3842 SIVAL(pdata,2,own_grp);
3846 case SMB_ACL_GROUP_OBJ:
3847 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3848 own_grp = (unsigned int)pst->st_ex_gid;
3849 SIVAL(pdata,2,own_grp);
3854 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3856 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3859 own_grp = (unsigned int)*pgid;
3860 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3861 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3862 SIVAL(pdata,2,own_grp);
3867 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3868 SIVAL(pdata,2,0xFFFFFFFF);
3869 SIVAL(pdata,6,0xFFFFFFFF);
3872 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3873 SIVAL(pdata,2,0xFFFFFFFF);
3874 SIVAL(pdata,6,0xFFFFFFFF);
3877 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3880 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3887 /****************************************************************************
3888 Store the FILE_UNIX_BASIC info.
3889 ****************************************************************************/
3891 static char *store_file_unix_basic(connection_struct *conn,
3894 const SMB_STRUCT_STAT *psbuf)
3896 uint64_t file_index = get_FileIndex(conn, psbuf);
3898 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3899 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3901 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3904 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3907 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3908 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3909 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3912 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3916 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3920 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3923 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3927 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3931 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
3934 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3938 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3945 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3946 * the chflags(2) (or equivalent) flags.
3948 * XXX: this really should be behind the VFS interface. To do this, we would
3949 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3950 * Each VFS module could then implement its own mapping as appropriate for the
3951 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3953 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3957 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3961 { UF_IMMUTABLE, EXT_IMMUTABLE },
3965 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3969 { UF_HIDDEN, EXT_HIDDEN },
3972 /* Do not remove. We need to guarantee that this array has at least one
3973 * entry to build on HP-UX.
3979 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3980 uint32 *smb_fflags, uint32 *smb_fmask)
3984 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3985 *smb_fmask |= info2_flags_map[i].smb_fflag;
3986 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3987 *smb_fflags |= info2_flags_map[i].smb_fflag;
3992 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3993 const uint32 smb_fflags,
3994 const uint32 smb_fmask,
3997 uint32 max_fmask = 0;
4000 *stat_fflags = psbuf->st_ex_flags;
4002 /* For each flags requested in smb_fmask, check the state of the
4003 * corresponding flag in smb_fflags and set or clear the matching
4007 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4008 max_fmask |= info2_flags_map[i].smb_fflag;
4009 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4010 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4011 *stat_fflags |= info2_flags_map[i].stat_fflag;
4013 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4018 /* If smb_fmask is asking to set any bits that are not supported by
4019 * our flag mappings, we should fail.
4021 if ((smb_fmask & max_fmask) != smb_fmask) {
4029 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4030 * of file flags and birth (create) time.
4032 static char *store_file_unix_basic_info2(connection_struct *conn,
4035 const SMB_STRUCT_STAT *psbuf)
4037 uint32 file_flags = 0;
4038 uint32 flags_mask = 0;
4040 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4042 /* Create (birth) time 64 bit */
4043 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4046 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4047 SIVAL(pdata, 0, file_flags); /* flags */
4048 SIVAL(pdata, 4, flags_mask); /* mask */
4054 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4055 const struct stream_struct *streams,
4057 unsigned int max_data_bytes,
4058 unsigned int *data_size)
4061 unsigned int ofs = 0;
4063 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4064 unsigned int next_offset;
4066 smb_ucs2_t *namebuf;
4068 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4069 streams[i].name, &namelen) ||
4072 return NT_STATUS_INVALID_PARAMETER;
4076 * name_buf is now null-terminated, we need to marshall as not
4082 SIVAL(data, ofs+4, namelen);
4083 SOFF_T(data, ofs+8, streams[i].size);
4084 SOFF_T(data, ofs+16, streams[i].alloc_size);
4085 memcpy(data+ofs+24, namebuf, namelen);
4086 TALLOC_FREE(namebuf);
4088 next_offset = ofs + 24 + namelen;
4090 if (i == num_streams-1) {
4091 SIVAL(data, ofs, 0);
4094 unsigned int align = ndr_align_size(next_offset, 8);
4096 memset(data+next_offset, 0, align);
4097 next_offset += align;
4099 SIVAL(data, ofs, next_offset - ofs);
4108 return NT_STATUS_OK;
4111 /****************************************************************************
4112 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4113 ****************************************************************************/
4115 static void call_trans2qpipeinfo(connection_struct *conn,
4116 struct smb_request *req,
4117 unsigned int tran_call,
4118 char **pparams, int total_params,
4119 char **ppdata, int total_data,
4120 unsigned int max_data_bytes)
4122 char *params = *pparams;
4123 char *pdata = *ppdata;
4124 unsigned int data_size = 0;
4125 unsigned int param_size = 2;
4130 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4134 if (total_params < 4) {
4135 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4139 fsp = file_fsp(req, SVAL(params,0));
4140 if (!fsp_is_np(fsp)) {
4141 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4145 info_level = SVAL(params,2);
4147 *pparams = (char *)SMB_REALLOC(*pparams,2);
4148 if (*pparams == NULL) {
4149 reply_nterror(req, NT_STATUS_NO_MEMORY);
4154 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4155 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4156 if (*ppdata == NULL ) {
4157 reply_nterror(req, NT_STATUS_NO_MEMORY);
4162 switch (info_level) {
4163 case SMB_FILE_STANDARD_INFORMATION:
4165 SOFF_T(pdata,0,4096LL);
4172 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4176 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4182 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4183 TALLOC_CTX *mem_ctx,
4184 uint16_t info_level,
4186 struct smb_filename *smb_fname,
4187 bool delete_pending,
4188 struct timespec write_time_ts,
4189 struct ea_list *ea_list,
4190 int lock_data_count,
4193 unsigned int max_data_bytes,
4195 unsigned int *pdata_size)
4197 char *pdata = *ppdata;
4198 char *dstart, *dend;
4199 unsigned int data_size;
4200 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4201 time_t create_time, mtime, atime, c_time;
4202 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4209 uint64_t file_size = 0;
4211 uint64_t allocation_size = 0;
4212 uint64_t file_index = 0;
4213 uint32_t access_mask = 0;
4215 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4216 return NT_STATUS_INVALID_LEVEL;
4219 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4220 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4221 info_level, max_data_bytes));
4223 mode = dos_mode(conn, smb_fname);
4224 nlink = psbuf->st_ex_nlink;
4226 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4230 if ((nlink > 0) && delete_pending) {
4234 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4235 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4236 if (*ppdata == NULL) {
4237 return NT_STATUS_NO_MEMORY;
4241 dend = dstart + data_size - 1;
4243 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4244 update_stat_ex_mtime(psbuf, write_time_ts);
4247 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4248 mtime_ts = psbuf->st_ex_mtime;
4249 atime_ts = psbuf->st_ex_atime;
4250 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4252 if (lp_dos_filetime_resolution(SNUM(conn))) {
4253 dos_filetime_timespec(&create_time_ts);
4254 dos_filetime_timespec(&mtime_ts);
4255 dos_filetime_timespec(&atime_ts);
4256 dos_filetime_timespec(&ctime_ts);
4259 create_time = convert_timespec_to_time_t(create_time_ts);
4260 mtime = convert_timespec_to_time_t(mtime_ts);
4261 atime = convert_timespec_to_time_t(atime_ts);
4262 c_time = convert_timespec_to_time_t(ctime_ts);
4264 p = strrchr_m(smb_fname->base_name,'/');
4266 base_name = smb_fname->base_name;
4270 /* NT expects the name to be in an exact form of the *full*
4271 filename. See the trans2 torture test */
4272 if (ISDOT(base_name)) {
4273 dos_fname = talloc_strdup(mem_ctx, "\\");
4275 return NT_STATUS_NO_MEMORY;
4278 dos_fname = talloc_asprintf(mem_ctx,
4280 smb_fname->base_name);
4282 return NT_STATUS_NO_MEMORY;
4284 if (is_ntfs_stream_smb_fname(smb_fname)) {
4285 dos_fname = talloc_asprintf(dos_fname, "%s",
4286 smb_fname->stream_name);
4288 return NT_STATUS_NO_MEMORY;
4292 string_replace(dos_fname, '/', '\\');
4295 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4298 /* Do we have this path open ? */
4300 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4301 fsp1 = file_find_di_first(conn->sconn, fileid);
4302 if (fsp1 && fsp1->initial_allocation_size) {
4303 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4307 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4308 file_size = get_file_size_stat(psbuf);
4312 pos = fsp->fh->position_information;
4316 access_mask = fsp->access_mask;
4318 /* GENERIC_EXECUTE mapping from Windows */
4319 access_mask = 0x12019F;
4322 /* This should be an index number - looks like
4325 I think this causes us to fail the IFSKIT
4326 BasicFileInformationTest. -tpot */
4327 file_index = get_FileIndex(conn, psbuf);
4329 switch (info_level) {
4330 case SMB_INFO_STANDARD:
4331 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4333 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4334 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4335 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4336 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4337 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4338 SSVAL(pdata,l1_attrFile,mode);
4341 case SMB_INFO_QUERY_EA_SIZE:
4343 unsigned int ea_size =
4344 estimate_ea_size(conn, fsp,
4345 smb_fname->base_name);
4346 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4348 srv_put_dos_date2(pdata,0,create_time);
4349 srv_put_dos_date2(pdata,4,atime);
4350 srv_put_dos_date2(pdata,8,mtime); /* write time */
4351 SIVAL(pdata,12,(uint32)file_size);
4352 SIVAL(pdata,16,(uint32)allocation_size);
4353 SSVAL(pdata,20,mode);
4354 SIVAL(pdata,22,ea_size);
4358 case SMB_INFO_IS_NAME_VALID:
4359 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4361 /* os/2 needs this ? really ?*/
4362 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4364 /* This is only reached for qpathinfo */
4368 case SMB_INFO_QUERY_EAS_FROM_LIST:
4370 size_t total_ea_len = 0;
4371 struct ea_list *ea_file_list = NULL;
4373 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4376 get_ea_list_from_file(mem_ctx, conn, fsp,
4377 smb_fname->base_name,
4379 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4381 if (!ea_list || (total_ea_len > data_size)) {
4383 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4387 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4391 case SMB_INFO_QUERY_ALL_EAS:
4393 /* We have data_size bytes to put EA's into. */
4394 size_t total_ea_len = 0;
4396 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4398 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4399 smb_fname->base_name,
4401 if (!ea_list || (total_ea_len > data_size)) {
4403 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4407 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4411 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4413 /* This is FileFullEaInformation - 0xF which maps to
4414 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4416 /* We have data_size bytes to put EA's into. */
4417 size_t total_ea_len = 0;
4418 struct ea_list *ea_file_list = NULL;
4420 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4422 /*TODO: add filtering and index handling */
4425 get_ea_list_from_file(mem_ctx, conn, fsp,
4426 smb_fname->base_name,
4428 if (!ea_file_list) {
4429 return NT_STATUS_NO_EAS_ON_FILE;
4432 status = fill_ea_chained_buffer(mem_ctx,
4436 conn, ea_file_list);
4437 if (!NT_STATUS_IS_OK(status)) {
4443 case SMB_FILE_BASIC_INFORMATION:
4444 case SMB_QUERY_FILE_BASIC_INFO:
4446 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4447 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4448 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4450 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4454 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4455 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4456 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4457 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4458 SIVAL(pdata,32,mode);
4460 DEBUG(5,("SMB_QFBI - "));
4461 DEBUG(5,("create: %s ", ctime(&create_time)));
4462 DEBUG(5,("access: %s ", ctime(&atime)));
4463 DEBUG(5,("write: %s ", ctime(&mtime)));
4464 DEBUG(5,("change: %s ", ctime(&c_time)));
4465 DEBUG(5,("mode: %x\n", mode));
4468 case SMB_FILE_STANDARD_INFORMATION:
4469 case SMB_QUERY_FILE_STANDARD_INFO:
4471 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4473 SOFF_T(pdata,0,allocation_size);
4474 SOFF_T(pdata,8,file_size);
4475 SIVAL(pdata,16,nlink);
4476 SCVAL(pdata,20,delete_pending?1:0);
4477 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4478 SSVAL(pdata,22,0); /* Padding. */
4481 case SMB_FILE_EA_INFORMATION:
4482 case SMB_QUERY_FILE_EA_INFO:
4484 unsigned int ea_size =
4485 estimate_ea_size(conn, fsp, smb_fname->base_name);
4486 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4488 SIVAL(pdata,0,ea_size);
4492 /* Get the 8.3 name - used if NT SMB was negotiated. */
4493 case SMB_QUERY_FILE_ALT_NAME_INFO:
4494 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4497 char mangled_name[13];
4498 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4499 if (!name_to_8_3(base_name,mangled_name,
4500 True,conn->params)) {
4501 return NT_STATUS_NO_MEMORY;
4503 len = srvstr_push(dstart, flags2,
4504 pdata+4, mangled_name,
4505 PTR_DIFF(dend, pdata+4),
4507 data_size = 4 + len;
4512 case SMB_QUERY_FILE_NAME_INFO:
4516 this must be *exactly* right for ACLs on mapped drives to work
4518 len = srvstr_push(dstart, flags2,
4520 PTR_DIFF(dend, pdata+4),
4522 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4523 data_size = 4 + len;
4528 case SMB_FILE_ALLOCATION_INFORMATION:
4529 case SMB_QUERY_FILE_ALLOCATION_INFO:
4530 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4532 SOFF_T(pdata,0,allocation_size);
4535 case SMB_FILE_END_OF_FILE_INFORMATION:
4536 case SMB_QUERY_FILE_END_OF_FILEINFO:
4537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4539 SOFF_T(pdata,0,file_size);
4542 case SMB_QUERY_FILE_ALL_INFO:
4543 case SMB_FILE_ALL_INFORMATION:
4546 unsigned int ea_size =
4547 estimate_ea_size(conn, fsp, smb_fname->base_name);
4548 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4549 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4550 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4551 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4552 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4553 SIVAL(pdata,32,mode);
4554 SIVAL(pdata,36,0); /* padding. */
4556 SOFF_T(pdata,0,allocation_size);
4557 SOFF_T(pdata,8,file_size);
4558 SIVAL(pdata,16,nlink);
4559 SCVAL(pdata,20,delete_pending);
4560 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4563 SIVAL(pdata,0,ea_size);
4564 pdata += 4; /* EA info */
4565 len = srvstr_push(dstart, flags2,
4567 PTR_DIFF(dend, pdata+4),
4571 data_size = PTR_DIFF(pdata,(*ppdata));
4575 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4578 unsigned int ea_size =
4579 estimate_ea_size(conn, fsp, smb_fname->base_name);
4580 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4581 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4582 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4583 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4584 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4585 SIVAL(pdata, 0x20, mode);
4586 SIVAL(pdata, 0x24, 0); /* padding. */
4587 SBVAL(pdata, 0x28, allocation_size);
4588 SBVAL(pdata, 0x30, file_size);
4589 SIVAL(pdata, 0x38, nlink);
4590 SCVAL(pdata, 0x3C, delete_pending);
4591 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4592 SSVAL(pdata, 0x3E, 0); /* padding */
4593 SBVAL(pdata, 0x40, file_index);
4594 SIVAL(pdata, 0x48, ea_size);
4595 SIVAL(pdata, 0x4C, access_mask);
4596 SBVAL(pdata, 0x50, pos);
4597 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4598 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4602 len = srvstr_push(dstart, flags2,
4604 PTR_DIFF(dend, pdata+4),
4608 data_size = PTR_DIFF(pdata,(*ppdata));
4611 case SMB_FILE_INTERNAL_INFORMATION:
4613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4614 SBVAL(pdata, 0, file_index);
4618 case SMB_FILE_ACCESS_INFORMATION:
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4620 SIVAL(pdata, 0, access_mask);
4624 case SMB_FILE_NAME_INFORMATION:
4625 /* Pathname with leading '\'. */
4628 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4629 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4630 SIVAL(pdata,0,byte_len);
4631 data_size = 4 + byte_len;
4635 case SMB_FILE_DISPOSITION_INFORMATION:
4636 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4638 SCVAL(pdata,0,delete_pending);
4641 case SMB_FILE_POSITION_INFORMATION:
4642 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4644 SOFF_T(pdata,0,pos);
4647 case SMB_FILE_MODE_INFORMATION:
4648 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4649 SIVAL(pdata,0,mode);
4653 case SMB_FILE_ALIGNMENT_INFORMATION:
4654 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4655 SIVAL(pdata,0,0); /* No alignment needed. */
4660 * NT4 server just returns "invalid query" to this - if we try
4661 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4664 /* The first statement above is false - verified using Thursby
4665 * client against NT4 -- gcolley.
4667 case SMB_QUERY_FILE_STREAM_INFO:
4668 case SMB_FILE_STREAM_INFORMATION: {
4669 unsigned int num_streams;
4670 struct stream_struct *streams;
4672 DEBUG(10,("smbd_do_qfilepathinfo: "
4673 "SMB_FILE_STREAM_INFORMATION\n"));
4675 if (is_ntfs_stream_smb_fname(smb_fname)) {
4676 return NT_STATUS_INVALID_PARAMETER;
4679 status = SMB_VFS_STREAMINFO(
4680 conn, fsp, smb_fname->base_name, talloc_tos(),
4681 &num_streams, &streams);
4683 if (!NT_STATUS_IS_OK(status)) {
4684 DEBUG(10, ("could not get stream info: %s\n",
4685 nt_errstr(status)));
4689 status = marshall_stream_info(num_streams, streams,
4690 pdata, max_data_bytes,
4693 if (!NT_STATUS_IS_OK(status)) {
4694 DEBUG(10, ("marshall_stream_info failed: %s\n",
4695 nt_errstr(status)));
4699 TALLOC_FREE(streams);
4703 case SMB_QUERY_COMPRESSION_INFO:
4704 case SMB_FILE_COMPRESSION_INFORMATION:
4705 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4706 SOFF_T(pdata,0,file_size);
4707 SIVAL(pdata,8,0); /* ??? */
4708 SIVAL(pdata,12,0); /* ??? */
4712 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4714 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4715 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4716 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4717 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4718 SOFF_T(pdata,32,allocation_size);
4719 SOFF_T(pdata,40,file_size);
4720 SIVAL(pdata,48,mode);
4721 SIVAL(pdata,52,0); /* ??? */
4725 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4726 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4727 SIVAL(pdata,0,mode);
4733 * CIFS UNIX Extensions.
4736 case SMB_QUERY_FILE_UNIX_BASIC:
4738 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4739 data_size = PTR_DIFF(pdata,(*ppdata));
4741 DEBUG(4,("smbd_do_qfilepathinfo: "
4742 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4743 dump_data(4, (uint8_t *)(*ppdata), data_size);
4747 case SMB_QUERY_FILE_UNIX_INFO2:
4749 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4750 data_size = PTR_DIFF(pdata,(*ppdata));
4754 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4756 for (i=0; i<100; i++)
4757 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4763 case SMB_QUERY_FILE_UNIX_LINK:
4766 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
4769 return NT_STATUS_NO_MEMORY;
4772 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4774 if(!S_ISLNK(psbuf->st_ex_mode)) {
4775 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4778 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4780 len = SMB_VFS_READLINK(conn,
4781 smb_fname->base_name,
4784 return map_nt_error_from_unix(errno);
4787 len = srvstr_push(dstart, flags2,
4789 PTR_DIFF(dend, pdata),
4792 data_size = PTR_DIFF(pdata,(*ppdata));
4797 #if defined(HAVE_POSIX_ACLS)
4798 case SMB_QUERY_POSIX_ACL:
4800 SMB_ACL_T file_acl = NULL;
4801 SMB_ACL_T def_acl = NULL;
4802 uint16 num_file_acls = 0;
4803 uint16 num_def_acls = 0;
4805 if (fsp && fsp->fh->fd != -1) {
4806 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4809 SMB_VFS_SYS_ACL_GET_FILE(conn,
4810 smb_fname->base_name,
4811 SMB_ACL_TYPE_ACCESS);
4814 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4815 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4816 "not implemented on "
4817 "filesystem containing %s\n",
4818 smb_fname->base_name));
4819 return NT_STATUS_NOT_IMPLEMENTED;
4822 if (S_ISDIR(psbuf->st_ex_mode)) {
4823 if (fsp && fsp->is_directory) {
4825 SMB_VFS_SYS_ACL_GET_FILE(
4827 fsp->fsp_name->base_name,
4828 SMB_ACL_TYPE_DEFAULT);
4831 SMB_VFS_SYS_ACL_GET_FILE(
4833 smb_fname->base_name,
4834 SMB_ACL_TYPE_DEFAULT);
4836 def_acl = free_empty_sys_acl(conn, def_acl);
4839 num_file_acls = count_acl_entries(conn, file_acl);
4840 num_def_acls = count_acl_entries(conn, def_acl);
4842 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4843 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4845 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4846 SMB_POSIX_ACL_HEADER_SIZE) ));
4848 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4851 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4853 return NT_STATUS_BUFFER_TOO_SMALL;
4856 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4857 SSVAL(pdata,2,num_file_acls);
4858 SSVAL(pdata,4,num_def_acls);
4859 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4861 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4864 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4866 return NT_STATUS_INTERNAL_ERROR;
4868 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4870 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4873 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4875 return NT_STATUS_INTERNAL_ERROR;
4879 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4882 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4884 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4890 case SMB_QUERY_POSIX_LOCK:
4895 enum brl_type lock_type;
4897 /* We need an open file with a real fd for this. */
4898 if (!fsp || fsp->fh->fd == -1) {
4899 return NT_STATUS_INVALID_LEVEL;
4902 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4903 return NT_STATUS_INVALID_PARAMETER;
4906 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4907 case POSIX_LOCK_TYPE_READ:
4908 lock_type = READ_LOCK;
4910 case POSIX_LOCK_TYPE_WRITE:
4911 lock_type = WRITE_LOCK;
4913 case POSIX_LOCK_TYPE_UNLOCK:
4915 /* There's no point in asking for an unlock... */
4916 return NT_STATUS_INVALID_PARAMETER;
4919 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4920 #if defined(HAVE_LONGLONG)
4921 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4922 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4923 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4924 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4925 #else /* HAVE_LONGLONG */
4926 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4927 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4928 #endif /* HAVE_LONGLONG */
4930 status = query_lock(fsp,
4937 if (ERROR_WAS_LOCK_DENIED(status)) {
4938 /* Here we need to report who has it locked... */
4939 data_size = POSIX_LOCK_DATA_SIZE;
4941 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4942 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4943 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4944 #if defined(HAVE_LONGLONG)
4945 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4946 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4947 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4948 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4949 #else /* HAVE_LONGLONG */
4950 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4951 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4952 #endif /* HAVE_LONGLONG */
4954 } else if (NT_STATUS_IS_OK(status)) {
4955 /* For success we just return a copy of what we sent
4956 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4957 data_size = POSIX_LOCK_DATA_SIZE;
4958 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4959 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4967 return NT_STATUS_INVALID_LEVEL;
4970 *pdata_size = data_size;
4971 return NT_STATUS_OK;
4974 /****************************************************************************
4975 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4976 file name or file id).
4977 ****************************************************************************/
4979 static void call_trans2qfilepathinfo(connection_struct *conn,
4980 struct smb_request *req,
4981 unsigned int tran_call,
4982 char **pparams, int total_params,
4983 char **ppdata, int total_data,
4984 unsigned int max_data_bytes)
4986 char *params = *pparams;
4987 char *pdata = *ppdata;
4989 unsigned int data_size = 0;
4990 unsigned int param_size = 2;
4991 struct smb_filename *smb_fname = NULL;
4992 bool delete_pending = False;
4993 struct timespec write_time_ts;
4994 files_struct *fsp = NULL;
4995 struct file_id fileid;
4996 struct ea_list *ea_list = NULL;
4997 int lock_data_count = 0;
4998 char *lock_data = NULL;
4999 NTSTATUS status = NT_STATUS_OK;
5002 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5006 ZERO_STRUCT(write_time_ts);
5008 if (tran_call == TRANSACT2_QFILEINFO) {
5009 if (total_params < 4) {
5010 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5015 call_trans2qpipeinfo(conn, req, tran_call,
5016 pparams, total_params,
5022 fsp = file_fsp(req, SVAL(params,0));
5023 info_level = SVAL(params,2);
5025 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5027 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5028 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5032 /* Initial check for valid fsp ptr. */
5033 if (!check_fsp_open(conn, req, fsp)) {
5037 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5039 if (!NT_STATUS_IS_OK(status)) {
5040 reply_nterror(req, status);
5044 if(fsp->fake_file_handle) {
5046 * This is actually for the QUOTA_FAKE_FILE --metze
5049 /* We know this name is ok, it's already passed the checks. */
5051 } else if(fsp->fh->fd == -1) {
5053 * This is actually a QFILEINFO on a directory
5054 * handle (returned from an NT SMB). NT5.0 seems
5055 * to do this call. JRA.
5058 if (INFO_LEVEL_IS_UNIX(info_level)) {
5059 /* Always do lstat for UNIX calls. */
5060 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5061 DEBUG(3,("call_trans2qfilepathinfo: "
5062 "SMB_VFS_LSTAT of %s failed "
5064 smb_fname_str_dbg(smb_fname),
5067 map_nt_error_from_unix(errno));
5070 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5071 DEBUG(3,("call_trans2qfilepathinfo: "
5072 "SMB_VFS_STAT of %s failed (%s)\n",
5073 smb_fname_str_dbg(smb_fname),
5076 map_nt_error_from_unix(errno));
5080 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5081 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5084 * Original code - this is an open file.
5086 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5087 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5088 fsp->fnum, strerror(errno)));
5090 map_nt_error_from_unix(errno));
5093 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5094 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5102 if (total_params < 7) {
5103 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5107 info_level = SVAL(params,0);
5109 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5111 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5112 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5116 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5118 STR_TERMINATE, &status);
5119 if (!NT_STATUS_IS_OK(status)) {
5120 reply_nterror(req, status);
5124 status = filename_convert(req,
5126 req->flags2 & FLAGS2_DFS_PATHNAMES,
5131 if (!NT_STATUS_IS_OK(status)) {
5132 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5133 reply_botherror(req,
5134 NT_STATUS_PATH_NOT_COVERED,
5135 ERRSRV, ERRbadpath);
5138 reply_nterror(req, status);
5142 /* If this is a stream, check if there is a delete_pending. */
5143 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5144 && is_ntfs_stream_smb_fname(smb_fname)) {
5145 struct smb_filename *smb_fname_base = NULL;
5147 /* Create an smb_filename with stream_name == NULL. */
5149 create_synthetic_smb_fname(talloc_tos(),
5150 smb_fname->base_name,
5153 if (!NT_STATUS_IS_OK(status)) {
5154 reply_nterror(req, status);
5158 if (INFO_LEVEL_IS_UNIX(info_level)) {
5159 /* Always do lstat for UNIX calls. */
5160 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5161 DEBUG(3,("call_trans2qfilepathinfo: "
5162 "SMB_VFS_LSTAT of %s failed "
5164 smb_fname_str_dbg(smb_fname_base),
5166 TALLOC_FREE(smb_fname_base);
5168 map_nt_error_from_unix(errno));
5172 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5173 DEBUG(3,("call_trans2qfilepathinfo: "
5174 "fileinfo of %s failed "
5176 smb_fname_str_dbg(smb_fname_base),
5178 TALLOC_FREE(smb_fname_base);
5180 map_nt_error_from_unix(errno));
5185 status = file_name_hash(conn,
5186 smb_fname_str_dbg(smb_fname_base),
5188 if (!NT_STATUS_IS_OK(status)) {
5189 TALLOC_FREE(smb_fname_base);
5190 reply_nterror(req, status);
5194 fileid = vfs_file_id_from_sbuf(conn,
5195 &smb_fname_base->st);
5196 TALLOC_FREE(smb_fname_base);
5197 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5198 if (delete_pending) {
5199 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5204 if (INFO_LEVEL_IS_UNIX(info_level)) {
5205 /* Always do lstat for UNIX calls. */
5206 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5207 DEBUG(3,("call_trans2qfilepathinfo: "
5208 "SMB_VFS_LSTAT of %s failed (%s)\n",
5209 smb_fname_str_dbg(smb_fname),
5212 map_nt_error_from_unix(errno));
5217 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5218 DEBUG(3,("call_trans2qfilepathinfo: "
5219 "SMB_VFS_STAT of %s failed (%s)\n",
5220 smb_fname_str_dbg(smb_fname),
5223 map_nt_error_from_unix(errno));
5228 status = file_name_hash(conn,
5229 smb_fname_str_dbg(smb_fname),
5231 if (!NT_STATUS_IS_OK(status)) {
5232 reply_nterror(req, status);
5236 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5237 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5238 if (delete_pending) {
5239 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5244 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5245 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5246 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5248 /* Pull out any data sent here before we realloc. */
5249 switch (info_level) {
5250 case SMB_INFO_QUERY_EAS_FROM_LIST:
5252 /* Pull any EA list from the data portion. */
5255 if (total_data < 4) {
5257 req, NT_STATUS_INVALID_PARAMETER);
5260 ea_size = IVAL(pdata,0);
5262 if (total_data > 0 && ea_size != total_data) {
5263 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5264 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5266 req, NT_STATUS_INVALID_PARAMETER);
5270 if (!lp_ea_support(SNUM(conn))) {
5271 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5275 /* Pull out the list of names. */
5276 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5279 req, NT_STATUS_INVALID_PARAMETER);
5285 case SMB_QUERY_POSIX_LOCK:
5287 if (fsp == NULL || fsp->fh->fd == -1) {
5288 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5292 if (total_data != POSIX_LOCK_DATA_SIZE) {
5294 req, NT_STATUS_INVALID_PARAMETER);
5298 /* Copy the lock range data. */
5299 lock_data = (char *)talloc_memdup(
5300 req, pdata, total_data);
5302 reply_nterror(req, NT_STATUS_NO_MEMORY);
5305 lock_data_count = total_data;
5311 *pparams = (char *)SMB_REALLOC(*pparams,2);
5312 if (*pparams == NULL) {
5313 reply_nterror(req, NT_STATUS_NO_MEMORY);
5320 * draft-leach-cifs-v1-spec-02.txt
5321 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5324 * The requested information is placed in the Data portion of the
5325 * transaction response. For the information levels greater than 0x100,
5326 * the transaction response has 1 parameter word which should be
5327 * ignored by the client.
5329 * However Windows only follows this rule for the IS_NAME_VALID call.
5331 switch (info_level) {
5332 case SMB_INFO_IS_NAME_VALID:
5337 if ((info_level & 0xFF00) == 0xFF00) {
5339 * We use levels that start with 0xFF00
5340 * internally to represent SMB2 specific levels
5342 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5346 status = smbd_do_qfilepathinfo(conn, req, info_level,
5348 delete_pending, write_time_ts,
5350 lock_data_count, lock_data,
5351 req->flags2, max_data_bytes,
5352 ppdata, &data_size);
5353 if (!NT_STATUS_IS_OK(status)) {
5354 reply_nterror(req, status);
5358 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5364 /****************************************************************************
5365 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5367 ****************************************************************************/
5369 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5370 connection_struct *conn,
5371 struct smb_request *req,
5372 bool overwrite_if_exists,
5373 const struct smb_filename *smb_fname_old,
5374 struct smb_filename *smb_fname_new)
5376 NTSTATUS status = NT_STATUS_OK;
5378 /* source must already exist. */
5379 if (!VALID_STAT(smb_fname_old->st)) {
5380 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5383 if (VALID_STAT(smb_fname_new->st)) {
5384 if (overwrite_if_exists) {
5385 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
5386 return NT_STATUS_FILE_IS_A_DIRECTORY;
5388 status = unlink_internals(conn,
5390 FILE_ATTRIBUTE_NORMAL,
5393 if (!NT_STATUS_IS_OK(status)) {
5397 /* Disallow if newname already exists. */
5398 return NT_STATUS_OBJECT_NAME_COLLISION;
5402 /* No links from a directory. */
5403 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5404 return NT_STATUS_FILE_IS_A_DIRECTORY;
5407 /* Setting a hardlink to/from a stream isn't currently supported. */
5408 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5409 is_ntfs_stream_smb_fname(smb_fname_new)) {
5410 return NT_STATUS_INVALID_PARAMETER;
5413 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5414 smb_fname_old->base_name, smb_fname_new->base_name));
5416 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5417 smb_fname_new->base_name) != 0) {
5418 status = map_nt_error_from_unix(errno);
5419 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5420 nt_errstr(status), smb_fname_old->base_name,
5421 smb_fname_new->base_name));
5426 /****************************************************************************
5427 Deal with setting the time from any of the setfilepathinfo functions.
5428 ****************************************************************************/
5430 NTSTATUS smb_set_file_time(connection_struct *conn,
5432 const struct smb_filename *smb_fname,
5433 struct smb_file_time *ft,
5434 bool setting_write_time)
5436 struct smb_filename smb_fname_base;
5438 FILE_NOTIFY_CHANGE_LAST_ACCESS
5439 |FILE_NOTIFY_CHANGE_LAST_WRITE
5440 |FILE_NOTIFY_CHANGE_CREATION;
5442 if (!VALID_STAT(smb_fname->st)) {
5443 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5446 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
5447 return NT_STATUS_ACCESS_DENIED;
5450 /* get some defaults (no modifications) if any info is zero or -1. */
5451 if (null_timespec(ft->create_time)) {
5452 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5455 if (null_timespec(ft->atime)) {
5456 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5459 if (null_timespec(ft->mtime)) {
5460 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5463 if (!setting_write_time) {
5464 /* ft->mtime comes from change time, not write time. */
5465 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5468 /* Ensure the resolution is the correct for
5469 * what we can store on this filesystem. */
5471 round_timespec(conn->ts_res, &ft->create_time);
5472 round_timespec(conn->ts_res, &ft->ctime);
5473 round_timespec(conn->ts_res, &ft->atime);
5474 round_timespec(conn->ts_res, &ft->mtime);
5476 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5477 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5478 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5479 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5480 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5481 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5482 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5483 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5485 if (setting_write_time) {
5487 * This was a Windows setfileinfo on an open file.
5488 * NT does this a lot. We also need to
5489 * set the time here, as it can be read by
5490 * FindFirst/FindNext and with the patch for bug #2045
5491 * in smbd/fileio.c it ensures that this timestamp is
5492 * kept sticky even after a write. We save the request
5493 * away and will set it on file close and after a write. JRA.
5496 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5497 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5500 if (fsp->base_fsp) {
5501 set_sticky_write_time_fsp(fsp->base_fsp,
5504 set_sticky_write_time_fsp(fsp, ft->mtime);
5507 set_sticky_write_time_path(
5508 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5513 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5515 /* Always call ntimes on the base, even if a stream was passed in. */
5516 smb_fname_base = *smb_fname;
5517 smb_fname_base.stream_name = NULL;
5519 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
5520 return map_nt_error_from_unix(errno);
5523 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5524 smb_fname->base_name);
5525 return NT_STATUS_OK;
5528 /****************************************************************************
5529 Deal with setting the dosmode from any of the setfilepathinfo functions.
5530 ****************************************************************************/
5532 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5533 const struct smb_filename *smb_fname,
5536 struct smb_filename *smb_fname_base = NULL;
5539 if (!VALID_STAT(smb_fname->st)) {
5540 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5543 /* Always operate on the base_name, even if a stream was passed in. */
5544 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5545 NULL, &smb_fname->st,
5547 if (!NT_STATUS_IS_OK(status)) {
5552 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5553 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
5555 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
5559 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5561 /* check the mode isn't different, before changing it */
5562 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5563 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5564 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5565 (unsigned int)dosmode));
5567 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5569 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5571 smb_fname_str_dbg(smb_fname_base),
5573 status = map_nt_error_from_unix(errno);
5577 status = NT_STATUS_OK;
5579 TALLOC_FREE(smb_fname_base);
5583 /****************************************************************************
5584 Deal with setting the size from any of the setfilepathinfo functions.
5585 ****************************************************************************/
5587 static NTSTATUS smb_set_file_size(connection_struct *conn,
5588 struct smb_request *req,
5590 const struct smb_filename *smb_fname,
5591 const SMB_STRUCT_STAT *psbuf,
5593 bool fail_after_createfile)
5595 NTSTATUS status = NT_STATUS_OK;
5596 struct smb_filename *smb_fname_tmp = NULL;
5597 files_struct *new_fsp = NULL;
5599 if (!VALID_STAT(*psbuf)) {
5600 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5603 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
5604 return NT_STATUS_ACCESS_DENIED;
5607 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5609 if (size == get_file_size_stat(psbuf)) {
5610 return NT_STATUS_OK;
5613 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5614 smb_fname_str_dbg(smb_fname), (double)size));
5616 if (fsp && fsp->fh->fd != -1) {
5617 /* Handle based call. */
5618 if (vfs_set_filelen(fsp, size) == -1) {
5619 return map_nt_error_from_unix(errno);
5621 trigger_write_time_update_immediate(fsp);
5622 return NT_STATUS_OK;
5625 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5626 if (!NT_STATUS_IS_OK(status)) {
5630 smb_fname_tmp->st = *psbuf;
5632 status = SMB_VFS_CREATE_FILE(
5635 0, /* root_dir_fid */
5636 smb_fname_tmp, /* fname */
5637 FILE_WRITE_DATA, /* access_mask */
5638 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5640 FILE_OPEN, /* create_disposition*/
5641 0, /* create_options */
5642 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5643 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5644 0, /* allocation_size */
5645 0, /* private_flags */
5648 &new_fsp, /* result */
5651 TALLOC_FREE(smb_fname_tmp);
5653 if (!NT_STATUS_IS_OK(status)) {
5654 /* NB. We check for open_was_deferred in the caller. */
5658 /* See RAW-SFILEINFO-END-OF-FILE */
5659 if (fail_after_createfile) {
5660 close_file(req, new_fsp,NORMAL_CLOSE);
5661 return NT_STATUS_INVALID_LEVEL;
5664 if (vfs_set_filelen(new_fsp, size) == -1) {
5665 status = map_nt_error_from_unix(errno);
5666 close_file(req, new_fsp,NORMAL_CLOSE);
5670 trigger_write_time_update_immediate(new_fsp);
5671 close_file(req, new_fsp,NORMAL_CLOSE);
5672 return NT_STATUS_OK;
5675 /****************************************************************************
5676 Deal with SMB_INFO_SET_EA.
5677 ****************************************************************************/
5679 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5683 const struct smb_filename *smb_fname)
5685 struct ea_list *ea_list = NULL;
5686 TALLOC_CTX *ctx = NULL;
5687 NTSTATUS status = NT_STATUS_OK;
5689 if (total_data < 10) {
5691 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5692 length. They seem to have no effect. Bug #3212. JRA */
5694 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5695 /* We're done. We only get EA info in this call. */
5696 return NT_STATUS_OK;
5699 return NT_STATUS_INVALID_PARAMETER;
5702 if (IVAL(pdata,0) > total_data) {
5703 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5704 IVAL(pdata,0), (unsigned int)total_data));
5705 return NT_STATUS_INVALID_PARAMETER;
5709 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5711 return NT_STATUS_INVALID_PARAMETER;
5714 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5715 return NT_STATUS_ACCESS_DENIED;
5718 status = set_ea(conn, fsp, smb_fname, ea_list);
5723 /****************************************************************************
5724 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5725 ****************************************************************************/
5727 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5732 struct ea_list *ea_list = NULL;
5736 return NT_STATUS_INVALID_HANDLE;
5739 if (!lp_ea_support(SNUM(conn))) {
5740 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5741 "EA's not supported.\n",
5742 (unsigned int)total_data));
5743 return NT_STATUS_EAS_NOT_SUPPORTED;
5746 if (total_data < 10) {
5747 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5749 (unsigned int)total_data));
5750 return NT_STATUS_INVALID_PARAMETER;
5753 ea_list = read_nttrans_ea_list(talloc_tos(),
5758 return NT_STATUS_INVALID_PARAMETER;
5761 if (fsp && !(fsp->access_mask & FILE_WRITE_EA)) {
5762 return NT_STATUS_ACCESS_DENIED;
5765 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5767 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5768 smb_fname_str_dbg(fsp->fsp_name),
5769 nt_errstr(status) ));
5775 /****************************************************************************
5776 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5777 ****************************************************************************/
5779 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5783 struct smb_filename *smb_fname)
5785 NTSTATUS status = NT_STATUS_OK;
5786 bool delete_on_close;
5789 if (total_data < 1) {
5790 return NT_STATUS_INVALID_PARAMETER;
5794 return NT_STATUS_INVALID_HANDLE;
5797 delete_on_close = (CVAL(pdata,0) ? True : False);
5798 dosmode = dos_mode(conn, smb_fname);
5800 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5801 "delete_on_close = %u\n",
5802 smb_fname_str_dbg(smb_fname),
5803 (unsigned int)dosmode,
5804 (unsigned int)delete_on_close ));
5806 if (delete_on_close) {
5807 status = can_set_delete_on_close(fsp, dosmode);
5808 if (!NT_STATUS_IS_OK(status)) {
5813 /* The set is across all open files on this dev/inode pair. */
5814 if (!set_delete_on_close(fsp, delete_on_close,
5815 conn->session_info->unix_token)) {
5816 return NT_STATUS_ACCESS_DENIED;
5818 return NT_STATUS_OK;
5821 /****************************************************************************
5822 Deal with SMB_FILE_POSITION_INFORMATION.
5823 ****************************************************************************/
5825 static NTSTATUS smb_file_position_information(connection_struct *conn,
5830 uint64_t position_information;
5832 if (total_data < 8) {
5833 return NT_STATUS_INVALID_PARAMETER;
5837 /* Ignore on pathname based set. */
5838 return NT_STATUS_OK;
5841 position_information = (uint64_t)IVAL(pdata,0);
5842 #ifdef LARGE_SMB_OFF_T
5843 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5844 #else /* LARGE_SMB_OFF_T */
5845 if (IVAL(pdata,4) != 0) {
5846 /* more than 32 bits? */
5847 return NT_STATUS_INVALID_PARAMETER;
5849 #endif /* LARGE_SMB_OFF_T */
5851 DEBUG(10,("smb_file_position_information: Set file position "
5852 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5853 (double)position_information));
5854 fsp->fh->position_information = position_information;
5855 return NT_STATUS_OK;
5858 /****************************************************************************
5859 Deal with SMB_FILE_MODE_INFORMATION.
5860 ****************************************************************************/
5862 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5868 if (total_data < 4) {
5869 return NT_STATUS_INVALID_PARAMETER;
5871 mode = IVAL(pdata,0);
5872 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5873 return NT_STATUS_INVALID_PARAMETER;
5875 return NT_STATUS_OK;
5878 /****************************************************************************
5879 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5880 ****************************************************************************/
5882 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5883 struct smb_request *req,
5886 const struct smb_filename *smb_fname)
5888 char *link_target = NULL;
5889 const char *newname = smb_fname->base_name;
5890 TALLOC_CTX *ctx = talloc_tos();
5892 /* Set a symbolic link. */
5893 /* Don't allow this if follow links is false. */
5895 if (total_data == 0) {
5896 return NT_STATUS_INVALID_PARAMETER;
5899 if (!lp_symlinks(SNUM(conn))) {
5900 return NT_STATUS_ACCESS_DENIED;
5903 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5904 total_data, STR_TERMINATE);
5907 return NT_STATUS_INVALID_PARAMETER;
5910 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5911 newname, link_target ));
5913 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5914 return map_nt_error_from_unix(errno);
5917 return NT_STATUS_OK;
5920 /****************************************************************************
5921 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5922 ****************************************************************************/
5924 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5925 struct smb_request *req,
5926 const char *pdata, int total_data,
5927 struct smb_filename *smb_fname_new)
5929 char *oldname = NULL;
5930 struct smb_filename *smb_fname_old = NULL;
5931 TALLOC_CTX *ctx = talloc_tos();
5932 NTSTATUS status = NT_STATUS_OK;
5934 /* Set a hard link. */
5935 if (total_data == 0) {
5936 return NT_STATUS_INVALID_PARAMETER;
5939 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5940 total_data, STR_TERMINATE, &status);
5941 if (!NT_STATUS_IS_OK(status)) {
5945 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5946 smb_fname_str_dbg(smb_fname_new), oldname));
5948 status = filename_convert(ctx,
5950 req->flags2 & FLAGS2_DFS_PATHNAMES,
5955 if (!NT_STATUS_IS_OK(status)) {
5959 return hardlink_internals(ctx, conn, req, false,
5960 smb_fname_old, smb_fname_new);
5963 /****************************************************************************
5964 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
5965 ****************************************************************************/
5967 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
5968 struct smb_request *req,
5972 struct smb_filename *smb_fname_src)
5976 char *newname = NULL;
5977 struct smb_filename *smb_fname_dst = NULL;
5978 NTSTATUS status = NT_STATUS_OK;
5979 TALLOC_CTX *ctx = talloc_tos();
5982 return NT_STATUS_INVALID_HANDLE;
5985 if (total_data < 20) {
5986 return NT_STATUS_INVALID_PARAMETER;
5989 overwrite = (CVAL(pdata,0) ? True : False);
5990 len = IVAL(pdata,16);
5992 if (len > (total_data - 20) || (len == 0)) {
5993 return NT_STATUS_INVALID_PARAMETER;
5996 srvstr_get_path(ctx, pdata, req->flags2, &newname,
5997 &pdata[20], len, STR_TERMINATE,
5999 if (!NT_STATUS_IS_OK(status)) {
6003 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6006 status = filename_convert(ctx,
6008 req->flags2 & FLAGS2_DFS_PATHNAMES,
6013 if (!NT_STATUS_IS_OK(status)) {
6017 if (fsp->base_fsp) {
6018 /* newname must be a stream name. */
6019 if (newname[0] != ':') {
6020 return NT_STATUS_NOT_SUPPORTED;
6023 /* Create an smb_fname to call rename_internals_fsp() with. */
6024 status = create_synthetic_smb_fname(talloc_tos(),
6025 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6027 if (!NT_STATUS_IS_OK(status)) {
6032 * Set the original last component, since
6033 * rename_internals_fsp() requires it.
6035 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6037 if (smb_fname_dst->original_lcomp == NULL) {
6038 status = NT_STATUS_NO_MEMORY;
6044 DEBUG(10,("smb2_file_rename_information: "
6045 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6046 fsp->fnum, fsp_str_dbg(fsp),
6047 smb_fname_str_dbg(smb_fname_dst)));
6048 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6049 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6053 TALLOC_FREE(smb_fname_dst);
6057 static NTSTATUS smb_file_link_information(connection_struct *conn,
6058 struct smb_request *req,
6062 struct smb_filename *smb_fname_src)
6066 char *newname = NULL;
6067 struct smb_filename *smb_fname_dst = NULL;
6068 NTSTATUS status = NT_STATUS_OK;
6069 TALLOC_CTX *ctx = talloc_tos();
6072 return NT_STATUS_INVALID_HANDLE;
6075 if (total_data < 20) {
6076 return NT_STATUS_INVALID_PARAMETER;
6079 overwrite = (CVAL(pdata,0) ? true : false);
6080 len = IVAL(pdata,16);
6082 if (len > (total_data - 20) || (len == 0)) {
6083 return NT_STATUS_INVALID_PARAMETER;
6086 srvstr_get_path(ctx, pdata, req->flags2, &newname,
6087 &pdata[20], len, STR_TERMINATE,
6089 if (!NT_STATUS_IS_OK(status)) {
6093 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6096 status = filename_convert(ctx,
6098 req->flags2 & FLAGS2_DFS_PATHNAMES,
6103 if (!NT_STATUS_IS_OK(status)) {
6107 if (fsp->base_fsp) {
6108 /* No stream names. */
6109 return NT_STATUS_NOT_SUPPORTED;
6112 DEBUG(10,("smb_file_link_information: "
6113 "SMB_FILE_LINK_INFORMATION (fnum %d) %s -> %s\n",
6114 fsp->fnum, fsp_str_dbg(fsp),
6115 smb_fname_str_dbg(smb_fname_dst)));
6116 status = hardlink_internals(ctx,
6123 TALLOC_FREE(smb_fname_dst);
6127 /****************************************************************************
6128 Deal with SMB_FILE_RENAME_INFORMATION.
6129 ****************************************************************************/
6131 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6132 struct smb_request *req,
6136 struct smb_filename *smb_fname_src)
6141 char *newname = NULL;
6142 struct smb_filename *smb_fname_dst = NULL;
6143 bool dest_has_wcard = False;
6144 NTSTATUS status = NT_STATUS_OK;
6146 TALLOC_CTX *ctx = talloc_tos();
6148 if (total_data < 13) {
6149 return NT_STATUS_INVALID_PARAMETER;
6152 overwrite = (CVAL(pdata,0) ? True : False);
6153 root_fid = IVAL(pdata,4);
6154 len = IVAL(pdata,8);
6156 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6157 return NT_STATUS_INVALID_PARAMETER;
6160 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
6163 if (!NT_STATUS_IS_OK(status)) {
6167 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6170 status = resolve_dfspath_wcard(ctx, conn,
6171 req->flags2 & FLAGS2_DFS_PATHNAMES,
6176 if (!NT_STATUS_IS_OK(status)) {
6180 /* Check the new name has no '/' characters. */
6181 if (strchr_m(newname, '/')) {
6182 return NT_STATUS_NOT_SUPPORTED;
6185 if (fsp && fsp->base_fsp) {
6186 /* newname must be a stream name. */
6187 if (newname[0] != ':') {
6188 return NT_STATUS_NOT_SUPPORTED;
6191 /* Create an smb_fname to call rename_internals_fsp() with. */
6192 status = create_synthetic_smb_fname(talloc_tos(),
6193 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6195 if (!NT_STATUS_IS_OK(status)) {
6200 * Set the original last component, since
6201 * rename_internals_fsp() requires it.
6203 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6205 if (smb_fname_dst->original_lcomp == NULL) {
6206 status = NT_STATUS_NO_MEMORY;
6212 * Build up an smb_fname_dst based on the filename passed in.
6213 * We basically just strip off the last component, and put on
6214 * the newname instead.
6216 char *base_name = NULL;
6218 /* newname must *not* be a stream name. */
6219 if (newname[0] == ':') {
6220 return NT_STATUS_NOT_SUPPORTED;
6224 * Strip off the last component (filename) of the path passed
6227 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6229 return NT_STATUS_NO_MEMORY;
6231 p = strrchr_m(base_name, '/');
6235 base_name = talloc_strdup(ctx, "");
6237 return NT_STATUS_NO_MEMORY;
6240 /* Append the new name. */
6241 base_name = talloc_asprintf_append(base_name,
6245 return NT_STATUS_NO_MEMORY;
6248 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6251 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6254 /* If an error we expect this to be
6255 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6257 if (!NT_STATUS_IS_OK(status)) {
6258 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6262 /* Create an smb_fname to call rename_internals_fsp() */
6263 status = create_synthetic_smb_fname(ctx,
6267 if (!NT_STATUS_IS_OK(status)) {
6274 DEBUG(10,("smb_file_rename_information: "
6275 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6276 fsp->fnum, fsp_str_dbg(fsp),
6277 smb_fname_str_dbg(smb_fname_dst)));
6278 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6281 DEBUG(10,("smb_file_rename_information: "
6282 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6283 smb_fname_str_dbg(smb_fname_src),
6284 smb_fname_str_dbg(smb_fname_dst)));
6285 status = rename_internals(ctx, conn, req, smb_fname_src,
6286 smb_fname_dst, 0, overwrite, false,
6288 FILE_WRITE_ATTRIBUTES);
6291 TALLOC_FREE(smb_fname_dst);
6295 /****************************************************************************
6296 Deal with SMB_SET_POSIX_ACL.
6297 ****************************************************************************/
6299 #if defined(HAVE_POSIX_ACLS)
6300 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6304 const struct smb_filename *smb_fname)
6306 uint16 posix_acl_version;
6307 uint16 num_file_acls;
6308 uint16 num_def_acls;
6309 bool valid_file_acls = True;
6310 bool valid_def_acls = True;
6312 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6313 return NT_STATUS_INVALID_PARAMETER;
6315 posix_acl_version = SVAL(pdata,0);
6316 num_file_acls = SVAL(pdata,2);
6317 num_def_acls = SVAL(pdata,4);
6319 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6320 valid_file_acls = False;
6324 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6325 valid_def_acls = False;
6329 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6330 return NT_STATUS_INVALID_PARAMETER;
6333 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6334 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6335 return NT_STATUS_INVALID_PARAMETER;
6338 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6339 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6340 (unsigned int)num_file_acls,
6341 (unsigned int)num_def_acls));
6343 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6344 smb_fname->base_name, num_file_acls,
6345 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6346 return map_nt_error_from_unix(errno);
6349 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6350 smb_fname->base_name, &smb_fname->st, num_def_acls,
6351 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6352 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6353 return map_nt_error_from_unix(errno);
6355 return NT_STATUS_OK;
6359 /****************************************************************************
6360 Deal with SMB_SET_POSIX_LOCK.
6361 ****************************************************************************/
6363 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6364 struct smb_request *req,
6372 bool blocking_lock = False;
6373 enum brl_type lock_type;
6375 NTSTATUS status = NT_STATUS_OK;
6377 if (fsp == NULL || fsp->fh->fd == -1) {
6378 return NT_STATUS_INVALID_HANDLE;
6381 if (total_data != POSIX_LOCK_DATA_SIZE) {
6382 return NT_STATUS_INVALID_PARAMETER;
6385 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6386 case POSIX_LOCK_TYPE_READ:
6387 lock_type = READ_LOCK;
6389 case POSIX_LOCK_TYPE_WRITE:
6390 /* Return the right POSIX-mappable error code for files opened read-only. */
6391 if (!fsp->can_write) {
6392 return NT_STATUS_INVALID_HANDLE;
6394 lock_type = WRITE_LOCK;
6396 case POSIX_LOCK_TYPE_UNLOCK:
6397 lock_type = UNLOCK_LOCK;
6400 return NT_STATUS_INVALID_PARAMETER;
6403 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6404 blocking_lock = False;
6405 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6406 blocking_lock = True;
6408 return NT_STATUS_INVALID_PARAMETER;
6411 if (!lp_blocking_locks(SNUM(conn))) {
6412 blocking_lock = False;
6415 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6416 #if defined(HAVE_LONGLONG)
6417 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6418 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6419 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6420 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6421 #else /* HAVE_LONGLONG */
6422 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6423 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6424 #endif /* HAVE_LONGLONG */
6426 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6427 "smblctx = %llu, count = %.0f, offset = %.0f\n",
6429 (unsigned int)lock_type,
6430 (unsigned long long)smblctx,
6434 if (lock_type == UNLOCK_LOCK) {
6435 status = do_unlock(req->sconn->msg_ctx,
6442 uint64_t block_smblctx;
6444 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
6456 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6458 * A blocking lock was requested. Package up
6459 * this smb into a queued request and push it
6460 * onto the blocking lock queue.
6462 if(push_blocking_lock_request(br_lck,
6465 -1, /* infinite timeout. */
6473 TALLOC_FREE(br_lck);
6477 TALLOC_FREE(br_lck);
6483 /****************************************************************************
6484 Deal with SMB_SET_FILE_BASIC_INFO.
6485 ****************************************************************************/
6487 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6491 const struct smb_filename *smb_fname)
6493 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6494 struct smb_file_time ft;
6496 NTSTATUS status = NT_STATUS_OK;
6500 if (total_data < 36) {
6501 return NT_STATUS_INVALID_PARAMETER;
6504 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6505 return NT_STATUS_ACCESS_DENIED;
6508 /* Set the attributes */
6509 dosmode = IVAL(pdata,32);
6510 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6511 if (!NT_STATUS_IS_OK(status)) {
6516 ft.create_time = interpret_long_date(pdata);
6519 ft.atime = interpret_long_date(pdata+8);
6522 ft.mtime = interpret_long_date(pdata+16);
6525 ft.ctime = interpret_long_date(pdata+24);
6527 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6528 smb_fname_str_dbg(smb_fname)));
6530 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6534 /****************************************************************************
6535 Deal with SMB_INFO_STANDARD.
6536 ****************************************************************************/
6538 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6542 const struct smb_filename *smb_fname)
6544 struct smb_file_time ft;
6548 if (total_data < 12) {
6549 return NT_STATUS_INVALID_PARAMETER;
6552 if (fsp && !(fsp->access_mask & FILE_WRITE_ATTRIBUTES)) {
6553 return NT_STATUS_ACCESS_DENIED;
6557 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6559 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6561 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6563 DEBUG(10,("smb_set_info_standard: file %s\n",
6564 smb_fname_str_dbg(smb_fname)));
6566 return smb_set_file_time(conn,
6573 /****************************************************************************
6574 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6575 ****************************************************************************/
6577 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6578 struct smb_request *req,
6582 struct smb_filename *smb_fname)
6584 uint64_t allocation_size = 0;
6585 NTSTATUS status = NT_STATUS_OK;
6586 files_struct *new_fsp = NULL;
6588 if (!VALID_STAT(smb_fname->st)) {
6589 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6592 if (total_data < 8) {
6593 return NT_STATUS_INVALID_PARAMETER;
6596 allocation_size = (uint64_t)IVAL(pdata,0);
6597 #ifdef LARGE_SMB_OFF_T
6598 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6599 #else /* LARGE_SMB_OFF_T */
6600 if (IVAL(pdata,4) != 0) {
6601 /* more than 32 bits? */
6602 return NT_STATUS_INVALID_PARAMETER;
6604 #endif /* LARGE_SMB_OFF_T */
6606 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6607 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6608 (double)allocation_size));
6610 if (allocation_size) {
6611 allocation_size = smb_roundup(conn, allocation_size);
6614 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6615 return NT_STATUS_ACCESS_DENIED;
6618 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6619 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6620 (double)allocation_size));
6622 if (fsp && fsp->fh->fd != -1) {
6623 /* Open file handle. */
6624 /* Only change if needed. */
6625 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6626 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6627 return map_nt_error_from_unix(errno);
6630 /* But always update the time. */
6632 * This is equivalent to a write. Ensure it's seen immediately
6633 * if there are no pending writes.
6635 trigger_write_time_update_immediate(fsp);
6636 return NT_STATUS_OK;
6639 /* Pathname or stat or directory file. */
6640 status = SMB_VFS_CREATE_FILE(
6643 0, /* root_dir_fid */
6644 smb_fname, /* fname */
6645 FILE_WRITE_DATA, /* access_mask */
6646 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6648 FILE_OPEN, /* create_disposition*/
6649 0, /* create_options */
6650 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6651 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6652 0, /* allocation_size */
6653 0, /* private_flags */
6656 &new_fsp, /* result */
6659 if (!NT_STATUS_IS_OK(status)) {
6660 /* NB. We check for open_was_deferred in the caller. */
6664 /* Only change if needed. */
6665 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6666 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6667 status = map_nt_error_from_unix(errno);
6668 close_file(req, new_fsp, NORMAL_CLOSE);
6673 /* Changing the allocation size should set the last mod time. */
6675 * This is equivalent to a write. Ensure it's seen immediately
6676 * if there are no pending writes.
6678 trigger_write_time_update_immediate(new_fsp);
6680 close_file(req, new_fsp, NORMAL_CLOSE);
6681 return NT_STATUS_OK;
6684 /****************************************************************************
6685 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6686 ****************************************************************************/
6688 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6689 struct smb_request *req,
6693 const struct smb_filename *smb_fname,
6694 bool fail_after_createfile)
6698 if (total_data < 8) {
6699 return NT_STATUS_INVALID_PARAMETER;
6702 size = IVAL(pdata,0);
6703 #ifdef LARGE_SMB_OFF_T
6704 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6705 #else /* LARGE_SMB_OFF_T */
6706 if (IVAL(pdata,4) != 0) {
6707 /* more than 32 bits? */
6708 return NT_STATUS_INVALID_PARAMETER;
6710 #endif /* LARGE_SMB_OFF_T */
6711 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6712 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6715 if (fsp && !(fsp->access_mask & FILE_WRITE_DATA)) {
6716 return NT_STATUS_ACCESS_DENIED;
6719 return smb_set_file_size(conn, req,
6724 fail_after_createfile);
6727 /****************************************************************************
6728 Allow a UNIX info mknod.
6729 ****************************************************************************/
6731 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6734 const struct smb_filename *smb_fname)
6736 uint32 file_type = IVAL(pdata,56);
6737 #if defined(HAVE_MAKEDEV)
6738 uint32 dev_major = IVAL(pdata,60);
6739 uint32 dev_minor = IVAL(pdata,68);
6741 SMB_DEV_T dev = (SMB_DEV_T)0;
6742 uint32 raw_unixmode = IVAL(pdata,84);
6746 if (total_data < 100) {
6747 return NT_STATUS_INVALID_PARAMETER;
6750 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6751 PERM_NEW_FILE, &unixmode);
6752 if (!NT_STATUS_IS_OK(status)) {
6756 #if defined(HAVE_MAKEDEV)
6757 dev = makedev(dev_major, dev_minor);
6760 switch (file_type) {
6761 #if defined(S_IFIFO)
6762 case UNIX_TYPE_FIFO:
6763 unixmode |= S_IFIFO;
6766 #if defined(S_IFSOCK)
6767 case UNIX_TYPE_SOCKET:
6768 unixmode |= S_IFSOCK;
6771 #if defined(S_IFCHR)
6772 case UNIX_TYPE_CHARDEV:
6773 unixmode |= S_IFCHR;
6776 #if defined(S_IFBLK)
6777 case UNIX_TYPE_BLKDEV:
6778 unixmode |= S_IFBLK;
6782 return NT_STATUS_INVALID_PARAMETER;
6785 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6786 "%.0f mode 0%o for file %s\n", (double)dev,
6787 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6789 /* Ok - do the mknod. */
6790 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6791 return map_nt_error_from_unix(errno);
6794 /* If any of the other "set" calls fail we
6795 * don't want to end up with a half-constructed mknod.
6798 if (lp_inherit_perms(SNUM(conn))) {
6800 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6802 return NT_STATUS_NO_MEMORY;
6804 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6806 TALLOC_FREE(parent);
6809 return NT_STATUS_OK;
6812 /****************************************************************************
6813 Deal with SMB_SET_FILE_UNIX_BASIC.
6814 ****************************************************************************/
6816 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6817 struct smb_request *req,
6821 const struct smb_filename *smb_fname)
6823 struct smb_file_time ft;
6824 uint32 raw_unixmode;
6827 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6828 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6829 NTSTATUS status = NT_STATUS_OK;
6830 bool delete_on_fail = False;
6831 enum perm_type ptype;
6832 files_struct *all_fsps = NULL;
6833 bool modify_mtime = true;
6835 struct smb_filename *smb_fname_tmp = NULL;
6836 SMB_STRUCT_STAT sbuf;
6840 if (total_data < 100) {
6841 return NT_STATUS_INVALID_PARAMETER;
6844 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6845 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6846 size=IVAL(pdata,0); /* first 8 Bytes are size */
6847 #ifdef LARGE_SMB_OFF_T
6848 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6849 #else /* LARGE_SMB_OFF_T */
6850 if (IVAL(pdata,4) != 0) {
6851 /* more than 32 bits? */
6852 return NT_STATUS_INVALID_PARAMETER;
6854 #endif /* LARGE_SMB_OFF_T */
6857 ft.atime = interpret_long_date(pdata+24); /* access_time */
6858 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6859 set_owner = (uid_t)IVAL(pdata,40);
6860 set_grp = (gid_t)IVAL(pdata,48);
6861 raw_unixmode = IVAL(pdata,84);
6863 if (VALID_STAT(smb_fname->st)) {
6864 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6865 ptype = PERM_EXISTING_DIR;
6867 ptype = PERM_EXISTING_FILE;
6870 ptype = PERM_NEW_FILE;
6873 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6875 if (!NT_STATUS_IS_OK(status)) {
6879 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6880 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6881 smb_fname_str_dbg(smb_fname), (double)size,
6882 (unsigned int)set_owner, (unsigned int)set_grp,
6883 (int)raw_unixmode));
6885 sbuf = smb_fname->st;
6887 if (!VALID_STAT(sbuf)) {
6889 * The only valid use of this is to create character and block
6890 * devices, and named pipes. This is deprecated (IMHO) and
6891 * a new info level should be used for mknod. JRA.
6894 status = smb_unix_mknod(conn,
6898 if (!NT_STATUS_IS_OK(status)) {
6902 status = copy_smb_filename(talloc_tos(), smb_fname,
6904 if (!NT_STATUS_IS_OK(status)) {
6908 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6909 status = map_nt_error_from_unix(errno);
6910 TALLOC_FREE(smb_fname_tmp);
6911 SMB_VFS_UNLINK(conn, smb_fname);
6915 sbuf = smb_fname_tmp->st;
6916 smb_fname = smb_fname_tmp;
6918 /* Ensure we don't try and change anything else. */
6919 raw_unixmode = SMB_MODE_NO_CHANGE;
6920 size = get_file_size_stat(&sbuf);
6921 ft.atime = sbuf.st_ex_atime;
6922 ft.mtime = sbuf.st_ex_mtime;
6924 * We continue here as we might want to change the
6927 delete_on_fail = True;
6931 /* Horrible backwards compatibility hack as an old server bug
6932 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6936 size = get_file_size_stat(&sbuf);
6941 * Deal with the UNIX specific mode set.
6944 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6945 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6946 "setting mode 0%o for file %s\n",
6947 (unsigned int)unixmode,
6948 smb_fname_str_dbg(smb_fname)));
6949 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6950 return map_nt_error_from_unix(errno);
6955 * Deal with the UNIX specific uid set.
6958 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6959 (sbuf.st_ex_uid != set_owner)) {
6962 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6963 "changing owner %u for path %s\n",
6964 (unsigned int)set_owner,
6965 smb_fname_str_dbg(smb_fname)));
6967 if (S_ISLNK(sbuf.st_ex_mode)) {
6968 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6969 set_owner, (gid_t)-1);
6971 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6972 set_owner, (gid_t)-1);
6976 status = map_nt_error_from_unix(errno);
6977 if (delete_on_fail) {
6978 SMB_VFS_UNLINK(conn, smb_fname);
6985 * Deal with the UNIX specific gid set.
6988 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6989 (sbuf.st_ex_gid != set_grp)) {
6990 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6991 "changing group %u for file %s\n",
6992 (unsigned int)set_owner,
6993 smb_fname_str_dbg(smb_fname)));
6994 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6996 status = map_nt_error_from_unix(errno);
6997 if (delete_on_fail) {
6998 SMB_VFS_UNLINK(conn, smb_fname);
7004 /* Deal with any size changes. */
7006 status = smb_set_file_size(conn, req,
7012 if (!NT_STATUS_IS_OK(status)) {
7016 /* Deal with any time changes. */
7017 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7018 /* No change, don't cancel anything. */
7022 id = vfs_file_id_from_sbuf(conn, &sbuf);
7023 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7024 all_fsps = file_find_di_next(all_fsps)) {
7026 * We're setting the time explicitly for UNIX.
7027 * Cancel any pending changes over all handles.
7029 all_fsps->update_write_time_on_close = false;
7030 TALLOC_FREE(all_fsps->update_write_time_event);
7034 * Override the "setting_write_time"
7035 * parameter here as it almost does what
7036 * we need. Just remember if we modified
7037 * mtime and send the notify ourselves.
7039 if (null_timespec(ft.mtime)) {
7040 modify_mtime = false;
7043 status = smb_set_file_time(conn,
7049 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7050 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7055 /****************************************************************************
7056 Deal with SMB_SET_FILE_UNIX_INFO2.
7057 ****************************************************************************/
7059 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7060 struct smb_request *req,
7064 const struct smb_filename *smb_fname)
7070 if (total_data < 116) {
7071 return NT_STATUS_INVALID_PARAMETER;
7074 /* Start by setting all the fields that are common between UNIX_BASIC
7077 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7079 if (!NT_STATUS_IS_OK(status)) {
7083 smb_fflags = IVAL(pdata, 108);
7084 smb_fmask = IVAL(pdata, 112);
7086 /* NB: We should only attempt to alter the file flags if the client
7087 * sends a non-zero mask.
7089 if (smb_fmask != 0) {
7090 int stat_fflags = 0;
7092 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7093 smb_fmask, &stat_fflags)) {
7094 /* Client asked to alter a flag we don't understand. */
7095 return NT_STATUS_INVALID_PARAMETER;
7098 if (fsp && fsp->fh->fd != -1) {
7099 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7100 return NT_STATUS_NOT_SUPPORTED;
7102 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7103 stat_fflags) != 0) {
7104 return map_nt_error_from_unix(errno);
7109 /* XXX: need to add support for changing the create_time here. You
7110 * can do this for paths on Darwin with setattrlist(2). The right way
7111 * to hook this up is probably by extending the VFS utimes interface.
7114 return NT_STATUS_OK;
7117 /****************************************************************************
7118 Create a directory with POSIX semantics.
7119 ****************************************************************************/
7121 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7122 struct smb_request *req,
7125 struct smb_filename *smb_fname,
7126 int *pdata_return_size)
7128 NTSTATUS status = NT_STATUS_OK;
7129 uint32 raw_unixmode = 0;
7130 uint32 mod_unixmode = 0;
7131 mode_t unixmode = (mode_t)0;
7132 files_struct *fsp = NULL;
7133 uint16 info_level_return = 0;
7135 char *pdata = *ppdata;
7137 if (total_data < 18) {
7138 return NT_STATUS_INVALID_PARAMETER;
7141 raw_unixmode = IVAL(pdata,8);
7142 /* Next 4 bytes are not yet defined. */
7144 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7145 PERM_NEW_DIR, &unixmode);
7146 if (!NT_STATUS_IS_OK(status)) {
7150 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7152 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7153 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7155 status = SMB_VFS_CREATE_FILE(
7158 0, /* root_dir_fid */
7159 smb_fname, /* fname */
7160 FILE_READ_ATTRIBUTES, /* access_mask */
7161 FILE_SHARE_NONE, /* share_access */
7162 FILE_CREATE, /* create_disposition*/
7163 FILE_DIRECTORY_FILE, /* create_options */
7164 mod_unixmode, /* file_attributes */
7165 0, /* oplock_request */
7166 0, /* allocation_size */
7167 0, /* private_flags */
7173 if (NT_STATUS_IS_OK(status)) {
7174 close_file(req, fsp, NORMAL_CLOSE);
7177 info_level_return = SVAL(pdata,16);
7179 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7180 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7181 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7182 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7184 *pdata_return_size = 12;
7187 /* Realloc the data size */
7188 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7189 if (*ppdata == NULL) {
7190 *pdata_return_size = 0;
7191 return NT_STATUS_NO_MEMORY;
7195 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7196 SSVAL(pdata,2,0); /* No fnum. */
7197 SIVAL(pdata,4,info); /* Was directory created. */
7199 switch (info_level_return) {
7200 case SMB_QUERY_FILE_UNIX_BASIC:
7201 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7202 SSVAL(pdata,10,0); /* Padding. */
7203 store_file_unix_basic(conn, pdata + 12, fsp,
7206 case SMB_QUERY_FILE_UNIX_INFO2:
7207 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7208 SSVAL(pdata,10,0); /* Padding. */
7209 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7213 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7214 SSVAL(pdata,10,0); /* Padding. */
7221 /****************************************************************************
7222 Open/Create a file with POSIX semantics.
7223 ****************************************************************************/
7225 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7226 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7228 static NTSTATUS smb_posix_open(connection_struct *conn,
7229 struct smb_request *req,
7232 struct smb_filename *smb_fname,
7233 int *pdata_return_size)
7235 bool extended_oplock_granted = False;
7236 char *pdata = *ppdata;
7238 uint32 wire_open_mode = 0;
7239 uint32 raw_unixmode = 0;
7240 uint32 mod_unixmode = 0;
7241 uint32 create_disp = 0;
7242 uint32 access_mask = 0;
7243 uint32 create_options = FILE_NON_DIRECTORY_FILE;
7244 NTSTATUS status = NT_STATUS_OK;
7245 mode_t unixmode = (mode_t)0;
7246 files_struct *fsp = NULL;
7247 int oplock_request = 0;
7249 uint16 info_level_return = 0;
7251 if (total_data < 18) {
7252 return NT_STATUS_INVALID_PARAMETER;
7255 flags = IVAL(pdata,0);
7256 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7257 if (oplock_request) {
7258 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7261 wire_open_mode = IVAL(pdata,4);
7263 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7264 return smb_posix_mkdir(conn, req,
7271 switch (wire_open_mode & SMB_ACCMODE) {
7273 access_mask = SMB_O_RDONLY_MAPPING;
7276 access_mask = SMB_O_WRONLY_MAPPING;
7279 access_mask = (SMB_O_RDONLY_MAPPING|
7280 SMB_O_WRONLY_MAPPING);
7283 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7284 (unsigned int)wire_open_mode ));
7285 return NT_STATUS_INVALID_PARAMETER;
7288 wire_open_mode &= ~SMB_ACCMODE;
7290 /* First take care of O_CREAT|O_EXCL interactions. */
7291 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
7292 case (SMB_O_CREAT | SMB_O_EXCL):
7293 /* File exists fail. File not exist create. */
7294 create_disp = FILE_CREATE;
7297 /* File exists open. File not exist create. */
7298 create_disp = FILE_OPEN_IF;
7301 /* File exists open. File not exist fail. */
7302 create_disp = FILE_OPEN;
7305 /* O_EXCL on its own without O_CREAT is undefined. */
7307 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7308 (unsigned int)wire_open_mode ));
7309 return NT_STATUS_INVALID_PARAMETER;
7312 /* Next factor in the effects of O_TRUNC. */
7313 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
7315 if (wire_open_mode & SMB_O_TRUNC) {
7316 switch (create_disp) {
7318 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
7319 /* Leave create_disp alone as
7320 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
7322 /* File exists fail. File not exist create. */
7325 /* SMB_O_CREAT | SMB_O_TRUNC */
7326 /* File exists overwrite. File not exist create. */
7327 create_disp = FILE_OVERWRITE_IF;
7331 /* File exists overwrite. File not exist fail. */
7332 create_disp = FILE_OVERWRITE;
7335 /* Cannot get here. */
7336 smb_panic("smb_posix_open: logic error");
7337 return NT_STATUS_INVALID_PARAMETER;
7341 raw_unixmode = IVAL(pdata,8);
7342 /* Next 4 bytes are not yet defined. */
7344 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7345 (VALID_STAT(smb_fname->st) ?
7346 PERM_EXISTING_FILE : PERM_NEW_FILE),
7349 if (!NT_STATUS_IS_OK(status)) {
7353 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7355 if (wire_open_mode & SMB_O_SYNC) {
7356 create_options |= FILE_WRITE_THROUGH;
7358 if (wire_open_mode & SMB_O_APPEND) {
7359 access_mask |= FILE_APPEND_DATA;
7361 if (wire_open_mode & SMB_O_DIRECT) {
7362 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7365 if ((wire_open_mode & SMB_O_DIRECTORY) ||
7366 VALID_STAT_OF_DIR(smb_fname->st)) {
7367 if (access_mask != SMB_O_RDONLY_MAPPING) {
7368 return NT_STATUS_FILE_IS_A_DIRECTORY;
7370 create_options &= ~FILE_NON_DIRECTORY_FILE;
7371 create_options |= FILE_DIRECTORY_FILE;
7374 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7375 smb_fname_str_dbg(smb_fname),
7376 (unsigned int)wire_open_mode,
7377 (unsigned int)unixmode ));
7379 status = SMB_VFS_CREATE_FILE(
7382 0, /* root_dir_fid */
7383 smb_fname, /* fname */
7384 access_mask, /* access_mask */
7385 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7387 create_disp, /* create_disposition*/
7388 create_options, /* create_options */
7389 mod_unixmode, /* file_attributes */
7390 oplock_request, /* oplock_request */
7391 0, /* allocation_size */
7392 0, /* private_flags */
7398 if (!NT_STATUS_IS_OK(status)) {
7402 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7403 extended_oplock_granted = True;
7406 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7407 extended_oplock_granted = True;
7410 info_level_return = SVAL(pdata,16);
7412 /* Allocate the correct return size. */
7414 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7415 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7416 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7417 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7419 *pdata_return_size = 12;
7422 /* Realloc the data size */
7423 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7424 if (*ppdata == NULL) {
7425 close_file(req, fsp, ERROR_CLOSE);
7426 *pdata_return_size = 0;
7427 return NT_STATUS_NO_MEMORY;
7431 if (extended_oplock_granted) {
7432 if (flags & REQUEST_BATCH_OPLOCK) {
7433 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7435 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7437 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7438 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7440 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7443 SSVAL(pdata,2,fsp->fnum);
7444 SIVAL(pdata,4,info); /* Was file created etc. */
7446 switch (info_level_return) {
7447 case SMB_QUERY_FILE_UNIX_BASIC:
7448 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7449 SSVAL(pdata,10,0); /* padding. */
7450 store_file_unix_basic(conn, pdata + 12, fsp,
7453 case SMB_QUERY_FILE_UNIX_INFO2:
7454 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7455 SSVAL(pdata,10,0); /* padding. */
7456 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7460 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7461 SSVAL(pdata,10,0); /* padding. */
7464 return NT_STATUS_OK;
7467 /****************************************************************************
7468 Delete a file with POSIX semantics.
7469 ****************************************************************************/
7471 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7472 struct smb_request *req,
7475 struct smb_filename *smb_fname)
7477 NTSTATUS status = NT_STATUS_OK;
7478 files_struct *fsp = NULL;
7482 int create_options = 0;
7484 struct share_mode_lock *lck = NULL;
7486 if (total_data < 2) {
7487 return NT_STATUS_INVALID_PARAMETER;
7490 flags = SVAL(pdata,0);
7492 if (!VALID_STAT(smb_fname->st)) {
7493 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7496 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7497 !VALID_STAT_OF_DIR(smb_fname->st)) {
7498 return NT_STATUS_NOT_A_DIRECTORY;
7501 DEBUG(10,("smb_posix_unlink: %s %s\n",
7502 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7503 smb_fname_str_dbg(smb_fname)));
7505 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7506 create_options |= FILE_DIRECTORY_FILE;
7509 status = SMB_VFS_CREATE_FILE(
7512 0, /* root_dir_fid */
7513 smb_fname, /* fname */
7514 DELETE_ACCESS, /* access_mask */
7515 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7517 FILE_OPEN, /* create_disposition*/
7518 create_options, /* create_options */
7519 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7520 0, /* oplock_request */
7521 0, /* allocation_size */
7522 0, /* private_flags */
7528 if (!NT_STATUS_IS_OK(status)) {
7533 * Don't lie to client. If we can't really delete due to
7534 * non-POSIX opens return SHARING_VIOLATION.
7537 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7540 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7541 "lock for file %s\n", fsp_str_dbg(fsp)));
7542 close_file(req, fsp, NORMAL_CLOSE);
7543 return NT_STATUS_INVALID_PARAMETER;
7547 * See if others still have the file open. If this is the case, then
7548 * don't delete. If all opens are POSIX delete we can set the delete
7549 * on close disposition.
7551 for (i=0; i<lck->num_share_modes; i++) {
7552 struct share_mode_entry *e = &lck->share_modes[i];
7553 if (is_valid_share_mode_entry(e)) {
7554 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7557 /* Fail with sharing violation. */
7558 close_file(req, fsp, NORMAL_CLOSE);
7560 return NT_STATUS_SHARING_VIOLATION;
7565 * Set the delete on close.
7567 status = smb_set_file_disposition_info(conn,
7573 if (!NT_STATUS_IS_OK(status)) {
7574 close_file(req, fsp, NORMAL_CLOSE);
7579 return close_file(req, fsp, NORMAL_CLOSE);
7582 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7583 struct smb_request *req,
7584 TALLOC_CTX *mem_ctx,
7585 uint16_t info_level,
7587 struct smb_filename *smb_fname,
7588 char **ppdata, int total_data,
7591 char *pdata = *ppdata;
7592 NTSTATUS status = NT_STATUS_OK;
7593 int data_return_size = 0;
7597 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7598 return NT_STATUS_INVALID_LEVEL;
7601 if (!CAN_WRITE(conn)) {
7602 /* Allow POSIX opens. The open path will deny
7603 * any non-readonly opens. */
7604 if (info_level != SMB_POSIX_PATH_OPEN) {
7605 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7609 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7610 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7611 fsp ? fsp->fnum : -1, info_level, total_data));
7613 switch (info_level) {
7615 case SMB_INFO_STANDARD:
7617 status = smb_set_info_standard(conn,
7625 case SMB_INFO_SET_EA:
7627 status = smb_info_set_ea(conn,
7635 case SMB_SET_FILE_BASIC_INFO:
7636 case SMB_FILE_BASIC_INFORMATION:
7638 status = smb_set_file_basic_info(conn,
7646 case SMB_FILE_ALLOCATION_INFORMATION:
7647 case SMB_SET_FILE_ALLOCATION_INFO:
7649 status = smb_set_file_allocation_info(conn, req,
7657 case SMB_FILE_END_OF_FILE_INFORMATION:
7658 case SMB_SET_FILE_END_OF_FILE_INFO:
7661 * XP/Win7 both fail after the createfile with
7662 * SMB_SET_FILE_END_OF_FILE_INFO but not
7663 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
7664 * The level is known here, so pass it down
7668 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
7670 status = smb_set_file_end_of_file_info(conn, req,
7679 case SMB_FILE_DISPOSITION_INFORMATION:
7680 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7683 /* JRA - We used to just ignore this on a path ?
7684 * Shouldn't this be invalid level on a pathname
7687 if (tran_call != TRANSACT2_SETFILEINFO) {
7688 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7691 status = smb_set_file_disposition_info(conn,
7699 case SMB_FILE_POSITION_INFORMATION:
7701 status = smb_file_position_information(conn,
7708 case SMB_FILE_FULL_EA_INFORMATION:
7710 status = smb_set_file_full_ea_info(conn,
7717 /* From tridge Samba4 :
7718 * MODE_INFORMATION in setfileinfo (I have no
7719 * idea what "mode information" on a file is - it takes a value of 0,
7720 * 2, 4 or 6. What could it be?).
7723 case SMB_FILE_MODE_INFORMATION:
7725 status = smb_file_mode_information(conn,
7732 * CIFS UNIX extensions.
7735 case SMB_SET_FILE_UNIX_BASIC:
7737 status = smb_set_file_unix_basic(conn, req,
7745 case SMB_SET_FILE_UNIX_INFO2:
7747 status = smb_set_file_unix_info2(conn, req,
7755 case SMB_SET_FILE_UNIX_LINK:
7758 /* We must have a pathname for this. */
7759 return NT_STATUS_INVALID_LEVEL;
7761 status = smb_set_file_unix_link(conn, req, pdata,
7762 total_data, smb_fname);
7766 case SMB_SET_FILE_UNIX_HLINK:
7769 /* We must have a pathname for this. */
7770 return NT_STATUS_INVALID_LEVEL;
7772 status = smb_set_file_unix_hlink(conn, req,
7778 case SMB_FILE_RENAME_INFORMATION:
7780 status = smb_file_rename_information(conn, req,
7786 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
7788 /* SMB2 rename information. */
7789 status = smb2_file_rename_information(conn, req,
7795 case SMB_FILE_LINK_INFORMATION:
7797 status = smb_file_link_information(conn, req,
7803 #if defined(HAVE_POSIX_ACLS)
7804 case SMB_SET_POSIX_ACL:
7806 status = smb_set_posix_acl(conn,
7815 case SMB_SET_POSIX_LOCK:
7818 return NT_STATUS_INVALID_LEVEL;
7820 status = smb_set_posix_lock(conn, req,
7821 pdata, total_data, fsp);
7825 case SMB_POSIX_PATH_OPEN:
7828 /* We must have a pathname for this. */
7829 return NT_STATUS_INVALID_LEVEL;
7832 status = smb_posix_open(conn, req,
7840 case SMB_POSIX_PATH_UNLINK:
7843 /* We must have a pathname for this. */
7844 return NT_STATUS_INVALID_LEVEL;
7847 status = smb_posix_unlink(conn, req,
7855 return NT_STATUS_INVALID_LEVEL;
7858 if (!NT_STATUS_IS_OK(status)) {
7862 *ret_data_size = data_return_size;
7863 return NT_STATUS_OK;
7866 /****************************************************************************
7867 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7868 ****************************************************************************/
7870 static void call_trans2setfilepathinfo(connection_struct *conn,
7871 struct smb_request *req,
7872 unsigned int tran_call,
7873 char **pparams, int total_params,
7874 char **ppdata, int total_data,
7875 unsigned int max_data_bytes)
7877 char *params = *pparams;
7878 char *pdata = *ppdata;
7880 struct smb_filename *smb_fname = NULL;
7881 files_struct *fsp = NULL;
7882 NTSTATUS status = NT_STATUS_OK;
7883 int data_return_size = 0;
7886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7890 if (tran_call == TRANSACT2_SETFILEINFO) {
7891 if (total_params < 4) {
7892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7896 fsp = file_fsp(req, SVAL(params,0));
7897 /* Basic check for non-null fsp. */
7898 if (!check_fsp_open(conn, req, fsp)) {
7901 info_level = SVAL(params,2);
7903 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7905 if (!NT_STATUS_IS_OK(status)) {
7906 reply_nterror(req, status);
7910 if(fsp->fh->fd == -1) {
7912 * This is actually a SETFILEINFO on a directory
7913 * handle (returned from an NT SMB). NT5.0 seems
7914 * to do this call. JRA.
7916 if (INFO_LEVEL_IS_UNIX(info_level)) {
7917 /* Always do lstat for UNIX calls. */
7918 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7919 DEBUG(3,("call_trans2setfilepathinfo: "
7920 "SMB_VFS_LSTAT of %s failed "
7922 smb_fname_str_dbg(smb_fname),
7924 reply_nterror(req, map_nt_error_from_unix(errno));
7928 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7929 DEBUG(3,("call_trans2setfilepathinfo: "
7930 "fileinfo of %s failed (%s)\n",
7931 smb_fname_str_dbg(smb_fname),
7933 reply_nterror(req, map_nt_error_from_unix(errno));
7937 } else if (fsp->print_file) {
7939 * Doing a DELETE_ON_CLOSE should cancel a print job.
7941 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7942 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
7944 DEBUG(3,("call_trans2setfilepathinfo: "
7945 "Cancelling print job (%s)\n",
7949 send_trans2_replies(conn, req, params, 2,
7955 NT_STATUS_OBJECT_PATH_NOT_FOUND);
7960 * Original code - this is an open file.
7962 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7963 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7964 "of fnum %d failed (%s)\n", fsp->fnum,
7966 reply_nterror(req, map_nt_error_from_unix(errno));
7974 if (total_params < 7) {
7975 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7979 info_level = SVAL(params,0);
7980 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7981 total_params - 6, STR_TERMINATE,
7983 if (!NT_STATUS_IS_OK(status)) {
7984 reply_nterror(req, status);
7988 status = filename_convert(req, conn,
7989 req->flags2 & FLAGS2_DFS_PATHNAMES,
7994 if (!NT_STATUS_IS_OK(status)) {
7995 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7996 reply_botherror(req,
7997 NT_STATUS_PATH_NOT_COVERED,
7998 ERRSRV, ERRbadpath);
8001 reply_nterror(req, status);
8005 if (INFO_LEVEL_IS_UNIX(info_level)) {
8007 * For CIFS UNIX extensions the target name may not exist.
8010 /* Always do lstat for UNIX calls. */
8011 SMB_VFS_LSTAT(conn, smb_fname);
8013 } else if (!VALID_STAT(smb_fname->st) &&
8014 SMB_VFS_STAT(conn, smb_fname)) {
8015 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8017 smb_fname_str_dbg(smb_fname),
8019 reply_nterror(req, map_nt_error_from_unix(errno));
8024 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
8025 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8026 fsp ? fsp->fnum : -1, info_level,total_data));
8028 /* Realloc the parameter size */
8029 *pparams = (char *)SMB_REALLOC(*pparams,2);
8030 if (*pparams == NULL) {
8031 reply_nterror(req, NT_STATUS_NO_MEMORY);
8038 status = smbd_do_setfilepathinfo(conn, req, req,
8044 if (!NT_STATUS_IS_OK(status)) {
8045 if (open_was_deferred(req->sconn, req->mid)) {
8046 /* We have re-scheduled this call. */
8049 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8050 /* We have re-scheduled this call. */
8053 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8054 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8055 ERRSRV, ERRbadpath);
8058 if (info_level == SMB_POSIX_PATH_OPEN) {
8059 reply_openerror(req, status);
8063 reply_nterror(req, status);
8067 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
8073 /****************************************************************************
8074 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8075 ****************************************************************************/
8077 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8078 char **pparams, int total_params,
8079 char **ppdata, int total_data,
8080 unsigned int max_data_bytes)
8082 struct smb_filename *smb_dname = NULL;
8083 char *params = *pparams;
8084 char *pdata = *ppdata;
8085 char *directory = NULL;
8086 NTSTATUS status = NT_STATUS_OK;
8087 struct ea_list *ea_list = NULL;
8088 TALLOC_CTX *ctx = talloc_tos();
8090 if (!CAN_WRITE(conn)) {
8091 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8095 if (total_params < 5) {
8096 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8100 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
8101 total_params - 4, STR_TERMINATE,
8103 if (!NT_STATUS_IS_OK(status)) {
8104 reply_nterror(req, status);
8108 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8110 status = filename_convert(ctx,
8112 req->flags2 & FLAGS2_DFS_PATHNAMES,
8118 if (!NT_STATUS_IS_OK(status)) {
8119 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8120 reply_botherror(req,
8121 NT_STATUS_PATH_NOT_COVERED,
8122 ERRSRV, ERRbadpath);
8125 reply_nterror(req, status);
8130 * OS/2 workplace shell seems to send SET_EA requests of "null"
8131 * length (4 bytes containing IVAL 4).
8132 * They seem to have no effect. Bug #3212. JRA.
8135 if (total_data && (total_data != 4)) {
8136 /* Any data in this call is an EA list. */
8137 if (total_data < 10) {
8138 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8142 if (IVAL(pdata,0) > total_data) {
8143 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8144 IVAL(pdata,0), (unsigned int)total_data));
8145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8149 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8156 if (!lp_ea_support(SNUM(conn))) {
8157 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8161 /* If total_data == 4 Windows doesn't care what values
8162 * are placed in that field, it just ignores them.
8163 * The System i QNTC IBM SMB client puts bad values here,
8164 * so ignore them. */
8166 status = create_directory(conn, req, smb_dname);
8168 if (!NT_STATUS_IS_OK(status)) {
8169 reply_nterror(req, status);
8173 /* Try and set any given EA. */
8175 status = set_ea(conn, NULL, smb_dname, ea_list);
8176 if (!NT_STATUS_IS_OK(status)) {
8177 reply_nterror(req, status);
8182 /* Realloc the parameter and data sizes */
8183 *pparams = (char *)SMB_REALLOC(*pparams,2);
8184 if(*pparams == NULL) {
8185 reply_nterror(req, NT_STATUS_NO_MEMORY);
8192 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
8195 TALLOC_FREE(smb_dname);
8199 /****************************************************************************
8200 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
8201 We don't actually do this - we just send a null response.
8202 ****************************************************************************/
8204 static void call_trans2findnotifyfirst(connection_struct *conn,
8205 struct smb_request *req,
8206 char **pparams, int total_params,
8207 char **ppdata, int total_data,
8208 unsigned int max_data_bytes)
8210 char *params = *pparams;
8213 if (total_params < 6) {
8214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8218 info_level = SVAL(params,4);
8219 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
8221 switch (info_level) {
8226 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
8230 /* Realloc the parameter and data sizes */
8231 *pparams = (char *)SMB_REALLOC(*pparams,6);
8232 if (*pparams == NULL) {
8233 reply_nterror(req, NT_STATUS_NO_MEMORY);
8238 SSVAL(params,0,fnf_handle);
8239 SSVAL(params,2,0); /* No changes */
8240 SSVAL(params,4,0); /* No EA errors */
8247 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
8252 /****************************************************************************
8253 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
8254 changes). Currently this does nothing.
8255 ****************************************************************************/
8257 static void call_trans2findnotifynext(connection_struct *conn,
8258 struct smb_request *req,
8259 char **pparams, int total_params,
8260 char **ppdata, int total_data,
8261 unsigned int max_data_bytes)
8263 char *params = *pparams;
8265 DEBUG(3,("call_trans2findnotifynext\n"));
8267 /* Realloc the parameter and data sizes */
8268 *pparams = (char *)SMB_REALLOC(*pparams,4);
8269 if (*pparams == NULL) {
8270 reply_nterror(req, NT_STATUS_NO_MEMORY);
8275 SSVAL(params,0,0); /* No changes */
8276 SSVAL(params,2,0); /* No EA errors */
8278 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8283 /****************************************************************************
8284 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8285 ****************************************************************************/
8287 static void call_trans2getdfsreferral(connection_struct *conn,
8288 struct smb_request *req,
8289 char **pparams, int total_params,
8290 char **ppdata, int total_data,
8291 unsigned int max_data_bytes)
8293 char *params = *pparams;
8294 char *pathname = NULL;
8296 int max_referral_level;
8297 NTSTATUS status = NT_STATUS_OK;
8298 TALLOC_CTX *ctx = talloc_tos();
8300 DEBUG(10,("call_trans2getdfsreferral\n"));
8302 if (total_params < 3) {
8303 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8307 max_referral_level = SVAL(params,0);
8309 if(!lp_host_msdfs()) {
8310 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8314 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8315 total_params - 2, STR_TERMINATE);
8317 reply_nterror(req, NT_STATUS_NOT_FOUND);
8320 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8321 ppdata,&status)) < 0) {
8322 reply_nterror(req, status);
8326 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
8327 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8328 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8333 #define LMCAT_SPL 0x53
8334 #define LMFUNC_GETJOBID 0x60
8336 /****************************************************************************
8337 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8338 ****************************************************************************/
8340 static void call_trans2ioctl(connection_struct *conn,
8341 struct smb_request *req,
8342 char **pparams, int total_params,
8343 char **ppdata, int total_data,
8344 unsigned int max_data_bytes)
8346 char *pdata = *ppdata;
8347 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8349 /* check for an invalid fid before proceeding */
8352 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
8356 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8357 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8358 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8359 if (*ppdata == NULL) {
8360 reply_nterror(req, NT_STATUS_NO_MEMORY);
8365 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8366 CAN ACCEPT THIS IN UNICODE. JRA. */
8369 if (fsp->print_file) {
8370 SSVAL(pdata, 0, fsp->print_file->rap_jobid);
8374 srvstr_push(pdata, req->flags2, pdata + 2,
8375 lp_netbios_name(), 15,
8376 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8377 srvstr_push(pdata, req->flags2, pdata+18,
8378 lp_servicename(SNUM(conn)), 13,
8379 STR_ASCII|STR_TERMINATE); /* Service name */
8380 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8385 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8386 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8389 /****************************************************************************
8390 Reply to a SMBfindclose (stop trans2 directory search).
8391 ****************************************************************************/
8393 void reply_findclose(struct smb_request *req)
8396 struct smbd_server_connection *sconn = req->sconn;
8398 START_PROFILE(SMBfindclose);
8401 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8402 END_PROFILE(SMBfindclose);
8406 dptr_num = SVALS(req->vwv+0, 0);
8408 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8410 dptr_close(sconn, &dptr_num);
8412 reply_outbuf(req, 0, 0);
8414 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8416 END_PROFILE(SMBfindclose);
8420 /****************************************************************************
8421 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8422 ****************************************************************************/
8424 void reply_findnclose(struct smb_request *req)
8428 START_PROFILE(SMBfindnclose);
8431 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8432 END_PROFILE(SMBfindnclose);
8436 dptr_num = SVAL(req->vwv+0, 0);
8438 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8440 /* We never give out valid handles for a
8441 findnotifyfirst - so any dptr_num is ok here.
8444 reply_outbuf(req, 0, 0);
8446 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8448 END_PROFILE(SMBfindnclose);
8452 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8453 struct trans_state *state)
8455 if (get_Protocol() >= PROTOCOL_NT1) {
8456 req->flags2 |= 0x40; /* IS_LONG_NAME */
8457 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
8460 if (conn->encrypt_level == Required && !req->encrypted) {
8461 if (state->call != TRANSACT2_QFSINFO &&
8462 state->call != TRANSACT2_SETFSINFO) {
8463 DEBUG(0,("handle_trans2: encryption required "
8465 (unsigned int)state->call));
8466 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8471 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8473 /* Now we must call the relevant TRANS2 function */
8474 switch(state->call) {
8475 case TRANSACT2_OPEN:
8477 START_PROFILE(Trans2_open);
8478 call_trans2open(conn, req,
8479 &state->param, state->total_param,
8480 &state->data, state->total_data,
8481 state->max_data_return);
8482 END_PROFILE(Trans2_open);
8486 case TRANSACT2_FINDFIRST:
8488 START_PROFILE(Trans2_findfirst);
8489 call_trans2findfirst(conn, req,
8490 &state->param, state->total_param,
8491 &state->data, state->total_data,
8492 state->max_data_return);
8493 END_PROFILE(Trans2_findfirst);
8497 case TRANSACT2_FINDNEXT:
8499 START_PROFILE(Trans2_findnext);
8500 call_trans2findnext(conn, req,
8501 &state->param, state->total_param,
8502 &state->data, state->total_data,
8503 state->max_data_return);
8504 END_PROFILE(Trans2_findnext);
8508 case TRANSACT2_QFSINFO:
8510 START_PROFILE(Trans2_qfsinfo);
8511 call_trans2qfsinfo(conn, req,
8512 &state->param, state->total_param,
8513 &state->data, state->total_data,
8514 state->max_data_return);
8515 END_PROFILE(Trans2_qfsinfo);
8519 case TRANSACT2_SETFSINFO:
8521 START_PROFILE(Trans2_setfsinfo);
8522 call_trans2setfsinfo(conn, req,
8523 &state->param, state->total_param,
8524 &state->data, state->total_data,
8525 state->max_data_return);
8526 END_PROFILE(Trans2_setfsinfo);
8530 case TRANSACT2_QPATHINFO:
8531 case TRANSACT2_QFILEINFO:
8533 START_PROFILE(Trans2_qpathinfo);
8534 call_trans2qfilepathinfo(conn, req, state->call,
8535 &state->param, state->total_param,
8536 &state->data, state->total_data,
8537 state->max_data_return);
8538 END_PROFILE(Trans2_qpathinfo);
8542 case TRANSACT2_SETPATHINFO:
8543 case TRANSACT2_SETFILEINFO:
8545 START_PROFILE(Trans2_setpathinfo);
8546 call_trans2setfilepathinfo(conn, req, state->call,
8547 &state->param, state->total_param,
8548 &state->data, state->total_data,
8549 state->max_data_return);
8550 END_PROFILE(Trans2_setpathinfo);
8554 case TRANSACT2_FINDNOTIFYFIRST:
8556 START_PROFILE(Trans2_findnotifyfirst);
8557 call_trans2findnotifyfirst(conn, req,
8558 &state->param, state->total_param,
8559 &state->data, state->total_data,
8560 state->max_data_return);
8561 END_PROFILE(Trans2_findnotifyfirst);
8565 case TRANSACT2_FINDNOTIFYNEXT:
8567 START_PROFILE(Trans2_findnotifynext);
8568 call_trans2findnotifynext(conn, req,
8569 &state->param, state->total_param,
8570 &state->data, state->total_data,
8571 state->max_data_return);
8572 END_PROFILE(Trans2_findnotifynext);
8576 case TRANSACT2_MKDIR:
8578 START_PROFILE(Trans2_mkdir);
8579 call_trans2mkdir(conn, req,
8580 &state->param, state->total_param,
8581 &state->data, state->total_data,
8582 state->max_data_return);
8583 END_PROFILE(Trans2_mkdir);
8587 case TRANSACT2_GET_DFS_REFERRAL:
8589 START_PROFILE(Trans2_get_dfs_referral);
8590 call_trans2getdfsreferral(conn, req,
8591 &state->param, state->total_param,
8592 &state->data, state->total_data,
8593 state->max_data_return);
8594 END_PROFILE(Trans2_get_dfs_referral);
8598 case TRANSACT2_IOCTL:
8600 START_PROFILE(Trans2_ioctl);
8601 call_trans2ioctl(conn, req,
8602 &state->param, state->total_param,
8603 &state->data, state->total_data,
8604 state->max_data_return);
8605 END_PROFILE(Trans2_ioctl);
8610 /* Error in request */
8611 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8612 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
8616 /****************************************************************************
8617 Reply to a SMBtrans2.
8618 ****************************************************************************/
8620 void reply_trans2(struct smb_request *req)
8622 connection_struct *conn = req->conn;
8627 unsigned int tran_call;
8628 struct trans_state *state;
8631 START_PROFILE(SMBtrans2);
8633 if (req->wct < 14) {
8634 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8635 END_PROFILE(SMBtrans2);
8639 dsoff = SVAL(req->vwv+12, 0);
8640 dscnt = SVAL(req->vwv+11, 0);
8641 psoff = SVAL(req->vwv+10, 0);
8642 pscnt = SVAL(req->vwv+9, 0);
8643 tran_call = SVAL(req->vwv+14, 0);
8645 result = allow_new_trans(conn->pending_trans, req->mid);
8646 if (!NT_STATUS_IS_OK(result)) {
8647 DEBUG(2, ("Got invalid trans2 request: %s\n",
8648 nt_errstr(result)));
8649 reply_nterror(req, result);
8650 END_PROFILE(SMBtrans2);
8655 switch (tran_call) {
8656 /* List the allowed trans2 calls on IPC$ */
8657 case TRANSACT2_OPEN:
8658 case TRANSACT2_GET_DFS_REFERRAL:
8659 case TRANSACT2_QFILEINFO:
8660 case TRANSACT2_QFSINFO:
8661 case TRANSACT2_SETFSINFO:
8664 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8665 END_PROFILE(SMBtrans2);
8670 if ((state = talloc(conn, struct trans_state)) == NULL) {
8671 DEBUG(0, ("talloc failed\n"));
8672 reply_nterror(req, NT_STATUS_NO_MEMORY);
8673 END_PROFILE(SMBtrans2);
8677 state->cmd = SMBtrans2;
8679 state->mid = req->mid;
8680 state->vuid = req->vuid;
8681 state->setup_count = SVAL(req->vwv+13, 0);
8682 state->setup = NULL;
8683 state->total_param = SVAL(req->vwv+0, 0);
8684 state->param = NULL;
8685 state->total_data = SVAL(req->vwv+1, 0);
8687 state->max_param_return = SVAL(req->vwv+2, 0);
8688 state->max_data_return = SVAL(req->vwv+3, 0);
8689 state->max_setup_return = SVAL(req->vwv+4, 0);
8690 state->close_on_completion = BITSETW(req->vwv+5, 0);
8691 state->one_way = BITSETW(req->vwv+5, 1);
8693 state->call = tran_call;
8695 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8696 is so as a sanity check */
8697 if (state->setup_count != 1) {
8699 * Need to have rc=0 for ioctl to get job id for OS/2.
8700 * Network printing will fail if function is not successful.
8701 * Similar function in reply.c will be used if protocol
8702 * is LANMAN1.0 instead of LM1.2X002.
8703 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8704 * outbuf doesn't have to be set(only job id is used).
8706 if ( (state->setup_count == 4)
8707 && (tran_call == TRANSACT2_IOCTL)
8708 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8709 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8710 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8712 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8713 DEBUG(2,("Transaction is %d\n",tran_call));
8715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8716 END_PROFILE(SMBtrans2);
8721 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8724 if (state->total_data) {
8726 if (trans_oob(state->total_data, 0, dscnt)
8727 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8731 /* Can't use talloc here, the core routines do realloc on the
8732 * params and data. */
8733 state->data = (char *)SMB_MALLOC(state->total_data);
8734 if (state->data == NULL) {
8735 DEBUG(0,("reply_trans2: data malloc fail for %u "
8736 "bytes !\n", (unsigned int)state->total_data));
8738 reply_nterror(req, NT_STATUS_NO_MEMORY);
8739 END_PROFILE(SMBtrans2);
8743 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8746 if (state->total_param) {
8748 if (trans_oob(state->total_param, 0, pscnt)
8749 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8753 /* Can't use talloc here, the core routines do realloc on the
8754 * params and data. */
8755 state->param = (char *)SMB_MALLOC(state->total_param);
8756 if (state->param == NULL) {
8757 DEBUG(0,("reply_trans: param malloc fail for %u "
8758 "bytes !\n", (unsigned int)state->total_param));
8759 SAFE_FREE(state->data);
8761 reply_nterror(req, NT_STATUS_NO_MEMORY);
8762 END_PROFILE(SMBtrans2);
8766 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8769 state->received_data = dscnt;
8770 state->received_param = pscnt;
8772 if ((state->received_param == state->total_param) &&
8773 (state->received_data == state->total_data)) {
8775 handle_trans2(conn, req, state);
8777 SAFE_FREE(state->data);
8778 SAFE_FREE(state->param);
8780 END_PROFILE(SMBtrans2);
8784 DLIST_ADD(conn->pending_trans, state);
8786 /* We need to send an interim response then receive the rest
8787 of the parameter/data bytes */
8788 reply_outbuf(req, 0, 0);
8789 show_msg((char *)req->outbuf);
8790 END_PROFILE(SMBtrans2);
8795 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8796 SAFE_FREE(state->data);
8797 SAFE_FREE(state->param);
8799 END_PROFILE(SMBtrans2);
8800 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8804 /****************************************************************************
8805 Reply to a SMBtranss2
8806 ****************************************************************************/
8808 void reply_transs2(struct smb_request *req)
8810 connection_struct *conn = req->conn;
8811 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8812 struct trans_state *state;
8814 START_PROFILE(SMBtranss2);
8816 show_msg((const char *)req->inbuf);
8819 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8820 END_PROFILE(SMBtranss2);
8824 for (state = conn->pending_trans; state != NULL;
8825 state = state->next) {
8826 if (state->mid == req->mid) {
8831 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8832 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8833 END_PROFILE(SMBtranss2);
8837 /* Revise state->total_param and state->total_data in case they have
8838 changed downwards */
8840 if (SVAL(req->vwv+0, 0) < state->total_param)
8841 state->total_param = SVAL(req->vwv+0, 0);
8842 if (SVAL(req->vwv+1, 0) < state->total_data)
8843 state->total_data = SVAL(req->vwv+1, 0);
8845 pcnt = SVAL(req->vwv+2, 0);
8846 poff = SVAL(req->vwv+3, 0);
8847 pdisp = SVAL(req->vwv+4, 0);
8849 dcnt = SVAL(req->vwv+5, 0);
8850 doff = SVAL(req->vwv+6, 0);
8851 ddisp = SVAL(req->vwv+7, 0);
8853 state->received_param += pcnt;
8854 state->received_data += dcnt;
8856 if ((state->received_data > state->total_data) ||
8857 (state->received_param > state->total_param))
8861 if (trans_oob(state->total_param, pdisp, pcnt)
8862 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8865 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8869 if (trans_oob(state->total_data, ddisp, dcnt)
8870 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8873 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8876 if ((state->received_param < state->total_param) ||
8877 (state->received_data < state->total_data)) {
8878 END_PROFILE(SMBtranss2);
8882 handle_trans2(conn, req, state);
8884 DLIST_REMOVE(conn->pending_trans, state);
8885 SAFE_FREE(state->data);
8886 SAFE_FREE(state->param);
8889 END_PROFILE(SMBtranss2);
8894 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8895 DLIST_REMOVE(conn->pending_trans, state);
8896 SAFE_FREE(state->data);
8897 SAFE_FREE(state->param);
8899 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8900 END_PROFILE(SMBtranss2);