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,
75 SAMBA_XATTR_DOSTIMESTAMPS,
82 for (i = 0; prohibited_ea_names[i]; i++) {
83 if (strequal( prohibited_ea_names[i], unix_ea_name))
86 if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
87 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
93 /****************************************************************************
94 Get one EA value. Fill in a struct ea_struct.
95 ****************************************************************************/
97 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
98 files_struct *fsp, const char *fname,
99 const char *ea_name, struct ea_struct *pea)
101 /* Get the value of this xattr. Max size is 64k. */
102 size_t attr_size = 256;
108 val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size);
110 return NT_STATUS_NO_MEMORY;
113 if (fsp && fsp->fh->fd != -1) {
114 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
116 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
119 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
125 return map_nt_error_from_unix(errno);
128 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
129 dump_data(10, (uint8 *)val, sizeret);
132 if (strnequal(ea_name, "user.", 5)) {
133 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
135 pea->name = talloc_strdup(mem_ctx, ea_name);
137 if (pea->name == NULL) {
139 return NT_STATUS_NO_MEMORY;
141 pea->value.data = (unsigned char *)val;
142 pea->value.length = (size_t)sizeret;
146 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
147 files_struct *fsp, const char *fname,
148 char ***pnames, size_t *pnum_names)
150 /* Get a list of all xattrs. Max namesize is 64k. */
151 size_t ea_namelist_size = 1024;
152 char *ea_namelist = NULL;
157 ssize_t sizeret = -1;
159 if (!lp_ea_support(SNUM(conn))) {
168 * TALLOC the result early to get the talloc hierarchy right.
171 names = TALLOC_ARRAY(mem_ctx, char *, 1);
173 DEBUG(0, ("talloc failed\n"));
174 return NT_STATUS_NO_MEMORY;
177 while (ea_namelist_size <= 65536) {
179 ea_namelist = TALLOC_REALLOC_ARRAY(
180 names, ea_namelist, char, ea_namelist_size);
181 if (ea_namelist == NULL) {
182 DEBUG(0, ("talloc failed\n"));
184 return NT_STATUS_NO_MEMORY;
187 if (fsp && fsp->fh->fd != -1) {
188 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
191 sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist,
195 if ((sizeret == -1) && (errno == ERANGE)) {
196 ea_namelist_size *= 2;
205 return map_nt_error_from_unix(errno);
208 DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n",
209 (unsigned int)sizeret));
221 * Ensure the result is 0-terminated
224 if (ea_namelist[sizeret-1] != '\0') {
226 return NT_STATUS_INTERNAL_ERROR;
234 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
238 tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names);
240 DEBUG(0, ("talloc failed\n"));
242 return NT_STATUS_NO_MEMORY;
248 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
249 names[num_names++] = p;
257 *pnum_names = num_names;
261 /****************************************************************************
262 Return a linked list of the total EA's. Plus the total size
263 ****************************************************************************/
265 static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
266 const char *fname, size_t *pea_total_len)
268 /* Get a list of all xattrs. Max namesize is 64k. */
271 struct ea_list *ea_list_head = NULL;
276 if (!lp_ea_support(SNUM(conn))) {
280 status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname,
283 if (!NT_STATUS_IS_OK(status) || (num_names == 0)) {
287 for (i=0; i<num_names; i++) {
288 struct ea_list *listp;
291 if (strnequal(names[i], "system.", 7)
292 || samba_private_attr_name(names[i]))
295 listp = TALLOC_P(mem_ctx, struct ea_list);
300 if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp,
306 push_ascii_fstring(dos_ea_name, listp->ea.name);
309 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
311 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
312 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
313 (unsigned int)listp->ea.value.length));
315 DLIST_ADD_END(ea_list_head, listp, struct ea_list *);
319 /* Add on 4 for total length. */
320 if (*pea_total_len) {
324 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
325 (unsigned int)*pea_total_len));
330 /****************************************************************************
331 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
333 ****************************************************************************/
335 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
336 connection_struct *conn, struct ea_list *ea_list)
338 unsigned int ret_data_size = 4;
341 SMB_ASSERT(total_data_size >= 4);
343 if (!lp_ea_support(SNUM(conn))) {
348 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
351 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
352 dos_namelen = strlen(dos_ea_name);
353 if (dos_namelen > 255 || dos_namelen == 0) {
356 if (ea_list->ea.value.length > 65535) {
359 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
363 /* We know we have room. */
364 SCVAL(p,0,ea_list->ea.flags);
365 SCVAL(p,1,dos_namelen);
366 SSVAL(p,2,ea_list->ea.value.length);
367 fstrcpy(p+4, dos_ea_name);
368 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
370 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
371 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
374 ret_data_size = PTR_DIFF(p, pdata);
375 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
376 SIVAL(pdata,0,ret_data_size);
377 return ret_data_size;
380 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
382 unsigned int total_data_size,
383 unsigned int *ret_data_size,
384 connection_struct *conn,
385 struct ea_list *ea_list)
387 uint8_t *p = (uint8_t *)pdata;
388 uint8_t *last_start = NULL;
392 if (!lp_ea_support(SNUM(conn))) {
393 return NT_STATUS_NO_EAS_ON_FILE;
396 for (; ea_list; ea_list = ea_list->next) {
402 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
406 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
407 dos_namelen = strlen(dos_ea_name);
408 if (dos_namelen > 255 || dos_namelen == 0) {
409 return NT_STATUS_INTERNAL_ERROR;
411 if (ea_list->ea.value.length > 65535) {
412 return NT_STATUS_INTERNAL_ERROR;
415 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
418 size_t pad = 4 - (this_size % 4);
422 if (this_size > total_data_size) {
423 return NT_STATUS_INFO_LENGTH_MISMATCH;
426 /* We know we have room. */
427 SIVAL(p, 0x00, 0); /* next offset */
428 SCVAL(p, 0x04, ea_list->ea.flags);
429 SCVAL(p, 0x05, dos_namelen);
430 SSVAL(p, 0x06, ea_list->ea.value.length);
431 fstrcpy((char *)(p+0x08), dos_ea_name);
432 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
434 total_data_size -= this_size;
438 *ret_data_size = PTR_DIFF(p, pdata);
439 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
443 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const char *fname)
445 size_t total_ea_len = 0;
446 TALLOC_CTX *mem_ctx = NULL;
448 if (!lp_ea_support(SNUM(conn))) {
451 mem_ctx = talloc_tos();
452 (void)get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
456 /****************************************************************************
457 Ensure the EA name is case insensitive by matching any existing EA name.
458 ****************************************************************************/
460 static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
463 TALLOC_CTX *mem_ctx = talloc_tos();
464 struct ea_list *ea_list = get_ea_list_from_file(mem_ctx, conn, fsp, fname, &total_ea_len);
466 for (; ea_list; ea_list = ea_list->next) {
467 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
468 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
469 &unix_ea_name[5], ea_list->ea.name));
470 safe_strcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-6);
476 /****************************************************************************
477 Set or delete an extended attribute.
478 ****************************************************************************/
480 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
481 const struct smb_filename *smb_fname, struct ea_list *ea_list)
485 if (!lp_ea_support(SNUM(conn))) {
486 return NT_STATUS_EAS_NOT_SUPPORTED;
489 /* For now setting EAs on streams isn't supported. */
490 fname = smb_fname->base_name;
492 for (;ea_list; ea_list = ea_list->next) {
494 fstring unix_ea_name;
496 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
497 fstrcat(unix_ea_name, ea_list->ea.name);
499 canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
501 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
503 if (samba_private_attr_name(unix_ea_name)) {
504 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
505 return NT_STATUS_ACCESS_DENIED;
508 if (ea_list->ea.value.length == 0) {
509 /* Remove the attribute. */
510 if (fsp && (fsp->fh->fd != -1)) {
511 DEBUG(10,("set_ea: deleting ea name %s on "
512 "file %s by file descriptor.\n",
513 unix_ea_name, fsp_str_dbg(fsp)));
514 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
516 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
517 unix_ea_name, fname));
518 ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
521 /* Removing a non existent attribute always succeeds. */
522 if (ret == -1 && errno == ENOATTR) {
523 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
529 if (fsp && (fsp->fh->fd != -1)) {
530 DEBUG(10,("set_ea: setting ea name %s on file "
531 "%s by file descriptor.\n",
532 unix_ea_name, fsp_str_dbg(fsp)));
533 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
534 ea_list->ea.value.data, ea_list->ea.value.length, 0);
536 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
537 unix_ea_name, fname));
538 ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
539 ea_list->ea.value.data, ea_list->ea.value.length, 0);
545 if (errno == ENOTSUP) {
546 return NT_STATUS_EAS_NOT_SUPPORTED;
549 return map_nt_error_from_unix(errno);
555 /****************************************************************************
556 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
557 ****************************************************************************/
559 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
561 struct ea_list *ea_list_head = NULL;
562 size_t converted_size, offset = 0;
564 while (offset + 2 < data_size) {
565 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
566 unsigned int namelen = CVAL(pdata,offset);
568 offset++; /* Go past the namelen byte. */
570 /* integer wrap paranioa. */
571 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
572 (offset > data_size) || (namelen > data_size) ||
573 (offset + namelen >= data_size)) {
576 /* Ensure the name is null terminated. */
577 if (pdata[offset + namelen] != '\0') {
580 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
582 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
583 "failed: %s", strerror(errno)));
589 offset += (namelen + 1); /* Go past the name + terminating zero. */
590 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
591 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
597 /****************************************************************************
598 Read one EA list entry from the buffer.
599 ****************************************************************************/
601 struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t data_size, size_t *pbytes_used)
603 struct ea_list *eal = TALLOC_ZERO_P(ctx, struct ea_list);
605 unsigned int namelen;
606 size_t converted_size;
616 eal->ea.flags = CVAL(pdata,0);
617 namelen = CVAL(pdata,1);
618 val_len = SVAL(pdata,2);
620 if (4 + namelen + 1 + val_len > data_size) {
624 /* Ensure the name is null terminated. */
625 if (pdata[namelen + 4] != '\0') {
628 if (!pull_ascii_talloc(ctx, &eal->ea.name, pdata + 4, &converted_size)) {
629 DEBUG(0,("read_ea_list_entry: pull_ascii_talloc failed: %s",
636 eal->ea.value = data_blob_talloc(eal, NULL, (size_t)val_len + 1);
637 if (!eal->ea.value.data) {
641 memcpy(eal->ea.value.data, pdata + 4 + namelen + 1, val_len);
643 /* Ensure we're null terminated just in case we print the value. */
644 eal->ea.value.data[val_len] = '\0';
645 /* But don't count the null. */
646 eal->ea.value.length--;
649 *pbytes_used = 4 + namelen + 1 + val_len;
652 DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
653 dump_data(10, eal->ea.value.data, eal->ea.value.length);
658 /****************************************************************************
659 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
660 ****************************************************************************/
662 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
664 struct ea_list *ea_list_head = NULL;
666 size_t bytes_used = 0;
668 while (offset < data_size) {
669 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
675 DLIST_ADD_END(ea_list_head, eal, struct ea_list *);
676 offset += bytes_used;
682 /****************************************************************************
683 Count the total EA size needed.
684 ****************************************************************************/
686 static size_t ea_list_size(struct ea_list *ealist)
689 struct ea_list *listp;
692 for (listp = ealist; listp; listp = listp->next) {
693 push_ascii_fstring(dos_ea_name, listp->ea.name);
694 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
696 /* Add on 4 for total length. */
704 /****************************************************************************
705 Return a union of EA's from a file list and a list of names.
706 The TALLOC context for the two lists *MUST* be identical as we steal
707 memory from one list to add to another. JRA.
708 ****************************************************************************/
710 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
712 struct ea_list *nlistp, *flistp;
714 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
715 for (flistp = file_list; flistp; flistp = flistp->next) {
716 if (strequal(nlistp->ea.name, flistp->ea.name)) {
722 /* Copy the data from this entry. */
723 nlistp->ea.flags = flistp->ea.flags;
724 nlistp->ea.value = flistp->ea.value;
727 nlistp->ea.flags = 0;
728 ZERO_STRUCT(nlistp->ea.value);
732 *total_ea_len = ea_list_size(name_list);
736 /****************************************************************************
737 Send the required number of replies back.
738 We assume all fields other than the data fields are
739 set correctly for the type of call.
740 HACK ! Always assumes smb_setup field is zero.
741 ****************************************************************************/
743 void send_trans2_replies(connection_struct *conn,
744 struct smb_request *req,
751 /* As we are using a protocol > LANMAN1 then the max_send
752 variable must have been set in the sessetupX call.
753 This takes precedence over the max_xmit field in the
754 global struct. These different max_xmit variables should
755 be merged as this is now too confusing */
757 int data_to_send = datasize;
758 int params_to_send = paramsize;
760 const char *pp = params;
761 const char *pd = pdata;
762 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
763 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
764 int data_alignment_offset = 0;
765 bool overflow = False;
766 struct smbd_server_connection *sconn = smbd_server_conn;
767 int max_send = sconn->smb1.sessions.max_send;
769 /* Modify the data_to_send and datasize and set the error if
770 we're trying to send more than max_data_bytes. We still send
771 the part of the packet(s) that fit. Strange, but needed
774 if (max_data_bytes > 0 && datasize > max_data_bytes) {
775 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
776 max_data_bytes, datasize ));
777 datasize = data_to_send = max_data_bytes;
781 /* If there genuinely are no parameters or data to send just send the empty packet */
783 if(params_to_send == 0 && data_to_send == 0) {
784 reply_outbuf(req, 10, 0);
785 show_msg((char *)req->outbuf);
786 if (!srv_send_smb(smbd_server_fd(),
789 IS_CONN_ENCRYPTED(conn),
791 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
793 TALLOC_FREE(req->outbuf);
797 /* When sending params and data ensure that both are nicely aligned */
798 /* Only do this alignment when there is also data to send - else
799 can cause NT redirector problems. */
801 if (((params_to_send % 4) != 0) && (data_to_send != 0))
802 data_alignment_offset = 4 - (params_to_send % 4);
804 /* Space is bufsize minus Netbios over TCP header minus SMB header */
805 /* The alignment_offset is to align the param bytes on an even byte
806 boundary. NT 4.0 Beta needs this to work correctly. */
808 useable_space = max_send - (smb_size
811 + data_alignment_offset);
813 if (useable_space < 0) {
814 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
815 "= %d!!!", useable_space));
816 exit_server_cleanly("send_trans2_replies: Not enough space");
819 while (params_to_send || data_to_send) {
820 /* Calculate whether we will totally or partially fill this packet */
822 total_sent_thistime = params_to_send + data_to_send;
824 /* We can never send more than useable_space */
826 * Note that 'useable_space' does not include the alignment offsets,
827 * but we must include the alignment offsets in the calculation of
828 * the length of the data we send over the wire, as the alignment offsets
829 * are sent here. Fix from Marc_Jacobsen@hp.com.
832 total_sent_thistime = MIN(total_sent_thistime, useable_space);
834 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
835 + data_alignment_offset);
838 * We might have SMBtrans2s in req which was transferred to
839 * the outbuf, fix that.
841 SCVAL(req->outbuf, smb_com, SMBtrans2);
843 /* Set total params and data to be sent */
844 SSVAL(req->outbuf,smb_tprcnt,paramsize);
845 SSVAL(req->outbuf,smb_tdrcnt,datasize);
847 /* Calculate how many parameters and data we can fit into
848 * this packet. Parameters get precedence
851 params_sent_thistime = MIN(params_to_send,useable_space);
852 data_sent_thistime = useable_space - params_sent_thistime;
853 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
855 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
857 /* smb_proff is the offset from the start of the SMB header to the
858 parameter bytes, however the first 4 bytes of outbuf are
859 the Netbios over TCP header. Thus use smb_base() to subtract
860 them from the calculation */
862 SSVAL(req->outbuf,smb_proff,
863 ((smb_buf(req->outbuf)+alignment_offset)
864 - smb_base(req->outbuf)));
866 if(params_sent_thistime == 0)
867 SSVAL(req->outbuf,smb_prdisp,0);
869 /* Absolute displacement of param bytes sent in this packet */
870 SSVAL(req->outbuf,smb_prdisp,pp - params);
872 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
873 if(data_sent_thistime == 0) {
874 SSVAL(req->outbuf,smb_droff,0);
875 SSVAL(req->outbuf,smb_drdisp, 0);
877 /* The offset of the data bytes is the offset of the
878 parameter bytes plus the number of parameters being sent this time */
879 SSVAL(req->outbuf, smb_droff,
880 ((smb_buf(req->outbuf)+alignment_offset)
881 - smb_base(req->outbuf))
882 + params_sent_thistime + data_alignment_offset);
883 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
886 /* Initialize the padding for alignment */
888 if (alignment_offset != 0) {
889 memset(smb_buf(req->outbuf), 0, alignment_offset);
892 /* Copy the param bytes into the packet */
894 if(params_sent_thistime) {
895 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
896 params_sent_thistime);
899 /* Copy in the data bytes */
900 if(data_sent_thistime) {
901 if (data_alignment_offset != 0) {
902 memset((smb_buf(req->outbuf)+alignment_offset+
903 params_sent_thistime), 0,
904 data_alignment_offset);
906 memcpy(smb_buf(req->outbuf)+alignment_offset
907 +params_sent_thistime+data_alignment_offset,
908 pd,data_sent_thistime);
911 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
912 params_sent_thistime, data_sent_thistime, useable_space));
913 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
914 params_to_send, data_to_send, paramsize, datasize));
917 error_packet_set((char *)req->outbuf,
918 ERRDOS,ERRbufferoverflow,
919 STATUS_BUFFER_OVERFLOW,
923 /* Send the packet */
924 show_msg((char *)req->outbuf);
925 if (!srv_send_smb(smbd_server_fd(),
928 IS_CONN_ENCRYPTED(conn),
930 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
932 TALLOC_FREE(req->outbuf);
934 pp += params_sent_thistime;
935 pd += data_sent_thistime;
937 params_to_send -= params_sent_thistime;
938 data_to_send -= data_sent_thistime;
941 if(params_to_send < 0 || data_to_send < 0) {
942 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
943 params_to_send, data_to_send));
951 /****************************************************************************
952 Reply to a TRANSACT2_OPEN.
953 ****************************************************************************/
955 static void call_trans2open(connection_struct *conn,
956 struct smb_request *req,
957 char **pparams, int total_params,
958 char **ppdata, int total_data,
959 unsigned int max_data_bytes)
961 struct smb_filename *smb_fname = NULL;
962 char *params = *pparams;
963 char *pdata = *ppdata;
968 bool return_additional_info;
981 struct ea_list *ea_list = NULL;
986 uint32 create_disposition;
987 uint32 create_options = 0;
988 TALLOC_CTX *ctx = talloc_tos();
991 * Ensure we have enough parameters to perform the operation.
994 if (total_params < 29) {
995 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
999 flags = SVAL(params, 0);
1000 deny_mode = SVAL(params, 2);
1001 open_attr = SVAL(params,6);
1002 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1003 if (oplock_request) {
1004 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1008 return_additional_info = BITSETW(params,0);
1009 open_sattr = SVAL(params, 4);
1010 open_time = make_unix_date3(params+8);
1012 open_ofun = SVAL(params,12);
1013 open_size = IVAL(params,14);
1014 pname = ¶ms[28];
1017 reply_doserror(req, ERRSRV, ERRaccess);
1021 srvstr_get_path(ctx, params, req->flags2, &fname, pname,
1022 total_params - 28, STR_TERMINATE,
1024 if (!NT_STATUS_IS_OK(status)) {
1025 reply_nterror(req, status);
1029 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1030 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1031 (unsigned int)open_ofun, open_size));
1033 status = filename_convert(ctx,
1035 req->flags2 & FLAGS2_DFS_PATHNAMES,
1040 if (!NT_STATUS_IS_OK(status)) {
1041 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1042 reply_botherror(req,
1043 NT_STATUS_PATH_NOT_COVERED,
1044 ERRSRV, ERRbadpath);
1047 reply_nterror(req, status);
1051 if (open_ofun == 0) {
1052 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1056 if (!map_open_params_to_ntcreate(smb_fname, deny_mode, open_ofun,
1057 &access_mask, &share_mode,
1058 &create_disposition,
1060 reply_doserror(req, ERRDOS, ERRbadaccess);
1064 /* Any data in this call is an EA list. */
1065 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
1066 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1070 if (total_data != 4) {
1071 if (total_data < 10) {
1072 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1076 if (IVAL(pdata,0) > total_data) {
1077 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1078 IVAL(pdata,0), (unsigned int)total_data));
1079 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1083 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1086 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1089 } else if (IVAL(pdata,0) != 4) {
1090 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1094 status = SMB_VFS_CREATE_FILE(
1097 0, /* root_dir_fid */
1098 smb_fname, /* fname */
1099 access_mask, /* access_mask */
1100 share_mode, /* share_access */
1101 create_disposition, /* create_disposition*/
1102 create_options, /* create_options */
1103 open_attr, /* file_attributes */
1104 oplock_request, /* oplock_request */
1105 open_size, /* allocation_size */
1107 ea_list, /* ea_list */
1109 &smb_action); /* psbuf */
1111 if (!NT_STATUS_IS_OK(status)) {
1112 if (open_was_deferred(req->mid)) {
1113 /* We have re-scheduled this call. */
1116 reply_openerror(req, status);
1120 size = get_file_size_stat(&smb_fname->st);
1121 fattr = dos_mode(conn, smb_fname);
1122 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1123 inode = smb_fname->st.st_ex_ino;
1125 close_file(req, fsp, ERROR_CLOSE);
1126 reply_doserror(req, ERRDOS,ERRnoaccess);
1130 /* Realloc the size of parameters and data we will return */
1131 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1132 if(*pparams == NULL ) {
1133 reply_nterror(req, NT_STATUS_NO_MEMORY);
1138 SSVAL(params,0,fsp->fnum);
1139 SSVAL(params,2,fattr);
1140 srv_put_dos_date2(params,4, mtime);
1141 SIVAL(params,8, (uint32)size);
1142 SSVAL(params,12,deny_mode);
1143 SSVAL(params,14,0); /* open_type - file or directory. */
1144 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1146 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1147 smb_action |= EXTENDED_OPLOCK_GRANTED;
1150 SSVAL(params,18,smb_action);
1153 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1155 SIVAL(params,20,inode);
1156 SSVAL(params,24,0); /* Padding. */
1158 uint32 ea_size = estimate_ea_size(conn, fsp,
1159 fsp->fsp_name->base_name);
1160 SIVAL(params, 26, ea_size);
1162 SIVAL(params, 26, 0);
1165 /* Send the required number of replies */
1166 send_trans2_replies(conn, req, params, 30, *ppdata, 0, max_data_bytes);
1168 TALLOC_FREE(smb_fname);
1171 /*********************************************************
1172 Routine to check if a given string matches exactly.
1173 as a special case a mask of "." does NOT match. That
1174 is required for correct wildcard semantics
1175 Case can be significant or not.
1176 **********************************************************/
1178 static bool exact_match(bool has_wild,
1179 bool case_sensitive,
1183 if (mask[0] == '.' && mask[1] == 0) {
1191 if (case_sensitive) {
1192 return strcmp(str,mask)==0;
1194 return StrCaseCmp(str,mask) == 0;
1198 /****************************************************************************
1199 Return the filetype for UNIX extensions.
1200 ****************************************************************************/
1202 static uint32 unix_filetype(mode_t mode)
1205 return UNIX_TYPE_FILE;
1206 else if(S_ISDIR(mode))
1207 return UNIX_TYPE_DIR;
1209 else if(S_ISLNK(mode))
1210 return UNIX_TYPE_SYMLINK;
1213 else if(S_ISCHR(mode))
1214 return UNIX_TYPE_CHARDEV;
1217 else if(S_ISBLK(mode))
1218 return UNIX_TYPE_BLKDEV;
1221 else if(S_ISFIFO(mode))
1222 return UNIX_TYPE_FIFO;
1225 else if(S_ISSOCK(mode))
1226 return UNIX_TYPE_SOCKET;
1229 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1230 return UNIX_TYPE_UNKNOWN;
1233 /****************************************************************************
1234 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1235 ****************************************************************************/
1237 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1239 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1240 const SMB_STRUCT_STAT *psbuf,
1242 enum perm_type ptype,
1247 if (perms == SMB_MODE_NO_CHANGE) {
1248 if (!VALID_STAT(*psbuf)) {
1249 return NT_STATUS_INVALID_PARAMETER;
1251 *ret_perms = psbuf->st_ex_mode;
1252 return NT_STATUS_OK;
1256 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1257 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1258 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1259 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1260 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1261 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1262 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1263 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1264 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1266 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1269 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1272 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1277 /* Apply mode mask */
1278 ret &= lp_create_mask(SNUM(conn));
1279 /* Add in force bits */
1280 ret |= lp_force_create_mode(SNUM(conn));
1283 ret &= lp_dir_mask(SNUM(conn));
1284 /* Add in force bits */
1285 ret |= lp_force_dir_mode(SNUM(conn));
1287 case PERM_EXISTING_FILE:
1288 /* Apply mode mask */
1289 ret &= lp_security_mask(SNUM(conn));
1290 /* Add in force bits */
1291 ret |= lp_force_security_mode(SNUM(conn));
1293 case PERM_EXISTING_DIR:
1294 /* Apply mode mask */
1295 ret &= lp_dir_security_mask(SNUM(conn));
1296 /* Add in force bits */
1297 ret |= lp_force_dir_security_mode(SNUM(conn));
1302 return NT_STATUS_OK;
1305 /****************************************************************************
1306 Needed to show the msdfs symlinks as directories. Modifies psbuf
1307 to be a directory if it's a msdfs link.
1308 ****************************************************************************/
1310 static bool check_msdfs_link(connection_struct *conn,
1311 const char *pathname,
1312 SMB_STRUCT_STAT *psbuf)
1314 int saved_errno = errno;
1315 if(lp_host_msdfs() &&
1316 lp_msdfs_root(SNUM(conn)) &&
1317 is_msdfs_link(conn, pathname, psbuf)) {
1319 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1322 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1323 errno = saved_errno;
1326 errno = saved_errno;
1331 /****************************************************************************
1332 Get a level dependent lanman2 dir entry.
1333 ****************************************************************************/
1335 struct smbd_dirptr_lanman2_state {
1336 connection_struct *conn;
1337 uint32_t info_level;
1338 bool check_mangled_names;
1340 bool got_exact_match;
1343 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1349 struct smbd_dirptr_lanman2_state *state =
1350 (struct smbd_dirptr_lanman2_state *)private_data;
1352 char mangled_name[13]; /* mangled 8.3 name. */
1356 /* Mangle fname if it's an illegal name. */
1357 if (mangle_must_mangle(dname, state->conn->params)) {
1358 ok = name_to_8_3(dname, mangled_name,
1359 true, state->conn->params);
1363 fname = mangled_name;
1368 got_match = exact_match(state->has_wild,
1369 state->conn->case_sensitive,
1371 state->got_exact_match = got_match;
1373 got_match = mask_match(fname, mask,
1374 state->conn->case_sensitive);
1377 if(!got_match && state->check_mangled_names &&
1378 !mangle_is_8_3(fname, false, state->conn->params)) {
1380 * It turns out that NT matches wildcards against
1381 * both long *and* short names. This may explain some
1382 * of the wildcard wierdness from old DOS clients
1383 * that some people have been seeing.... JRA.
1385 /* Force the mangling into 8.3. */
1386 ok = name_to_8_3(fname, mangled_name,
1387 false, state->conn->params);
1392 got_match = exact_match(state->has_wild,
1393 state->conn->case_sensitive,
1394 mangled_name, mask);
1395 state->got_exact_match = got_match;
1397 got_match = mask_match(mangled_name, mask,
1398 state->conn->case_sensitive);
1406 *_fname = talloc_strdup(ctx, fname);
1407 if (*_fname == NULL) {
1414 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1416 struct smb_filename *smb_fname,
1419 struct smbd_dirptr_lanman2_state *state =
1420 (struct smbd_dirptr_lanman2_state *)private_data;
1421 bool ms_dfs_link = false;
1424 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1425 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1426 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1427 "Couldn't lstat [%s] (%s)\n",
1428 smb_fname_str_dbg(smb_fname),
1432 } else if (!VALID_STAT(smb_fname->st) &&
1433 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1434 /* Needed to show the msdfs symlinks as
1437 ms_dfs_link = check_msdfs_link(state->conn,
1438 smb_fname->base_name,
1441 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1442 "Couldn't stat [%s] (%s)\n",
1443 smb_fname_str_dbg(smb_fname),
1450 mode = dos_mode_msdfs(state->conn, smb_fname);
1452 mode = dos_mode(state->conn, smb_fname);
1459 static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1460 connection_struct *conn,
1462 uint32_t info_level,
1463 struct ea_list *name_list,
1464 bool check_mangled_names,
1465 bool requires_resume_key,
1468 const struct smb_filename *smb_fname,
1469 uint64_t space_remaining,
1476 uint64_t *last_entry_off)
1478 char *p, *q, *pdata = *ppdata;
1480 uint64_t file_size = 0;
1481 uint64_t allocation_size = 0;
1483 struct timespec mdate_ts, adate_ts, cdate_ts, create_date_ts;
1484 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1485 time_t c_date = (time_t)0;
1487 char *last_entry_ptr;
1489 uint32_t nt_extmode; /* Used for NT connections instead of mode */
1493 *out_of_space = false;
1495 ZERO_STRUCT(mdate_ts);
1496 ZERO_STRUCT(adate_ts);
1497 ZERO_STRUCT(create_date_ts);
1498 ZERO_STRUCT(cdate_ts);
1500 if (!(mode & aDIR)) {
1501 file_size = get_file_size_stat(&smb_fname->st);
1503 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1505 mdate_ts = smb_fname->st.st_ex_mtime;
1506 adate_ts = smb_fname->st.st_ex_atime;
1507 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1508 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1510 if (lp_dos_filetime_resolution(SNUM(conn))) {
1511 dos_filetime_timespec(&create_date_ts);
1512 dos_filetime_timespec(&mdate_ts);
1513 dos_filetime_timespec(&adate_ts);
1514 dos_filetime_timespec(&cdate_ts);
1517 create_date = convert_timespec_to_time_t(create_date_ts);
1518 mdate = convert_timespec_to_time_t(mdate_ts);
1519 adate = convert_timespec_to_time_t(adate_ts);
1520 c_date = convert_timespec_to_time_t(cdate_ts);
1522 /* align the record */
1523 off = PTR_DIFF(pdata, base_data);
1524 pad = (off + (align-1)) & ~(align-1);
1527 /* initialize padding to 0 */
1529 memset(pdata, 0, pad);
1531 space_remaining -= pad;
1540 nt_extmode = mode ? mode : FILE_ATTRIBUTE_NORMAL;
1542 switch (info_level) {
1543 case SMB_FIND_INFO_STANDARD:
1544 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1545 if(requires_resume_key) {
1549 srv_put_dos_date2(p,0,create_date);
1550 srv_put_dos_date2(p,4,adate);
1551 srv_put_dos_date2(p,8,mdate);
1552 SIVAL(p,12,(uint32)file_size);
1553 SIVAL(p,16,(uint32)allocation_size);
1557 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1558 p += ucs2_align(base_data, p, 0);
1560 len = srvstr_push(base_data, flags2, p,
1561 fname, PTR_DIFF(end_data, p),
1563 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1565 SCVAL(nameptr, -1, len - 2);
1567 SCVAL(nameptr, -1, 0);
1571 SCVAL(nameptr, -1, len - 1);
1573 SCVAL(nameptr, -1, 0);
1579 case SMB_FIND_EA_SIZE:
1580 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_SIZE\n"));
1581 if (requires_resume_key) {
1585 srv_put_dos_date2(p,0,create_date);
1586 srv_put_dos_date2(p,4,adate);
1587 srv_put_dos_date2(p,8,mdate);
1588 SIVAL(p,12,(uint32)file_size);
1589 SIVAL(p,16,(uint32)allocation_size);
1592 unsigned int ea_size = estimate_ea_size(conn, NULL,
1593 smb_fname->base_name);
1594 SIVAL(p,22,ea_size); /* Extended attributes */
1598 len = srvstr_push(base_data, flags2,
1599 p, fname, PTR_DIFF(end_data, p),
1600 STR_TERMINATE | STR_NOALIGN);
1601 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1614 SCVAL(nameptr,0,len);
1616 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1619 case SMB_FIND_EA_LIST:
1621 struct ea_list *file_list = NULL;
1624 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_EA_LIST\n"));
1628 if (requires_resume_key) {
1632 srv_put_dos_date2(p,0,create_date);
1633 srv_put_dos_date2(p,4,adate);
1634 srv_put_dos_date2(p,8,mdate);
1635 SIVAL(p,12,(uint32)file_size);
1636 SIVAL(p,16,(uint32)allocation_size);
1638 p += 22; /* p now points to the EA area. */
1640 file_list = get_ea_list_from_file(ctx, conn, NULL,
1641 smb_fname->base_name,
1643 name_list = ea_list_union(name_list, file_list, &ea_len);
1645 /* We need to determine if this entry will fit in the space available. */
1646 /* Max string size is 255 bytes. */
1647 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1648 *out_of_space = true;
1649 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
1650 return False; /* Not finished - just out of space */
1653 /* Push the ea_data followed by the name. */
1654 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1656 len = srvstr_push(base_data, flags2,
1657 p + 1, fname, PTR_DIFF(end_data, p+1),
1658 STR_TERMINATE | STR_NOALIGN);
1659 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1672 SCVAL(nameptr,0,len);
1674 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1678 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1679 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1680 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1682 SIVAL(p,0,reskey); p += 4;
1683 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1684 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1685 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1686 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1687 SOFF_T(p,0,file_size); p += 8;
1688 SOFF_T(p,0,allocation_size); p += 8;
1689 SIVAL(p,0,nt_extmode); p += 4;
1690 q = p; p += 4; /* q is placeholder for name length. */
1692 unsigned int ea_size = estimate_ea_size(conn, NULL,
1693 smb_fname->base_name);
1694 SIVAL(p,0,ea_size); /* Extended attributes */
1697 /* Clear the short name buffer. This is
1698 * IMPORTANT as not doing so will trigger
1699 * a Win2k client bug. JRA.
1701 if (!was_8_3 && check_mangled_names) {
1702 char mangled_name[13]; /* mangled 8.3 name. */
1703 if (!name_to_8_3(fname,mangled_name,True,
1705 /* Error - mangle failed ! */
1706 memset(mangled_name,'\0',12);
1708 mangled_name[12] = 0;
1709 len = srvstr_push(base_data, flags2,
1710 p+2, mangled_name, 24,
1711 STR_UPPER|STR_UNICODE);
1713 memset(p + 2 + len,'\0',24 - len);
1720 len = srvstr_push(base_data, flags2, p,
1721 fname, PTR_DIFF(end_data, p),
1722 STR_TERMINATE_ASCII);
1726 len = PTR_DIFF(p, pdata);
1727 pad = (len + (align-1)) & ~(align-1);
1729 * offset to the next entry, the caller
1730 * will overwrite it for the last entry
1731 * that's why we always include the padding
1735 * set padding to zero
1738 memset(p, 0, pad - len);
1745 case SMB_FIND_FILE_DIRECTORY_INFO:
1746 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1748 SIVAL(p,0,reskey); p += 4;
1749 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1750 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1751 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1752 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1753 SOFF_T(p,0,file_size); p += 8;
1754 SOFF_T(p,0,allocation_size); p += 8;
1755 SIVAL(p,0,nt_extmode); p += 4;
1756 len = srvstr_push(base_data, flags2,
1757 p + 4, fname, PTR_DIFF(end_data, p+4),
1758 STR_TERMINATE_ASCII);
1762 len = PTR_DIFF(p, pdata);
1763 pad = (len + (align-1)) & ~(align-1);
1765 * offset to the next entry, the caller
1766 * will overwrite it for the last entry
1767 * that's why we always include the padding
1771 * set padding to zero
1774 memset(p, 0, pad - len);
1781 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1782 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1784 SIVAL(p,0,reskey); p += 4;
1785 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1786 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1787 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1788 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1789 SOFF_T(p,0,file_size); p += 8;
1790 SOFF_T(p,0,allocation_size); p += 8;
1791 SIVAL(p,0,nt_extmode); p += 4;
1792 q = p; p += 4; /* q is placeholder for name length. */
1794 unsigned int ea_size = estimate_ea_size(conn, NULL,
1795 smb_fname->base_name);
1796 SIVAL(p,0,ea_size); /* Extended attributes */
1799 len = srvstr_push(base_data, flags2, p,
1800 fname, PTR_DIFF(end_data, p),
1801 STR_TERMINATE_ASCII);
1805 len = PTR_DIFF(p, pdata);
1806 pad = (len + (align-1)) & ~(align-1);
1808 * offset to the next entry, the caller
1809 * will overwrite it for the last entry
1810 * that's why we always include the padding
1814 * set padding to zero
1817 memset(p, 0, pad - len);
1824 case SMB_FIND_FILE_NAMES_INFO:
1825 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1827 SIVAL(p,0,reskey); p += 4;
1829 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1830 acl on a dir (tridge) */
1831 len = srvstr_push(base_data, flags2, p,
1832 fname, PTR_DIFF(end_data, p),
1833 STR_TERMINATE_ASCII);
1837 len = PTR_DIFF(p, pdata);
1838 pad = (len + (align-1)) & ~(align-1);
1840 * offset to the next entry, the caller
1841 * will overwrite it for the last entry
1842 * that's why we always include the padding
1846 * set padding to zero
1849 memset(p, 0, pad - len);
1856 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1857 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1859 SIVAL(p,0,reskey); p += 4;
1860 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1861 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1862 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1863 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1864 SOFF_T(p,0,file_size); p += 8;
1865 SOFF_T(p,0,allocation_size); p += 8;
1866 SIVAL(p,0,nt_extmode); p += 4;
1867 q = p; p += 4; /* q is placeholder for name length. */
1869 unsigned int ea_size = estimate_ea_size(conn, NULL,
1870 smb_fname->base_name);
1871 SIVAL(p,0,ea_size); /* Extended attributes */
1874 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1875 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1876 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1877 len = srvstr_push(base_data, flags2, p,
1878 fname, PTR_DIFF(end_data, p),
1879 STR_TERMINATE_ASCII);
1883 len = PTR_DIFF(p, pdata);
1884 pad = (len + (align-1)) & ~(align-1);
1886 * offset to the next entry, the caller
1887 * will overwrite it for the last entry
1888 * that's why we always include the padding
1892 * set padding to zero
1895 memset(p, 0, pad - len);
1902 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1903 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1904 was_8_3 = mangle_is_8_3(fname, True, conn->params);
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,nt_extmode); 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 /* Clear the short name buffer. This is
1922 * IMPORTANT as not doing so will trigger
1923 * a Win2k client bug. JRA.
1925 if (!was_8_3 && check_mangled_names) {
1926 char mangled_name[13]; /* mangled 8.3 name. */
1927 if (!name_to_8_3(fname,mangled_name,True,
1929 /* Error - mangle failed ! */
1930 memset(mangled_name,'\0',12);
1932 mangled_name[12] = 0;
1933 len = srvstr_push(base_data, flags2,
1934 p+2, mangled_name, 24,
1935 STR_UPPER|STR_UNICODE);
1938 memset(p + 2 + len,'\0',24 - len);
1945 SSVAL(p,0,0); p += 2; /* Reserved ? */
1946 SIVAL(p,0,smb_fname->st.st_ex_ino); p += 4; /* FileIndexLow */
1947 SIVAL(p,0,smb_fname->st.st_ex_dev); p += 4; /* FileIndexHigh */
1948 len = srvstr_push(base_data, flags2, p,
1949 fname, PTR_DIFF(end_data, p),
1950 STR_TERMINATE_ASCII);
1954 len = PTR_DIFF(p, pdata);
1955 pad = (len + (align-1)) & ~(align-1);
1957 * offset to the next entry, the caller
1958 * will overwrite it for the last entry
1959 * that's why we always include the padding
1963 * set padding to zero
1966 memset(p, 0, pad - len);
1973 /* CIFS UNIX Extension. */
1975 case SMB_FIND_FILE_UNIX:
1976 case SMB_FIND_FILE_UNIX_INFO2:
1978 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1980 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1982 if (info_level == SMB_FIND_FILE_UNIX) {
1983 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX\n"));
1984 p = store_file_unix_basic(conn, p,
1985 NULL, &smb_fname->st);
1986 len = srvstr_push(base_data, flags2, p,
1987 fname, PTR_DIFF(end_data, p),
1990 DEBUG(10,("get_lanman2_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1991 p = store_file_unix_basic_info2(conn, p,
1992 NULL, &smb_fname->st);
1995 len = srvstr_push(base_data, flags2, p, fname,
1996 PTR_DIFF(end_data, p), 0);
1997 SIVAL(nameptr, 0, len);
2002 len = PTR_DIFF(p, pdata);
2003 pad = (len + (align-1)) & ~(align-1);
2005 * offset to the next entry, the caller
2006 * will overwrite it for the last entry
2007 * that's why we always include the padding
2011 * set padding to zero
2014 memset(p, 0, pad - len);
2019 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2027 if (PTR_DIFF(p,pdata) > space_remaining) {
2028 *out_of_space = true;
2029 DEBUG(9,("get_lanman2_dir_entry: out of space\n"));
2030 return false; /* Not finished - just out of space */
2033 /* Setup the last entry pointer, as an offset from base_data */
2034 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2035 /* Advance the data pointer to the next slot */
2041 bool smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2042 connection_struct *conn,
2043 struct dptr_struct *dirptr,
2045 const char *path_mask,
2048 int requires_resume_key,
2056 int space_remaining,
2058 bool *got_exact_match,
2059 int *_last_entry_off,
2060 struct ea_list *name_list)
2063 const char *mask = NULL;
2064 long prev_dirpos = 0;
2067 struct smb_filename *smb_fname = NULL;
2068 struct smbd_dirptr_lanman2_state state;
2070 uint64_t last_entry_off = 0;
2074 state.info_level = info_level;
2075 state.check_mangled_names = lp_manglednames(conn->params);
2076 state.has_wild = dptr_has_wild(dirptr);
2077 state.got_exact_match = false;
2079 *out_of_space = false;
2080 *got_exact_match = false;
2082 p = strrchr_m(path_mask,'/');
2093 ok = smbd_dirptr_get_entry(ctx,
2099 smbd_dirptr_lanman2_match_fn,
2100 smbd_dirptr_lanman2_mode_fn,
2110 *got_exact_match = state.got_exact_match;
2112 ok = smbd_marshall_dir_entry(ctx,
2117 state.check_mangled_names,
2118 requires_resume_key,
2131 TALLOC_FREE(smb_fname);
2132 if (*out_of_space) {
2133 dptr_SeekDir(dirptr, prev_dirpos);
2140 *_last_entry_off = last_entry_off;
2144 static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
2145 connection_struct *conn,
2146 struct dptr_struct *dirptr,
2148 const char *path_mask,
2151 int requires_resume_key,
2157 int space_remaining,
2159 bool *got_exact_match,
2160 int *last_entry_off,
2161 struct ea_list *name_list)
2163 bool resume_key = false;
2165 const bool do_pad = true;
2167 if (requires_resume_key) {
2171 if (info_level >= 1 && info_level <= 3) {
2172 /* No alignment on earlier info levels. */
2176 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2177 path_mask, dirtype, info_level,
2178 resume_key, dont_descend, ask_sharemode,
2180 ppdata, base_data, end_data,
2182 out_of_space, got_exact_match,
2183 last_entry_off, name_list);
2186 /****************************************************************************
2187 Reply to a TRANS2_FINDFIRST.
2188 ****************************************************************************/
2190 static void call_trans2findfirst(connection_struct *conn,
2191 struct smb_request *req,
2192 char **pparams, int total_params,
2193 char **ppdata, int total_data,
2194 unsigned int max_data_bytes)
2196 /* We must be careful here that we don't return more than the
2197 allowed number of data bytes. If this means returning fewer than
2198 maxentries then so be it. We assume that the redirector has
2199 enough room for the fixed number of parameter bytes it has
2201 struct smb_filename *smb_dname = NULL;
2202 char *params = *pparams;
2203 char *pdata = *ppdata;
2207 uint16 findfirst_flags;
2208 bool close_after_first;
2210 bool requires_resume_key;
2212 char *directory = NULL;
2215 int last_entry_off=0;
2219 bool finished = False;
2220 bool dont_descend = False;
2221 bool out_of_space = False;
2222 int space_remaining;
2223 bool mask_contains_wcard = False;
2224 struct ea_list *ea_list = NULL;
2225 NTSTATUS ntstatus = NT_STATUS_OK;
2226 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2227 TALLOC_CTX *ctx = talloc_tos();
2228 struct dptr_struct *dirptr = NULL;
2229 struct smbd_server_connection *sconn = smbd_server_conn;
2231 if (total_params < 13) {
2232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2236 dirtype = SVAL(params,0);
2237 maxentries = SVAL(params,2);
2238 findfirst_flags = SVAL(params,4);
2239 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2240 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2241 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2242 info_level = SVAL(params,6);
2244 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2245 close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
2246 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2247 info_level, max_data_bytes));
2250 /* W2K3 seems to treat zero as 1. */
2254 switch (info_level) {
2255 case SMB_FIND_INFO_STANDARD:
2256 case SMB_FIND_EA_SIZE:
2257 case SMB_FIND_EA_LIST:
2258 case SMB_FIND_FILE_DIRECTORY_INFO:
2259 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2260 case SMB_FIND_FILE_NAMES_INFO:
2261 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2262 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2263 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2265 case SMB_FIND_FILE_UNIX:
2266 case SMB_FIND_FILE_UNIX_INFO2:
2267 /* Always use filesystem for UNIX mtime query. */
2268 ask_sharemode = false;
2269 if (!lp_unix_extensions()) {
2270 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2275 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2279 srvstr_get_path_wcard(ctx, params, req->flags2, &directory,
2280 params+12, total_params - 12,
2281 STR_TERMINATE, &ntstatus, &mask_contains_wcard);
2282 if (!NT_STATUS_IS_OK(ntstatus)) {
2283 reply_nterror(req, ntstatus);
2287 ntstatus = filename_convert(ctx, conn,
2288 req->flags2 & FLAGS2_DFS_PATHNAMES,
2291 UCF_ALWAYS_ALLOW_WCARD_LCOMP),
2292 &mask_contains_wcard,
2294 if (!NT_STATUS_IS_OK(ntstatus)) {
2295 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2296 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2297 ERRSRV, ERRbadpath);
2300 reply_nterror(req, ntstatus);
2304 mask = smb_dname->original_lcomp;
2306 directory = smb_dname->base_name;
2308 p = strrchr_m(directory,'/');
2310 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2311 if((directory[0] == '.') && (directory[1] == '\0')) {
2312 mask = talloc_strdup(ctx,"*");
2314 reply_nterror(req, NT_STATUS_NO_MEMORY);
2317 mask_contains_wcard = True;
2319 directory = talloc_strdup(talloc_tos(), "./");
2321 reply_nterror(req, NT_STATUS_NO_MEMORY);
2328 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2330 if (info_level == SMB_FIND_EA_LIST) {
2333 if (total_data < 4) {
2334 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2338 ea_size = IVAL(pdata,0);
2339 if (ea_size != total_data) {
2340 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2341 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2342 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2346 if (!lp_ea_support(SNUM(conn))) {
2347 reply_doserror(req, ERRDOS, ERReasnotsupported);
2351 /* Pull out the list of names. */
2352 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2354 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2359 *ppdata = (char *)SMB_REALLOC(
2360 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2361 if(*ppdata == NULL ) {
2362 reply_nterror(req, NT_STATUS_NO_MEMORY);
2366 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2368 /* Realloc the params space */
2369 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2370 if (*pparams == NULL) {
2371 reply_nterror(req, NT_STATUS_NO_MEMORY);
2376 /* Save the wildcard match and attribs we are using on this directory -
2377 needed as lanman2 assumes these are being saved between calls */
2379 ntstatus = dptr_create(conn,
2385 mask_contains_wcard,
2389 if (!NT_STATUS_IS_OK(ntstatus)) {
2390 reply_nterror(req, ntstatus);
2394 dptr_num = dptr_dnum(dirptr);
2395 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2397 /* Initialize per TRANS2_FIND_FIRST operation data */
2398 dptr_init_search_op(dirptr);
2400 /* We don't need to check for VOL here as this is returned by
2401 a different TRANS2 call. */
2403 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2404 directory,lp_dontdescend(SNUM(conn))));
2405 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2406 dont_descend = True;
2409 space_remaining = max_data_bytes;
2410 out_of_space = False;
2412 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2413 bool got_exact_match = False;
2415 /* this is a heuristic to avoid seeking the dirptr except when
2416 absolutely necessary. It allows for a filename of about 40 chars */
2417 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2418 out_of_space = True;
2421 finished = !get_lanman2_dir_entry(ctx,
2425 mask,dirtype,info_level,
2426 requires_resume_key,dont_descend,
2429 space_remaining, &out_of_space,
2431 &last_entry_off, ea_list);
2434 if (finished && out_of_space)
2437 if (!finished && !out_of_space)
2441 * As an optimisation if we know we aren't looking
2442 * for a wildcard name (ie. the name matches the wildcard exactly)
2443 * then we can finish on any (first) match.
2444 * This speeds up large directory searches. JRA.
2450 /* Ensure space_remaining never goes -ve. */
2451 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2452 space_remaining = 0;
2453 out_of_space = true;
2455 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2459 /* Check if we can close the dirptr */
2460 if(close_after_first || (finished && close_if_end)) {
2461 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2462 dptr_close(sconn, &dptr_num);
2466 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2467 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2468 * the protocol level is less than NT1. Tested with smbclient. JRA.
2469 * This should fix the OS/2 client bug #2335.
2472 if(numentries == 0) {
2473 dptr_close(sconn, &dptr_num);
2474 if (Protocol < PROTOCOL_NT1) {
2475 reply_doserror(req, ERRDOS, ERRnofiles);
2478 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2479 ERRDOS, ERRbadfile);
2484 /* At this point pdata points to numentries directory entries. */
2486 /* Set up the return parameter block */
2487 SSVAL(params,0,dptr_num);
2488 SSVAL(params,2,numentries);
2489 SSVAL(params,4,finished);
2490 SSVAL(params,6,0); /* Never an EA error */
2491 SSVAL(params,8,last_entry_off);
2493 send_trans2_replies(conn, req, params, 10, pdata, PTR_DIFF(p,pdata),
2496 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2497 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2499 reply_nterror(req, NT_STATUS_NO_MEMORY);
2503 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2504 smb_fn_name(req->cmd),
2505 mask, directory, dirtype, numentries ) );
2508 * Force a name mangle here to ensure that the
2509 * mask as an 8.3 name is top of the mangled cache.
2510 * The reasons for this are subtle. Don't remove
2511 * this code unless you know what you are doing
2512 * (see PR#13758). JRA.
2515 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2516 char mangled_name[13];
2517 name_to_8_3(mask, mangled_name, True, conn->params);
2520 TALLOC_FREE(smb_dname);
2524 /****************************************************************************
2525 Reply to a TRANS2_FINDNEXT.
2526 ****************************************************************************/
2528 static void call_trans2findnext(connection_struct *conn,
2529 struct smb_request *req,
2530 char **pparams, int total_params,
2531 char **ppdata, int total_data,
2532 unsigned int max_data_bytes)
2534 /* We must be careful here that we don't return more than the
2535 allowed number of data bytes. If this means returning fewer than
2536 maxentries then so be it. We assume that the redirector has
2537 enough room for the fixed number of parameter bytes it has
2539 char *params = *pparams;
2540 char *pdata = *ppdata;
2546 uint16 findnext_flags;
2547 bool close_after_request;
2549 bool requires_resume_key;
2551 bool mask_contains_wcard = False;
2552 char *resume_name = NULL;
2553 const char *mask = NULL;
2554 const char *directory = NULL;
2558 int i, last_entry_off=0;
2559 bool finished = False;
2560 bool dont_descend = False;
2561 bool out_of_space = False;
2562 int space_remaining;
2563 struct ea_list *ea_list = NULL;
2564 NTSTATUS ntstatus = NT_STATUS_OK;
2565 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2566 TALLOC_CTX *ctx = talloc_tos();
2567 struct dptr_struct *dirptr;
2568 struct smbd_server_connection *sconn = smbd_server_conn;
2570 if (total_params < 13) {
2571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2575 dptr_num = SVAL(params,0);
2576 maxentries = SVAL(params,2);
2577 info_level = SVAL(params,4);
2578 resume_key = IVAL(params,6);
2579 findnext_flags = SVAL(params,10);
2580 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
2581 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2582 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2583 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
2585 if (!continue_bit) {
2586 /* We only need resume_name if continue_bit is zero. */
2587 srvstr_get_path_wcard(ctx, params, req->flags2, &resume_name,
2589 total_params - 12, STR_TERMINATE, &ntstatus,
2590 &mask_contains_wcard);
2591 if (!NT_STATUS_IS_OK(ntstatus)) {
2592 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
2593 complain (it thinks we're asking for the directory above the shared
2594 path or an invalid name). Catch this as the resume name is only compared, never used in
2595 a file access. JRA. */
2596 srvstr_pull_talloc(ctx, params, req->flags2,
2597 &resume_name, params+12,
2601 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
2602 reply_nterror(req, ntstatus);
2608 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
2609 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
2610 resume_key = %d resume name = %s continue=%d level = %d\n",
2611 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
2612 requires_resume_key, resume_key,
2613 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
2616 /* W2K3 seems to treat zero as 1. */
2620 switch (info_level) {
2621 case SMB_FIND_INFO_STANDARD:
2622 case SMB_FIND_EA_SIZE:
2623 case SMB_FIND_EA_LIST:
2624 case SMB_FIND_FILE_DIRECTORY_INFO:
2625 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2626 case SMB_FIND_FILE_NAMES_INFO:
2627 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2628 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2629 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2631 case SMB_FIND_FILE_UNIX:
2632 case SMB_FIND_FILE_UNIX_INFO2:
2633 /* Always use filesystem for UNIX mtime query. */
2634 ask_sharemode = false;
2635 if (!lp_unix_extensions()) {
2636 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2641 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2645 if (info_level == SMB_FIND_EA_LIST) {
2648 if (total_data < 4) {
2649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2653 ea_size = IVAL(pdata,0);
2654 if (ea_size != total_data) {
2655 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
2656 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2657 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2661 if (!lp_ea_support(SNUM(conn))) {
2662 reply_doserror(req, ERRDOS, ERReasnotsupported);
2666 /* Pull out the list of names. */
2667 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
2669 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2674 *ppdata = (char *)SMB_REALLOC(
2675 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2676 if(*ppdata == NULL) {
2677 reply_nterror(req, NT_STATUS_NO_MEMORY);
2682 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2684 /* Realloc the params space */
2685 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
2686 if(*pparams == NULL ) {
2687 reply_nterror(req, NT_STATUS_NO_MEMORY);
2693 /* Check that the dptr is valid */
2694 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
2695 reply_doserror(req, ERRDOS, ERRnofiles);
2699 directory = dptr_path(sconn, dptr_num);
2701 /* Get the wildcard mask from the dptr */
2702 if((p = dptr_wcard(sconn, dptr_num))== NULL) {
2703 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
2704 reply_doserror(req, ERRDOS, ERRnofiles);
2710 /* Get the attr mask from the dptr */
2711 dirtype = dptr_attr(sconn, dptr_num);
2713 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld)\n",
2714 dptr_num, mask, dirtype,
2716 dptr_TellDir(dirptr)));
2718 /* Initialize per TRANS2_FIND_NEXT operation data */
2719 dptr_init_search_op(dirptr);
2721 /* We don't need to check for VOL here as this is returned by
2722 a different TRANS2 call. */
2724 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2725 directory,lp_dontdescend(SNUM(conn))));
2726 if (in_list(directory,lp_dontdescend(SNUM(conn)),conn->case_sensitive))
2727 dont_descend = True;
2730 space_remaining = max_data_bytes;
2731 out_of_space = False;
2734 * Seek to the correct position. We no longer use the resume key but
2735 * depend on the last file name instead.
2738 if(!continue_bit && resume_name && *resume_name) {
2741 long current_pos = 0;
2743 * Remember, name_to_8_3 is called by
2744 * get_lanman2_dir_entry(), so the resume name
2745 * could be mangled. Ensure we check the unmangled name.
2748 if (mangle_is_mangled(resume_name, conn->params)) {
2749 char *new_resume_name = NULL;
2750 mangle_lookup_name_from_8_3(ctx,
2754 if (new_resume_name) {
2755 resume_name = new_resume_name;
2760 * Fix for NT redirector problem triggered by resume key indexes
2761 * changing between directory scans. We now return a resume key of 0
2762 * and instead look for the filename to continue from (also given
2763 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
2764 * findfirst/findnext (as is usual) then the directory pointer
2765 * should already be at the correct place.
2768 finished = !dptr_SearchDir(dirptr, resume_name, ¤t_pos, &st);
2769 } /* end if resume_name && !continue_bit */
2771 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
2772 bool got_exact_match = False;
2774 /* this is a heuristic to avoid seeking the dirptr except when
2775 absolutely necessary. It allows for a filename of about 40 chars */
2776 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2777 out_of_space = True;
2780 finished = !get_lanman2_dir_entry(ctx,
2784 mask,dirtype,info_level,
2785 requires_resume_key,dont_descend,
2788 space_remaining, &out_of_space,
2790 &last_entry_off, ea_list);
2793 if (finished && out_of_space)
2796 if (!finished && !out_of_space)
2800 * As an optimisation if we know we aren't looking
2801 * for a wildcard name (ie. the name matches the wildcard exactly)
2802 * then we can finish on any (first) match.
2803 * This speeds up large directory searches. JRA.
2809 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2812 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2813 smb_fn_name(req->cmd),
2814 mask, directory, dirtype, numentries ) );
2816 /* Check if we can close the dirptr */
2817 if(close_after_request || (finished && close_if_end)) {
2818 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
2819 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
2822 /* Set up the return parameter block */
2823 SSVAL(params,0,numentries);
2824 SSVAL(params,2,finished);
2825 SSVAL(params,4,0); /* Never an EA error */
2826 SSVAL(params,6,last_entry_off);
2828 send_trans2_replies(conn, req, params, 8, pdata, PTR_DIFF(p,pdata),
2834 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2836 E_md4hash(lp_servicename(SNUM(conn)),objid);
2840 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2842 SMB_ASSERT(extended_info != NULL);
2844 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2845 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2846 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2847 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2848 #ifdef SAMBA_VERSION_REVISION
2849 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2851 extended_info->samba_subversion = 0;
2852 #ifdef SAMBA_VERSION_RC_RELEASE
2853 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2855 #ifdef SAMBA_VERSION_PRE_RELEASE
2856 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2859 #ifdef SAMBA_VERSION_VENDOR_PATCH
2860 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2862 extended_info->samba_gitcommitdate = 0;
2863 #ifdef SAMBA_VERSION_GIT_COMMIT_TIME
2864 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME);
2867 memset(extended_info->samba_version_string, 0,
2868 sizeof(extended_info->samba_version_string));
2870 snprintf (extended_info->samba_version_string,
2871 sizeof(extended_info->samba_version_string),
2872 "%s", samba_version_string());
2875 NTSTATUS smbd_do_qfsinfo(connection_struct *conn,
2876 TALLOC_CTX *mem_ctx,
2877 uint16_t info_level,
2879 unsigned int max_data_bytes,
2883 char *pdata, *end_data;
2884 int data_len = 0, len;
2885 const char *vname = volume_label(SNUM(conn));
2886 int snum = SNUM(conn);
2887 char *fstype = lp_fstype(SNUM(conn));
2888 uint32 additional_flags = 0;
2889 struct smb_filename *smb_fname_dot = NULL;
2894 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2895 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2896 "info level (0x%x) on IPC$.\n",
2897 (unsigned int)info_level));
2898 return NT_STATUS_ACCESS_DENIED;
2902 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2904 status = create_synthetic_smb_fname(talloc_tos(), ".", NULL, NULL,
2906 if (!NT_STATUS_IS_OK(status)) {
2910 if(SMB_VFS_STAT(conn, smb_fname_dot) != 0) {
2911 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2912 TALLOC_FREE(smb_fname_dot);
2913 return map_nt_error_from_unix(errno);
2916 st = smb_fname_dot->st;
2917 TALLOC_FREE(smb_fname_dot);
2919 *ppdata = (char *)SMB_REALLOC(
2920 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2921 if (*ppdata == NULL) {
2922 return NT_STATUS_NO_MEMORY;
2926 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2927 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2929 switch (info_level) {
2930 case SMB_INFO_ALLOCATION:
2932 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
2934 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
2935 return map_nt_error_from_unix(errno);
2938 block_size = lp_block_size(snum);
2939 if (bsize < block_size) {
2940 uint64_t factor = block_size/bsize;
2945 if (bsize > block_size) {
2946 uint64_t factor = bsize/block_size;
2951 bytes_per_sector = 512;
2952 sectors_per_unit = bsize/bytes_per_sector;
2954 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2955 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2956 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2958 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2959 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2960 SIVAL(pdata,l1_cUnit,dsize);
2961 SIVAL(pdata,l1_cUnitAvail,dfree);
2962 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2966 case SMB_INFO_VOLUME:
2967 /* Return volume name */
2969 * Add volume serial number - hash of a combination of
2970 * the called hostname and the service name.
2972 SIVAL(pdata,0,str_checksum(lp_servicename(snum)) ^ (str_checksum(get_local_machine_name())<<16) );
2974 * Win2k3 and previous mess this up by sending a name length
2975 * one byte short. I believe only older clients (OS/2 Win9x) use
2976 * this call so try fixing this by adding a terminating null to
2977 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2981 pdata+l2_vol_szVolLabel, vname,
2982 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2983 STR_NOALIGN|STR_TERMINATE);
2984 SCVAL(pdata,l2_vol_cch,len);
2985 data_len = l2_vol_szVolLabel + len;
2986 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %d, name = %s\n",
2987 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2991 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2992 case SMB_FS_ATTRIBUTE_INFORMATION:
2994 additional_flags = 0;
2995 #if defined(HAVE_SYS_QUOTAS)
2996 additional_flags |= FILE_VOLUME_QUOTAS;
2999 if(lp_nt_acl_support(SNUM(conn))) {
3000 additional_flags |= FILE_PERSISTENT_ACLS;
3003 /* Capabilities are filled in at connection time through STATVFS call */
3004 additional_flags |= conn->fs_capabilities;
3005 additional_flags |= lp_parm_int(conn->params->service,
3006 "share", "fake_fscaps",
3009 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3010 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3011 additional_flags); /* FS ATTRIBUTES */
3013 SIVAL(pdata,4,255); /* Max filename component length */
3014 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3015 and will think we can't do long filenames */
3016 len = srvstr_push(pdata, flags2, pdata+12, fstype,
3017 PTR_DIFF(end_data, pdata+12),
3020 data_len = 12 + len;
3023 case SMB_QUERY_FS_LABEL_INFO:
3024 case SMB_FS_LABEL_INFORMATION:
3025 len = srvstr_push(pdata, flags2, pdata+4, vname,
3026 PTR_DIFF(end_data, pdata+4), 0);
3031 case SMB_QUERY_FS_VOLUME_INFO:
3032 case SMB_FS_VOLUME_INFORMATION:
3035 * Add volume serial number - hash of a combination of
3036 * the called hostname and the service name.
3038 SIVAL(pdata,8,str_checksum(lp_servicename(snum)) ^
3039 (str_checksum(get_local_machine_name())<<16));
3041 /* Max label len is 32 characters. */
3042 len = srvstr_push(pdata, flags2, pdata+18, vname,
3043 PTR_DIFF(end_data, pdata+18),
3045 SIVAL(pdata,12,len);
3048 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3049 (int)strlen(vname),vname, lp_servicename(snum)));
3052 case SMB_QUERY_FS_SIZE_INFO:
3053 case SMB_FS_SIZE_INFORMATION:
3055 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3057 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3058 return map_nt_error_from_unix(errno);
3060 block_size = lp_block_size(snum);
3061 if (bsize < block_size) {
3062 uint64_t factor = block_size/bsize;
3067 if (bsize > block_size) {
3068 uint64_t factor = bsize/block_size;
3073 bytes_per_sector = 512;
3074 sectors_per_unit = bsize/bytes_per_sector;
3075 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3076 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3077 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3078 SBIG_UINT(pdata,0,dsize);
3079 SBIG_UINT(pdata,8,dfree);
3080 SIVAL(pdata,16,sectors_per_unit);
3081 SIVAL(pdata,20,bytes_per_sector);
3085 case SMB_FS_FULL_SIZE_INFORMATION:
3087 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit,bytes_per_sector;
3089 if (get_dfree_info(conn,".",False,&bsize,&dfree,&dsize) == (uint64_t)-1) {
3090 return map_nt_error_from_unix(errno);
3092 block_size = lp_block_size(snum);
3093 if (bsize < block_size) {
3094 uint64_t factor = block_size/bsize;
3099 if (bsize > block_size) {
3100 uint64_t factor = bsize/block_size;
3105 bytes_per_sector = 512;
3106 sectors_per_unit = bsize/bytes_per_sector;
3107 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3108 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3109 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3110 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3111 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3112 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3113 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3114 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3118 case SMB_QUERY_FS_DEVICE_INFO:
3119 case SMB_FS_DEVICE_INFORMATION:
3121 SIVAL(pdata,0,0); /* dev type */
3122 SIVAL(pdata,4,0); /* characteristics */
3125 #ifdef HAVE_SYS_QUOTAS
3126 case SMB_FS_QUOTA_INFORMATION:
3128 * what we have to send --metze:
3130 * Unknown1: 24 NULL bytes
3131 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3132 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3133 * Quota Flags: 2 byte :
3134 * Unknown3: 6 NULL bytes
3138 * details for Quota Flags:
3140 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3141 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3142 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3143 * 0x0001 Enable Quotas: enable quota for this fs
3147 /* we need to fake up a fsp here,
3148 * because its not send in this call
3151 SMB_NTQUOTA_STRUCT quotas;
3154 ZERO_STRUCT(quotas);
3160 if (conn->server_info->utok.uid != sec_initial_uid()) {
3161 DEBUG(0,("set_user_quota: access_denied "
3162 "service [%s] user [%s]\n",
3163 lp_servicename(SNUM(conn)),
3164 conn->server_info->unix_name));
3165 return NT_STATUS_ACCESS_DENIED;
3168 if (vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3169 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3170 return map_nt_error_from_unix(errno);
3175 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3176 lp_servicename(SNUM(conn))));
3178 /* Unknown1 24 NULL bytes*/
3179 SBIG_UINT(pdata,0,(uint64_t)0);
3180 SBIG_UINT(pdata,8,(uint64_t)0);
3181 SBIG_UINT(pdata,16,(uint64_t)0);
3183 /* Default Soft Quota 8 bytes */
3184 SBIG_UINT(pdata,24,quotas.softlim);
3186 /* Default Hard Quota 8 bytes */
3187 SBIG_UINT(pdata,32,quotas.hardlim);
3189 /* Quota flag 2 bytes */
3190 SSVAL(pdata,40,quotas.qflags);
3192 /* Unknown3 6 NULL bytes */
3198 #endif /* HAVE_SYS_QUOTAS */
3199 case SMB_FS_OBJECTID_INFORMATION:
3201 unsigned char objid[16];
3202 struct smb_extended_info extended_info;
3203 memcpy(pdata,create_volume_objectid(conn, objid),16);
3204 samba_extended_info_version (&extended_info);
3205 SIVAL(pdata,16,extended_info.samba_magic);
3206 SIVAL(pdata,20,extended_info.samba_version);
3207 SIVAL(pdata,24,extended_info.samba_subversion);
3208 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3209 memcpy(pdata+36,extended_info.samba_version_string,28);
3215 * Query the version and capabilities of the CIFS UNIX extensions
3219 case SMB_QUERY_CIFS_UNIX_INFO:
3221 bool large_write = lp_min_receive_file_size() &&
3222 !srv_is_signing_active(smbd_server_conn);
3223 bool large_read = !srv_is_signing_active(smbd_server_conn);
3224 int encrypt_caps = 0;
3226 if (!lp_unix_extensions()) {
3227 return NT_STATUS_INVALID_LEVEL;
3230 switch (conn->encrypt_level) {
3236 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3239 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3240 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3241 large_write = false;
3247 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3248 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3250 /* We have POSIX ACLs, pathname, encryption,
3251 * large read/write, and locking capability. */
3253 SBIG_UINT(pdata,4,((uint64_t)(
3254 CIFS_UNIX_POSIX_ACLS_CAP|
3255 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3256 CIFS_UNIX_FCNTL_LOCKS_CAP|
3257 CIFS_UNIX_EXTATTR_CAP|
3258 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3260 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3262 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3266 case SMB_QUERY_POSIX_FS_INFO:
3269 vfs_statvfs_struct svfs;
3271 if (!lp_unix_extensions()) {
3272 return NT_STATUS_INVALID_LEVEL;
3275 rc = SMB_VFS_STATVFS(conn, ".", &svfs);
3279 SIVAL(pdata,0,svfs.OptimalTransferSize);
3280 SIVAL(pdata,4,svfs.BlockSize);
3281 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3282 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3283 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3284 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3285 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3286 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3287 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3289 } else if (rc == EOPNOTSUPP) {
3290 return NT_STATUS_INVALID_LEVEL;
3291 #endif /* EOPNOTSUPP */
3293 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3294 return NT_STATUS_DOS(ERRSRV, ERRerror);
3299 case SMB_QUERY_POSIX_WHOAMI:
3305 if (!lp_unix_extensions()) {
3306 return NT_STATUS_INVALID_LEVEL;
3309 if (max_data_bytes < 40) {
3310 return NT_STATUS_BUFFER_TOO_SMALL;
3313 /* We ARE guest if global_sid_Builtin_Guests is
3314 * in our list of SIDs.
3316 if (nt_token_check_sid(&global_sid_Builtin_Guests,
3317 conn->server_info->ptok)) {
3318 flags |= SMB_WHOAMI_GUEST;
3321 /* We are NOT guest if global_sid_Authenticated_Users
3322 * is in our list of SIDs.
3324 if (nt_token_check_sid(&global_sid_Authenticated_Users,
3325 conn->server_info->ptok)) {
3326 flags &= ~SMB_WHOAMI_GUEST;
3329 /* NOTE: 8 bytes for UID/GID, irrespective of native
3330 * platform size. This matches
3331 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3333 data_len = 4 /* flags */
3340 + 4 /* pad/reserved */
3341 + (conn->server_info->utok.ngroups * 8)
3343 + (conn->server_info->ptok->num_sids *
3347 SIVAL(pdata, 0, flags);
3348 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3350 (uint64_t)conn->server_info->utok.uid);
3351 SBIG_UINT(pdata, 16,
3352 (uint64_t)conn->server_info->utok.gid);
3355 if (data_len >= max_data_bytes) {
3356 /* Potential overflow, skip the GIDs and SIDs. */
3358 SIVAL(pdata, 24, 0); /* num_groups */
3359 SIVAL(pdata, 28, 0); /* num_sids */
3360 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3361 SIVAL(pdata, 36, 0); /* reserved */
3367 SIVAL(pdata, 24, conn->server_info->utok.ngroups);
3368 SIVAL(pdata, 28, conn->server_info->num_sids);
3370 /* We walk the SID list twice, but this call is fairly
3371 * infrequent, and I don't expect that it's performance
3372 * sensitive -- jpeach
3374 for (i = 0, sid_bytes = 0;
3375 i < conn->server_info->ptok->num_sids; ++i) {
3376 sid_bytes += ndr_size_dom_sid(
3377 &conn->server_info->ptok->user_sids[i],
3382 /* SID list byte count */
3383 SIVAL(pdata, 32, sid_bytes);
3385 /* 4 bytes pad/reserved - must be zero */
3386 SIVAL(pdata, 36, 0);
3390 for (i = 0; i < conn->server_info->utok.ngroups; ++i) {
3391 SBIG_UINT(pdata, data_len,
3392 (uint64_t)conn->server_info->utok.groups[i]);
3398 i < conn->server_info->ptok->num_sids; ++i) {
3399 int sid_len = ndr_size_dom_sid(
3400 &conn->server_info->ptok->user_sids[i],
3404 sid_linearize(pdata + data_len, sid_len,
3405 &conn->server_info->ptok->user_sids[i]);
3406 data_len += sid_len;
3412 case SMB_MAC_QUERY_FS_INFO:
3414 * Thursby MAC extension... ONLY on NTFS filesystems
3415 * once we do streams then we don't need this
3417 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3419 SIVAL(pdata,84,0x100); /* Don't support mac... */
3424 return NT_STATUS_INVALID_LEVEL;
3427 *ret_data_len = data_len;
3428 return NT_STATUS_OK;
3431 /****************************************************************************
3432 Reply to a TRANS2_QFSINFO (query filesystem info).
3433 ****************************************************************************/
3435 static void call_trans2qfsinfo(connection_struct *conn,
3436 struct smb_request *req,
3437 char **pparams, int total_params,
3438 char **ppdata, int total_data,
3439 unsigned int max_data_bytes)
3441 char *params = *pparams;
3442 uint16_t info_level;
3446 if (total_params < 2) {
3447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3451 info_level = SVAL(params,0);
3453 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3454 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3455 DEBUG(0,("call_trans2qfsinfo: encryption required "
3456 "and info level 0x%x sent.\n",
3457 (unsigned int)info_level));
3458 exit_server_cleanly("encryption required "
3464 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
3466 status = smbd_do_qfsinfo(conn, req,
3471 if (!NT_STATUS_IS_OK(status)) {
3472 reply_nterror(req, status);
3476 send_trans2_replies(conn, req, params, 0, *ppdata, data_len,
3479 DEBUG( 4, ( "%s info_level = %d\n",
3480 smb_fn_name(req->cmd), info_level) );
3485 /****************************************************************************
3486 Reply to a TRANS2_SETFSINFO (set filesystem info).
3487 ****************************************************************************/
3489 static void call_trans2setfsinfo(connection_struct *conn,
3490 struct smb_request *req,
3491 char **pparams, int total_params,
3492 char **ppdata, int total_data,
3493 unsigned int max_data_bytes)
3495 char *pdata = *ppdata;
3496 char *params = *pparams;
3499 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",lp_servicename(SNUM(conn))));
3502 if (total_params < 4) {
3503 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
3505 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3509 info_level = SVAL(params,2);
3512 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
3513 info_level != SMB_SET_CIFS_UNIX_INFO) {
3514 DEBUG(0,("call_trans2setfsinfo: not an allowed "
3515 "info level (0x%x) on IPC$.\n",
3516 (unsigned int)info_level));
3517 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3522 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
3523 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
3524 DEBUG(0,("call_trans2setfsinfo: encryption required "
3525 "and info level 0x%x sent.\n",
3526 (unsigned int)info_level));
3527 exit_server_cleanly("encryption required "
3533 switch(info_level) {
3534 case SMB_SET_CIFS_UNIX_INFO:
3536 uint16 client_unix_major;
3537 uint16 client_unix_minor;
3538 uint32 client_unix_cap_low;
3539 uint32 client_unix_cap_high;
3541 if (!lp_unix_extensions()) {
3543 NT_STATUS_INVALID_LEVEL);
3547 /* There should be 12 bytes of capabilities set. */
3548 if (total_data < 8) {
3551 NT_STATUS_INVALID_PARAMETER);
3554 client_unix_major = SVAL(pdata,0);
3555 client_unix_minor = SVAL(pdata,2);
3556 client_unix_cap_low = IVAL(pdata,4);
3557 client_unix_cap_high = IVAL(pdata,8);
3558 /* Just print these values for now. */
3559 DEBUG(10,("call_trans2setfsinfo: set unix info. major = %u, minor = %u \
3560 cap_low = 0x%x, cap_high = 0x%x\n",
3561 (unsigned int)client_unix_major,
3562 (unsigned int)client_unix_minor,
3563 (unsigned int)client_unix_cap_low,
3564 (unsigned int)client_unix_cap_high ));
3566 /* Here is where we must switch to posix pathname processing... */
3567 if (client_unix_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
3568 lp_set_posix_pathnames();
3569 mangle_change_to_posix();
3572 if ((client_unix_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
3573 !(client_unix_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
3574 /* Client that knows how to do posix locks,
3575 * but not posix open/mkdir operations. Set a
3576 * default type for read/write checks. */
3578 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
3584 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
3587 size_t param_len = 0;
3588 size_t data_len = total_data;
3590 if (!lp_unix_extensions()) {
3593 NT_STATUS_INVALID_LEVEL);
3597 if (lp_smb_encrypt(SNUM(conn)) == false) {
3600 NT_STATUS_NOT_SUPPORTED);
3604 DEBUG( 4,("call_trans2setfsinfo: "
3605 "request transport encryption.\n"));
3607 status = srv_request_encryption_setup(conn,
3608 (unsigned char **)ppdata,
3610 (unsigned char **)pparams,
3613 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
3614 !NT_STATUS_IS_OK(status)) {
3615 reply_nterror(req, status);
3619 send_trans2_replies(conn, req,
3626 if (NT_STATUS_IS_OK(status)) {
3627 /* Server-side transport
3628 * encryption is now *on*. */
3629 status = srv_encryption_start(conn);
3630 if (!NT_STATUS_IS_OK(status)) {
3631 exit_server_cleanly(
3632 "Failure in setting "
3633 "up encrypted transport");
3639 case SMB_FS_QUOTA_INFORMATION:
3641 files_struct *fsp = NULL;
3642 SMB_NTQUOTA_STRUCT quotas;
3644 ZERO_STRUCT(quotas);
3647 if ((conn->server_info->utok.uid != sec_initial_uid())
3648 ||!CAN_WRITE(conn)) {
3649 DEBUG(0,("set_user_quota: access_denied service [%s] user [%s]\n",
3650 lp_servicename(SNUM(conn)),
3651 conn->server_info->unix_name));
3652 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
3656 /* note: normaly there're 48 bytes,
3657 * but we didn't use the last 6 bytes for now
3660 fsp = file_fsp(req, SVAL(params,0));
3662 if (!check_fsp_ntquota_handle(conn, req,
3664 DEBUG(3,("TRANSACT_GET_USER_QUOTA: no valid QUOTA HANDLE\n"));
3666 req, NT_STATUS_INVALID_HANDLE);
3670 if (total_data < 42) {
3671 DEBUG(0,("call_trans2setfsinfo: SET_FS_QUOTA: requires total_data(%d) >= 42 bytes!\n",
3675 NT_STATUS_INVALID_PARAMETER);
3679 /* unknown_1 24 NULL bytes in pdata*/
3681 /* the soft quotas 8 bytes (uint64_t)*/
3682 quotas.softlim = (uint64_t)IVAL(pdata,24);
3683 #ifdef LARGE_SMB_OFF_T
3684 quotas.softlim |= (((uint64_t)IVAL(pdata,28)) << 32);
3685 #else /* LARGE_SMB_OFF_T */
3686 if ((IVAL(pdata,28) != 0)&&
3687 ((quotas.softlim != 0xFFFFFFFF)||
3688 (IVAL(pdata,28)!=0xFFFFFFFF))) {
3689 /* more than 32 bits? */
3692 NT_STATUS_INVALID_PARAMETER);
3695 #endif /* LARGE_SMB_OFF_T */
3697 /* the hard quotas 8 bytes (uint64_t)*/
3698 quotas.hardlim = (uint64_t)IVAL(pdata,32);
3699 #ifdef LARGE_SMB_OFF_T
3700 quotas.hardlim |= (((uint64_t)IVAL(pdata,36)) << 32);
3701 #else /* LARGE_SMB_OFF_T */
3702 if ((IVAL(pdata,36) != 0)&&
3703 ((quotas.hardlim != 0xFFFFFFFF)||
3704 (IVAL(pdata,36)!=0xFFFFFFFF))) {
3705 /* more than 32 bits? */
3708 NT_STATUS_INVALID_PARAMETER);
3711 #endif /* LARGE_SMB_OFF_T */
3713 /* quota_flags 2 bytes **/
3714 quotas.qflags = SVAL(pdata,40);
3716 /* unknown_2 6 NULL bytes follow*/
3718 /* now set the quotas */
3719 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, "as)!=0) {
3720 DEBUG(0,("vfs_set_ntquota() failed for service [%s]\n",lp_servicename(SNUM(conn))));
3721 reply_nterror(req, map_nt_error_from_unix(errno));
3728 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
3730 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3736 * sending this reply works fine,
3737 * but I'm not sure it's the same
3738 * like windows do...
3741 reply_outbuf(req, 10, 0);
3744 #if defined(HAVE_POSIX_ACLS)
3745 /****************************************************************************
3746 Utility function to count the number of entries in a POSIX acl.
3747 ****************************************************************************/
3749 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
3751 unsigned int ace_count = 0;
3752 int entry_id = SMB_ACL_FIRST_ENTRY;
3753 SMB_ACL_ENTRY_T entry;
3755 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3757 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3758 entry_id = SMB_ACL_NEXT_ENTRY;
3765 /****************************************************************************
3766 Utility function to marshall a POSIX acl into wire format.
3767 ****************************************************************************/
3769 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
3771 int entry_id = SMB_ACL_FIRST_ENTRY;
3772 SMB_ACL_ENTRY_T entry;
3774 while ( posix_acl && (SMB_VFS_SYS_ACL_GET_ENTRY(conn, posix_acl, entry_id, &entry) == 1)) {
3775 SMB_ACL_TAG_T tagtype;
3776 SMB_ACL_PERMSET_T permset;
3777 unsigned char perms = 0;
3778 unsigned int own_grp;
3781 if (entry_id == SMB_ACL_FIRST_ENTRY) {
3782 entry_id = SMB_ACL_NEXT_ENTRY;
3785 if (SMB_VFS_SYS_ACL_GET_TAG_TYPE(conn, entry, &tagtype) == -1) {
3786 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
3790 if (SMB_VFS_SYS_ACL_GET_PERMSET(conn, entry, &permset) == -1) {
3791 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
3795 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
3796 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
3797 perms |= (SMB_VFS_SYS_ACL_GET_PERM(conn, permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
3799 SCVAL(pdata,1,perms);
3802 case SMB_ACL_USER_OBJ:
3803 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
3804 own_grp = (unsigned int)pst->st_ex_uid;
3805 SIVAL(pdata,2,own_grp);
3810 uid_t *puid = (uid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3812 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3815 own_grp = (unsigned int)*puid;
3816 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)puid,tagtype);
3817 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3818 SIVAL(pdata,2,own_grp);
3822 case SMB_ACL_GROUP_OBJ:
3823 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3824 own_grp = (unsigned int)pst->st_ex_gid;
3825 SIVAL(pdata,2,own_grp);
3830 gid_t *pgid= (gid_t *)SMB_VFS_SYS_ACL_GET_QUALIFIER(conn, entry);
3832 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3835 own_grp = (unsigned int)*pgid;
3836 SMB_VFS_SYS_ACL_FREE_QUALIFIER(conn, (void *)pgid,tagtype);
3837 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3838 SIVAL(pdata,2,own_grp);
3843 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3844 SIVAL(pdata,2,0xFFFFFFFF);
3845 SIVAL(pdata,6,0xFFFFFFFF);
3848 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3849 SIVAL(pdata,2,0xFFFFFFFF);
3850 SIVAL(pdata,6,0xFFFFFFFF);
3853 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3856 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3863 /****************************************************************************
3864 Store the FILE_UNIX_BASIC info.
3865 ****************************************************************************/
3867 static char *store_file_unix_basic(connection_struct *conn,
3870 const SMB_STRUCT_STAT *psbuf)
3872 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3873 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3875 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3878 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3881 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
3882 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
3883 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3886 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3890 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3894 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3897 SIVAL(pdata,0,unix_dev_major(psbuf->st_ex_rdev)); /* Major device number if type is device */
3901 SIVAL(pdata,0,unix_dev_minor(psbuf->st_ex_rdev)); /* Minor device number if type is device */
3905 SINO_T_VAL(pdata,0,(SMB_INO_T)psbuf->st_ex_ino); /* inode number */
3908 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3912 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3919 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3920 * the chflags(2) (or equivalent) flags.
3922 * XXX: this really should be behind the VFS interface. To do this, we would
3923 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3924 * Each VFS module could then implement its own mapping as appropriate for the
3925 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3927 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3931 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3935 { UF_IMMUTABLE, EXT_IMMUTABLE },
3939 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3943 { UF_HIDDEN, EXT_HIDDEN },
3946 /* Do not remove. We need to guarantee that this array has at least one
3947 * entry to build on HP-UX.
3953 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3954 uint32 *smb_fflags, uint32 *smb_fmask)
3958 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3959 *smb_fmask |= info2_flags_map[i].smb_fflag;
3960 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3961 *smb_fflags |= info2_flags_map[i].smb_fflag;
3966 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3967 const uint32 smb_fflags,
3968 const uint32 smb_fmask,
3971 uint32 max_fmask = 0;
3974 *stat_fflags = psbuf->st_ex_flags;
3976 /* For each flags requested in smb_fmask, check the state of the
3977 * corresponding flag in smb_fflags and set or clear the matching
3981 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3982 max_fmask |= info2_flags_map[i].smb_fflag;
3983 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3984 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3985 *stat_fflags |= info2_flags_map[i].stat_fflag;
3987 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3992 /* If smb_fmask is asking to set any bits that are not supported by
3993 * our flag mappings, we should fail.
3995 if ((smb_fmask & max_fmask) != smb_fmask) {
4003 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4004 * of file flags and birth (create) time.
4006 static char *store_file_unix_basic_info2(connection_struct *conn,
4009 const SMB_STRUCT_STAT *psbuf)
4011 uint32 file_flags = 0;
4012 uint32 flags_mask = 0;
4014 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4016 /* Create (birth) time 64 bit */
4017 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4020 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4021 SIVAL(pdata, 0, file_flags); /* flags */
4022 SIVAL(pdata, 4, flags_mask); /* mask */
4028 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4029 const struct stream_struct *streams,
4031 unsigned int max_data_bytes,
4032 unsigned int *data_size)
4035 unsigned int ofs = 0;
4037 for (i = 0; i < num_streams && ofs <= max_data_bytes; i++) {
4038 unsigned int next_offset;
4040 smb_ucs2_t *namebuf;
4042 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4043 streams[i].name, &namelen) ||
4046 return NT_STATUS_INVALID_PARAMETER;
4050 * name_buf is now null-terminated, we need to marshall as not
4056 SIVAL(data, ofs+4, namelen);
4057 SOFF_T(data, ofs+8, streams[i].size);
4058 SOFF_T(data, ofs+16, streams[i].alloc_size);
4059 memcpy(data+ofs+24, namebuf, namelen);
4060 TALLOC_FREE(namebuf);
4062 next_offset = ofs + 24 + namelen;
4064 if (i == num_streams-1) {
4065 SIVAL(data, ofs, 0);
4068 unsigned int align = ndr_align_size(next_offset, 8);
4070 memset(data+next_offset, 0, align);
4071 next_offset += align;
4073 SIVAL(data, ofs, next_offset - ofs);
4082 return NT_STATUS_OK;
4085 /****************************************************************************
4086 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4087 ****************************************************************************/
4089 static void call_trans2qpipeinfo(connection_struct *conn,
4090 struct smb_request *req,
4091 unsigned int tran_call,
4092 char **pparams, int total_params,
4093 char **ppdata, int total_data,
4094 unsigned int max_data_bytes)
4096 char *params = *pparams;
4097 char *pdata = *ppdata;
4098 unsigned int data_size = 0;
4099 unsigned int param_size = 2;
4104 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4108 if (total_params < 4) {
4109 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4113 fsp = file_fsp(req, SVAL(params,0));
4114 if (!fsp_is_np(fsp)) {
4115 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4119 info_level = SVAL(params,2);
4121 *pparams = (char *)SMB_REALLOC(*pparams,2);
4122 if (*pparams == NULL) {
4123 reply_nterror(req, NT_STATUS_NO_MEMORY);
4128 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4129 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4130 if (*ppdata == NULL ) {
4131 reply_nterror(req, NT_STATUS_NO_MEMORY);
4136 switch (info_level) {
4137 case SMB_FILE_STANDARD_INFORMATION:
4139 SOFF_T(pdata,0,4096LL);
4146 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4150 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
4156 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4157 TALLOC_CTX *mem_ctx,
4158 uint16_t info_level,
4160 struct smb_filename *smb_fname,
4161 bool delete_pending,
4162 struct timespec write_time_ts,
4164 struct ea_list *ea_list,
4165 int lock_data_count,
4168 unsigned int max_data_bytes,
4170 unsigned int *pdata_size)
4172 char *pdata = *ppdata;
4173 char *dstart, *dend;
4174 unsigned int data_size;
4175 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4176 time_t create_time, mtime, atime, c_time;
4177 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4184 uint64_t file_size = 0;
4186 uint64_t allocation_size = 0;
4187 uint64_t file_index = 0;
4188 uint32_t access_mask = 0;
4190 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4191 return NT_STATUS_INVALID_LEVEL;
4194 DEBUG(5,("smbd_do_qfilepathinfo: %s (fnum = %d) level=%d max_data=%u\n",
4195 smb_fname_str_dbg(smb_fname), fsp ? fsp->fnum : -1,
4196 info_level, max_data_bytes));
4199 mode = dos_mode_msdfs(conn, smb_fname);
4201 mode = dos_mode(conn, smb_fname);
4204 mode = FILE_ATTRIBUTE_NORMAL;
4206 nlink = psbuf->st_ex_nlink;
4208 if (nlink && (mode&aDIR)) {
4212 if ((nlink > 0) && delete_pending) {
4216 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4217 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4218 if (*ppdata == NULL) {
4219 return NT_STATUS_NO_MEMORY;
4223 dend = dstart + data_size - 1;
4225 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4226 update_stat_ex_mtime(psbuf, write_time_ts);
4229 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4230 mtime_ts = psbuf->st_ex_mtime;
4231 atime_ts = psbuf->st_ex_atime;
4232 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4234 if (lp_dos_filetime_resolution(SNUM(conn))) {
4235 dos_filetime_timespec(&create_time_ts);
4236 dos_filetime_timespec(&mtime_ts);
4237 dos_filetime_timespec(&atime_ts);
4238 dos_filetime_timespec(&ctime_ts);
4241 create_time = convert_timespec_to_time_t(create_time_ts);
4242 mtime = convert_timespec_to_time_t(mtime_ts);
4243 atime = convert_timespec_to_time_t(atime_ts);
4244 c_time = convert_timespec_to_time_t(ctime_ts);
4246 p = strrchr_m(smb_fname->base_name,'/');
4248 base_name = smb_fname->base_name;
4252 /* NT expects the name to be in an exact form of the *full*
4253 filename. See the trans2 torture test */
4254 if (ISDOT(base_name)) {
4255 dos_fname = talloc_strdup(mem_ctx, "\\");
4257 return NT_STATUS_NO_MEMORY;
4260 dos_fname = talloc_asprintf(mem_ctx,
4262 smb_fname->base_name);
4264 return NT_STATUS_NO_MEMORY;
4266 if (is_ntfs_stream_smb_fname(smb_fname)) {
4267 dos_fname = talloc_asprintf(dos_fname, "%s",
4268 smb_fname->stream_name);
4270 return NT_STATUS_NO_MEMORY;
4274 string_replace(dos_fname, '/', '\\');
4277 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4280 /* Do we have this path open ? */
4282 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4283 fsp1 = file_find_di_first(fileid);
4284 if (fsp1 && fsp1->initial_allocation_size) {
4285 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4289 if (!(mode & aDIR)) {
4290 file_size = get_file_size_stat(psbuf);
4294 pos = fsp->fh->position_information;
4298 access_mask = fsp->access_mask;
4300 /* GENERIC_EXECUTE mapping from Windows */
4301 access_mask = 0x12019F;
4304 /* This should be an index number - looks like
4307 I think this causes us to fail the IFSKIT
4308 BasicFileInformationTest. -tpot */
4309 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
4310 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
4312 switch (info_level) {
4313 case SMB_INFO_STANDARD:
4314 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4316 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4317 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4318 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4319 SIVAL(pdata,l1_cbFile,(uint32)file_size);
4320 SIVAL(pdata,l1_cbFileAlloc,(uint32)allocation_size);
4321 SSVAL(pdata,l1_attrFile,mode);
4324 case SMB_INFO_QUERY_EA_SIZE:
4326 unsigned int ea_size =
4327 estimate_ea_size(conn, fsp,
4328 smb_fname->base_name);
4329 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4331 srv_put_dos_date2(pdata,0,create_time);
4332 srv_put_dos_date2(pdata,4,atime);
4333 srv_put_dos_date2(pdata,8,mtime); /* write time */
4334 SIVAL(pdata,12,(uint32)file_size);
4335 SIVAL(pdata,16,(uint32)allocation_size);
4336 SSVAL(pdata,20,mode);
4337 SIVAL(pdata,22,ea_size);
4341 case SMB_INFO_IS_NAME_VALID:
4342 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4344 /* os/2 needs this ? really ?*/
4345 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4347 /* This is only reached for qpathinfo */
4351 case SMB_INFO_QUERY_EAS_FROM_LIST:
4353 size_t total_ea_len = 0;
4354 struct ea_list *ea_file_list = NULL;
4356 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4359 get_ea_list_from_file(mem_ctx, conn, fsp,
4360 smb_fname->base_name,
4362 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4364 if (!ea_list || (total_ea_len > data_size)) {
4366 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4370 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4374 case SMB_INFO_QUERY_ALL_EAS:
4376 /* We have data_size bytes to put EA's into. */
4377 size_t total_ea_len = 0;
4379 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
4381 ea_list = get_ea_list_from_file(mem_ctx, conn, fsp,
4382 smb_fname->base_name,
4384 if (!ea_list || (total_ea_len > data_size)) {
4386 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4390 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
4394 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
4396 /* This is FileFullEaInformation - 0xF which maps to
4397 * 1015 (decimal) in smbd_do_setfilepathinfo. */
4399 /* We have data_size bytes to put EA's into. */
4400 size_t total_ea_len = 0;
4401 struct ea_list *ea_file_list = NULL;
4403 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
4405 /*TODO: add filtering and index handling */
4408 get_ea_list_from_file(mem_ctx, conn, fsp,
4409 smb_fname->base_name,
4411 if (!ea_file_list) {
4412 return NT_STATUS_NO_EAS_ON_FILE;
4415 status = fill_ea_chained_buffer(mem_ctx,
4419 conn, ea_file_list);
4420 if (!NT_STATUS_IS_OK(status)) {
4426 case SMB_FILE_BASIC_INFORMATION:
4427 case SMB_QUERY_FILE_BASIC_INFO:
4429 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
4430 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
4431 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
4433 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
4437 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4438 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4439 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4440 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4441 SIVAL(pdata,32,mode);
4443 DEBUG(5,("SMB_QFBI - "));
4444 DEBUG(5,("create: %s ", ctime(&create_time)));
4445 DEBUG(5,("access: %s ", ctime(&atime)));
4446 DEBUG(5,("write: %s ", ctime(&mtime)));
4447 DEBUG(5,("change: %s ", ctime(&c_time)));
4448 DEBUG(5,("mode: %x\n", mode));
4451 case SMB_FILE_STANDARD_INFORMATION:
4452 case SMB_QUERY_FILE_STANDARD_INFO:
4454 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
4456 SOFF_T(pdata,0,allocation_size);
4457 SOFF_T(pdata,8,file_size);
4458 SIVAL(pdata,16,nlink);
4459 SCVAL(pdata,20,delete_pending?1:0);
4460 SCVAL(pdata,21,(mode&aDIR)?1:0);
4461 SSVAL(pdata,22,0); /* Padding. */
4464 case SMB_FILE_EA_INFORMATION:
4465 case SMB_QUERY_FILE_EA_INFO:
4467 unsigned int ea_size =
4468 estimate_ea_size(conn, fsp, smb_fname->base_name);
4469 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
4471 SIVAL(pdata,0,ea_size);
4475 /* Get the 8.3 name - used if NT SMB was negotiated. */
4476 case SMB_QUERY_FILE_ALT_NAME_INFO:
4477 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
4480 char mangled_name[13];
4481 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
4482 if (!name_to_8_3(base_name,mangled_name,
4483 True,conn->params)) {
4484 return NT_STATUS_NO_MEMORY;
4486 len = srvstr_push(dstart, flags2,
4487 pdata+4, mangled_name,
4488 PTR_DIFF(dend, pdata+4),
4490 data_size = 4 + len;
4495 case SMB_QUERY_FILE_NAME_INFO:
4499 this must be *exactly* right for ACLs on mapped drives to work
4501 len = srvstr_push(dstart, flags2,
4503 PTR_DIFF(dend, pdata+4),
4505 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
4506 data_size = 4 + len;
4511 case SMB_FILE_ALLOCATION_INFORMATION:
4512 case SMB_QUERY_FILE_ALLOCATION_INFO:
4513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
4515 SOFF_T(pdata,0,allocation_size);
4518 case SMB_FILE_END_OF_FILE_INFORMATION:
4519 case SMB_QUERY_FILE_END_OF_FILEINFO:
4520 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
4522 SOFF_T(pdata,0,file_size);
4525 case SMB_QUERY_FILE_ALL_INFO:
4526 case SMB_FILE_ALL_INFORMATION:
4529 unsigned int ea_size =
4530 estimate_ea_size(conn, fsp, smb_fname->base_name);
4531 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4532 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4533 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4534 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4535 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4536 SIVAL(pdata,32,mode);
4537 SIVAL(pdata,36,0); /* padding. */
4539 SOFF_T(pdata,0,allocation_size);
4540 SOFF_T(pdata,8,file_size);
4541 SIVAL(pdata,16,nlink);
4542 SCVAL(pdata,20,delete_pending);
4543 SCVAL(pdata,21,(mode&aDIR)?1:0);
4546 SIVAL(pdata,0,ea_size);
4547 pdata += 4; /* EA info */
4548 len = srvstr_push(dstart, flags2,
4550 PTR_DIFF(dend, pdata+4),
4554 data_size = PTR_DIFF(pdata,(*ppdata));
4558 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
4561 unsigned int ea_size =
4562 estimate_ea_size(conn, fsp, smb_fname->base_name);
4563 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4564 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
4565 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
4566 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
4567 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
4568 SIVAL(pdata, 0x20, mode);
4569 SIVAL(pdata, 0x24, 0); /* padding. */
4570 SBVAL(pdata, 0x28, allocation_size);
4571 SBVAL(pdata, 0x30, file_size);
4572 SIVAL(pdata, 0x38, nlink);
4573 SCVAL(pdata, 0x3C, delete_pending);
4574 SCVAL(pdata, 0x3D, (mode&aDIR)?1:0);
4575 SSVAL(pdata, 0x3E, 0); /* padding */
4576 SBVAL(pdata, 0x40, file_index);
4577 SIVAL(pdata, 0x48, ea_size);
4578 SIVAL(pdata, 0x4C, access_mask);
4579 SBVAL(pdata, 0x50, pos);
4580 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4581 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4585 len = srvstr_push(dstart, flags2,
4587 PTR_DIFF(dend, pdata+4),
4591 data_size = PTR_DIFF(pdata,(*ppdata));
4594 case SMB_FILE_INTERNAL_INFORMATION:
4596 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4597 SBVAL(pdata, 0, file_index);
4601 case SMB_FILE_ACCESS_INFORMATION:
4602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4603 SIVAL(pdata, 0, access_mask);
4607 case SMB_FILE_NAME_INFORMATION:
4608 /* Pathname with leading '\'. */
4611 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4612 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4613 SIVAL(pdata,0,byte_len);
4614 data_size = 4 + byte_len;
4618 case SMB_FILE_DISPOSITION_INFORMATION:
4619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4621 SCVAL(pdata,0,delete_pending);
4624 case SMB_FILE_POSITION_INFORMATION:
4625 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4627 SOFF_T(pdata,0,pos);
4630 case SMB_FILE_MODE_INFORMATION:
4631 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4632 SIVAL(pdata,0,mode);
4636 case SMB_FILE_ALIGNMENT_INFORMATION:
4637 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4638 SIVAL(pdata,0,0); /* No alignment needed. */
4643 * NT4 server just returns "invalid query" to this - if we try
4644 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4647 /* The first statement above is false - verified using Thursby
4648 * client against NT4 -- gcolley.
4650 case SMB_QUERY_FILE_STREAM_INFO:
4651 case SMB_FILE_STREAM_INFORMATION: {
4652 unsigned int num_streams;
4653 struct stream_struct *streams;
4655 DEBUG(10,("smbd_do_qfilepathinfo: "
4656 "SMB_FILE_STREAM_INFORMATION\n"));
4658 if (is_ntfs_stream_smb_fname(smb_fname)) {
4659 return NT_STATUS_INVALID_PARAMETER;
4662 status = SMB_VFS_STREAMINFO(
4663 conn, fsp, smb_fname->base_name, talloc_tos(),
4664 &num_streams, &streams);
4666 if (!NT_STATUS_IS_OK(status)) {
4667 DEBUG(10, ("could not get stream info: %s\n",
4668 nt_errstr(status)));
4672 status = marshall_stream_info(num_streams, streams,
4673 pdata, max_data_bytes,
4676 if (!NT_STATUS_IS_OK(status)) {
4677 DEBUG(10, ("marshall_stream_info failed: %s\n",
4678 nt_errstr(status)));
4682 TALLOC_FREE(streams);
4686 case SMB_QUERY_COMPRESSION_INFO:
4687 case SMB_FILE_COMPRESSION_INFORMATION:
4688 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4689 SOFF_T(pdata,0,file_size);
4690 SIVAL(pdata,8,0); /* ??? */
4691 SIVAL(pdata,12,0); /* ??? */
4695 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4696 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4697 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
4698 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
4699 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
4700 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
4701 SOFF_T(pdata,32,allocation_size);
4702 SOFF_T(pdata,40,file_size);
4703 SIVAL(pdata,48,mode);
4704 SIVAL(pdata,52,0); /* ??? */
4708 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4709 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4710 SIVAL(pdata,0,mode);
4716 * CIFS UNIX Extensions.
4719 case SMB_QUERY_FILE_UNIX_BASIC:
4721 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4722 data_size = PTR_DIFF(pdata,(*ppdata));
4726 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_BASIC "));
4728 for (i=0; i<100; i++)
4729 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4735 case SMB_QUERY_FILE_UNIX_INFO2:
4737 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4738 data_size = PTR_DIFF(pdata,(*ppdata));
4742 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4744 for (i=0; i<100; i++)
4745 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4751 case SMB_QUERY_FILE_UNIX_LINK:
4754 char *buffer = TALLOC_ARRAY(mem_ctx, char, PATH_MAX+1);
4757 return NT_STATUS_NO_MEMORY;
4760 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
4762 if(!S_ISLNK(psbuf->st_ex_mode)) {
4763 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4766 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
4768 len = SMB_VFS_READLINK(conn,
4769 smb_fname->base_name,
4772 return map_nt_error_from_unix(errno);
4775 len = srvstr_push(dstart, flags2,
4777 PTR_DIFF(dend, pdata),
4780 data_size = PTR_DIFF(pdata,(*ppdata));
4785 #if defined(HAVE_POSIX_ACLS)
4786 case SMB_QUERY_POSIX_ACL:
4788 SMB_ACL_T file_acl = NULL;
4789 SMB_ACL_T def_acl = NULL;
4790 uint16 num_file_acls = 0;
4791 uint16 num_def_acls = 0;
4793 if (fsp && !fsp->is_directory && (fsp->fh->fd != -1)) {
4794 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp);
4797 SMB_VFS_SYS_ACL_GET_FILE(conn,
4798 smb_fname->base_name,
4799 SMB_ACL_TYPE_ACCESS);
4802 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4803 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
4804 "not implemented on "
4805 "filesystem containing %s\n",
4806 smb_fname->base_name));
4807 return NT_STATUS_NOT_IMPLEMENTED;
4810 if (S_ISDIR(psbuf->st_ex_mode)) {
4811 if (fsp && fsp->is_directory) {
4813 SMB_VFS_SYS_ACL_GET_FILE(
4815 fsp->fsp_name->base_name,
4816 SMB_ACL_TYPE_DEFAULT);
4819 SMB_VFS_SYS_ACL_GET_FILE(
4821 smb_fname->base_name,
4822 SMB_ACL_TYPE_DEFAULT);
4824 def_acl = free_empty_sys_acl(conn, def_acl);
4827 num_file_acls = count_acl_entries(conn, file_acl);
4828 num_def_acls = count_acl_entries(conn, def_acl);
4830 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
4831 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
4833 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
4834 SMB_POSIX_ACL_HEADER_SIZE) ));
4836 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4839 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4841 return NT_STATUS_BUFFER_TOO_SMALL;
4844 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4845 SSVAL(pdata,2,num_file_acls);
4846 SSVAL(pdata,4,num_def_acls);
4847 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
4849 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4852 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4854 return NT_STATUS_INTERNAL_ERROR;
4856 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
4858 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4861 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4863 return NT_STATUS_INTERNAL_ERROR;
4867 SMB_VFS_SYS_ACL_FREE_ACL(conn, file_acl);
4870 SMB_VFS_SYS_ACL_FREE_ACL(conn, def_acl);
4872 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
4878 case SMB_QUERY_POSIX_LOCK:
4883 enum brl_type lock_type;
4885 /* We need an open file with a real fd for this. */
4886 if (!fsp || fsp->is_directory || fsp->fh->fd == -1) {
4887 return NT_STATUS_INVALID_LEVEL;
4890 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4891 return NT_STATUS_INVALID_PARAMETER;
4894 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4895 case POSIX_LOCK_TYPE_READ:
4896 lock_type = READ_LOCK;
4898 case POSIX_LOCK_TYPE_WRITE:
4899 lock_type = WRITE_LOCK;
4901 case POSIX_LOCK_TYPE_UNLOCK:
4903 /* There's no point in asking for an unlock... */
4904 return NT_STATUS_INVALID_PARAMETER;
4907 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4908 #if defined(HAVE_LONGLONG)
4909 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
4910 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
4911 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
4912 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
4913 #else /* HAVE_LONGLONG */
4914 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
4915 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4916 #endif /* HAVE_LONGLONG */
4918 status = query_lock(fsp,
4925 if (ERROR_WAS_LOCK_DENIED(status)) {
4926 /* Here we need to report who has it locked... */
4927 data_size = POSIX_LOCK_DATA_SIZE;
4929 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4930 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4931 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, lock_pid);
4932 #if defined(HAVE_LONGLONG)
4933 SIVAL(pdata, POSIX_LOCK_START_OFFSET, (uint32)(offset & 0xFFFFFFFF));
4934 SIVAL(pdata, POSIX_LOCK_START_OFFSET + 4, (uint32)((offset >> 32) & 0xFFFFFFFF));
4935 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, (uint32)(count & 0xFFFFFFFF));
4936 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET + 4, (uint32)((count >> 32) & 0xFFFFFFFF));
4937 #else /* HAVE_LONGLONG */
4938 SIVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4939 SIVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4940 #endif /* HAVE_LONGLONG */
4942 } else if (NT_STATUS_IS_OK(status)) {
4943 /* For success we just return a copy of what we sent
4944 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4945 data_size = POSIX_LOCK_DATA_SIZE;
4946 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4947 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4955 return NT_STATUS_INVALID_LEVEL;
4958 *pdata_size = data_size;
4959 return NT_STATUS_OK;
4962 /****************************************************************************
4963 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
4964 file name or file id).
4965 ****************************************************************************/
4967 static void call_trans2qfilepathinfo(connection_struct *conn,
4968 struct smb_request *req,
4969 unsigned int tran_call,
4970 char **pparams, int total_params,
4971 char **ppdata, int total_data,
4972 unsigned int max_data_bytes)
4974 char *params = *pparams;
4975 char *pdata = *ppdata;
4977 unsigned int data_size = 0;
4978 unsigned int param_size = 2;
4979 struct smb_filename *smb_fname = NULL;
4980 bool delete_pending = False;
4981 struct timespec write_time_ts;
4982 files_struct *fsp = NULL;
4983 struct file_id fileid;
4984 struct ea_list *ea_list = NULL;
4985 int lock_data_count = 0;
4986 char *lock_data = NULL;
4987 bool ms_dfs_link = false;
4988 NTSTATUS status = NT_STATUS_OK;
4991 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4995 ZERO_STRUCT(write_time_ts);
4997 if (tran_call == TRANSACT2_QFILEINFO) {
4998 if (total_params < 4) {
4999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5004 call_trans2qpipeinfo(conn, req, tran_call,
5005 pparams, total_params,
5011 fsp = file_fsp(req, SVAL(params,0));
5012 info_level = SVAL(params,2);
5014 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5016 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5017 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5021 /* Initial check for valid fsp ptr. */
5022 if (!check_fsp_open(conn, req, fsp)) {
5026 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
5028 if (!NT_STATUS_IS_OK(status)) {
5029 reply_nterror(req, status);
5033 if(fsp->fake_file_handle) {
5035 * This is actually for the QUOTA_FAKE_FILE --metze
5038 /* We know this name is ok, it's already passed the checks. */
5040 } else if(fsp->is_directory || fsp->fh->fd == -1) {
5042 * This is actually a QFILEINFO on a directory
5043 * handle (returned from an NT SMB). NT5.0 seems
5044 * to do this call. JRA.
5047 if (INFO_LEVEL_IS_UNIX(info_level)) {
5048 /* Always do lstat for UNIX calls. */
5049 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5050 DEBUG(3,("call_trans2qfilepathinfo: "
5051 "SMB_VFS_LSTAT of %s failed "
5053 smb_fname_str_dbg(smb_fname),
5056 map_nt_error_from_unix(errno));
5059 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5060 DEBUG(3,("call_trans2qfilepathinfo: "
5061 "SMB_VFS_STAT of %s failed (%s)\n",
5062 smb_fname_str_dbg(smb_fname),
5065 map_nt_error_from_unix(errno));
5069 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5070 get_file_infos(fileid, &delete_pending, &write_time_ts);
5073 * Original code - this is an open file.
5075 if (!check_fsp(conn, req, fsp)) {
5079 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5080 DEBUG(3, ("fstat of fnum %d failed (%s)\n",
5081 fsp->fnum, strerror(errno)));
5083 map_nt_error_from_unix(errno));
5086 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5087 get_file_infos(fileid, &delete_pending, &write_time_ts);
5094 if (total_params < 7) {
5095 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5099 info_level = SVAL(params,0);
5101 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5103 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5104 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5108 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
5110 STR_TERMINATE, &status);
5111 if (!NT_STATUS_IS_OK(status)) {
5112 reply_nterror(req, status);
5116 status = filename_convert(req,
5118 req->flags2 & FLAGS2_DFS_PATHNAMES,
5123 if (!NT_STATUS_IS_OK(status)) {
5124 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5125 reply_botherror(req,
5126 NT_STATUS_PATH_NOT_COVERED,
5127 ERRSRV, ERRbadpath);
5130 reply_nterror(req, status);
5134 /* If this is a stream, check if there is a delete_pending. */
5135 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5136 && is_ntfs_stream_smb_fname(smb_fname)) {
5137 struct smb_filename *smb_fname_base = NULL;
5139 /* Create an smb_filename with stream_name == NULL. */
5141 create_synthetic_smb_fname(talloc_tos(),
5142 smb_fname->base_name,
5145 if (!NT_STATUS_IS_OK(status)) {
5146 reply_nterror(req, status);
5150 if (INFO_LEVEL_IS_UNIX(info_level)) {
5151 /* Always do lstat for UNIX calls. */
5152 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5153 DEBUG(3,("call_trans2qfilepathinfo: "
5154 "SMB_VFS_LSTAT of %s failed "
5156 smb_fname_str_dbg(smb_fname_base),
5158 TALLOC_FREE(smb_fname_base);
5160 map_nt_error_from_unix(errno));
5164 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5165 DEBUG(3,("call_trans2qfilepathinfo: "
5166 "fileinfo of %s failed "
5168 smb_fname_str_dbg(smb_fname_base),
5170 TALLOC_FREE(smb_fname_base);
5172 map_nt_error_from_unix(errno));
5177 fileid = vfs_file_id_from_sbuf(conn,
5178 &smb_fname_base->st);
5179 TALLOC_FREE(smb_fname_base);
5180 get_file_infos(fileid, &delete_pending, NULL);
5181 if (delete_pending) {
5182 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5187 if (INFO_LEVEL_IS_UNIX(info_level)) {
5188 /* Always do lstat for UNIX calls. */
5189 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5190 DEBUG(3,("call_trans2qfilepathinfo: "
5191 "SMB_VFS_LSTAT of %s failed (%s)\n",
5192 smb_fname_str_dbg(smb_fname),
5195 map_nt_error_from_unix(errno));
5199 } else if (!VALID_STAT(smb_fname->st) &&
5200 SMB_VFS_STAT(conn, smb_fname) &&
5201 (info_level != SMB_INFO_IS_NAME_VALID)) {
5202 ms_dfs_link = check_msdfs_link(conn,
5203 smb_fname->base_name,
5207 DEBUG(3,("call_trans2qfilepathinfo: "
5208 "SMB_VFS_STAT of %s failed (%s)\n",
5209 smb_fname_str_dbg(smb_fname),
5212 map_nt_error_from_unix(errno));
5217 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5218 get_file_infos(fileid, &delete_pending, &write_time_ts);
5219 if (delete_pending) {
5220 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5225 DEBUG(3,("call_trans2qfilepathinfo %s (fnum = %d) level=%d call=%d "
5226 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5227 fsp ? fsp->fnum : -1, info_level,tran_call,total_data));
5229 /* Pull out any data sent here before we realloc. */
5230 switch (info_level) {
5231 case SMB_INFO_QUERY_EAS_FROM_LIST:
5233 /* Pull any EA list from the data portion. */
5236 if (total_data < 4) {
5238 req, NT_STATUS_INVALID_PARAMETER);
5241 ea_size = IVAL(pdata,0);
5243 if (total_data > 0 && ea_size != total_data) {
5244 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5245 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5247 req, NT_STATUS_INVALID_PARAMETER);
5251 if (!lp_ea_support(SNUM(conn))) {
5252 reply_doserror(req, ERRDOS,
5253 ERReasnotsupported);
5257 /* Pull out the list of names. */
5258 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5261 req, NT_STATUS_INVALID_PARAMETER);
5267 case SMB_QUERY_POSIX_LOCK:
5269 if (fsp == NULL || fsp->fh->fd == -1) {
5270 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5274 if (total_data != POSIX_LOCK_DATA_SIZE) {
5276 req, NT_STATUS_INVALID_PARAMETER);
5280 /* Copy the lock range data. */
5281 lock_data = (char *)TALLOC_MEMDUP(
5282 req, pdata, total_data);
5284 reply_nterror(req, NT_STATUS_NO_MEMORY);
5287 lock_data_count = total_data;
5293 *pparams = (char *)SMB_REALLOC(*pparams,2);
5294 if (*pparams == NULL) {
5295 reply_nterror(req, NT_STATUS_NO_MEMORY);
5302 * draft-leach-cifs-v1-spec-02.txt
5303 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5306 * The requested information is placed in the Data portion of the
5307 * transaction response. For the information levels greater than 0x100,
5308 * the transaction response has 1 parameter word which should be
5309 * ignored by the client.
5311 * However Windows only follows this rule for the IS_NAME_VALID call.
5313 switch (info_level) {
5314 case SMB_INFO_IS_NAME_VALID:
5319 if ((info_level & 0xFF00) == 0xFF00) {
5321 * We use levels that start with 0xFF00
5322 * internally to represent SMB2 specific levels
5324 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5328 status = smbd_do_qfilepathinfo(conn, req, info_level,
5330 delete_pending, write_time_ts,
5331 ms_dfs_link, ea_list,
5332 lock_data_count, lock_data,
5333 req->flags2, max_data_bytes,
5334 ppdata, &data_size);
5335 if (!NT_STATUS_IS_OK(status)) {
5336 reply_nterror(req, status);
5340 send_trans2_replies(conn, req, params, param_size, *ppdata, data_size,
5346 /****************************************************************************
5347 Set a hard link (called by UNIX extensions and by NT rename with HARD link
5349 ****************************************************************************/
5351 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
5352 connection_struct *conn,
5353 const struct smb_filename *smb_fname_old,
5354 const struct smb_filename *smb_fname_new)
5356 NTSTATUS status = NT_STATUS_OK;
5358 /* source must already exist. */
5359 if (!VALID_STAT(smb_fname_old->st)) {
5360 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5363 /* Disallow if newname already exists. */
5364 if (VALID_STAT(smb_fname_new->st)) {
5365 return NT_STATUS_OBJECT_NAME_COLLISION;
5368 /* No links from a directory. */
5369 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
5370 return NT_STATUS_FILE_IS_A_DIRECTORY;
5373 /* Setting a hardlink to/from a stream isn't currently supported. */
5374 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
5375 is_ntfs_stream_smb_fname(smb_fname_new)) {
5376 return NT_STATUS_INVALID_PARAMETER;
5379 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
5380 smb_fname_old->base_name, smb_fname_new->base_name));
5382 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
5383 smb_fname_new->base_name) != 0) {
5384 status = map_nt_error_from_unix(errno);
5385 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
5386 nt_errstr(status), smb_fname_old->base_name,
5387 smb_fname_new->base_name));
5392 /****************************************************************************
5393 Deal with setting the time from any of the setfilepathinfo functions.
5394 ****************************************************************************/
5396 NTSTATUS smb_set_file_time(connection_struct *conn,
5398 const struct smb_filename *smb_fname,
5399 struct smb_file_time *ft,
5400 bool setting_write_time)
5402 struct smb_filename *smb_fname_base = NULL;
5404 FILE_NOTIFY_CHANGE_LAST_ACCESS
5405 |FILE_NOTIFY_CHANGE_LAST_WRITE
5406 |FILE_NOTIFY_CHANGE_CREATION;
5409 if (!VALID_STAT(smb_fname->st)) {
5410 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5413 /* get some defaults (no modifications) if any info is zero or -1. */
5414 if (null_timespec(ft->create_time)) {
5415 action &= ~FILE_NOTIFY_CHANGE_CREATION;
5418 if (null_timespec(ft->atime)) {
5419 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
5422 if (null_timespec(ft->mtime)) {
5423 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5426 if (!setting_write_time) {
5427 /* ft->mtime comes from change time, not write time. */
5428 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
5431 /* Ensure the resolution is the correct for
5432 * what we can store on this filesystem. */
5434 round_timespec(conn->ts_res, &ft->create_time);
5435 round_timespec(conn->ts_res, &ft->ctime);
5436 round_timespec(conn->ts_res, &ft->atime);
5437 round_timespec(conn->ts_res, &ft->mtime);
5439 DEBUG(5,("smb_set_filetime: actime: %s\n ",
5440 time_to_asc(convert_timespec_to_time_t(ft->atime))));
5441 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
5442 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5443 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
5444 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
5445 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
5446 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
5448 if (setting_write_time) {
5450 * This was a Windows setfileinfo on an open file.
5451 * NT does this a lot. We also need to
5452 * set the time here, as it can be read by
5453 * FindFirst/FindNext and with the patch for bug #2045
5454 * in smbd/fileio.c it ensures that this timestamp is
5455 * kept sticky even after a write. We save the request
5456 * away and will set it on file close and after a write. JRA.
5459 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
5460 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
5463 if (fsp->base_fsp) {
5464 set_sticky_write_time_fsp(fsp->base_fsp,
5467 set_sticky_write_time_fsp(fsp, ft->mtime);
5470 set_sticky_write_time_path(
5471 vfs_file_id_from_sbuf(conn, &smb_fname->st),
5476 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
5478 /* Always call ntimes on the base, even if a stream was passed in. */
5479 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5480 NULL, &smb_fname->st,
5482 if (!NT_STATUS_IS_OK(status)) {
5486 if(file_ntimes(conn, smb_fname_base, ft)!=0) {
5487 TALLOC_FREE(smb_fname_base);
5488 return map_nt_error_from_unix(errno);
5490 TALLOC_FREE(smb_fname_base);
5492 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
5493 smb_fname->base_name);
5494 return NT_STATUS_OK;
5497 /****************************************************************************
5498 Deal with setting the dosmode from any of the setfilepathinfo functions.
5499 ****************************************************************************/
5501 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
5502 const struct smb_filename *smb_fname,
5505 struct smb_filename *smb_fname_base = NULL;
5508 if (!VALID_STAT(smb_fname->st)) {
5509 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5512 /* Always operate on the base_name, even if a stream was passed in. */
5513 status = create_synthetic_smb_fname(talloc_tos(), smb_fname->base_name,
5514 NULL, &smb_fname->st,
5516 if (!NT_STATUS_IS_OK(status)) {
5521 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
5528 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
5530 /* check the mode isn't different, before changing it */
5531 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
5532 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
5533 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
5534 (unsigned int)dosmode));
5536 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
5538 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
5540 smb_fname_str_dbg(smb_fname_base),
5542 status = map_nt_error_from_unix(errno);
5546 status = NT_STATUS_OK;
5548 TALLOC_FREE(smb_fname_base);
5552 /****************************************************************************
5553 Deal with setting the size from any of the setfilepathinfo functions.
5554 ****************************************************************************/
5556 static NTSTATUS smb_set_file_size(connection_struct *conn,
5557 struct smb_request *req,
5559 const struct smb_filename *smb_fname,
5560 const SMB_STRUCT_STAT *psbuf,
5563 NTSTATUS status = NT_STATUS_OK;
5564 struct smb_filename *smb_fname_tmp = NULL;
5565 files_struct *new_fsp = NULL;
5567 if (!VALID_STAT(*psbuf)) {
5568 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5571 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
5573 if (size == get_file_size_stat(psbuf)) {
5574 return NT_STATUS_OK;
5577 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
5578 smb_fname_str_dbg(smb_fname), (double)size));
5580 if (fsp && fsp->fh->fd != -1) {
5581 /* Handle based call. */
5582 if (vfs_set_filelen(fsp, size) == -1) {
5583 return map_nt_error_from_unix(errno);
5585 trigger_write_time_update_immediate(fsp);
5586 return NT_STATUS_OK;
5589 status = copy_smb_filename(talloc_tos(), smb_fname, &smb_fname_tmp);
5590 if (!NT_STATUS_IS_OK(status)) {
5594 smb_fname_tmp->st = *psbuf;
5596 status = SMB_VFS_CREATE_FILE(
5599 0, /* root_dir_fid */
5600 smb_fname_tmp, /* fname */
5601 FILE_WRITE_ATTRIBUTES, /* access_mask */
5602 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5604 FILE_OPEN, /* create_disposition*/
5605 0, /* create_options */
5606 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5607 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
5608 0, /* allocation_size */
5611 &new_fsp, /* result */
5614 TALLOC_FREE(smb_fname_tmp);
5616 if (!NT_STATUS_IS_OK(status)) {
5617 /* NB. We check for open_was_deferred in the caller. */
5621 if (vfs_set_filelen(new_fsp, size) == -1) {
5622 status = map_nt_error_from_unix(errno);
5623 close_file(req, new_fsp,NORMAL_CLOSE);
5627 trigger_write_time_update_immediate(new_fsp);
5628 close_file(req, new_fsp,NORMAL_CLOSE);
5629 return NT_STATUS_OK;
5632 /****************************************************************************
5633 Deal with SMB_INFO_SET_EA.
5634 ****************************************************************************/
5636 static NTSTATUS smb_info_set_ea(connection_struct *conn,
5640 const struct smb_filename *smb_fname)
5642 struct ea_list *ea_list = NULL;
5643 TALLOC_CTX *ctx = NULL;
5644 NTSTATUS status = NT_STATUS_OK;
5646 if (total_data < 10) {
5648 /* OS/2 workplace shell seems to send SET_EA requests of "null"
5649 length. They seem to have no effect. Bug #3212. JRA */
5651 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
5652 /* We're done. We only get EA info in this call. */
5653 return NT_STATUS_OK;
5656 return NT_STATUS_INVALID_PARAMETER;
5659 if (IVAL(pdata,0) > total_data) {
5660 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
5661 IVAL(pdata,0), (unsigned int)total_data));
5662 return NT_STATUS_INVALID_PARAMETER;
5666 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
5668 return NT_STATUS_INVALID_PARAMETER;
5670 status = set_ea(conn, fsp, smb_fname, ea_list);
5675 /****************************************************************************
5676 Deal with SMB_FILE_FULL_EA_INFORMATION set.
5677 ****************************************************************************/
5679 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
5684 struct ea_list *ea_list = NULL;
5688 return NT_STATUS_INVALID_HANDLE;
5691 if (!lp_ea_support(SNUM(conn))) {
5692 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
5693 "EA's not supported.\n",
5694 (unsigned int)total_data));
5695 return NT_STATUS_EAS_NOT_SUPPORTED;
5698 if (total_data < 10) {
5699 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
5701 (unsigned int)total_data));
5702 return NT_STATUS_INVALID_PARAMETER;
5705 ea_list = read_nttrans_ea_list(talloc_tos(),
5710 return NT_STATUS_INVALID_PARAMETER;
5712 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
5714 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
5715 smb_fname_str_dbg(fsp->fsp_name),
5716 nt_errstr(status) ));
5722 /****************************************************************************
5723 Deal with SMB_SET_FILE_DISPOSITION_INFO.
5724 ****************************************************************************/
5726 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
5730 const struct smb_filename *smb_fname)
5732 NTSTATUS status = NT_STATUS_OK;
5733 bool delete_on_close;
5736 if (total_data < 1) {
5737 return NT_STATUS_INVALID_PARAMETER;
5741 return NT_STATUS_INVALID_HANDLE;
5744 delete_on_close = (CVAL(pdata,0) ? True : False);
5745 dosmode = dos_mode(conn, smb_fname);
5747 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
5748 "delete_on_close = %u\n",
5749 smb_fname_str_dbg(smb_fname),
5750 (unsigned int)dosmode,
5751 (unsigned int)delete_on_close ));
5753 status = can_set_delete_on_close(fsp, delete_on_close, dosmode);
5755 if (!NT_STATUS_IS_OK(status)) {
5759 /* The set is across all open files on this dev/inode pair. */
5760 if (!set_delete_on_close(fsp, delete_on_close,
5761 &conn->server_info->utok)) {
5762 return NT_STATUS_ACCESS_DENIED;
5764 return NT_STATUS_OK;
5767 /****************************************************************************
5768 Deal with SMB_FILE_POSITION_INFORMATION.
5769 ****************************************************************************/
5771 static NTSTATUS smb_file_position_information(connection_struct *conn,
5776 uint64_t position_information;
5778 if (total_data < 8) {
5779 return NT_STATUS_INVALID_PARAMETER;
5783 /* Ignore on pathname based set. */
5784 return NT_STATUS_OK;
5787 position_information = (uint64_t)IVAL(pdata,0);
5788 #ifdef LARGE_SMB_OFF_T
5789 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
5790 #else /* LARGE_SMB_OFF_T */
5791 if (IVAL(pdata,4) != 0) {
5792 /* more than 32 bits? */
5793 return NT_STATUS_INVALID_PARAMETER;
5795 #endif /* LARGE_SMB_OFF_T */
5797 DEBUG(10,("smb_file_position_information: Set file position "
5798 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
5799 (double)position_information));
5800 fsp->fh->position_information = position_information;
5801 return NT_STATUS_OK;
5804 /****************************************************************************
5805 Deal with SMB_FILE_MODE_INFORMATION.
5806 ****************************************************************************/
5808 static NTSTATUS smb_file_mode_information(connection_struct *conn,
5814 if (total_data < 4) {
5815 return NT_STATUS_INVALID_PARAMETER;
5817 mode = IVAL(pdata,0);
5818 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
5819 return NT_STATUS_INVALID_PARAMETER;
5821 return NT_STATUS_OK;
5824 /****************************************************************************
5825 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
5826 ****************************************************************************/
5828 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
5829 struct smb_request *req,
5832 const struct smb_filename *smb_fname)
5834 char *link_target = NULL;
5835 const char *newname = smb_fname->base_name;
5836 NTSTATUS status = NT_STATUS_OK;
5837 TALLOC_CTX *ctx = talloc_tos();
5839 /* Set a symbolic link. */
5840 /* Don't allow this if follow links is false. */
5842 if (total_data == 0) {
5843 return NT_STATUS_INVALID_PARAMETER;
5846 if (!lp_symlinks(SNUM(conn))) {
5847 return NT_STATUS_ACCESS_DENIED;
5850 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
5851 total_data, STR_TERMINATE);
5854 return NT_STATUS_INVALID_PARAMETER;
5857 /* !widelinks forces the target path to be within the share. */
5858 /* This means we can interpret the target as a pathname. */
5859 if (!lp_widelinks(SNUM(conn))) {
5860 char *rel_name = NULL;
5861 char *last_dirp = NULL;
5863 if (*link_target == '/') {
5864 /* No absolute paths allowed. */
5865 return NT_STATUS_ACCESS_DENIED;
5867 rel_name = talloc_strdup(ctx,newname);
5869 return NT_STATUS_NO_MEMORY;
5871 last_dirp = strrchr_m(rel_name, '/');
5873 last_dirp[1] = '\0';
5875 rel_name = talloc_strdup(ctx,"./");
5877 return NT_STATUS_NO_MEMORY;
5880 rel_name = talloc_asprintf_append(rel_name,
5884 return NT_STATUS_NO_MEMORY;
5887 status = check_name(conn, rel_name);
5888 if (!NT_STATUS_IS_OK(status)) {
5893 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
5894 newname, link_target ));
5896 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
5897 return map_nt_error_from_unix(errno);
5900 return NT_STATUS_OK;
5903 /****************************************************************************
5904 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
5905 ****************************************************************************/
5907 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
5908 struct smb_request *req,
5909 const char *pdata, int total_data,
5910 const struct smb_filename *smb_fname_new)
5912 char *oldname = NULL;
5913 struct smb_filename *smb_fname_old = NULL;
5914 TALLOC_CTX *ctx = talloc_tos();
5915 NTSTATUS status = NT_STATUS_OK;
5917 /* Set a hard link. */
5918 if (total_data == 0) {
5919 return NT_STATUS_INVALID_PARAMETER;
5922 srvstr_get_path(ctx, pdata, req->flags2, &oldname, pdata,
5923 total_data, STR_TERMINATE, &status);
5924 if (!NT_STATUS_IS_OK(status)) {
5928 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
5929 smb_fname_str_dbg(smb_fname_new), oldname));
5931 status = filename_convert(ctx,
5933 req->flags2 & FLAGS2_DFS_PATHNAMES,
5938 if (!NT_STATUS_IS_OK(status)) {
5942 return hardlink_internals(ctx, conn, smb_fname_old, smb_fname_new);
5945 /****************************************************************************
5946 Deal with SMB_FILE_RENAME_INFORMATION.
5947 ****************************************************************************/
5949 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5950 struct smb_request *req,
5954 struct smb_filename *smb_fname_src)
5959 char *newname = NULL;
5960 struct smb_filename *smb_fname_dst = NULL;
5961 bool dest_has_wcard = False;
5962 NTSTATUS status = NT_STATUS_OK;
5964 TALLOC_CTX *ctx = talloc_tos();
5966 if (total_data < 13) {
5967 return NT_STATUS_INVALID_PARAMETER;
5970 overwrite = (CVAL(pdata,0) ? True : False);
5971 root_fid = IVAL(pdata,4);
5972 len = IVAL(pdata,8);
5974 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5975 return NT_STATUS_INVALID_PARAMETER;
5978 srvstr_get_path_wcard(ctx, pdata, req->flags2, &newname, &pdata[12],
5981 if (!NT_STATUS_IS_OK(status)) {
5985 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5988 status = resolve_dfspath_wcard(ctx, conn,
5989 req->flags2 & FLAGS2_DFS_PATHNAMES,
5993 if (!NT_STATUS_IS_OK(status)) {
5997 /* Check the new name has no '/' characters. */
5998 if (strchr_m(newname, '/')) {
5999 return NT_STATUS_NOT_SUPPORTED;
6002 if (fsp && fsp->base_fsp) {
6003 /* newname must be a stream name. */
6004 if (newname[0] != ':') {
6005 return NT_STATUS_NOT_SUPPORTED;
6008 /* Create an smb_fname to call rename_internals_fsp() with. */
6009 status = create_synthetic_smb_fname(talloc_tos(),
6010 fsp->base_fsp->fsp_name->base_name, newname, NULL,
6012 if (!NT_STATUS_IS_OK(status)) {
6017 * Set the original last component, since
6018 * rename_internals_fsp() requires it.
6020 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6022 if (smb_fname_dst->original_lcomp == NULL) {
6023 status = NT_STATUS_NO_MEMORY;
6029 * Build up an smb_fname_dst based on the filename passed in.
6030 * We basically just strip off the last component, and put on
6031 * the newname instead.
6033 char *base_name = NULL;
6035 /* newname must *not* be a stream name. */
6036 if (newname[0] == ':') {
6037 return NT_STATUS_NOT_SUPPORTED;
6041 * Strip off the last component (filename) of the path passed
6044 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6046 return NT_STATUS_NO_MEMORY;
6048 p = strrchr_m(base_name, '/');
6052 base_name = talloc_strdup(ctx, "./");
6054 return NT_STATUS_NO_MEMORY;
6057 /* Append the new name. */
6058 base_name = talloc_asprintf_append(base_name,
6062 return NT_STATUS_NO_MEMORY;
6065 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
6068 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
6071 /* If an error we expect this to be
6072 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
6074 if (!NT_STATUS_IS_OK(status)) {
6075 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
6079 /* Create an smb_fname to call rename_internals_fsp() */
6080 status = create_synthetic_smb_fname(ctx,
6084 if (!NT_STATUS_IS_OK(status)) {
6091 DEBUG(10,("smb_file_rename_information: "
6092 "SMB_FILE_RENAME_INFORMATION (fnum %d) %s -> %s\n",
6093 fsp->fnum, fsp_str_dbg(fsp),
6094 smb_fname_str_dbg(smb_fname_dst)));
6095 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
6098 DEBUG(10,("smb_file_rename_information: "
6099 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
6100 smb_fname_str_dbg(smb_fname_src),
6101 smb_fname_str_dbg(smb_fname_dst)));
6102 status = rename_internals(ctx, conn, req, smb_fname_src,
6103 smb_fname_dst, 0, overwrite, false,
6105 FILE_WRITE_ATTRIBUTES);
6108 TALLOC_FREE(smb_fname_dst);
6112 /****************************************************************************
6113 Deal with SMB_SET_POSIX_ACL.
6114 ****************************************************************************/
6116 #if defined(HAVE_POSIX_ACLS)
6117 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
6121 const struct smb_filename *smb_fname)
6123 uint16 posix_acl_version;
6124 uint16 num_file_acls;
6125 uint16 num_def_acls;
6126 bool valid_file_acls = True;
6127 bool valid_def_acls = True;
6129 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
6130 return NT_STATUS_INVALID_PARAMETER;
6132 posix_acl_version = SVAL(pdata,0);
6133 num_file_acls = SVAL(pdata,2);
6134 num_def_acls = SVAL(pdata,4);
6136 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6137 valid_file_acls = False;
6141 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
6142 valid_def_acls = False;
6146 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
6147 return NT_STATUS_INVALID_PARAMETER;
6150 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
6151 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
6152 return NT_STATUS_INVALID_PARAMETER;
6155 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
6156 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
6157 (unsigned int)num_file_acls,
6158 (unsigned int)num_def_acls));
6160 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
6161 smb_fname->base_name, num_file_acls,
6162 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
6163 return map_nt_error_from_unix(errno);
6166 if (valid_def_acls && !set_unix_posix_default_acl(conn,
6167 smb_fname->base_name, &smb_fname->st, num_def_acls,
6168 pdata + SMB_POSIX_ACL_HEADER_SIZE +
6169 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
6170 return map_nt_error_from_unix(errno);
6172 return NT_STATUS_OK;
6176 /****************************************************************************
6177 Deal with SMB_SET_POSIX_LOCK.
6178 ****************************************************************************/
6180 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
6181 struct smb_request *req,
6189 bool blocking_lock = False;
6190 enum brl_type lock_type;
6192 NTSTATUS status = NT_STATUS_OK;
6194 if (fsp == NULL || fsp->fh->fd == -1) {
6195 return NT_STATUS_INVALID_HANDLE;
6198 if (total_data != POSIX_LOCK_DATA_SIZE) {
6199 return NT_STATUS_INVALID_PARAMETER;
6202 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
6203 case POSIX_LOCK_TYPE_READ:
6204 lock_type = READ_LOCK;
6206 case POSIX_LOCK_TYPE_WRITE:
6207 /* Return the right POSIX-mappable error code for files opened read-only. */
6208 if (!fsp->can_write) {
6209 return NT_STATUS_INVALID_HANDLE;
6211 lock_type = WRITE_LOCK;
6213 case POSIX_LOCK_TYPE_UNLOCK:
6214 lock_type = UNLOCK_LOCK;
6217 return NT_STATUS_INVALID_PARAMETER;
6220 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
6221 blocking_lock = False;
6222 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
6223 blocking_lock = True;
6225 return NT_STATUS_INVALID_PARAMETER;
6228 if (!lp_blocking_locks(SNUM(conn))) {
6229 blocking_lock = False;
6232 lock_pid = IVAL(pdata, POSIX_LOCK_PID_OFFSET);
6233 #if defined(HAVE_LONGLONG)
6234 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
6235 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
6236 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
6237 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
6238 #else /* HAVE_LONGLONG */
6239 offset = (uint64_t)IVAL(pdata,POSIX_LOCK_START_OFFSET);
6240 count = (uint64_t)IVAL(pdata,POSIX_LOCK_LEN_OFFSET);
6241 #endif /* HAVE_LONGLONG */
6243 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
6244 "lock_pid = %u, count = %.0f, offset = %.0f\n",
6246 (unsigned int)lock_type,
6247 (unsigned int)lock_pid,
6251 if (lock_type == UNLOCK_LOCK) {
6252 status = do_unlock(smbd_messaging_context(),
6259 uint32 block_smbpid;
6261 struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
6273 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
6275 * A blocking lock was requested. Package up
6276 * this smb into a queued request and push it
6277 * onto the blocking lock queue.
6279 if(push_blocking_lock_request(br_lck,
6282 -1, /* infinite timeout. */
6290 TALLOC_FREE(br_lck);
6294 TALLOC_FREE(br_lck);
6300 /****************************************************************************
6301 Deal with SMB_SET_FILE_BASIC_INFO.
6302 ****************************************************************************/
6304 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
6308 const struct smb_filename *smb_fname)
6310 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
6311 struct smb_file_time ft;
6313 NTSTATUS status = NT_STATUS_OK;
6317 if (total_data < 36) {
6318 return NT_STATUS_INVALID_PARAMETER;
6321 /* Set the attributes */
6322 dosmode = IVAL(pdata,32);
6323 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
6324 if (!NT_STATUS_IS_OK(status)) {
6329 ft.create_time = interpret_long_date(pdata);
6332 ft.atime = interpret_long_date(pdata+8);
6335 ft.mtime = interpret_long_date(pdata+16);
6338 ft.ctime = interpret_long_date(pdata+24);
6340 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
6341 smb_fname_str_dbg(smb_fname)));
6343 return smb_set_file_time(conn, fsp, smb_fname, &ft,
6347 /****************************************************************************
6348 Deal with SMB_INFO_STANDARD.
6349 ****************************************************************************/
6351 static NTSTATUS smb_set_info_standard(connection_struct *conn,
6355 const struct smb_filename *smb_fname)
6357 struct smb_file_time ft;
6361 if (total_data < 12) {
6362 return NT_STATUS_INVALID_PARAMETER;
6366 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
6368 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
6370 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
6372 DEBUG(10,("smb_set_info_standard: file %s\n",
6373 smb_fname_str_dbg(smb_fname)));
6375 return smb_set_file_time(conn,
6382 /****************************************************************************
6383 Deal with SMB_SET_FILE_ALLOCATION_INFO.
6384 ****************************************************************************/
6386 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
6387 struct smb_request *req,
6391 struct smb_filename *smb_fname)
6393 uint64_t allocation_size = 0;
6394 NTSTATUS status = NT_STATUS_OK;
6395 files_struct *new_fsp = NULL;
6397 if (!VALID_STAT(smb_fname->st)) {
6398 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6401 if (total_data < 8) {
6402 return NT_STATUS_INVALID_PARAMETER;
6405 allocation_size = (uint64_t)IVAL(pdata,0);
6406 #ifdef LARGE_SMB_OFF_T
6407 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
6408 #else /* LARGE_SMB_OFF_T */
6409 if (IVAL(pdata,4) != 0) {
6410 /* more than 32 bits? */
6411 return NT_STATUS_INVALID_PARAMETER;
6413 #endif /* LARGE_SMB_OFF_T */
6415 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
6416 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6417 (double)allocation_size));
6419 if (allocation_size) {
6420 allocation_size = smb_roundup(conn, allocation_size);
6423 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
6424 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
6425 (double)allocation_size));
6427 if (fsp && fsp->fh->fd != -1) {
6428 /* Open file handle. */
6429 /* Only change if needed. */
6430 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6431 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
6432 return map_nt_error_from_unix(errno);
6435 /* But always update the time. */
6437 * This is equivalent to a write. Ensure it's seen immediately
6438 * if there are no pending writes.
6440 trigger_write_time_update_immediate(fsp);
6441 return NT_STATUS_OK;
6444 /* Pathname or stat or directory file. */
6445 status = SMB_VFS_CREATE_FILE(
6448 0, /* root_dir_fid */
6449 smb_fname, /* fname */
6450 FILE_WRITE_DATA, /* access_mask */
6451 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6453 FILE_OPEN, /* create_disposition*/
6454 0, /* create_options */
6455 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6456 FORCE_OPLOCK_BREAK_TO_NONE, /* oplock_request */
6457 0, /* allocation_size */
6460 &new_fsp, /* result */
6463 if (!NT_STATUS_IS_OK(status)) {
6464 /* NB. We check for open_was_deferred in the caller. */
6468 /* Only change if needed. */
6469 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
6470 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
6471 status = map_nt_error_from_unix(errno);
6472 close_file(req, new_fsp, NORMAL_CLOSE);
6477 /* Changing the allocation size should set the last mod time. */
6479 * This is equivalent to a write. Ensure it's seen immediately
6480 * if there are no pending writes.
6482 trigger_write_time_update_immediate(new_fsp);
6484 close_file(req, new_fsp, NORMAL_CLOSE);
6485 return NT_STATUS_OK;
6488 /****************************************************************************
6489 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
6490 ****************************************************************************/
6492 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
6493 struct smb_request *req,
6497 const struct smb_filename *smb_fname)
6501 if (total_data < 8) {
6502 return NT_STATUS_INVALID_PARAMETER;
6505 size = IVAL(pdata,0);
6506 #ifdef LARGE_SMB_OFF_T
6507 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6508 #else /* LARGE_SMB_OFF_T */
6509 if (IVAL(pdata,4) != 0) {
6510 /* more than 32 bits? */
6511 return NT_STATUS_INVALID_PARAMETER;
6513 #endif /* LARGE_SMB_OFF_T */
6514 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
6515 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
6518 return smb_set_file_size(conn, req,
6525 /****************************************************************************
6526 Allow a UNIX info mknod.
6527 ****************************************************************************/
6529 static NTSTATUS smb_unix_mknod(connection_struct *conn,
6532 const struct smb_filename *smb_fname)
6534 uint32 file_type = IVAL(pdata,56);
6535 #if defined(HAVE_MAKEDEV)
6536 uint32 dev_major = IVAL(pdata,60);
6537 uint32 dev_minor = IVAL(pdata,68);
6539 SMB_DEV_T dev = (SMB_DEV_T)0;
6540 uint32 raw_unixmode = IVAL(pdata,84);
6544 if (total_data < 100) {
6545 return NT_STATUS_INVALID_PARAMETER;
6548 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6549 PERM_NEW_FILE, &unixmode);
6550 if (!NT_STATUS_IS_OK(status)) {
6554 #if defined(HAVE_MAKEDEV)
6555 dev = makedev(dev_major, dev_minor);
6558 switch (file_type) {
6559 #if defined(S_IFIFO)
6560 case UNIX_TYPE_FIFO:
6561 unixmode |= S_IFIFO;
6564 #if defined(S_IFSOCK)
6565 case UNIX_TYPE_SOCKET:
6566 unixmode |= S_IFSOCK;
6569 #if defined(S_IFCHR)
6570 case UNIX_TYPE_CHARDEV:
6571 unixmode |= S_IFCHR;
6574 #if defined(S_IFBLK)
6575 case UNIX_TYPE_BLKDEV:
6576 unixmode |= S_IFBLK;
6580 return NT_STATUS_INVALID_PARAMETER;
6583 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
6584 "%.0f mode 0%o for file %s\n", (double)dev,
6585 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
6587 /* Ok - do the mknod. */
6588 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
6589 return map_nt_error_from_unix(errno);
6592 /* If any of the other "set" calls fail we
6593 * don't want to end up with a half-constructed mknod.
6596 if (lp_inherit_perms(SNUM(conn))) {
6598 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
6600 return NT_STATUS_NO_MEMORY;
6602 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
6604 TALLOC_FREE(parent);
6607 return NT_STATUS_OK;
6610 /****************************************************************************
6611 Deal with SMB_SET_FILE_UNIX_BASIC.
6612 ****************************************************************************/
6614 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
6615 struct smb_request *req,
6619 const struct smb_filename *smb_fname)
6621 struct smb_file_time ft;
6622 uint32 raw_unixmode;
6625 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
6626 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
6627 NTSTATUS status = NT_STATUS_OK;
6628 bool delete_on_fail = False;
6629 enum perm_type ptype;
6630 files_struct *all_fsps = NULL;
6631 bool modify_mtime = true;
6633 SMB_STRUCT_STAT sbuf;
6637 if (total_data < 100) {
6638 return NT_STATUS_INVALID_PARAMETER;
6641 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
6642 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
6643 size=IVAL(pdata,0); /* first 8 Bytes are size */
6644 #ifdef LARGE_SMB_OFF_T
6645 size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32);
6646 #else /* LARGE_SMB_OFF_T */
6647 if (IVAL(pdata,4) != 0) {
6648 /* more than 32 bits? */
6649 return NT_STATUS_INVALID_PARAMETER;
6651 #endif /* LARGE_SMB_OFF_T */
6654 ft.atime = interpret_long_date(pdata+24); /* access_time */
6655 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
6656 set_owner = (uid_t)IVAL(pdata,40);
6657 set_grp = (gid_t)IVAL(pdata,48);
6658 raw_unixmode = IVAL(pdata,84);
6660 if (VALID_STAT(smb_fname->st)) {
6661 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
6662 ptype = PERM_EXISTING_DIR;
6664 ptype = PERM_EXISTING_FILE;
6667 ptype = PERM_NEW_FILE;
6670 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6672 if (!NT_STATUS_IS_OK(status)) {
6676 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
6677 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
6678 smb_fname_str_dbg(smb_fname), (double)size,
6679 (unsigned int)set_owner, (unsigned int)set_grp,
6680 (int)raw_unixmode));
6682 sbuf = smb_fname->st;
6684 if (!VALID_STAT(sbuf)) {
6685 struct smb_filename *smb_fname_tmp = NULL;
6687 * The only valid use of this is to create character and block
6688 * devices, and named pipes. This is deprecated (IMHO) and
6689 * a new info level should be used for mknod. JRA.
6692 status = smb_unix_mknod(conn,
6696 if (!NT_STATUS_IS_OK(status)) {
6700 status = copy_smb_filename(talloc_tos(), smb_fname,
6702 if (!NT_STATUS_IS_OK(status)) {
6706 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
6707 status = map_nt_error_from_unix(errno);
6708 TALLOC_FREE(smb_fname_tmp);
6709 SMB_VFS_UNLINK(conn, smb_fname);
6713 sbuf = smb_fname_tmp->st;
6714 TALLOC_FREE(smb_fname_tmp);
6716 /* Ensure we don't try and change anything else. */
6717 raw_unixmode = SMB_MODE_NO_CHANGE;
6718 size = get_file_size_stat(&sbuf);
6719 ft.atime = sbuf.st_ex_atime;
6720 ft.mtime = sbuf.st_ex_mtime;
6722 * We continue here as we might want to change the
6725 delete_on_fail = True;
6729 /* Horrible backwards compatibility hack as an old server bug
6730 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
6734 size = get_file_size_stat(&sbuf);
6739 * Deal with the UNIX specific mode set.
6742 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
6743 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6744 "setting mode 0%o for file %s\n",
6745 (unsigned int)unixmode,
6746 smb_fname_str_dbg(smb_fname)));
6747 if (SMB_VFS_CHMOD(conn, smb_fname->base_name, unixmode) != 0) {
6748 return map_nt_error_from_unix(errno);
6753 * Deal with the UNIX specific uid set.
6756 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
6757 (sbuf.st_ex_uid != set_owner)) {
6760 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6761 "changing owner %u for path %s\n",
6762 (unsigned int)set_owner,
6763 smb_fname_str_dbg(smb_fname)));
6765 if (S_ISLNK(sbuf.st_ex_mode)) {
6766 ret = SMB_VFS_LCHOWN(conn, smb_fname->base_name,
6767 set_owner, (gid_t)-1);
6769 ret = SMB_VFS_CHOWN(conn, smb_fname->base_name,
6770 set_owner, (gid_t)-1);
6774 status = map_nt_error_from_unix(errno);
6775 if (delete_on_fail) {
6776 SMB_VFS_UNLINK(conn, smb_fname);
6783 * Deal with the UNIX specific gid set.
6786 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6787 (sbuf.st_ex_gid != set_grp)) {
6788 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6789 "changing group %u for file %s\n",
6790 (unsigned int)set_owner,
6791 smb_fname_str_dbg(smb_fname)));
6792 if (SMB_VFS_CHOWN(conn, smb_fname->base_name, (uid_t)-1,
6794 status = map_nt_error_from_unix(errno);
6795 if (delete_on_fail) {
6796 SMB_VFS_UNLINK(conn, smb_fname);
6802 /* Deal with any size changes. */
6804 status = smb_set_file_size(conn, req,
6809 if (!NT_STATUS_IS_OK(status)) {
6813 /* Deal with any time changes. */
6814 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
6815 /* No change, don't cancel anything. */
6819 id = vfs_file_id_from_sbuf(conn, &sbuf);
6820 for(all_fsps = file_find_di_first(id); all_fsps;
6821 all_fsps = file_find_di_next(all_fsps)) {
6823 * We're setting the time explicitly for UNIX.
6824 * Cancel any pending changes over all handles.
6826 all_fsps->update_write_time_on_close = false;
6827 TALLOC_FREE(all_fsps->update_write_time_event);
6831 * Override the "setting_write_time"
6832 * parameter here as it almost does what
6833 * we need. Just remember if we modified
6834 * mtime and send the notify ourselves.
6836 if (null_timespec(ft.mtime)) {
6837 modify_mtime = false;
6840 status = smb_set_file_time(conn,
6846 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6847 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6852 /****************************************************************************
6853 Deal with SMB_SET_FILE_UNIX_INFO2.
6854 ****************************************************************************/
6856 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6857 struct smb_request *req,
6861 const struct smb_filename *smb_fname)
6867 if (total_data < 116) {
6868 return NT_STATUS_INVALID_PARAMETER;
6871 /* Start by setting all the fields that are common between UNIX_BASIC
6874 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6876 if (!NT_STATUS_IS_OK(status)) {
6880 smb_fflags = IVAL(pdata, 108);
6881 smb_fmask = IVAL(pdata, 112);
6883 /* NB: We should only attempt to alter the file flags if the client
6884 * sends a non-zero mask.
6886 if (smb_fmask != 0) {
6887 int stat_fflags = 0;
6889 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6890 smb_fmask, &stat_fflags)) {
6891 /* Client asked to alter a flag we don't understand. */
6892 return NT_STATUS_INVALID_PARAMETER;
6895 if (fsp && fsp->fh->fd != -1) {
6896 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
6897 return NT_STATUS_NOT_SUPPORTED;
6899 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
6900 stat_fflags) != 0) {
6901 return map_nt_error_from_unix(errno);
6906 /* XXX: need to add support for changing the create_time here. You
6907 * can do this for paths on Darwin with setattrlist(2). The right way
6908 * to hook this up is probably by extending the VFS utimes interface.
6911 return NT_STATUS_OK;
6914 /****************************************************************************
6915 Create a directory with POSIX semantics.
6916 ****************************************************************************/
6918 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
6919 struct smb_request *req,
6922 struct smb_filename *smb_fname,
6923 int *pdata_return_size)
6925 NTSTATUS status = NT_STATUS_OK;
6926 uint32 raw_unixmode = 0;
6927 uint32 mod_unixmode = 0;
6928 mode_t unixmode = (mode_t)0;
6929 files_struct *fsp = NULL;
6930 uint16 info_level_return = 0;
6932 char *pdata = *ppdata;
6934 if (total_data < 18) {
6935 return NT_STATUS_INVALID_PARAMETER;
6938 raw_unixmode = IVAL(pdata,8);
6939 /* Next 4 bytes are not yet defined. */
6941 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
6942 PERM_NEW_DIR, &unixmode);
6943 if (!NT_STATUS_IS_OK(status)) {
6947 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
6949 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
6950 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
6952 status = SMB_VFS_CREATE_FILE(
6955 0, /* root_dir_fid */
6956 smb_fname, /* fname */
6957 FILE_READ_ATTRIBUTES, /* access_mask */
6958 FILE_SHARE_NONE, /* share_access */
6959 FILE_CREATE, /* create_disposition*/
6960 FILE_DIRECTORY_FILE, /* create_options */
6961 mod_unixmode, /* file_attributes */
6962 0, /* oplock_request */
6963 0, /* allocation_size */
6969 if (NT_STATUS_IS_OK(status)) {
6970 close_file(req, fsp, NORMAL_CLOSE);
6973 info_level_return = SVAL(pdata,16);
6975 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
6976 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
6977 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
6978 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
6980 *pdata_return_size = 12;
6983 /* Realloc the data size */
6984 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
6985 if (*ppdata == NULL) {
6986 *pdata_return_size = 0;
6987 return NT_STATUS_NO_MEMORY;
6991 SSVAL(pdata,0,NO_OPLOCK_RETURN);
6992 SSVAL(pdata,2,0); /* No fnum. */
6993 SIVAL(pdata,4,info); /* Was directory created. */
6995 switch (info_level_return) {
6996 case SMB_QUERY_FILE_UNIX_BASIC:
6997 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
6998 SSVAL(pdata,10,0); /* Padding. */
6999 store_file_unix_basic(conn, pdata + 12, fsp,
7002 case SMB_QUERY_FILE_UNIX_INFO2:
7003 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7004 SSVAL(pdata,10,0); /* Padding. */
7005 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7009 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7010 SSVAL(pdata,10,0); /* Padding. */
7017 /****************************************************************************
7018 Open/Create a file with POSIX semantics.
7019 ****************************************************************************/
7021 static NTSTATUS smb_posix_open(connection_struct *conn,
7022 struct smb_request *req,
7025 struct smb_filename *smb_fname,
7026 int *pdata_return_size)
7028 bool extended_oplock_granted = False;
7029 char *pdata = *ppdata;
7031 uint32 wire_open_mode = 0;
7032 uint32 raw_unixmode = 0;
7033 uint32 mod_unixmode = 0;
7034 uint32 create_disp = 0;
7035 uint32 access_mask = 0;
7036 uint32 create_options = 0;
7037 NTSTATUS status = NT_STATUS_OK;
7038 mode_t unixmode = (mode_t)0;
7039 files_struct *fsp = NULL;
7040 int oplock_request = 0;
7042 uint16 info_level_return = 0;
7044 if (total_data < 18) {
7045 return NT_STATUS_INVALID_PARAMETER;
7048 flags = IVAL(pdata,0);
7049 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
7050 if (oplock_request) {
7051 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
7054 wire_open_mode = IVAL(pdata,4);
7056 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
7057 return smb_posix_mkdir(conn, req,
7064 switch (wire_open_mode & SMB_ACCMODE) {
7066 access_mask = FILE_READ_DATA;
7069 access_mask = FILE_WRITE_DATA;
7072 access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
7075 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
7076 (unsigned int)wire_open_mode ));
7077 return NT_STATUS_INVALID_PARAMETER;
7080 wire_open_mode &= ~SMB_ACCMODE;
7082 if((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) == (SMB_O_CREAT | SMB_O_EXCL)) {
7083 create_disp = FILE_CREATE;
7084 } else if((wire_open_mode & (SMB_O_CREAT | SMB_O_TRUNC)) == (SMB_O_CREAT | SMB_O_TRUNC)) {
7085 create_disp = FILE_OVERWRITE_IF;
7086 } else if((wire_open_mode & SMB_O_CREAT) == SMB_O_CREAT) {
7087 create_disp = FILE_OPEN_IF;
7088 } else if ((wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL | SMB_O_TRUNC)) == 0) {
7089 create_disp = FILE_OPEN;
7091 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
7092 (unsigned int)wire_open_mode ));
7093 return NT_STATUS_INVALID_PARAMETER;
7096 raw_unixmode = IVAL(pdata,8);
7097 /* Next 4 bytes are not yet defined. */
7099 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7100 (VALID_STAT(smb_fname->st) ?
7101 PERM_EXISTING_FILE : PERM_NEW_FILE),
7104 if (!NT_STATUS_IS_OK(status)) {
7108 mod_unixmode = (uint32)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7110 if (wire_open_mode & SMB_O_SYNC) {
7111 create_options |= FILE_WRITE_THROUGH;
7113 if (wire_open_mode & SMB_O_APPEND) {
7114 access_mask |= FILE_APPEND_DATA;
7116 if (wire_open_mode & SMB_O_DIRECT) {
7117 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
7120 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
7121 smb_fname_str_dbg(smb_fname),
7122 (unsigned int)wire_open_mode,
7123 (unsigned int)unixmode ));
7125 status = SMB_VFS_CREATE_FILE(
7128 0, /* root_dir_fid */
7129 smb_fname, /* fname */
7130 access_mask, /* access_mask */
7131 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7133 create_disp, /* create_disposition*/
7134 FILE_NON_DIRECTORY_FILE, /* create_options */
7135 mod_unixmode, /* file_attributes */
7136 oplock_request, /* oplock_request */
7137 0, /* allocation_size */
7143 if (!NT_STATUS_IS_OK(status)) {
7147 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
7148 extended_oplock_granted = True;
7151 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
7152 extended_oplock_granted = True;
7155 info_level_return = SVAL(pdata,16);
7157 /* Allocate the correct return size. */
7159 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7160 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7161 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7162 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7164 *pdata_return_size = 12;
7167 /* Realloc the data size */
7168 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7169 if (*ppdata == NULL) {
7170 close_file(req, fsp, ERROR_CLOSE);
7171 *pdata_return_size = 0;
7172 return NT_STATUS_NO_MEMORY;
7176 if (extended_oplock_granted) {
7177 if (flags & REQUEST_BATCH_OPLOCK) {
7178 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
7180 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
7182 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
7183 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
7185 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7188 SSVAL(pdata,2,fsp->fnum);
7189 SIVAL(pdata,4,info); /* Was file created etc. */
7191 switch (info_level_return) {
7192 case SMB_QUERY_FILE_UNIX_BASIC:
7193 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7194 SSVAL(pdata,10,0); /* padding. */
7195 store_file_unix_basic(conn, pdata + 12, fsp,
7198 case SMB_QUERY_FILE_UNIX_INFO2:
7199 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7200 SSVAL(pdata,10,0); /* padding. */
7201 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7205 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7206 SSVAL(pdata,10,0); /* padding. */
7209 return NT_STATUS_OK;
7212 /****************************************************************************
7213 Delete a file with POSIX semantics.
7214 ****************************************************************************/
7216 static NTSTATUS smb_posix_unlink(connection_struct *conn,
7217 struct smb_request *req,
7220 struct smb_filename *smb_fname)
7222 NTSTATUS status = NT_STATUS_OK;
7223 files_struct *fsp = NULL;
7227 int create_options = 0;
7229 struct share_mode_lock *lck = NULL;
7231 if (total_data < 2) {
7232 return NT_STATUS_INVALID_PARAMETER;
7235 flags = SVAL(pdata,0);
7237 if (!VALID_STAT(smb_fname->st)) {
7238 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7241 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
7242 !VALID_STAT_OF_DIR(smb_fname->st)) {
7243 return NT_STATUS_NOT_A_DIRECTORY;
7246 DEBUG(10,("smb_posix_unlink: %s %s\n",
7247 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
7248 smb_fname_str_dbg(smb_fname)));
7250 if (VALID_STAT_OF_DIR(smb_fname->st)) {
7251 create_options |= FILE_DIRECTORY_FILE;
7254 status = SMB_VFS_CREATE_FILE(
7257 0, /* root_dir_fid */
7258 smb_fname, /* fname */
7259 DELETE_ACCESS, /* access_mask */
7260 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7262 FILE_OPEN, /* create_disposition*/
7263 create_options, /* create_options */
7264 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
7265 0, /* oplock_request */
7266 0, /* allocation_size */
7272 if (!NT_STATUS_IS_OK(status)) {
7277 * Don't lie to client. If we can't really delete due to
7278 * non-POSIX opens return SHARING_VIOLATION.
7281 lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL,
7284 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
7285 "lock for file %s\n", fsp_str_dbg(fsp)));
7286 close_file(req, fsp, NORMAL_CLOSE);
7287 return NT_STATUS_INVALID_PARAMETER;
7291 * See if others still have the file open. If this is the case, then
7292 * don't delete. If all opens are POSIX delete we can set the delete
7293 * on close disposition.
7295 for (i=0; i<lck->num_share_modes; i++) {
7296 struct share_mode_entry *e = &lck->share_modes[i];
7297 if (is_valid_share_mode_entry(e)) {
7298 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
7301 /* Fail with sharing violation. */
7302 close_file(req, fsp, NORMAL_CLOSE);
7304 return NT_STATUS_SHARING_VIOLATION;
7309 * Set the delete on close.
7311 status = smb_set_file_disposition_info(conn,
7317 if (!NT_STATUS_IS_OK(status)) {
7318 close_file(req, fsp, NORMAL_CLOSE);
7323 return close_file(req, fsp, NORMAL_CLOSE);
7326 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
7327 struct smb_request *req,
7328 TALLOC_CTX *mem_ctx,
7329 uint16_t info_level,
7331 struct smb_filename *smb_fname,
7332 char **ppdata, int total_data,
7335 char *pdata = *ppdata;
7336 NTSTATUS status = NT_STATUS_OK;
7337 int data_return_size = 0;
7341 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
7342 return NT_STATUS_INVALID_LEVEL;
7345 if (!CAN_WRITE(conn)) {
7346 /* Allow POSIX opens. The open path will deny
7347 * any non-readonly opens. */
7348 if (info_level != SMB_POSIX_PATH_OPEN) {
7349 return NT_STATUS_DOS(ERRSRV, ERRaccess);
7353 DEBUG(3,("smbd_do_setfilepathinfo: %s (fnum %d) info_level=%d "
7354 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
7355 fsp ? fsp->fnum : -1, info_level, total_data));
7357 switch (info_level) {
7359 case SMB_INFO_STANDARD:
7361 status = smb_set_info_standard(conn,
7369 case SMB_INFO_SET_EA:
7371 status = smb_info_set_ea(conn,
7379 case SMB_SET_FILE_BASIC_INFO:
7380 case SMB_FILE_BASIC_INFORMATION:
7382 status = smb_set_file_basic_info(conn,
7390 case SMB_FILE_ALLOCATION_INFORMATION:
7391 case SMB_SET_FILE_ALLOCATION_INFO:
7393 status = smb_set_file_allocation_info(conn, req,
7401 case SMB_FILE_END_OF_FILE_INFORMATION:
7402 case SMB_SET_FILE_END_OF_FILE_INFO:
7404 status = smb_set_file_end_of_file_info(conn, req,
7412 case SMB_FILE_DISPOSITION_INFORMATION:
7413 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
7416 /* JRA - We used to just ignore this on a path ?
7417 * Shouldn't this be invalid level on a pathname
7420 if (tran_call != TRANSACT2_SETFILEINFO) {
7421 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
7424 status = smb_set_file_disposition_info(conn,
7432 case SMB_FILE_POSITION_INFORMATION:
7434 status = smb_file_position_information(conn,
7441 case SMB_FILE_FULL_EA_INFORMATION:
7443 status = smb_set_file_full_ea_info(conn,
7450 /* From tridge Samba4 :
7451 * MODE_INFORMATION in setfileinfo (I have no
7452 * idea what "mode information" on a file is - it takes a value of 0,
7453 * 2, 4 or 6. What could it be?).
7456 case SMB_FILE_MODE_INFORMATION:
7458 status = smb_file_mode_information(conn,
7465 * CIFS UNIX extensions.
7468 case SMB_SET_FILE_UNIX_BASIC:
7470 status = smb_set_file_unix_basic(conn, req,
7478 case SMB_SET_FILE_UNIX_INFO2:
7480 status = smb_set_file_unix_info2(conn, req,
7488 case SMB_SET_FILE_UNIX_LINK:
7491 /* We must have a pathname for this. */
7492 return NT_STATUS_INVALID_LEVEL;
7494 status = smb_set_file_unix_link(conn, req, pdata,
7495 total_data, smb_fname);
7499 case SMB_SET_FILE_UNIX_HLINK:
7502 /* We must have a pathname for this. */
7503 return NT_STATUS_INVALID_LEVEL;
7505 status = smb_set_file_unix_hlink(conn, req,
7511 case SMB_FILE_RENAME_INFORMATION:
7513 status = smb_file_rename_information(conn, req,
7519 #if defined(HAVE_POSIX_ACLS)
7520 case SMB_SET_POSIX_ACL:
7522 status = smb_set_posix_acl(conn,
7531 case SMB_SET_POSIX_LOCK:
7534 return NT_STATUS_INVALID_LEVEL;
7536 status = smb_set_posix_lock(conn, req,
7537 pdata, total_data, fsp);
7541 case SMB_POSIX_PATH_OPEN:
7544 /* We must have a pathname for this. */
7545 return NT_STATUS_INVALID_LEVEL;
7548 status = smb_posix_open(conn, req,
7556 case SMB_POSIX_PATH_UNLINK:
7559 /* We must have a pathname for this. */
7560 return NT_STATUS_INVALID_LEVEL;
7563 status = smb_posix_unlink(conn, req,
7571 return NT_STATUS_INVALID_LEVEL;
7574 if (!NT_STATUS_IS_OK(status)) {
7578 *ret_data_size = data_return_size;
7579 return NT_STATUS_OK;
7582 /****************************************************************************
7583 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
7584 ****************************************************************************/
7586 static void call_trans2setfilepathinfo(connection_struct *conn,
7587 struct smb_request *req,
7588 unsigned int tran_call,
7589 char **pparams, int total_params,
7590 char **ppdata, int total_data,
7591 unsigned int max_data_bytes)
7593 char *params = *pparams;
7594 char *pdata = *ppdata;
7596 struct smb_filename *smb_fname = NULL;
7597 files_struct *fsp = NULL;
7598 NTSTATUS status = NT_STATUS_OK;
7599 int data_return_size = 0;
7602 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7606 if (tran_call == TRANSACT2_SETFILEINFO) {
7607 if (total_params < 4) {
7608 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7612 fsp = file_fsp(req, SVAL(params,0));
7613 /* Basic check for non-null fsp. */
7614 if (!check_fsp_open(conn, req, fsp)) {
7617 info_level = SVAL(params,2);
7619 status = copy_smb_filename(talloc_tos(), fsp->fsp_name,
7621 if (!NT_STATUS_IS_OK(status)) {
7622 reply_nterror(req, status);
7626 if(fsp->is_directory || fsp->fh->fd == -1) {
7628 * This is actually a SETFILEINFO on a directory
7629 * handle (returned from an NT SMB). NT5.0 seems
7630 * to do this call. JRA.
7632 if (INFO_LEVEL_IS_UNIX(info_level)) {
7633 /* Always do lstat for UNIX calls. */
7634 if (SMB_VFS_LSTAT(conn, smb_fname)) {
7635 DEBUG(3,("call_trans2setfilepathinfo: "
7636 "SMB_VFS_LSTAT of %s failed "
7638 smb_fname_str_dbg(smb_fname),
7640 reply_nterror(req, map_nt_error_from_unix(errno));
7644 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
7645 DEBUG(3,("call_trans2setfilepathinfo: "
7646 "fileinfo of %s failed (%s)\n",
7647 smb_fname_str_dbg(smb_fname),
7649 reply_nterror(req, map_nt_error_from_unix(errno));
7653 } else if (fsp->print_file) {
7655 * Doing a DELETE_ON_CLOSE should cancel a print job.
7657 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
7658 fsp->fh->private_options |= FILE_DELETE_ON_CLOSE;
7660 DEBUG(3,("call_trans2setfilepathinfo: "
7661 "Cancelling print job (%s)\n",
7665 send_trans2_replies(conn, req, params, 2,
7670 reply_doserror(req, ERRDOS, ERRbadpath);
7675 * Original code - this is an open file.
7677 if (!check_fsp(conn, req, fsp)) {
7681 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
7682 DEBUG(3,("call_trans2setfilepathinfo: fstat "
7683 "of fnum %d failed (%s)\n", fsp->fnum,
7685 reply_nterror(req, map_nt_error_from_unix(errno));
7693 if (total_params < 7) {
7694 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7698 info_level = SVAL(params,0);
7699 srvstr_get_path(req, params, req->flags2, &fname, ¶ms[6],
7700 total_params - 6, STR_TERMINATE,
7702 if (!NT_STATUS_IS_OK(status)) {
7703 reply_nterror(req, status);
7707 status = filename_convert(req, conn,
7708 req->flags2 & FLAGS2_DFS_PATHNAMES,
7713 if (!NT_STATUS_IS_OK(status)) {
7714 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7715 reply_botherror(req,
7716 NT_STATUS_PATH_NOT_COVERED,
7717 ERRSRV, ERRbadpath);
7720 reply_nterror(req, status);
7724 if (INFO_LEVEL_IS_UNIX(info_level)) {
7726 * For CIFS UNIX extensions the target name may not exist.
7729 /* Always do lstat for UNIX calls. */
7730 SMB_VFS_LSTAT(conn, smb_fname);
7732 } else if (!VALID_STAT(smb_fname->st) &&
7733 SMB_VFS_STAT(conn, smb_fname)) {
7734 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
7736 smb_fname_str_dbg(smb_fname),
7738 reply_nterror(req, map_nt_error_from_unix(errno));
7743 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (fnum %d) info_level=%d "
7744 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
7745 fsp ? fsp->fnum : -1, info_level,total_data));
7747 /* Realloc the parameter size */
7748 *pparams = (char *)SMB_REALLOC(*pparams,2);
7749 if (*pparams == NULL) {
7750 reply_nterror(req, NT_STATUS_NO_MEMORY);
7757 status = smbd_do_setfilepathinfo(conn, req, req,
7763 if (!NT_STATUS_IS_OK(status)) {
7764 if (open_was_deferred(req->mid)) {
7765 /* We have re-scheduled this call. */
7768 if (blocking_lock_was_deferred(req->mid)) {
7769 /* We have re-scheduled this call. */
7772 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7773 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
7774 ERRSRV, ERRbadpath);
7777 if (info_level == SMB_POSIX_PATH_OPEN) {
7778 reply_openerror(req, status);
7782 reply_nterror(req, status);
7786 send_trans2_replies(conn, req, params, 2, *ppdata, data_return_size,
7792 /****************************************************************************
7793 Reply to a TRANS2_MKDIR (make directory with extended attributes).
7794 ****************************************************************************/
7796 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
7797 char **pparams, int total_params,
7798 char **ppdata, int total_data,
7799 unsigned int max_data_bytes)
7801 struct smb_filename *smb_dname = NULL;
7802 char *params = *pparams;
7803 char *pdata = *ppdata;
7804 char *directory = NULL;
7805 NTSTATUS status = NT_STATUS_OK;
7806 struct ea_list *ea_list = NULL;
7807 TALLOC_CTX *ctx = talloc_tos();
7809 if (!CAN_WRITE(conn)) {
7810 reply_doserror(req, ERRSRV, ERRaccess);
7814 if (total_params < 5) {
7815 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7819 srvstr_get_path(ctx, params, req->flags2, &directory, ¶ms[4],
7820 total_params - 4, STR_TERMINATE,
7822 if (!NT_STATUS_IS_OK(status)) {
7823 reply_nterror(req, status);
7827 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
7829 status = filename_convert(ctx,
7831 req->flags2 & FLAGS2_DFS_PATHNAMES,
7837 if (!NT_STATUS_IS_OK(status)) {
7838 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
7839 reply_botherror(req,
7840 NT_STATUS_PATH_NOT_COVERED,
7841 ERRSRV, ERRbadpath);
7844 reply_nterror(req, status);
7848 /* Any data in this call is an EA list. */
7849 if (total_data && (total_data != 4) && !lp_ea_support(SNUM(conn))) {
7850 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
7855 * OS/2 workplace shell seems to send SET_EA requests of "null"
7856 * length (4 bytes containing IVAL 4).
7857 * They seem to have no effect. Bug #3212. JRA.
7860 if (total_data != 4) {
7861 if (total_data < 10) {
7862 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7866 if (IVAL(pdata,0) > total_data) {
7867 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
7868 IVAL(pdata,0), (unsigned int)total_data));
7869 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7873 ea_list = read_ea_list(talloc_tos(), pdata + 4,
7876 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7880 /* If total_data == 4 Windows doesn't care what values
7881 * are placed in that field, it just ignores them.
7882 * The System i QNTC IBM SMB client puts bad values here,
7883 * so ignore them. */
7885 status = create_directory(conn, req, smb_dname);
7887 if (!NT_STATUS_IS_OK(status)) {
7888 reply_nterror(req, status);
7892 /* Try and set any given EA. */
7894 status = set_ea(conn, NULL, smb_dname, ea_list);
7895 if (!NT_STATUS_IS_OK(status)) {
7896 reply_nterror(req, status);
7901 /* Realloc the parameter and data sizes */
7902 *pparams = (char *)SMB_REALLOC(*pparams,2);
7903 if(*pparams == NULL) {
7904 reply_nterror(req, NT_STATUS_NO_MEMORY);
7911 send_trans2_replies(conn, req, params, 2, *ppdata, 0, max_data_bytes);
7914 TALLOC_FREE(smb_dname);
7918 /****************************************************************************
7919 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
7920 We don't actually do this - we just send a null response.
7921 ****************************************************************************/
7923 static void call_trans2findnotifyfirst(connection_struct *conn,
7924 struct smb_request *req,
7925 char **pparams, int total_params,
7926 char **ppdata, int total_data,
7927 unsigned int max_data_bytes)
7929 char *params = *pparams;
7932 if (total_params < 6) {
7933 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
7937 info_level = SVAL(params,4);
7938 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
7940 switch (info_level) {
7945 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
7949 /* Realloc the parameter and data sizes */
7950 *pparams = (char *)SMB_REALLOC(*pparams,6);
7951 if (*pparams == NULL) {
7952 reply_nterror(req, NT_STATUS_NO_MEMORY);
7957 SSVAL(params,0,fnf_handle);
7958 SSVAL(params,2,0); /* No changes */
7959 SSVAL(params,4,0); /* No EA errors */
7966 send_trans2_replies(conn, req, params, 6, *ppdata, 0, max_data_bytes);
7971 /****************************************************************************
7972 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
7973 changes). Currently this does nothing.
7974 ****************************************************************************/
7976 static void call_trans2findnotifynext(connection_struct *conn,
7977 struct smb_request *req,
7978 char **pparams, int total_params,
7979 char **ppdata, int total_data,
7980 unsigned int max_data_bytes)
7982 char *params = *pparams;
7984 DEBUG(3,("call_trans2findnotifynext\n"));
7986 /* Realloc the parameter and data sizes */
7987 *pparams = (char *)SMB_REALLOC(*pparams,4);
7988 if (*pparams == NULL) {
7989 reply_nterror(req, NT_STATUS_NO_MEMORY);
7994 SSVAL(params,0,0); /* No changes */
7995 SSVAL(params,2,0); /* No EA errors */
7997 send_trans2_replies(conn, req, params, 4, *ppdata, 0, max_data_bytes);
8002 /****************************************************************************
8003 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
8004 ****************************************************************************/
8006 static void call_trans2getdfsreferral(connection_struct *conn,
8007 struct smb_request *req,
8008 char **pparams, int total_params,
8009 char **ppdata, int total_data,
8010 unsigned int max_data_bytes)
8012 char *params = *pparams;
8013 char *pathname = NULL;
8015 int max_referral_level;
8016 NTSTATUS status = NT_STATUS_OK;
8017 TALLOC_CTX *ctx = talloc_tos();
8019 DEBUG(10,("call_trans2getdfsreferral\n"));
8021 if (total_params < 3) {
8022 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8026 max_referral_level = SVAL(params,0);
8028 if(!lp_host_msdfs()) {
8029 reply_doserror(req, ERRDOS, ERRbadfunc);
8033 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, ¶ms[2],
8034 total_params - 2, STR_TERMINATE);
8036 reply_nterror(req, NT_STATUS_NOT_FOUND);
8039 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
8040 ppdata,&status)) < 0) {
8041 reply_nterror(req, status);
8045 SSVAL(req->inbuf, smb_flg2,
8046 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
8047 send_trans2_replies(conn, req,0,0,*ppdata,reply_size, max_data_bytes);
8052 #define LMCAT_SPL 0x53
8053 #define LMFUNC_GETJOBID 0x60
8055 /****************************************************************************
8056 Reply to a TRANS2_IOCTL - used for OS/2 printing.
8057 ****************************************************************************/
8059 static void call_trans2ioctl(connection_struct *conn,
8060 struct smb_request *req,
8061 char **pparams, int total_params,
8062 char **ppdata, int total_data,
8063 unsigned int max_data_bytes)
8065 char *pdata = *ppdata;
8066 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
8068 /* check for an invalid fid before proceeding */
8071 reply_doserror(req, ERRDOS, ERRbadfid);
8075 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
8076 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8077 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
8078 if (*ppdata == NULL) {
8079 reply_nterror(req, NT_STATUS_NO_MEMORY);
8084 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
8085 CAN ACCEPT THIS IN UNICODE. JRA. */
8087 SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
8088 srvstr_push(pdata, req->flags2, pdata + 2,
8089 global_myname(), 15,
8090 STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
8091 srvstr_push(pdata, req->flags2, pdata+18,
8092 lp_servicename(SNUM(conn)), 13,
8093 STR_ASCII|STR_TERMINATE); /* Service name */
8094 send_trans2_replies(conn, req, *pparams, 0, *ppdata, 32,
8099 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
8100 reply_doserror(req, ERRSRV, ERRerror);
8103 /****************************************************************************
8104 Reply to a SMBfindclose (stop trans2 directory search).
8105 ****************************************************************************/
8107 void reply_findclose(struct smb_request *req)
8110 struct smbd_server_connection *sconn = smbd_server_conn;
8112 START_PROFILE(SMBfindclose);
8115 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8116 END_PROFILE(SMBfindclose);
8120 dptr_num = SVALS(req->vwv+0, 0);
8122 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
8124 dptr_close(sconn, &dptr_num);
8126 reply_outbuf(req, 0, 0);
8128 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
8130 END_PROFILE(SMBfindclose);
8134 /****************************************************************************
8135 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
8136 ****************************************************************************/
8138 void reply_findnclose(struct smb_request *req)
8142 START_PROFILE(SMBfindnclose);
8145 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8146 END_PROFILE(SMBfindnclose);
8150 dptr_num = SVAL(req->vwv+0, 0);
8152 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
8154 /* We never give out valid handles for a
8155 findnotifyfirst - so any dptr_num is ok here.
8158 reply_outbuf(req, 0, 0);
8160 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
8162 END_PROFILE(SMBfindnclose);
8166 static void handle_trans2(connection_struct *conn, struct smb_request *req,
8167 struct trans_state *state)
8169 if (Protocol >= PROTOCOL_NT1) {
8170 req->flags2 |= 0x40; /* IS_LONG_NAME */
8171 SSVAL(req->inbuf,smb_flg2,req->flags2);
8174 if (conn->encrypt_level == Required && !req->encrypted) {
8175 if (state->call != TRANSACT2_QFSINFO &&
8176 state->call != TRANSACT2_SETFSINFO) {
8177 DEBUG(0,("handle_trans2: encryption required "
8179 (unsigned int)state->call));
8180 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8185 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
8187 /* Now we must call the relevant TRANS2 function */
8188 switch(state->call) {
8189 case TRANSACT2_OPEN:
8191 START_PROFILE(Trans2_open);
8192 call_trans2open(conn, req,
8193 &state->param, state->total_param,
8194 &state->data, state->total_data,
8195 state->max_data_return);
8196 END_PROFILE(Trans2_open);
8200 case TRANSACT2_FINDFIRST:
8202 START_PROFILE(Trans2_findfirst);
8203 call_trans2findfirst(conn, req,
8204 &state->param, state->total_param,
8205 &state->data, state->total_data,
8206 state->max_data_return);
8207 END_PROFILE(Trans2_findfirst);
8211 case TRANSACT2_FINDNEXT:
8213 START_PROFILE(Trans2_findnext);
8214 call_trans2findnext(conn, req,
8215 &state->param, state->total_param,
8216 &state->data, state->total_data,
8217 state->max_data_return);
8218 END_PROFILE(Trans2_findnext);
8222 case TRANSACT2_QFSINFO:
8224 START_PROFILE(Trans2_qfsinfo);
8225 call_trans2qfsinfo(conn, req,
8226 &state->param, state->total_param,
8227 &state->data, state->total_data,
8228 state->max_data_return);
8229 END_PROFILE(Trans2_qfsinfo);
8233 case TRANSACT2_SETFSINFO:
8235 START_PROFILE(Trans2_setfsinfo);
8236 call_trans2setfsinfo(conn, req,
8237 &state->param, state->total_param,
8238 &state->data, state->total_data,
8239 state->max_data_return);
8240 END_PROFILE(Trans2_setfsinfo);
8244 case TRANSACT2_QPATHINFO:
8245 case TRANSACT2_QFILEINFO:
8247 START_PROFILE(Trans2_qpathinfo);
8248 call_trans2qfilepathinfo(conn, req, state->call,
8249 &state->param, state->total_param,
8250 &state->data, state->total_data,
8251 state->max_data_return);
8252 END_PROFILE(Trans2_qpathinfo);
8256 case TRANSACT2_SETPATHINFO:
8257 case TRANSACT2_SETFILEINFO:
8259 START_PROFILE(Trans2_setpathinfo);
8260 call_trans2setfilepathinfo(conn, req, state->call,
8261 &state->param, state->total_param,
8262 &state->data, state->total_data,
8263 state->max_data_return);
8264 END_PROFILE(Trans2_setpathinfo);
8268 case TRANSACT2_FINDNOTIFYFIRST:
8270 START_PROFILE(Trans2_findnotifyfirst);
8271 call_trans2findnotifyfirst(conn, req,
8272 &state->param, state->total_param,
8273 &state->data, state->total_data,
8274 state->max_data_return);
8275 END_PROFILE(Trans2_findnotifyfirst);
8279 case TRANSACT2_FINDNOTIFYNEXT:
8281 START_PROFILE(Trans2_findnotifynext);
8282 call_trans2findnotifynext(conn, req,
8283 &state->param, state->total_param,
8284 &state->data, state->total_data,
8285 state->max_data_return);
8286 END_PROFILE(Trans2_findnotifynext);
8290 case TRANSACT2_MKDIR:
8292 START_PROFILE(Trans2_mkdir);
8293 call_trans2mkdir(conn, req,
8294 &state->param, state->total_param,
8295 &state->data, state->total_data,
8296 state->max_data_return);
8297 END_PROFILE(Trans2_mkdir);
8301 case TRANSACT2_GET_DFS_REFERRAL:
8303 START_PROFILE(Trans2_get_dfs_referral);
8304 call_trans2getdfsreferral(conn, req,
8305 &state->param, state->total_param,
8306 &state->data, state->total_data,
8307 state->max_data_return);
8308 END_PROFILE(Trans2_get_dfs_referral);
8312 case TRANSACT2_IOCTL:
8314 START_PROFILE(Trans2_ioctl);
8315 call_trans2ioctl(conn, req,
8316 &state->param, state->total_param,
8317 &state->data, state->total_data,
8318 state->max_data_return);
8319 END_PROFILE(Trans2_ioctl);
8324 /* Error in request */
8325 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
8326 reply_doserror(req, ERRSRV,ERRerror);
8330 /****************************************************************************
8331 Reply to a SMBtrans2.
8332 ****************************************************************************/
8334 void reply_trans2(struct smb_request *req)
8336 connection_struct *conn = req->conn;
8341 unsigned int tran_call;
8342 struct trans_state *state;
8345 START_PROFILE(SMBtrans2);
8347 if (req->wct < 14) {
8348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8349 END_PROFILE(SMBtrans2);
8353 dsoff = SVAL(req->vwv+12, 0);
8354 dscnt = SVAL(req->vwv+11, 0);
8355 psoff = SVAL(req->vwv+10, 0);
8356 pscnt = SVAL(req->vwv+9, 0);
8357 tran_call = SVAL(req->vwv+14, 0);
8359 result = allow_new_trans(conn->pending_trans, req->mid);
8360 if (!NT_STATUS_IS_OK(result)) {
8361 DEBUG(2, ("Got invalid trans2 request: %s\n",
8362 nt_errstr(result)));
8363 reply_nterror(req, result);
8364 END_PROFILE(SMBtrans2);
8369 switch (tran_call) {
8370 /* List the allowed trans2 calls on IPC$ */
8371 case TRANSACT2_OPEN:
8372 case TRANSACT2_GET_DFS_REFERRAL:
8373 case TRANSACT2_QFILEINFO:
8374 case TRANSACT2_QFSINFO:
8375 case TRANSACT2_SETFSINFO:
8378 reply_doserror(req, ERRSRV, ERRaccess);
8379 END_PROFILE(SMBtrans2);
8384 if ((state = TALLOC_P(conn, struct trans_state)) == NULL) {
8385 DEBUG(0, ("talloc failed\n"));
8386 reply_nterror(req, NT_STATUS_NO_MEMORY);
8387 END_PROFILE(SMBtrans2);
8391 state->cmd = SMBtrans2;
8393 state->mid = req->mid;
8394 state->vuid = req->vuid;
8395 state->setup_count = SVAL(req->vwv+13, 0);
8396 state->setup = NULL;
8397 state->total_param = SVAL(req->vwv+0, 0);
8398 state->param = NULL;
8399 state->total_data = SVAL(req->vwv+1, 0);
8401 state->max_param_return = SVAL(req->vwv+2, 0);
8402 state->max_data_return = SVAL(req->vwv+3, 0);
8403 state->max_setup_return = SVAL(req->vwv+4, 0);
8404 state->close_on_completion = BITSETW(req->vwv+5, 0);
8405 state->one_way = BITSETW(req->vwv+5, 1);
8407 state->call = tran_call;
8409 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
8410 is so as a sanity check */
8411 if (state->setup_count != 1) {
8413 * Need to have rc=0 for ioctl to get job id for OS/2.
8414 * Network printing will fail if function is not successful.
8415 * Similar function in reply.c will be used if protocol
8416 * is LANMAN1.0 instead of LM1.2X002.
8417 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
8418 * outbuf doesn't have to be set(only job id is used).
8420 if ( (state->setup_count == 4)
8421 && (tran_call == TRANSACT2_IOCTL)
8422 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
8423 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
8424 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
8426 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
8427 DEBUG(2,("Transaction is %d\n",tran_call));
8429 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8430 END_PROFILE(SMBtrans2);
8435 if ((dscnt > state->total_data) || (pscnt > state->total_param))
8438 if (state->total_data) {
8440 if (trans_oob(state->total_data, 0, dscnt)
8441 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
8445 /* Can't use talloc here, the core routines do realloc on the
8446 * params and data. */
8447 state->data = (char *)SMB_MALLOC(state->total_data);
8448 if (state->data == NULL) {
8449 DEBUG(0,("reply_trans2: data malloc fail for %u "
8450 "bytes !\n", (unsigned int)state->total_data));
8452 reply_nterror(req, NT_STATUS_NO_MEMORY);
8453 END_PROFILE(SMBtrans2);
8457 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
8460 if (state->total_param) {
8462 if (trans_oob(state->total_param, 0, pscnt)
8463 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
8467 /* Can't use talloc here, the core routines do realloc on the
8468 * params and data. */
8469 state->param = (char *)SMB_MALLOC(state->total_param);
8470 if (state->param == NULL) {
8471 DEBUG(0,("reply_trans: param malloc fail for %u "
8472 "bytes !\n", (unsigned int)state->total_param));
8473 SAFE_FREE(state->data);
8475 reply_nterror(req, NT_STATUS_NO_MEMORY);
8476 END_PROFILE(SMBtrans2);
8480 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
8483 state->received_data = dscnt;
8484 state->received_param = pscnt;
8486 if ((state->received_param == state->total_param) &&
8487 (state->received_data == state->total_data)) {
8489 handle_trans2(conn, req, state);
8491 SAFE_FREE(state->data);
8492 SAFE_FREE(state->param);
8494 END_PROFILE(SMBtrans2);
8498 DLIST_ADD(conn->pending_trans, state);
8500 /* We need to send an interim response then receive the rest
8501 of the parameter/data bytes */
8502 reply_outbuf(req, 0, 0);
8503 show_msg((char *)req->outbuf);
8504 END_PROFILE(SMBtrans2);
8509 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
8510 SAFE_FREE(state->data);
8511 SAFE_FREE(state->param);
8513 END_PROFILE(SMBtrans2);
8514 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8518 /****************************************************************************
8519 Reply to a SMBtranss2
8520 ****************************************************************************/
8522 void reply_transs2(struct smb_request *req)
8524 connection_struct *conn = req->conn;
8525 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
8526 struct trans_state *state;
8528 START_PROFILE(SMBtranss2);
8530 show_msg((char *)req->inbuf);
8533 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8534 END_PROFILE(SMBtranss2);
8538 for (state = conn->pending_trans; state != NULL;
8539 state = state->next) {
8540 if (state->mid == req->mid) {
8545 if ((state == NULL) || (state->cmd != SMBtrans2)) {
8546 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8547 END_PROFILE(SMBtranss2);
8551 /* Revise state->total_param and state->total_data in case they have
8552 changed downwards */
8554 if (SVAL(req->vwv+0, 0) < state->total_param)
8555 state->total_param = SVAL(req->vwv+0, 0);
8556 if (SVAL(req->vwv+1, 0) < state->total_data)
8557 state->total_data = SVAL(req->vwv+1, 0);
8559 pcnt = SVAL(req->vwv+2, 0);
8560 poff = SVAL(req->vwv+3, 0);
8561 pdisp = SVAL(req->vwv+4, 0);
8563 dcnt = SVAL(req->vwv+5, 0);
8564 doff = SVAL(req->vwv+6, 0);
8565 ddisp = SVAL(req->vwv+7, 0);
8567 state->received_param += pcnt;
8568 state->received_data += dcnt;
8570 if ((state->received_data > state->total_data) ||
8571 (state->received_param > state->total_param))
8575 if (trans_oob(state->total_param, pdisp, pcnt)
8576 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
8579 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
8583 if (trans_oob(state->total_data, ddisp, dcnt)
8584 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
8587 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
8590 if ((state->received_param < state->total_param) ||
8591 (state->received_data < state->total_data)) {
8592 END_PROFILE(SMBtranss2);
8596 handle_trans2(conn, req, state);
8598 DLIST_REMOVE(conn->pending_trans, state);
8599 SAFE_FREE(state->data);
8600 SAFE_FREE(state->param);
8603 END_PROFILE(SMBtranss2);
8608 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
8609 DLIST_REMOVE(conn->pending_trans, state);
8610 SAFE_FREE(state->data);
8611 SAFE_FREE(state->param);
8613 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8614 END_PROFILE(SMBtranss2);