2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include "smbd/globals.h"
29 #include "../libcli/auth/libcli_auth.h"
31 extern enum protocol_types Protocol;
33 #define DIR_ENTRY_SAFETY_MARGIN 4096
35 static char *store_file_unix_basic(connection_struct *conn,
38 const SMB_STRUCT_STAT *psbuf);
40 static char *store_file_unix_basic_info2(connection_struct *conn,
43 const SMB_STRUCT_STAT *psbuf);
45 /********************************************************************
46 Roundup a value to the nearest allocation roundup size boundary.
47 Only do this for Windows clients.
48 ********************************************************************/
50 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
52 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
54 /* Only roundup for Windows clients. */
55 enum remote_arch_types ra_type = get_remote_arch();
56 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
57 val = SMB_ROUNDUP(val,rval);
62 /****************************************************************************
63 Utility functions for dealing with extended attributes.
64 ****************************************************************************/
66 /****************************************************************************
67 Refuse to allow clients to overwrite our private xattrs.
68 ****************************************************************************/
70 static bool samba_private_attr_name(const char *unix_ea_name)
72 static const char * const prohibited_ea_names[] = {
73 SAMBA_POSIX_INHERITANCE_EA_NAME,
74 SAMBA_XATTR_DOS_ATTRIB,
80 for (i = 0; prohibited_ea_names[i]; i++) {
81 if (strequal( prohibited_ea_names[i], unix_ea_name))
84 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
85 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
91 /****************************************************************************
92 Get one EA value. Fill in a struct ea_struct.
93 ****************************************************************************/
95 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
96 files_struct *fsp, const char *fname,
97 const char *ea_name, struct ea_struct *pea)
99 /* Get the value of this xattr. Max size is 64k. */
100 size_t attr_size = 256;
106 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
108 return NT_STATUS_NO_MEMORY;
111 if (fsp && fsp->fh->fd != -1) {
112 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
114 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
117 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
123 return map_nt_error_from_unix(errno);
126 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
127 dump_data(10, (uint8 *)val, sizeret);
130 if (strnequal(ea_name, "user.", 5)) {
131 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
133 pea->name = talloc_strdup(mem_ctx, ea_name);
135 if (pea->name == NULL) {
137 return NT_STATUS_NO_MEMORY;
139 pea->value.data = (unsigned char *)val;
140 pea->value.length = (size_t)sizeret;
144 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
145 files_struct *fsp, const char *fname,
146 char ***pnames, size_t *pnum_names)
148 /* Get a list of all xattrs. Max namesize is 64k. */
149 size_t ea_namelist_size = 1024;
150 char *ea_namelist = NULL;
155 ssize_t sizeret = -1;
157 if (!lp_ea_support(SNUM(conn))) {
164 * TALLOC the result early to get the talloc hierarchy right.
167 names = TALLOC_ARRAY(mem_ctx, char *, 1);
169 DEBUG(0, ("talloc failed\n"));
170 return NT_STATUS_NO_MEMORY;
173 while (ea_namelist_size <= 65536) {
175 ea_namelist = TALLOC_REALLOC_ARRAY(
176 names, ea_namelist, char, ea_namelist_size);
177 if (ea_namelist == NULL) {
178 DEBUG(0, ("talloc failed\n"));
180 return NT_STATUS_NO_MEMORY;
183 if (fsp && fsp->fh->fd != -1) {
184 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
187 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
191 if ((sizeret == -1) && (errno == ERANGE)) {
192 ea_namelist_size *= 2;
201 return map_nt_error_from_unix(errno);
204 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
205 (unsigned int)sizeret));
215 * Ensure the result is 0-terminated
218 if (ea_namelist[sizeret-1] != '\0') {
220 return NT_STATUS_INTERNAL_ERROR;
228 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
232 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
234 DEBUG(0, ("talloc failed\n"));
236 return NT_STATUS_NO_MEMORY;
242 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
243 names[num_names++] = p;
247 *pnum_names = num_names;
251 /****************************************************************************
252 Return a linked list of the total EA's. Plus the total size
253 ****************************************************************************/
255 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
256 const char *fname, size_t *pea_total_len)
258 /* Get a list of all xattrs. Max namesize is 64k. */
261 struct ea_list *ea_list_head = NULL;
266 if (!lp_ea_support(SNUM(conn))) {
270 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
273 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
277 for (i=0; i<num_names; i++) {
278 struct ea_list *listp;
281 if (strnequal(names[i], "system.", 7)
282 || samba_private_attr_name(names[i]))
285 listp = TALLOC_P(mem_ctx, struct ea_list);
290 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
296 push_ascii_fstring(dos_ea_name, listp->ea.name);
299 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
301 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
302 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
303 (unsigned int)listp->ea.value.length));
305 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
309 /* Add on 4 for total length. */
310 if (*pea_total_len) {
314 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
315 (unsigned int)*pea_total_len));
320 /****************************************************************************
321 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
323 ****************************************************************************/
325 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
326 connection_struct *conn, struct ea_list *ea_list)
328 unsigned int ret_data_size = 4;
331 SMB_ASSERT(total_data_size >= 4);
333 if (!lp_ea_support(SNUM(conn))) {
338 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
341 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
342 dos_namelen = strlen(dos_ea_name);
343 if (dos_namelen > 255 || dos_namelen == 0) {
346 if (ea_list->ea.value.length > 65535) {
349 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
353 /* We know we have room. */
354 SCVAL(p,0,ea_list->ea.flags);
355 SCVAL(p,1,dos_namelen);
356 SSVAL(p,2,ea_list->ea.value.length);
357 fstrcpy(p+4, dos_ea_name);
358 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
360 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
361 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
364 ret_data_size = PTR_DIFF(p, pdata);
365 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
366 SIVAL(pdata,0,ret_data_size);
367 return ret_data_size;
370 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
372 size_t total_ea_len = 0;
373 TALLOC_CTX *mem_ctx = NULL;
375 if (!lp_ea_support(SNUM(conn))) {
378 mem_ctx = talloc_tos();
379 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
383 /****************************************************************************
384 Ensure the EA name is case insensitive by matching any existing EA name.
385 ****************************************************************************/
387 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
390 TALLOC_CTX *mem_ctx = talloc_tos();
391 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
393 for (; ea_list; ea_list = ea_list->next) {
394 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
395 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
396 &unix_ea_name[5], ea_list->ea.name));
397 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
403 /****************************************************************************
404 Set or delete an extended attribute.
405 ****************************************************************************/
407 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp, const char *fname, struct ea_list *ea_list)
409 if (!lp_ea_support(SNUM(conn))) {
410 return NT_STATUS_EAS_NOT_SUPPORTED;
413 for (;ea_list; ea_list = ea_list->next) {
415 fstring unix_ea_name;
417 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
418 fstrcat(unix_ea_name, ea_list->ea.name);
420 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
422 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
424 if (samba_private_attr_name(unix_ea_name)) {
425 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
426 return NT_STATUS_ACCESS_DENIED;
429 if (ea_list->ea.value.length == 0) {
430 /* Remove the attribute. */
431 if (fsp && (fsp->fh->fd != -1)) {
432 DEBUG(10,("set_ea: deleting ea name %s on file %s by file descriptor.\n",
433 unix_ea_name, fsp->fsp_name));
434 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
436 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
437 unix_ea_name, fname));
438 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
441 /* Removing a non existent attribute always succeeds. */
442 if (ret == -1 && errno == ENOATTR) {
443 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
449 if (fsp && (fsp->fh->fd != -1)) {
450 DEBUG(10,("set_ea: setting ea name %s on file %s by file descriptor.\n",
451 unix_ea_name, fsp->fsp_name));
452 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
453 ea_list->ea.value.data, ea_list->ea.value.length, 0);
455 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
456 unix_ea_name, fname));
457 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
458 ea_list->ea.value.data, ea_list->ea.value.length, 0);
464 if (errno == ENOTSUP) {
465 return NT_STATUS_EAS_NOT_SUPPORTED;
468 return map_nt_error_from_unix(errno);
474 /****************************************************************************
475 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
476 ****************************************************************************/
478 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
480 struct ea_list *ea_list_head = NULL;
481 size_t converted_size, offset = 0;
483 while (offset + 2 < data_size) {
484 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
485 unsigned int namelen = CVAL(pdata,offset);
487 offset++; /* Go past the namelen byte. */
489 /* integer wrap paranioa. */
490 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
491 (offset > data_size) || (namelen > data_size) ||
492 (offset + namelen >= data_size)) {
495 /* Ensure the name is null terminated. */
496 if (pdata[offset + namelen] != '\0') {
499 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
501 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
502 "failed: %s", strerror(errno)));
508 offset += (namelen + 1); /* Go past the name + terminating zero. */
509 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
510 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
516 /****************************************************************************
517 Read one EA list entry from the buffer.
518 ****************************************************************************/
520 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
522 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
524 unsigned int namelen;
525 size_t converted_size;
535 eal->ea.flags = CVAL(pdata,0);
536 namelen = CVAL(pdata,1);
537 val_len = SVAL(pdata,2);
539 if (4 + namelen + 1 + val_len > data_size) {
543 /* Ensure the name is null terminated. */
544 if (pdata[namelen + 4] != '\0') {
547 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
548 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
555 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
556 if (!eal->ea.value.data) {
560 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
562 /* Ensure we're null terminated just in case we print the value. */
563 eal->ea.value.data[val_len] = '\0';
564 /* But don't count the null. */
565 eal->ea.value.length--;
568 *pbytes_used = 4 + namelen + 1 + val_len;
571 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
572 dump_data(10, eal->ea.value.data, eal->ea.value.length);
577 /****************************************************************************
578 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
579 ****************************************************************************/
581 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
583 struct ea_list *ea_list_head = NULL;
585 size_t bytes_used = 0;
587 while (offset < data_size) {
588 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
594 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
595 offset += bytes_used;
601 /****************************************************************************
602 Count the total EA size needed.
603 ****************************************************************************/
605 static size_t ea_list_size(struct ea_list *ealist)
608 struct ea_list *listp;
611 for (listp = ealist; listp; listp = listp->next) {
612 push_ascii_fstring(dos_ea_name, listp->ea.name);
613 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
615 /* Add on 4 for total length. */
623 /****************************************************************************
624 Return a union of EA's from a file list and a list of names.
625 The TALLOC context for the two lists *MUST* be identical as we steal
626 memory from one list to add to another. JRA.
627 ****************************************************************************/
629 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
631 struct ea_list *nlistp, *flistp;
633 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
634 for (flistp = file_list; flistp; flistp = flistp->next) {
635 if (strequal(nlistp->ea.name, flistp->ea.name)) {
641 /* Copy the data from this entry. */
642 nlistp->ea.flags = flistp->ea.flags;
643 nlistp->ea.value = flistp->ea.value;
646 nlistp->ea.flags = 0;
647 ZERO_STRUCT(nlistp->ea.value);
651 *total_ea_len = ea_list_size(name_list);
655 /****************************************************************************
656 Send the required number of replies back.
657 We assume all fields other than the data fields are
658 set correctly for the type of call.
659 HACK ! Always assumes smb_setup field is zero.
660 ****************************************************************************/
662 void send_trans2_replies(connection_struct *conn,
663 struct smb_request *req,
670 /* As we are using a protocol > LANMAN1 then the max_send
671 variable must have been set in the sessetupX call.
672 This takes precedence over the max_xmit field in the
673 global struct. These different max_xmit variables should
674 be merged as this is now too confusing */
676 int data_to_send = datasize;
677 int params_to_send = paramsize;
679 const char *pp = params;
680 const char *pd = pdata;
681 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
682 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
683 int data_alignment_offset = 0;
684 bool overflow = False;
686 /* Modify the data_to_send and datasize and set the error if
687 we're trying to send more than max_data_bytes. We still send
688 the part of the packet(s) that fit. Strange, but needed
691 if (max_data_bytes > 0 && datasize > max_data_bytes) {
692 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
693 max_data_bytes, datasize ));
694 datasize = data_to_send = max_data_bytes;
698 /* If there genuinely are no parameters or data to send just send the empty packet */
700 if(params_to_send == 0 && data_to_send == 0) {
701 reply_outbuf(req, 10, 0);
702 show_msg((char *)req->outbuf);
706 /* When sending params and data ensure that both are nicely aligned */
707 /* Only do this alignment when there is also data to send - else
708 can cause NT redirector problems. */
710 if (((params_to_send % 4) != 0) && (data_to_send != 0))
711 data_alignment_offset = 4 - (params_to_send % 4);
713 /* Space is bufsize minus Netbios over TCP header minus SMB header */
714 /* The alignment_offset is to align the param bytes on an even byte
715 boundary. NT 4.0 Beta needs this to work correctly. */
717 useable_space = max_send - (smb_size
720 + data_alignment_offset);
722 if (useable_space < 0) {
723 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
724 "= %d!!!", useable_space));
725 exit_server_cleanly("send_trans2_replies: Not enough space");
728 while (params_to_send || data_to_send) {
729 /* Calculate whether we will totally or partially fill this packet */
731 total_sent_thistime = params_to_send + data_to_send;
733 /* We can never send more than useable_space */
735 * Note that 'useable_space' does not include the alignment offsets,
736 * but we must include the alignment offsets in the calculation of
737 * the length of the data we send over the wire, as the alignment offsets
738 * are sent here. Fix from Marc_Jacobsen@hp.com.
741 total_sent_thistime = MIN(total_sent_thistime, useable_space);
743 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
744 + data_alignment_offset);
747 * We might have SMBtrans2s in req which was transferred to
748 * the outbuf, fix that.
750 SCVAL(req->outbuf, smb_com, SMBtrans2);
752 /* Set total params and data to be sent */
753 SSVAL(req->outbuf,smb_tprcnt,paramsize);
754 SSVAL(req->outbuf,smb_tdrcnt,datasize);
756 /* Calculate how many parameters and data we can fit into
757 * this packet. Parameters get precedence
760 params_sent_thistime = MIN(params_to_send,useable_space);
761 data_sent_thistime = useable_space - params_sent_thistime;
762 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
764 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
766 /* smb_proff is the offset from the start of the SMB header to the
767 parameter bytes, however the first 4 bytes of outbuf are
768 the Netbios over TCP header. Thus use smb_base() to subtract
769 them from the calculation */
771 SSVAL(req->outbuf,smb_proff,
772 ((smb_buf(req->outbuf)+alignment_offset)
773 - smb_base(req->outbuf)));
775 if(params_sent_thistime == 0)
776 SSVAL(req->outbuf,smb_prdisp,0);
778 /* Absolute displacement of param bytes sent in this packet */
779 SSVAL(req->outbuf,smb_prdisp,pp - params);
781 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
782 if(data_sent_thistime == 0) {
783 SSVAL(req->outbuf,smb_droff,0);
784 SSVAL(req->outbuf,smb_drdisp, 0);
786 /* The offset of the data bytes is the offset of the
787 parameter bytes plus the number of parameters being sent this time */
788 SSVAL(req->outbuf, smb_droff,
789 ((smb_buf(req->outbuf)+alignment_offset)
790 - smb_base(req->outbuf))
791 + params_sent_thistime + data_alignment_offset);
792 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
795 /* Initialize the padding for alignment */
797 if (alignment_offset != 0) {
798 memset(smb_buf(req->outbuf), 0, alignment_offset);
801 /* Copy the param bytes into the packet */
803 if(params_sent_thistime) {
804 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
805 params_sent_thistime);
808 /* Copy in the data bytes */
809 if(data_sent_thistime) {
810 if (data_alignment_offset != 0) {
811 memset((smb_buf(req->outbuf)+alignment_offset+
812 params_sent_thistime), 0,
813 data_alignment_offset);
815 memcpy(smb_buf(req->outbuf)+alignment_offset
816 +params_sent_thistime+data_alignment_offset,
817 pd,data_sent_thistime);
820 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
821 params_sent_thistime, data_sent_thistime, useable_space));
822 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
823 params_to_send, data_to_send, paramsize, datasize));
826 error_packet_set((char *)req->outbuf,
827 ERRDOS,ERRbufferoverflow,
828 STATUS_BUFFER_OVERFLOW,
832 /* Send the packet */
833 show_msg((char *)req->outbuf);
834 if (!srv_send_smb(smbd_server_fd(),
837 IS_CONN_ENCRYPTED(conn),
839 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
841 TALLOC_FREE(req->outbuf);
843 pp += params_sent_thistime;
844 pd += data_sent_thistime;
846 params_to_send -= params_sent_thistime;
847 data_to_send -= data_sent_thistime;
850 if(params_to_send < 0 || data_to_send < 0) {
851 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
852 params_to_send, data_to_send));
860 /****************************************************************************
861 Reply to a TRANSACT2_OPEN.
862 ****************************************************************************/
864 static void call_trans2open(connection_struct *conn,
865 struct smb_request *req,
866 char **pparams, int total_params,
867 char **ppdata, int total_data,
868 unsigned int max_data_bytes)
870 char *params = *pparams;
871 char *pdata = *ppdata;
876 bool return_additional_info;
887 SMB_STRUCT_STAT sbuf;
890 struct ea_list *ea_list = NULL;
895 uint32 create_disposition;
896 uint32 create_options = 0;
897 TALLOC_CTX *ctx = talloc_tos();
899 SET_STAT_INVALID(sbuf);
902 * Ensure we have enough parameters to perform the operation.
905 if (total_params < 29) {
906 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
910 flags = SVAL(params, 0);
911 deny_mode = SVAL(params, 2);
912 open_attr = SVAL(params,6);
913 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
914 if (oplock_request) {
915 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
919 return_additional_info = BITSETW(params,0);
920 open_sattr = SVAL(params, 4);
921 open_time = make_unix_date3(params+8);
923 open_ofun = SVAL(params,12);
924 open_size = IVAL(params,14);
928 reply_doserror(req, ERRSRV, ERRaccess);
932 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
933 total_params - 28, STR_TERMINATE,
935 if (!NT_STATUS_IS_OK(status)) {
936 reply_nterror(req, status);
940 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
941 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
942 (unsigned int)open_ofun, open_size));
944 if (open_ofun == 0) {
945 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
949 if (!map_open_params_to_ntcreate(fname, deny_mode, open_ofun,
954 reply_doserror(req, ERRDOS, ERRbadaccess);
958 /* Any data in this call is an EA list. */
959 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
960 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
964 if (total_data != 4) {
965 if (total_data < 10) {
966 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
970 if (IVAL(pdata,0) > total_data) {
971 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
972 IVAL(pdata,0), (unsigned int)total_data));
973 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
977 ea_list = read_ea_list(talloc_tos(), pdata + 4,
980 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
983 } else if (IVAL(pdata,0) != 4) {
984 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
988 status = SMB_VFS_CREATE_FILE(
991 0, /* root_dir_fid */
993 CFF_DOS_PATH, /* create_file_flags */
994 access_mask, /* access_mask */
995 share_mode, /* share_access */
996 create_disposition, /* create_disposition*/
997 create_options, /* create_options */
998 open_attr, /* file_attributes */
999 oplock_request, /* oplock_request */
1000 open_size, /* allocation_size */
1002 ea_list, /* ea_list */
1004 &smb_action, /* pinfo */
1007 if (!NT_STATUS_IS_OK(status)) {
1008 if (open_was_deferred(req->mid)) {
1009 /* We have re-scheduled this call. */
1012 reply_openerror(req, status);
1016 size = get_file_size_stat(&sbuf);
1017 fattr = dos_mode(conn,fsp->fsp_name,&sbuf);
1018 mtime = convert_timespec_to_time_t(sbuf.st_ex_mtime);
1019 inode = sbuf.st_ex_ino;
1021 close_file(req, fsp, ERROR_CLOSE);
1022 reply_doserror(req, ERRDOS,ERRnoaccess);
1026 /* Realloc the size of parameters and data we will return */
1027 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1028 if(*pparams == NULL ) {
1029 reply_nterror(req, NT_STATUS_NO_MEMORY);
1034 SSVAL(params,0,fsp->fnum);
1035 SSVAL(params,2,fattr);
1036 srv_put_dos_date2(params,4, mtime);
1037 SIVAL(params,8, (uint32)size);
1038 SSVAL(params,12,deny_mode);
1039 SSVAL(params,14,0); /* open_type - file or directory. */
1040 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1042 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1043 smb_action |= EXTENDED_OPLOCK_GRANTED;
1046 SSVAL(params,18,smb_action);
1049 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1051 SIVAL(params,20,inode);
1052 SSVAL(params,24,0); /* Padding. */
1054 uint32 ea_size = estimate_ea_size(conn, fsp, fsp->fsp_name);
1055 SIVAL(params, 26, ea_size);
1057 SIVAL(params, 26, 0);
1060 /* Send the required number of replies */
1061 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1064 /*********************************************************
1065 Routine to check if a given string matches exactly.
1066 as a special case a mask of "." does NOT match. That
1067 is required for correct wildcard semantics
1068 Case can be significant or not.
1069 **********************************************************/
1071 static bool exact_match(connection_struct *conn,
1075 if (mask[0] == '.' && mask[1] == 0)
1077 if (dptr_has_wild(conn->dirptr)) {
1080 if (conn->case_sensitive)
1081 return strcmp(str,mask)==0;
1083 return StrCaseCmp(str,mask) == 0;
1086 /****************************************************************************
1087 Return the filetype for UNIX extensions.
1088 ****************************************************************************/
1090 static uint32 unix_filetype(mode_t mode)
1093 return UNIX_TYPE_FILE;
1094 else if(S_ISDIR(mode))
1095 return UNIX_TYPE_DIR;
1097 else if(S_ISLNK(mode))
1098 return UNIX_TYPE_SYMLINK;
1101 else if(S_ISCHR(mode))
1102 return UNIX_TYPE_CHARDEV;
1105 else if(S_ISBLK(mode))
1106 return UNIX_TYPE_BLKDEV;
1109 else if(S_ISFIFO(mode))
1110 return UNIX_TYPE_FIFO;
1113 else if(S_ISSOCK(mode))
1114 return UNIX_TYPE_SOCKET;
1117 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1118 return UNIX_TYPE_UNKNOWN;
1121 /****************************************************************************
1122 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1123 ****************************************************************************/
1125 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1127 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1128 SMB_STRUCT_STAT *psbuf,
1130 enum perm_type ptype,
1135 if (perms == SMB_MODE_NO_CHANGE) {
1136 if (!VALID_STAT(*psbuf)) {
1137 return NT_STATUS_INVALID_PARAMETER;
1139 *ret_perms = psbuf->st_ex_mode;
1140 return NT_STATUS_OK;
1144 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1145 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1146 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1147 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1148 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1149 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1150 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1151 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1152 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1154 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1157 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1160 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1165 /* Apply mode mask */
1166 ret &= lp_create_mask(SNUM(conn));
1167 /* Add in force bits */
1168 ret |= lp_force_create_mode(SNUM(conn));
1171 ret &= lp_dir_mask(SNUM(conn));
1172 /* Add in force bits */
1173 ret |= lp_force_dir_mode(SNUM(conn));
1175 case PERM_EXISTING_FILE:
1176 /* Apply mode mask */
1177 ret &= lp_security_mask(SNUM(conn));
1178 /* Add in force bits */
1179 ret |= lp_force_security_mode(SNUM(conn));
1181 case PERM_EXISTING_DIR:
1182 /* Apply mode mask */
1183 ret &= lp_dir_security_mask(SNUM(conn));
1184 /* Add in force bits */
1185 ret |= lp_force_dir_security_mode(SNUM(conn));
1190 return NT_STATUS_OK;
1193 /****************************************************************************
1194 Needed to show the msdfs symlinks as directories. Modifies psbuf
1195 to be a directory if it's a msdfs link.
1196 ****************************************************************************/
1198 static bool check_msdfs_link(connection_struct *conn,
1199 const char *pathname,
1200 SMB_STRUCT_STAT *psbuf)
1202 int saved_errno = errno;
1203 if(lp_host_msdfs() &&
1204 lp_msdfs_root(SNUM(conn)) &&
1205 is_msdfs_link(conn, pathname, psbuf)) {
1207 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1210 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1211 errno = saved_errno;
1214 errno = saved_errno;
1219 /****************************************************************************
1220 Get a level dependent lanman2 dir entry.
1221 ****************************************************************************/
1223 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
1224 connection_struct *conn,
1226 const char *path_mask,
1229 int requires_resume_key,
1235 int space_remaining,
1237 bool *got_exact_match,
1238 int *last_entry_off,
1239 struct ea_list *name_list)
1243 SMB_STRUCT_STAT sbuf;
1244 const char *mask = NULL;
1245 char *pathreal = NULL;
1247 char *p, *q, *pdata = *ppdata;
1251 SMB_OFF_T file_size = 0;
1252 uint64_t allocation_size = 0;
1254 struct timespec mdate_ts, adate_ts, create_date_ts;
1255 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1257 char *last_entry_ptr;
1259 uint32 nt_extmode; /* Used for NT connections instead of mode */
1260 bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
1261 bool check_mangled_names = lp_manglednames(conn->params);
1262 char mangled_name[13]; /* mangled 8.3 name. */
1264 *out_of_space = False;
1265 *got_exact_match = False;
1267 ZERO_STRUCT(mdate_ts);
1268 ZERO_STRUCT(adate_ts);
1269 ZERO_STRUCT(create_date_ts);
1271 if (!conn->dirptr) {
1275 p = strrchr_m(path_mask,'/');
1278 mask = talloc_strdup(ctx,"*.*");
1288 bool ms_dfs_link = False;
1290 /* Needed if we run out of space */
1291 long curr_dirpos = prev_dirpos = dptr_TellDir(conn->dirptr);
1292 dname = dptr_ReadDirName(ctx,conn->dirptr,&curr_dirpos,&sbuf);
1295 * Due to bugs in NT client redirectors we are not using
1296 * resume keys any more - set them to zero.
1297 * Check out the related comments in findfirst/findnext.
1303 DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
1304 (long)conn->dirptr,curr_dirpos));
1311 * fname may get mangled, dname is never mangled.
1312 * Whenever we're accessing the filesystem we use
1313 * pathreal which is composed from dname.
1319 /* Mangle fname if it's an illegal name. */
1320 if (mangle_must_mangle(dname,conn->params)) {
1321 if (!name_to_8_3(dname,mangled_name,True,conn->params)) {
1323 continue; /* Error - couldn't mangle. */
1325 fname = talloc_strdup(ctx, mangled_name);
1331 if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
1332 got_match = mask_match(fname, mask, conn->case_sensitive);
1335 if(!got_match && check_mangled_names &&
1336 !mangle_is_8_3(fname, False, conn->params)) {
1338 * It turns out that NT matches wildcards against
1339 * both long *and* short names. This may explain some
1340 * of the wildcard wierdness from old DOS clients
1341 * that some people have been seeing.... JRA.
1343 /* Force the mangling into 8.3. */
1344 if (!name_to_8_3( fname, mangled_name, False, conn->params)) {
1346 continue; /* Error - couldn't mangle. */
1349 if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
1350 got_match = mask_match(mangled_name, mask, conn->case_sensitive);
1355 bool isdots = (ISDOT(dname) || ISDOTDOT(dname));
1357 if (dont_descend && !isdots) {
1364 pathreal = talloc_asprintf(ctx,
1369 pathreal = talloc_asprintf(ctx,
1380 if (INFO_LEVEL_IS_UNIX(info_level)) {
1381 if (SMB_VFS_LSTAT(conn,pathreal,&sbuf) != 0) {
1382 DEBUG(5,("get_lanman2_dir_entry:Couldn't lstat [%s] (%s)\n",
1383 pathreal,strerror(errno)));
1384 TALLOC_FREE(pathreal);
1388 } else if (!VALID_STAT(sbuf) && SMB_VFS_STAT(conn,pathreal,&sbuf) != 0) {
1389 /* Needed to show the msdfs symlinks as
1392 ms_dfs_link = check_msdfs_link(conn, pathreal, &sbuf);
1394 DEBUG(5,("get_lanman2_dir_entry:Couldn't stat [%s] (%s)\n",
1395 pathreal,strerror(errno)));
1396 TALLOC_FREE(pathreal);
1403 mode = dos_mode_msdfs(conn,pathreal,&sbuf);
1405 mode = dos_mode(conn,pathreal,&sbuf);
1408 if (!dir_check_ftype(conn,mode,dirtype)) {
1409 DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
1410 TALLOC_FREE(pathreal);
1415 if (!(mode & aDIR)) {
1416 file_size = get_file_size_stat(&sbuf);
1418 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
1420 mdate_ts = sbuf.st_ex_mtime;
1421 adate_ts = sbuf.st_ex_atime;
1422 create_date_ts = sbuf.st_ex_btime;
1424 if (ask_sharemode) {
1425 struct timespec write_time_ts;
1426 struct file_id fileid;
1428 fileid = vfs_file_id_from_sbuf(conn, &sbuf);
1429 get_file_infos(fileid, NULL, &write_time_ts);
1430 if (!null_timespec(write_time_ts)) {
1431 mdate_ts = write_time_ts;
1435 if (lp_dos_filetime_resolution(SNUM(conn))) {
1436 dos_filetime_timespec(&create_date_ts);
1437 dos_filetime_timespec(&mdate_ts);
1438 dos_filetime_timespec(&adate_ts);
1441 create_date = convert_timespec_to_time_t(create_date_ts);
1442 mdate = convert_timespec_to_time_t(mdate_ts);
1443 adate = convert_timespec_to_time_t(adate_ts);
1445 DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",
1450 dptr_DirCacheAdd(conn->dirptr, dname, curr_dirpos);
1460 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1462 switch (info_level) {
1463 case SMB_FIND_INFO_STANDARD:
1464 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1465 if(requires_resume_key) {
1469 srv_put_dos_date2(p,0,create_date);
1470 srv_put_dos_date2(p,4,adate);
1471 srv_put_dos_date2(p,8,mdate);
1472 SIVAL(p,12,(uint32)file_size);
1473 SIVAL(p,16,(uint32)allocation_size);
1477 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1478 p += ucs2_align(base_data, p, 0);
1480 len = srvstr_push(base_data, flags2, p,
1481 fname, PTR_DIFF(end_data, p),
1483 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1485 SCVAL(nameptr, -1, len - 2);
1487 SCVAL(nameptr, -1, 0);
1491 SCVAL(nameptr, -1, len - 1);
1493 SCVAL(nameptr, -1, 0);
1499 case SMB_FIND_EA_SIZE:
1500 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1501 if(requires_resume_key) {
1505 srv_put_dos_date2(p,0,create_date);
1506 srv_put_dos_date2(p,4,adate);
1507 srv_put_dos_date2(p,8,mdate);
1508 SIVAL(p,12,(uint32)file_size);
1509 SIVAL(p,16,(uint32)allocation_size);
1512 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1513 SIVAL(p,22,ea_size); /* Extended attributes */
1517 len = srvstr_push(base_data, flags2,
1518 p, fname, PTR_DIFF(end_data, p),
1519 STR_TERMINATE | STR_NOALIGN);
1520 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1533 SCVAL(nameptr,0,len);
1535 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1538 case SMB_FIND_EA_LIST:
1540 struct ea_list *file_list = NULL;
1543 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1547 if(requires_resume_key) {
1551 srv_put_dos_date2(p,0,create_date);
1552 srv_put_dos_date2(p,4,adate);
1553 srv_put_dos_date2(p,8,mdate);
1554 SIVAL(p,12,(uint32)file_size);
1555 SIVAL(p,16,(uint32)allocation_size);
1557 p += 22; /* p now points to the EA area. */
1559 file_list = get_ea_list_from_file(ctx, conn, NULL, pathreal, &ea_len);
1560 name_list = ea_list_union(name_list, file_list, &ea_len);
1562 /* We need to determine if this entry will fit in the space available. */
1563 /* Max string size is 255 bytes. */
1564 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1565 /* Move the dirptr back to prev_dirpos */
1566 dptr_SeekDir(conn->dirptr, prev_dirpos);
1567 *out_of_space = True;
1568 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1569 return False; /* Not finished - just out of space */
1572 /* Push the ea_data followed by the name. */
1573 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1575 len = srvstr_push(base_data, flags2,
1576 p + 1, fname, PTR_DIFF(end_data, p+1),
1577 STR_TERMINATE | STR_NOALIGN);
1578 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1591 SCVAL(nameptr,0,len);
1593 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1597 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1598 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1599 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1601 SIVAL(p,0,reskey); p += 4;
1602 put_long_date_timespec(p,create_date_ts); p += 8;
1603 put_long_date_timespec(p,adate_ts); p += 8;
1604 put_long_date_timespec(p,mdate_ts); p += 8;
1605 put_long_date_timespec(p,mdate_ts); p += 8;
1606 SOFF_T(p,0,file_size); p += 8;
1607 SOFF_T(p,0,allocation_size); p += 8;
1608 SIVAL(p,0,nt_extmode); p += 4;
1609 q = p; p += 4; /* q is placeholder for name length. */
1611 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1612 SIVAL(p,0,ea_size); /* Extended attributes */
1615 /* Clear the short name buffer. This is
1616 * IMPORTANT as not doing so will trigger
1617 * a Win2k client bug. JRA.
1619 if (!was_8_3 && check_mangled_names) {
1620 if (!name_to_8_3(fname,mangled_name,True,
1622 /* Error - mangle failed ! */
1623 memset(mangled_name,'\0',12);
1625 mangled_name[12] = 0;
1626 len = srvstr_push(base_data, flags2,
1627 p+2, mangled_name, 24,
1628 STR_UPPER|STR_UNICODE);
1630 memset(p + 2 + len,'\0',24 - len);
1637 len = srvstr_push(base_data, flags2, p,
1638 fname, PTR_DIFF(end_data, p),
1639 STR_TERMINATE_ASCII);
1642 SIVAL(p,0,0); /* Ensure any padding is null. */
1643 len = PTR_DIFF(p, pdata);
1644 len = (len + 3) & ~3;
1649 case SMB_FIND_FILE_DIRECTORY_INFO:
1650 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1652 SIVAL(p,0,reskey); p += 4;
1653 put_long_date_timespec(p,create_date_ts); p += 8;
1654 put_long_date_timespec(p,adate_ts); p += 8;
1655 put_long_date_timespec(p,mdate_ts); p += 8;
1656 put_long_date_timespec(p,mdate_ts); p += 8;
1657 SOFF_T(p,0,file_size); p += 8;
1658 SOFF_T(p,0,allocation_size); p += 8;
1659 SIVAL(p,0,nt_extmode); p += 4;
1660 len = srvstr_push(base_data, flags2,
1661 p + 4, fname, PTR_DIFF(end_data, p+4),
1662 STR_TERMINATE_ASCII);
1665 SIVAL(p,0,0); /* Ensure any padding is null. */
1666 len = PTR_DIFF(p, pdata);
1667 len = (len + 3) & ~3;
1672 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1673 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1675 SIVAL(p,0,reskey); p += 4;
1676 put_long_date_timespec(p,create_date_ts); p += 8;
1677 put_long_date_timespec(p,adate_ts); p += 8;
1678 put_long_date_timespec(p,mdate_ts); p += 8;
1679 put_long_date_timespec(p,mdate_ts); p += 8;
1680 SOFF_T(p,0,file_size); p += 8;
1681 SOFF_T(p,0,allocation_size); p += 8;
1682 SIVAL(p,0,nt_extmode); p += 4;
1683 q = p; p += 4; /* q is placeholder for name length. */
1685 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1686 SIVAL(p,0,ea_size); /* Extended attributes */
1689 len = srvstr_push(base_data, flags2, p,
1690 fname, PTR_DIFF(end_data, p),
1691 STR_TERMINATE_ASCII);
1695 SIVAL(p,0,0); /* Ensure any padding is null. */
1696 len = PTR_DIFF(p, pdata);
1697 len = (len + 3) & ~3;
1702 case SMB_FIND_FILE_NAMES_INFO:
1703 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1705 SIVAL(p,0,reskey); p += 4;
1707 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1708 acl on a dir (tridge) */
1709 len = srvstr_push(base_data, flags2, p,
1710 fname, PTR_DIFF(end_data, p),
1711 STR_TERMINATE_ASCII);
1714 SIVAL(p,0,0); /* Ensure any padding is null. */
1715 len = PTR_DIFF(p, pdata);
1716 len = (len + 3) & ~3;
1721 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1722 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1724 SIVAL(p,0,reskey); p += 4;
1725 put_long_date_timespec(p,create_date_ts); p += 8;
1726 put_long_date_timespec(p,adate_ts); p += 8;
1727 put_long_date_timespec(p,mdate_ts); p += 8;
1728 put_long_date_timespec(p,mdate_ts); p += 8;
1729 SOFF_T(p,0,file_size); p += 8;
1730 SOFF_T(p,0,allocation_size); p += 8;
1731 SIVAL(p,0,nt_extmode); p += 4;
1732 q = p; p += 4; /* q is placeholder for name length. */
1734 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1735 SIVAL(p,0,ea_size); /* Extended attributes */
1738 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1739 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1740 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1741 len = srvstr_push(base_data, flags2, p,
1742 fname, PTR_DIFF(end_data, p),
1743 STR_TERMINATE_ASCII);
1746 SIVAL(p,0,0); /* Ensure any padding is null. */
1747 len = PTR_DIFF(p, pdata);
1748 len = (len + 3) & ~3;
1753 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1754 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1755 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1757 SIVAL(p,0,reskey); p += 4;
1758 put_long_date_timespec(p,create_date_ts); p += 8;
1759 put_long_date_timespec(p,adate_ts); p += 8;
1760 put_long_date_timespec(p,mdate_ts); p += 8;
1761 put_long_date_timespec(p,mdate_ts); p += 8;
1762 SOFF_T(p,0,file_size); p += 8;
1763 SOFF_T(p,0,allocation_size); p += 8;
1764 SIVAL(p,0,nt_extmode); p += 4;
1765 q = p; p += 4; /* q is placeholder for name length */
1767 unsigned int ea_size = estimate_ea_size(conn, NULL, pathreal);
1768 SIVAL(p,0,ea_size); /* Extended attributes */
1771 /* Clear the short name buffer. This is
1772 * IMPORTANT as not doing so will trigger
1773 * a Win2k client bug. JRA.
1775 if (!was_8_3 && check_mangled_names) {
1776 if (!name_to_8_3(fname,mangled_name,True,
1778 /* Error - mangle failed ! */
1779 memset(mangled_name,'\0',12);
1781 mangled_name[12] = 0;
1782 len = srvstr_push(base_data, flags2,
1783 p+2, mangled_name, 24,
1784 STR_UPPER|STR_UNICODE);
1787 memset(p + 2 + len,'\0',24 - len);
1794 SSVAL(p,0,0); p += 2; /* Reserved ? */
1795 SIVAL(p,0,sbuf.st_ex_ino); p += 4; /* FileIndexLow */
1796 SIVAL(p,0,sbuf.st_ex_dev); p += 4; /* FileIndexHigh */
1797 len = srvstr_push(base_data, flags2, p,
1798 fname, PTR_DIFF(end_data, p),
1799 STR_TERMINATE_ASCII);
1802 SIVAL(p,0,0); /* Ensure any padding is null. */
1803 len = PTR_DIFF(p, pdata);
1804 len = (len + 3) & ~3;
1809 /* CIFS UNIX Extension. */
1811 case SMB_FIND_FILE_UNIX:
1812 case SMB_FIND_FILE_UNIX_INFO2:
1814 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1816 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1818 if (info_level == SMB_FIND_FILE_UNIX) {
1819 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1820 p = store_file_unix_basic(conn, p,
1822 len = srvstr_push(base_data, flags2, p,
1823 fname, PTR_DIFF(end_data, p),
1826 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1827 p = store_file_unix_basic_info2(conn, p,
1831 len = srvstr_push(base_data, flags2, p, fname,
1832 PTR_DIFF(end_data, p), 0);
1833 SIVAL(nameptr, 0, len);
1837 SIVAL(p,0,0); /* Ensure any padding is null. */
1839 len = PTR_DIFF(p, pdata);
1840 len = (len + 3) & ~3;
1841 SIVAL(pdata,0,len); /* Offset from this structure to the beginning of the next one */
1843 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1853 if (PTR_DIFF(p,pdata) > space_remaining) {
1854 /* Move the dirptr back to prev_dirpos */
1855 dptr_SeekDir(conn->dirptr, prev_dirpos);
1856 *out_of_space = True;
1857 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1858 return False; /* Not finished - just out of space */
1861 /* Setup the last entry pointer, as an offset from base_data */
1862 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1863 /* Advance the data pointer to the next slot */
1869 /****************************************************************************
1870 Reply to a TRANS2_FINDFIRST.
1871 ****************************************************************************/
1873 static void call_trans2findfirst(connection_struct *conn,
1874 struct smb_request *req,
1875 char **pparams, int total_params,
1876 char **ppdata, int total_data,
1877 unsigned int max_data_bytes)
1879 /* We must be careful here that we don't return more than the
1880 allowed number of data bytes. If this means returning fewer than
1881 maxentries then so be it. We assume that the redirector has
1882 enough room for the fixed number of parameter bytes it has
1884 struct smb_filename *smb_dname = NULL;
1885 char *params = *pparams;
1886 char *pdata = *ppdata;
1890 uint16 findfirst_flags;
1891 bool close_after_first;
1893 bool requires_resume_key;
1895 char *directory = NULL;
1898 int last_entry_off=0;
1902 bool finished = False;
1903 bool dont_descend = False;
1904 bool out_of_space = False;
1905 int space_remaining;
1906 bool mask_contains_wcard = False;
1907 struct ea_list *ea_list = NULL;
1908 NTSTATUS ntstatus = NT_STATUS_OK;
1909 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
1910 TALLOC_CTX *ctx = talloc_tos();
1912 if (total_params < 13) {
1913 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1917 dirtype = SVAL(params,0);
1918 maxentries = SVAL(params,2);
1919 findfirst_flags = SVAL(params,4);
1920 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
1921 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
1922 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
1923 info_level = SVAL(params,6);
1925 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
1926 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
1927 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
1928 info_level, max_data_bytes));
1931 /* W2K3 seems to treat zero as 1. */
1935 switch (info_level) {
1936 case SMB_FIND_INFO_STANDARD:
1937 case SMB_FIND_EA_SIZE:
1938 case SMB_FIND_EA_LIST:
1939 case SMB_FIND_FILE_DIRECTORY_INFO:
1940 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1941 case SMB_FIND_FILE_NAMES_INFO:
1942 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1943 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1944 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1946 case SMB_FIND_FILE_UNIX:
1947 case SMB_FIND_FILE_UNIX_INFO2:
1948 /* Always use filesystem for UNIX mtime query. */
1949 ask_sharemode = false;
1950 if (!lp_unix_extensions()) {
1951 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1956 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
1960 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
1961 params+12, total_params - 12,
1962 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
1963 if (!NT_STATUS_IS_OK(ntstatus)) {
1964 reply_nterror(req, ntstatus);
1968 ntstatus = resolve_dfspath_wcard(ctx, conn,
1969 req->flags2 & FLAGS2_DFS_PATHNAMES,
1972 &mask_contains_wcard);
1973 if (!NT_STATUS_IS_OK(ntstatus)) {
1974 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
1975 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
1976 ERRSRV, ERRbadpath);
1979 reply_nterror(req, ntstatus);
1983 ntstatus = unix_convert(ctx, conn, directory, &smb_dname,
1984 (UCF_SAVE_LCOMP | UCF_ALLOW_WCARD_LCOMP));
1985 if (!NT_STATUS_IS_OK(ntstatus)) {
1986 reply_nterror(req, ntstatus);
1990 mask = smb_dname->original_lcomp;
1992 ntstatus = get_full_smb_filename(ctx, smb_dname, &directory);
1993 TALLOC_FREE(smb_dname);
1994 if (!NT_STATUS_IS_OK(ntstatus)) {
1995 reply_nterror(req, ntstatus);
1999 ntstatus = check_name(conn, directory);
2000 if (!NT_STATUS_IS_OK(ntstatus)) {
2001 reply_nterror(req, ntstatus);
2005 p = strrchr_m(directory,'/');
2007 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2008 if((directory[0] == '.') && (directory[1] == '\0')) {
2009 mask = talloc_strdup(ctx,"*");
2011 reply_nterror(req, NT_STATUS_NO_MEMORY);
2014 mask_contains_wcard = True;
2016 directory = talloc_strdup(talloc_tos(), "./");
2018 reply_nterror(req, NT_STATUS_NO_MEMORY);
2025 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2027 if (info_level == SMB_FIND_EA_LIST) {
2030 if (total_data < 4) {
2031 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2035 ea_size = IVAL(pdata,0);
2036 if (ea_size != total_data) {
2037 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2038 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2039 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2043 if (!lp_ea_support(SNUM(conn))) {
2044 reply_doserror(req, ERRDOS, ERReasnotsupported);
2048 /* Pull out the list of names. */
2049 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2051 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2056 *ppdata = (char *)SMB_REALLOC(
2057 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2058 if(*ppdata == NULL ) {
2059 reply_nterror(req, NT_STATUS_NO_MEMORY);
2063 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2065 /* Realloc the params space */
2066 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2067 if (*pparams == NULL) {
2068 reply_nterror(req, NT_STATUS_NO_MEMORY);
2073 /* Save the wildcard match and attribs we are using on this directory -
2074 needed as lanman2 assumes these are being saved between calls */
2076 ntstatus = dptr_create(conn,
2082 mask_contains_wcard,
2086 if (!NT_STATUS_IS_OK(ntstatus)) {
2087 reply_nterror(req, ntstatus);
2091 dptr_num = dptr_dnum(conn->dirptr);
2092 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2094 /* Initialize per TRANS2_FIND_FIRST operation data */
2095 dptr_init_search_op(conn->dirptr);
2097 /* We don't need to check for VOL here as this is returned by
2098 a different TRANS2 call. */
2100 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n", conn->dirpath,lp_dontdescend(SNUM(conn))));
2101 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2102 dont_descend = True;
2105 space_remaining = max_data_bytes;
2106 out_of_space = False;
2108 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2109 bool got_exact_match = False;
2111 /* this is a heuristic to avoid seeking the dirptr except when
2112 absolutely necessary. It allows for a filename of about 40 chars */
2113 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2114 out_of_space = True;
2117 finished = !get_lanman2_dir_entry(ctx,
2120 mask,dirtype,info_level,
2121 requires_resume_key,dont_descend,
2124 space_remaining, &out_of_space,
2126 &last_entry_off, ea_list);
2129 if (finished && out_of_space)
2132 if (!finished && !out_of_space)
2136 * As an optimisation if we know we aren't looking
2137 * for a wildcard name (ie. the name matches the wildcard exactly)
2138 * then we can finish on any (first) match.
2139 * This speeds up large directory searches. JRA.
2145 /* Ensure space_remaining never goes -ve. */
2146 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2147 space_remaining = 0;
2148 out_of_space = true;
2150 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2154 /* Check if we can close the dirptr */
2155 if(close_after_first || (finished && close_if_end)) {
2156 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2157 dptr_close(&dptr_num);
2161 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2162 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2163 * the protocol level is less than NT1. Tested with smbclient. JRA.
2164 * This should fix the OS/2 client bug #2335.
2167 if(numentries == 0) {
2168 dptr_close(&dptr_num);
2169 if (Protocol < PROTOCOL_NT1) {
2170 reply_doserror(req, ERRDOS, ERRnofiles);
2173 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2174 ERRDOS, ERRbadfile);
2179 /* At this point pdata points to numentries directory entries. */
2181 /* Set up the return parameter block */
2182 SSVAL(params,0,dptr_num);
2183 SSVAL(params,2,numentries);
2184 SSVAL(params,4,finished);
2185 SSVAL(params,6,0); /* Never an EA error */
2186 SSVAL(params,8,last_entry_off);
2188 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2191 if ((! *directory) && dptr_path(dptr_num)) {
2192 directory = talloc_strdup(talloc_tos(),dptr_path(dptr_num));
2194 reply_nterror(req, NT_STATUS_NO_MEMORY);
2198 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2199 smb_fn_name(req->cmd),
2200 mask, directory, dirtype, numentries ) );
2203 * Force a name mangle here to ensure that the
2204 * mask as an 8.3 name is top of the mangled cache.
2205 * The reasons for this are subtle. Don't remove
2206 * this code unless you know what you are doing
2207 * (see PR#13758). JRA.
2210 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2211 char mangled_name[13];
2212 name_to_8_3(mask, mangled_name, True, conn->params);
2218 /****************************************************************************
2219 Reply to a TRANS2_FINDNEXT.
2220 ****************************************************************************/
2222 static void call_trans2findnext(connection_struct *conn,
2223 struct smb_request *req,
2224 char **pparams, int total_params,
2225 char **ppdata, int total_data,
2226 unsigned int max_data_bytes)
2228 /* We must be careful here that we don't return more than the
2229 allowed number of data bytes. If this means returning fewer than
2230 maxentries then so be it. We assume that the redirector has
2231 enough room for the fixed number of parameter bytes it has
2233 char *params = *pparams;
2234 char *pdata = *ppdata;
2240 uint16 findnext_flags;
2241 bool close_after_request;
2243 bool requires_resume_key;
2245 bool mask_contains_wcard = False;
2246 char *resume_name = NULL;
2247 const char *mask = NULL;
2248 const char *directory = NULL;
2252 int i, last_entry_off=0;
2253 bool finished = False;
2254 bool dont_descend = False;
2255 bool out_of_space = False;
2256 int space_remaining;
2257 struct ea_list *ea_list = NULL;
2258 NTSTATUS ntstatus = NT_STATUS_OK;
2259 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2260 TALLOC_CTX *ctx = talloc_tos();
2262 if (total_params < 13) {
2263 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2267 dptr_num = SVAL(params,0);
2268 maxentries = SVAL(params,2);
2269 info_level = SVAL(params,4);
2270 resume_key = IVAL(params,6);
2271 findnext_flags = SVAL(params,10);
2272 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2273 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2274 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2275 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2277 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2279 total_params - 12, STR_TERMINATE, &ntstatus,
2280 &mask_contains_wcard);
2281 if (!NT_STATUS_IS_OK(ntstatus)) {
2282 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2283 complain (it thinks we're asking for the directory above the shared
2284 path or an invalid name). Catch this as the resume name is only compared, never used in
2285 a file access. JRA. */
2286 srvstr_pull_talloc(ctx, params, req->flags2,
2287 &resume_name, params+12,
2291 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2292 reply_nterror(req, ntstatus);
2297 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2298 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2299 resume_key = %d resume name = %s continue=%d level = %d\n",
2300 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2301 requires_resume_key, resume_key, resume_name, continue_bit, info_level));
2304 /* W2K3 seems to treat zero as 1. */
2308 switch (info_level) {
2309 case SMB_FIND_INFO_STANDARD:
2310 case SMB_FIND_EA_SIZE:
2311 case SMB_FIND_EA_LIST:
2312 case SMB_FIND_FILE_DIRECTORY_INFO:
2313 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2314 case SMB_FIND_FILE_NAMES_INFO:
2315 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2316 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2317 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2319 case SMB_FIND_FILE_UNIX:
2320 case SMB_FIND_FILE_UNIX_INFO2:
2321 /* Always use filesystem for UNIX mtime query. */
2322 ask_sharemode = false;
2323 if (!lp_unix_extensions()) {
2324 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2329 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2333 if (info_level == SMB_FIND_EA_LIST) {
2336 if (total_data < 4) {
2337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2341 ea_size = IVAL(pdata,0);
2342 if (ea_size != total_data) {
2343 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2344 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2345 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2349 if (!lp_ea_support(SNUM(conn))) {
2350 reply_doserror(req, ERRDOS, ERReasnotsupported);
2354 /* Pull out the list of names. */
2355 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2357 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2362 *ppdata = (char *)SMB_REALLOC(
2363 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2364 if(*ppdata == NULL) {
2365 reply_nterror(req, NT_STATUS_NO_MEMORY);
2370 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2372 /* Realloc the params space */
2373 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2374 if(*pparams == NULL ) {
2375 reply_nterror(req, NT_STATUS_NO_MEMORY);
2381 /* Check that the dptr is valid */
2382 if(!(conn->dirptr = dptr_fetch_lanman2(dptr_num))) {
2383 reply_doserror(req, ERRDOS, ERRnofiles);
2387 string_set(&conn->dirpath,dptr_path(dptr_num));
2389 /* Get the wildcard mask from the dptr */
2390 if((p = dptr_wcard(dptr_num))== NULL) {
2391 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2392 reply_doserror(req, ERRDOS, ERRnofiles);
2397 directory = conn->dirpath;
2399 /* Get the attr mask from the dptr */
2400 dirtype = dptr_attr(dptr_num);
2402 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2403 dptr_num, mask, dirtype,
2405 dptr_TellDir(conn->dirptr)));
2407 /* Initialize per TRANS2_FIND_NEXT operation data */
2408 dptr_init_search_op(conn->dirptr);
2410 /* We don't need to check for VOL here as this is returned by
2411 a different TRANS2 call. */
2413 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",conn->dirpath,lp_dontdescend(SNUM(conn))));
2414 if (in_list(conn->dirpath,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2415 dont_descend = True;
2418 space_remaining = max_data_bytes;
2419 out_of_space = False;
2422 * Seek to the correct position. We no longer use the resume key but
2423 * depend on the last file name instead.
2426 if(*resume_name && !continue_bit) {
2429 long current_pos = 0;
2431 * Remember, name_to_8_3 is called by
2432 * get_lanman2_dir_entry(), so the resume name
2433 * could be mangled. Ensure we check the unmangled name.
2436 if (mangle_is_mangled(resume_name, conn->params)) {
2437 char *new_resume_name = NULL;
2438 mangle_lookup_name_from_8_3(ctx,
2442 if (new_resume_name) {
2443 resume_name = new_resume_name;
2448 * Fix for NT redirector problem triggered by resume key indexes
2449 * changing between directory scans. We now return a resume key of 0
2450 * and instead look for the filename to continue from (also given
2451 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2452 * findfirst/findnext (as is usual) then the directory pointer
2453 * should already be at the correct place.
2456 finished = !dptr_SearchDir(conn->dirptr, resume_name, ¤t_pos, &st);
2457 } /* end if resume_name && !continue_bit */
2459 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2460 bool got_exact_match = False;
2462 /* this is a heuristic to avoid seeking the dirptr except when
2463 absolutely necessary. It allows for a filename of about 40 chars */
2464 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2465 out_of_space = True;
2468 finished = !get_lanman2_dir_entry(ctx,
2471 mask,dirtype,info_level,
2472 requires_resume_key,dont_descend,
2475 space_remaining, &out_of_space,
2477 &last_entry_off, ea_list);
2480 if (finished && out_of_space)
2483 if (!finished && !out_of_space)
2487 * As an optimisation if we know we aren't looking
2488 * for a wildcard name (ie. the name matches the wildcard exactly)
2489 * then we can finish on any (first) match.
2490 * This speeds up large directory searches. JRA.
2496 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2499 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2500 smb_fn_name(req->cmd),
2501 mask, directory, dirtype, numentries ) );
2503 /* Check if we can close the dirptr */
2504 if(close_after_request || (finished && close_if_end)) {
2505 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2506 dptr_close(&dptr_num); /* This frees up the saved mask */
2509 /* Set up the return parameter block */
2510 SSVAL(params,0,numentries);
2511 SSVAL(params,2,finished);
2512 SSVAL(params,4,0); /* Never an EA error */
2513 SSVAL(params,6,last_entry_off);
2515 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2521 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2523 E_md4hash(lp_servicename(SNUM(conn)),objid);
2527 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2529 SMB_ASSERT(extended_info != NULL);
2531 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2532 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2533 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2534 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2535 #ifdef SAMBA_VERSION_REVISION
2536 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2538 extended_info->samba_subversion = 0;
2539 #ifdef SAMBA_VERSION_RC_RELEASE
2540 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2542 #ifdef SAMBA_VERSION_PRE_RELEASE
2543 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2546 #ifdef SAMBA_VERSION_VENDOR_PATCH
2547 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2549 extended_info->samba_gitcommitdate = 0;
2550 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2551 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2554 memset(extended_info->samba_version_string, 0,
2555 sizeof(extended_info->samba_version_string));
2557 snprintf (extended_info->samba_version_string,
2558 sizeof(extended_info->samba_version_string),
2559 "%s", samba_version_string());
2562 /****************************************************************************
2563 Reply to a TRANS2_QFSINFO (query filesystem info).
2564 ****************************************************************************/
2566 static void call_trans2qfsinfo(connection_struct *conn,
2567 struct smb_request *req,
2568 char **pparams, int total_params,
2569 char **ppdata, int total_data,
2570 unsigned int max_data_bytes)
2572 char *pdata, *end_data;
2573 char *params = *pparams;
2577 const char *vname = volume_label(SNUM(conn));
2578 int snum = SNUM(conn);
2579 char *fstype = lp_fstype(SNUM(conn));
2580 uint32 additional_flags = 0;
2582 if (total_params < 2) {
2583 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2587 info_level = SVAL(params,0);
2590 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2591 DEBUG(0,("call_trans2qfsinfo: not an allowed "
2592 "info level (0x%x) on IPC$.\n",
2593 (unsigned int)info_level));
2594 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
2599 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
2600 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2601 DEBUG(0,("call_trans2qfsinfo: encryption required "
2602 "and info level 0x%x sent.\n",
2603 (unsigned int)info_level));
2604 exit_server_cleanly("encryption required "
2610 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
2612 if(SMB_VFS_STAT(conn,".",&st)!=0) {
2613 DEBUG(2,("call_trans2qfsinfo: stat of . failed (%s)\n", strerror(errno)));
2614 reply_doserror(req, ERRSRV, ERRinvdevice);
2618 *ppdata = (char *)SMB_REALLOC(
2619 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2620 if (*ppdata == NULL ) {
2621 reply_nterror(req, NT_STATUS_NO_MEMORY);
2626 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2627 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2629 switch (info_level) {
2630 case SMB_INFO_ALLOCATION:
2632 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2634 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2635 reply_unixerror(req, ERRHRD, ERRgeneral);
2639 block_size = lp_block_size(snum);
2640 if (bsize < block_size) {
2641 uint64_t factor = block_size/bsize;
2646 if (bsize > block_size) {
2647 uint64_t factor = bsize/block_size;
2652 bytes_per_sector = 512;
2653 sectors_per_unit = bsize/bytes_per_sector;
2655 DEBUG(5,("call_trans2qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2656 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2657 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2659 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2660 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2661 SIVAL(pdata,l1_cUnit,dsize);
2662 SIVAL(pdata,l1_cUnitAvail,dfree);
2663 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2667 case SMB_INFO_VOLUME:
2668 /* Return volume name */
2670 * Add volume serial number - hash of a combination of
2671 * the called hostname and the service name.
2673 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2675 * Win2k3 and previous mess this up by sending a name length
2676 * one byte short. I believe only older clients (OS/2 Win9x) use
2677 * this call so try fixing this by adding a terminating null to
2678 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2682 pdata+l2_vol_szVolLabel, vname,
2683 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2684 STR_NOALIGN|STR_TERMINATE);
2685 SCVAL(pdata,l2_vol_cch,len);
2686 data_len = l2_vol_szVolLabel + len;
2687 DEBUG(5,("call_trans2qfsinfo : time = %x, namelen = %d, name = %s\n",
2688 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2692 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2693 case SMB_FS_ATTRIBUTE_INFORMATION:
2695 additional_flags = 0;
2696 #if defined(HAVE_SYS_QUOTAS)
2697 additional_flags |= FILE_VOLUME_QUOTAS;
2700 if(lp_nt_acl_support(SNUM(conn))) {
2701 additional_flags |= FILE_PERSISTENT_ACLS;
2704 /* Capabilities are filled in at connection time through STATVFS call */
2705 additional_flags |= conn->fs_capabilities;
2707 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2708 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2709 additional_flags); /* FS ATTRIBUTES */
2711 SIVAL(pdata,4,255); /* Max filename component length */
2712 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2713 and will think we can't do long filenames */
2714 len = srvstr_push(pdata, req->flags2, pdata+12, fstype,
2715 PTR_DIFF(end_data, pdata+12),
2718 data_len = 12 + len;
2721 case SMB_QUERY_FS_LABEL_INFO:
2722 case SMB_FS_LABEL_INFORMATION:
2723 len = srvstr_push(pdata, req->flags2, pdata+4, vname,
2724 PTR_DIFF(end_data, pdata+4), 0);
2729 case SMB_QUERY_FS_VOLUME_INFO:
2730 case SMB_FS_VOLUME_INFORMATION:
2733 * Add volume serial number - hash of a combination of
2734 * the called hostname and the service name.
2736 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
2737 (str_checksum(get_local_machine_name())<<16));
2739 /* Max label len is 32 characters. */
2740 len = srvstr_push(pdata, req->flags2, pdata+18, vname,
2741 PTR_DIFF(end_data, pdata+18),
2743 SIVAL(pdata,12,len);
2746 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
2747 (int)strlen(vname),vname, lp_servicename(snum)));
2750 case SMB_QUERY_FS_SIZE_INFO:
2751 case SMB_FS_SIZE_INFORMATION:
2753 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2755 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2756 reply_unixerror(req, ERRHRD, ERRgeneral);
2759 block_size = lp_block_size(snum);
2760 if (bsize < block_size) {
2761 uint64_t factor = block_size/bsize;
2766 if (bsize > block_size) {
2767 uint64_t factor = bsize/block_size;
2772 bytes_per_sector = 512;
2773 sectors_per_unit = bsize/bytes_per_sector;
2774 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2775 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2776 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2777 SBIG_UINT(pdata,0,dsize);
2778 SBIG_UINT(pdata,8,dfree);
2779 SIVAL(pdata,16,sectors_per_unit);
2780 SIVAL(pdata,20,bytes_per_sector);
2784 case SMB_FS_FULL_SIZE_INFORMATION:
2786 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2788 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2789 reply_unixerror(req, ERRHRD, ERRgeneral);
2792 block_size = lp_block_size(snum);
2793 if (bsize < block_size) {
2794 uint64_t factor = block_size/bsize;
2799 if (bsize > block_size) {
2800 uint64_t factor = bsize/block_size;
2805 bytes_per_sector = 512;
2806 sectors_per_unit = bsize/bytes_per_sector;
2807 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2808 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2809 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2810 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2811 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2812 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2813 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2814 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2818 case SMB_QUERY_FS_DEVICE_INFO:
2819 case SMB_FS_DEVICE_INFORMATION:
2821 SIVAL(pdata,0,0); /* dev type */
2822 SIVAL(pdata,4,0); /* characteristics */
2825 #ifdef HAVE_SYS_QUOTAS
2826 case SMB_FS_QUOTA_INFORMATION:
2828 * what we have to send --metze:
2830 * Unknown1: 24 NULL bytes
2831 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2832 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2833 * Quota Flags: 2 byte :
2834 * Unknown3: 6 NULL bytes
2838 * details for Quota Flags:
2840 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2841 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2842 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2843 * 0x0001 Enable Quotas: enable quota for this fs
2847 /* we need to fake up a fsp here,
2848 * because its not send in this call
2851 SMB_NTQUOTA_STRUCT quotas;
2854 ZERO_STRUCT(quotas);
2860 if (conn->server_info->utok.uid != 0) {
2861 DEBUG(0,("set_user_quota: access_denied "
2862 "service [%s] user [%s]\n",
2863 lp_servicename(SNUM(conn)),
2864 conn->server_info->unix_name));
2865 reply_doserror(req, ERRDOS, ERRnoaccess);
2869 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
2870 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2871 reply_doserror(req, ERRSRV, ERRerror);
2877 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",lp_servicename(SNUM(conn))));
2879 /* Unknown1 24 NULL bytes*/
2880 SBIG_UINT(pdata,0,(uint64_t)0);
2881 SBIG_UINT(pdata,8,(uint64_t)0);
2882 SBIG_UINT(pdata,16,(uint64_t)0);
2884 /* Default Soft Quota 8 bytes */
2885 SBIG_UINT(pdata,24,quotas.softlim);
2887 /* Default Hard Quota 8 bytes */
2888 SBIG_UINT(pdata,32,quotas.hardlim);
2890 /* Quota flag 2 bytes */
2891 SSVAL(pdata,40,quotas.qflags);
2893 /* Unknown3 6 NULL bytes */
2899 #endif /* HAVE_SYS_QUOTAS */
2900 case SMB_FS_OBJECTID_INFORMATION:
2902 unsigned char objid[16];
2903 struct smb_extended_info extended_info;
2904 memcpy(pdata,create_volume_objectid(conn, objid),16);
2905 samba_extended_info_version (&extended_info);
2906 SIVAL(pdata,16,extended_info.samba_magic);
2907 SIVAL(pdata,20,extended_info.samba_version);
2908 SIVAL(pdata,24,extended_info.samba_subversion);
2909 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2910 memcpy(pdata+36,extended_info.samba_version_string,28);
2916 * Query the version and capabilities of the CIFS UNIX extensions
2920 case SMB_QUERY_CIFS_UNIX_INFO:
2922 bool large_write = lp_min_receive_file_size() &&
2923 !srv_is_signing_active(smbd_server_conn);
2924 bool large_read = !srv_is_signing_active(smbd_server_conn);
2925 int encrypt_caps = 0;
2927 if (!lp_unix_extensions()) {
2928 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2932 switch (conn->encrypt_level) {
2938 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2941 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2942 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2943 large_write = false;
2949 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2950 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2952 /* We have POSIX ACLs, pathname, encryption,
2953 * large read/write, and locking capability. */
2955 SBIG_UINT(pdata,4,((uint64_t)(
2956 CIFS_UNIX_POSIX_ACLS_CAP|
2957 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2958 CIFS_UNIX_FCNTL_LOCKS_CAP|
2959 CIFS_UNIX_EXTATTR_CAP|
2960 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2962 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2964 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2968 case SMB_QUERY_POSIX_FS_INFO:
2971 vfs_statvfs_struct svfs;
2973 if (!lp_unix_extensions()) {
2974 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2978 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
2982 SIVAL(pdata,0,svfs.OptimalTransferSize);
2983 SIVAL(pdata,4,svfs.BlockSize);
2984 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2985 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2986 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2987 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2988 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2989 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2990 DEBUG(5,("call_trans2qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2992 } else if (rc == EOPNOTSUPP) {
2993 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2995 #endif /* EOPNOTSUPP */
2997 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
2998 reply_doserror(req, ERRSRV, ERRerror);
3004 case SMB_QUERY_POSIX_WHOAMI:
3010 if (!lp_unix_extensions()) {
3011 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3015 if (max_data_bytes < 40) {
3016 reply_nterror(req, NT_STATUS_BUFFER_TOO_SMALL);
3020 /* We ARE guest if global_sid_Builtin_Guests is
3021 * in our list of SIDs.
3023 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3024 conn->server_info->ptok)) {
3025 flags |= SMB_WHOAMI_GUEST;
3028 /* We are NOT guest if global_sid_Authenticated_Users
3029 * is in our list of SIDs.
3031 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3032 conn->server_info->ptok)) {
3033 flags &= ~SMB_WHOAMI_GUEST;
3036 /* NOTE: 8 bytes for UID/GID, irrespective of native
3037 * platform size. This matches
3038 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3040 data_len = 4 /* flags */
3047 + 4 /* pad/reserved */
3048 + (conn->server_info->utok.ngroups * 8)
3050 + (conn->server_info->ptok->num_sids *
3054 SIVAL(pdata, 0, flags);
3055 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3057 (uint64_t)conn->server_info->utok.uid);
3058 SBIG_UINT(pdata, 16,
3059 (uint64_t)conn->server_info->utok.gid);
3062 if (data_len >= max_data_bytes) {
3063 /* Potential overflow, skip the GIDs and SIDs. */
3065 SIVAL(pdata, 24, 0); /* num_groups */
3066 SIVAL(pdata, 28, 0); /* num_sids */
3067 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3068 SIVAL(pdata, 36, 0); /* reserved */
3074 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3075 SIVAL(pdata, 28, conn->server_info->num_sids);
3077 /* We walk the SID list twice, but this call is fairly
3078 * infrequent, and I don't expect that it's performance
3079 * sensitive -- jpeach
3081 for (i = 0, sid_bytes = 0;
3082 i < conn->server_info->ptok->num_sids; ++i) {
3083 sid_bytes += ndr_size_dom_sid(
3084 &conn->server_info->ptok->user_sids[i],
3089 /* SID list byte count */
3090 SIVAL(pdata, 32, sid_bytes);
3092 /* 4 bytes pad/reserved - must be zero */
3093 SIVAL(pdata, 36, 0);
3097 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3098 SBIG_UINT(pdata, data_len,
3099 (uint64_t)conn->server_info->utok.groups[i]);
3105 i < conn->server_info->ptok->num_sids; ++i) {
3106 int sid_len = ndr_size_dom_sid(
3107 &conn->server_info->ptok->user_sids[i],
3111 sid_linearize(pdata + data_len, sid_len,
3112 &conn->server_info->ptok->user_sids[i]);
3113 data_len += sid_len;
3119 case SMB_MAC_QUERY_FS_INFO:
3121 * Thursby MAC extension... ONLY on NTFS filesystems
3122 * once we do streams then we don't need this
3124 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3126 SIVAL(pdata,84,0x100); /* Don't support mac... */
3131 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3136 send_trans2_replies(conn, req, params, 0, pdata, data_len,
3139 DEBUG( 4, ( "%s info_level = %d\n",
3140 smb_fn_name(req->cmd), info_level) );
3145 /****************************************************************************
3146 Reply to a TRANS2_SETFSINFO (set filesystem info).
3147 ****************************************************************************/
3149 static void call_trans2setfsinfo(connection_struct *conn,
3150 struct smb_request *req,
3151 char **pparams, int total_params,
3152 char **ppdata, int total_data,
3153 unsigned int max_data_bytes)
3155 char *pdata = *ppdata;
3156 char *params = *pparams;
3159 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3162 if (total_params < 4) {
3163 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3165 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3169 info_level = SVAL(params,2);
3172 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3173 info_level != SMB_SET_CIFS_UNIX_INFO) {
3174 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3175 "info level (0x%x) on IPC$.\n",
3176 (unsigned int)info_level));
3177 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3182 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3183 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3184 DEBUG(0,("call_trans2setfsinfo: encryption required "
3185 "and info level 0x%x sent.\n",
3186 (unsigned int)info_level));
3187 exit_server_cleanly("encryption required "
3193 switch(info_level) {
3194 case SMB_SET_CIFS_UNIX_INFO:
3196 uint16 client_unix_major;
3197 uint16 client_unix_minor;
3198 uint32 client_unix_cap_low;
3199 uint32 client_unix_cap_high;
3201 if (!lp_unix_extensions()) {
3203 NT_STATUS_INVALID_LEVEL);
3207 /* There should be 12 bytes of capabilities set. */
3208 if (total_data < 8) {
3211 NT_STATUS_INVALID_PARAMETER);
3214 client_unix_major = SVAL(pdata,0);
3215 client_unix_minor = SVAL(pdata,2);
3216 client_unix_cap_low = IVAL(pdata,4);
3217 client_unix_cap_high = IVAL(pdata,8);
3218 /* Just print these values for now. */
3219 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3220 cap_low = 0x%x, cap_high = 0x%x\n",
3221 (unsigned int)client_unix_major,
3222 (unsigned int)client_unix_minor,
3223 (unsigned int)client_unix_cap_low,
3224 (unsigned int)client_unix_cap_high ));
3226 /* Here is where we must switch to posix pathname processing... */
3227 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3228 lp_set_posix_pathnames();
3229 mangle_change_to_posix();
3232 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3233 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3234 /* Client that knows how to do posix locks,
3235 * but not posix open/mkdir operations. Set a
3236 * default type for read/write checks. */
3238 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3244 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3247 size_t param_len = 0;
3248 size_t data_len = total_data;
3250 if (!lp_unix_extensions()) {
3253 NT_STATUS_INVALID_LEVEL);
3257 if (lp_smb_encrypt(SNUM(conn)) == false) {
3260 NT_STATUS_NOT_SUPPORTED);
3264 DEBUG( 4,("call_trans2setfsinfo: "
3265 "request transport encryption.\n"));
3267 status = srv_request_encryption_setup(conn,
3268 (unsigned char **)ppdata,
3270 (unsigned char **)pparams,
3273 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3274 !NT_STATUS_IS_OK(status)) {
3275 reply_nterror(req, status);
3279 send_trans2_replies(conn, req,
3286 if (NT_STATUS_IS_OK(status)) {
3287 /* Server-side transport
3288 * encryption is now *on*. */
3289 status = srv_encryption_start(conn);
3290 if (!NT_STATUS_IS_OK(status)) {
3291 exit_server_cleanly(
3292 "Failure in setting "
3293 "up encrypted transport");
3299 case SMB_FS_QUOTA_INFORMATION:
3301 files_struct *fsp = NULL;
3302 SMB_NTQUOTA_STRUCT quotas;
3304 ZERO_STRUCT(quotas);
3307 if ((conn->server_info->utok.uid != 0)
3308 ||!CAN_WRITE(conn)) {
3309 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3310 lp_servicename(SNUM(conn)),
3311 conn->server_info->unix_name));
3312 reply_doserror(req, ERRSRV, ERRaccess);
3316 /* note: normaly there're 48 bytes,
3317 * but we didn't use the last 6 bytes for now
3320 fsp = file_fsp(req, SVAL(params,0));
3322 if (!check_fsp_ntquota_handle(conn, req,
3324 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3326 req, NT_STATUS_INVALID_HANDLE);
3330 if (total_data < 42) {
3331 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3335 NT_STATUS_INVALID_PARAMETER);
3339 /* unknown_1 24 NULL bytes in pdata*/
3341 /* the soft quotas 8 bytes (uint64_t)*/
3342 quotas.softlim = (uint64_t)IVAL(pdata,24);
3343 #ifdef LARGE_SMB_OFF_T
3344 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3345 #else /* LARGE_SMB_OFF_T */
3346 if ((IVAL(pdata,28) != 0)&&
3347 ((quotas.softlim != 0xFFFFFFFF)||
3348 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3349 /* more than 32 bits? */
3352 NT_STATUS_INVALID_PARAMETER);
3355 #endif /* LARGE_SMB_OFF_T */
3357 /* the hard quotas 8 bytes (uint64_t)*/
3358 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3359 #ifdef LARGE_SMB_OFF_T
3360 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3361 #else /* LARGE_SMB_OFF_T */
3362 if ((IVAL(pdata,36) != 0)&&
3363 ((quotas.hardlim != 0xFFFFFFFF)||
3364 (IVAL(pdata,36)!=0xFFFFFFFF))) {